/* ==================================================================
   app.css — 布局与组件
   结构：浮动顶栏（左：品牌 + 胶囊按钮组，右：设置） / 居中主体 / 底部输入框
   ================================================================== */

/* 顶栏、侧边栏、抽屉都是 position: fixed，不参与文档流。
   因此这里用纵向 flex 而不是 grid —— grid 会把 fixed 子元素之外的内容
   按顺序塞进 auto / 1fr 行，导致 main 落进 auto 行。 */
.app-shell {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

/* ================================================================== */
/* 浮动顶栏                                                            */
/* ================================================================== */

.topbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 14px 16px;
  padding-top: calc(14px + env(safe-area-inset-top));
  pointer-events: none;
}

.topbar > * {
  pointer-events: auto;
}

.topbar-left {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 6px;
}

.brand {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  flex: none;
  border-radius: 11px;
  will-change: transform;
}

.brand:hover {
  text-decoration: none;
}

.brand-mark {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  color: #fff;
  background: var(--gradient);
  border-radius: 10px;
  box-shadow: 0 4px 14px rgba(79, 70, 229, 0.26);
  will-change: transform;
}

.brand-mark .icon {
  width: 19px;
  height: 19px;
}

/* 胶囊按钮组 */
.control-cluster {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: rgba(255, 255, 255, 0.78);
  backdrop-filter: saturate(1.6) blur(12px);
  -webkit-backdrop-filter: saturate(1.6) blur(12px);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  box-shadow: var(--shadow-sm);
}

.cluster-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  flex: none;
  color: var(--text-2);
  border-radius: 50%;
  overflow: hidden;
  transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.cluster-btn:hover {
  color: var(--text);
  background: var(--surface-3);
}

.cluster-btn.is-active {
  color: var(--accent);
  background: var(--accent-soft);
}

.cluster-btn .icon {
  width: 17px;
  height: 17px;
}

.cluster-btn-lg {
  width: 38px;
  height: 38px;
  background: rgba(255, 255, 255, 0.78);
  backdrop-filter: saturate(1.6) blur(12px);
  -webkit-backdrop-filter: saturate(1.6) blur(12px);
  border: 1px solid var(--border);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
}

.cluster-btn-lg:hover {
  border-color: var(--border-strong);
  background: #fff;
}

.cluster-btn-lg .icon {
  width: 18px;
  height: 18px;
}

.cluster-divider {
  width: 1px;
  height: 16px;
  background: var(--border);
  flex: none;
}

/* ================================================================== */
/* 侧边栏                                                              */
/* ================================================================== */

.sidebar {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  z-index: 40;
  display: flex;
  flex-direction: column;
  width: var(--sidebar-w);
  padding-top: env(safe-area-inset-top);
  background: var(--surface);
  border-right: 1px solid var(--border);
  border-radius: 0 var(--r-xl) var(--r-xl) 0;
  box-shadow: var(--shadow-lg);
  transform: translate3d(-102%, 0, 0);
  will-change: transform;
  visibility: hidden;
}

.sidebar[data-open='true'] {
  visibility: visible;
}

.sidebar-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 62px;
  padding: 0 10px 0 20px;
  border-bottom: 1px solid var(--border);
}

.sidebar-title {
  font-size: var(--fs-sm);
  font-weight: 640;
  letter-spacing: -0.01em;
  color: var(--text-2);
}

.session-list {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.session-item {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 10px;
  border-radius: var(--r-md);
  cursor: pointer;
  transition: background-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.session-item:hover {
  background: var(--surface-2);
}

.session-item.is-active {
  background: var(--accent-soft);
}

.session-item-icon {
  display: grid;
  place-items: center;
  flex: none;
  color: var(--text-3);
}

.session-item.is-active .session-item-icon {
  color: var(--accent);
}

.session-item-text {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-sm);
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.session-item.is-active .session-item-text {
  color: var(--accent);
  font-weight: 550;
}

.session-item-time {
  font-size: 10px;
  color: var(--text-3);
  flex: none;
}

.session-del {
  flex: none;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out);
}

.session-item:hover .session-del,
.session-del:focus-visible {
  opacity: 1;
}

.sidebar-empty {
  padding: 28px 16px;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--text-3);
  line-height: 1.8;
}

.sidebar-foot {
  padding: 12px;
  border-top: 1px solid var(--border);
}

.identity-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 11px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  cursor: default;
}

.identity-icon {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: none;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-xs);
}

.identity-icon .icon {
  width: 15px;
  height: 15px;
}

.identity-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--text-2);
}

.identity-text small {
  color: var(--text-3);
  font-size: 10px;
}

.scrim {
  position: fixed;
  inset: 0;
  z-index: 35;
  background: rgba(15, 23, 42, 0.24);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  opacity: 0;
  will-change: opacity;
}

/* ================================================================== */
/* 主体                                                                */
/* ================================================================== */

.main {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1 1 0;
  min-height: 0;
  overflow: hidden;
}

.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  flex: 1 1 0;
  min-height: 0;
  padding: 72px 24px 24px;
  text-align: center;
  will-change: transform, opacity;
}

.hero[hidden] {
  display: none;
}

.hero-badge {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 2px;
  color: #fff;
  background: var(--gradient);
  border-radius: 14px;
  box-shadow: 0 8px 22px rgba(79, 70, 229, 0.24);
  will-change: transform;
}

.hero-badge .icon {
  width: 24px;
  height: 24px;
}

.hero-title {
  font-size: clamp(1.35rem, 2.4vw, 1.75rem);
  font-weight: 660;
  letter-spacing: -0.025em;
  line-height: 1.3;
  color: var(--text);
}

.hero-sub {
  max-width: 480px;
  font-size: var(--fs-base);
  color: var(--text-3);
}

.hero-sub code {
  padding: 2px 6px;
  font-size: 0.86em;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-xs);
}

.suggestions {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(232px, 1fr));
  gap: 10px;
  width: 100%;
  max-width: 760px;
  margin-top: 18px;
}

.suggestion {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 13px 15px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xs);
  overflow: hidden;
  transition:
    border-color var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out),
    background-color var(--dur-base) var(--ease-out);
  will-change: transform;
}

.suggestion:hover {
  border-color: var(--border-focus);
  background: var(--bg-tint);
  box-shadow: var(--shadow-md);
}

.suggestion-icon {
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  flex: none;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-sm);
}

.suggestion-icon .icon {
  width: 15px;
  height: 15px;
}

.suggestion-text {
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--text-2);
}

/* transcript -------------------------------------------------------- */

.transcript {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  overflow-x: hidden;
  /*
   * 顶部不留 padding，首条消息的避让交给 .transcript-inner。
   *
   * 原因：sticky 的约束矩形是滚动容器的**内容盒**。只要这里有 padding-top，
   * 内容盒顶就在 y=72，`top: 0` 也只能停在 y=72 —— 而那 72px 仍属于滚动区，
   * 代码会从吸顶栏上方滚过去，看起来就像顶栏没置顶。
   */
  padding: 0 24px 26px;
  outline: none;
  scroll-padding-top: 72px;
  /* 吸顶元素停在页面最顶部 */
  --sticky-top: 0px;
}

.transcript[hidden] {
  display: none;
}

.transcript-inner {
  max-width: var(--transcript-max);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 26px;
  /* 首条消息避开浮动顶栏。放在这里而不是 .transcript 的 padding 上，
     否则会把 sticky 的约束矩形一起推下去。 */
  padding-top: 72px;
}

.message {
  display: flex;
  gap: 13px;
  will-change: transform, opacity;
}

.message-avatar {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  margin-top: 2px;
  border-radius: var(--r-sm);
}

.message-avatar .icon {
  width: 17px;
  height: 17px;
}

.message-user .message-avatar {
  color: var(--text-2);
  background: var(--surface-3);
  border: 1px solid var(--border);
}

.message-assistant .message-avatar {
  color: #fff;
  background: var(--gradient);
  box-shadow: 0 3px 10px rgba(79, 70, 229, 0.22);
}

.message-body {
  flex: 1 1 auto;
  min-width: 0;
}

/* 用户消息：靠右的独立气泡，头像在右侧（与助手的左侧布局对称） */
.message-user {
  flex-direction: row-reverse;
  justify-content: flex-start;
}

.message-user .message-body {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  flex: 0 1 auto;
  max-width: min(78%, 620px);
}

.message-user .message-head {
  flex-direction: row-reverse;
}

.message-user .message-content {
  display: inline-block;
  max-width: 100%;
  padding: 11px 16px;
  font-size: var(--fs-base);
  line-height: 1.7;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  text-align: left;
  background: var(--accent-soft);
  border: 1px solid #dfe3ff;
  border-radius: 16px 4px 16px 16px;
}

.message-user .message-actions {
  justify-content: flex-end;
}

.message-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 6px;
  font-size: var(--fs-xs);
  color: var(--text-3);
}

.message-role {
  font-weight: 620;
  color: var(--text-2);
  letter-spacing: 0.01em;
}

.message-meta {
  font-family: var(--font-mono);
  font-size: 10.5px;
}

.message-actions {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 10px;
  /* 默认整行隐藏（含时间戳），鼠标移到消息上才浮现 */
  opacity: 0;
  transform: translateY(-3px);
  transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}

.message:hover .message-actions,
.message:focus-within .message-actions,
.message.is-streaming .message-actions {
  opacity: 1;
  transform: translateY(0);
}

/* 消息结束时间：位于复制 / 重新生成右侧 */
.message-time {
  margin-left: 8px;
  padding: 2px 8px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  line-height: 1.6;
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  white-space: nowrap;
  cursor: default;
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

.message-time:hover {
  color: var(--text-2);
  border-color: var(--border-strong);
}

.message-actions .icon-btn {
  width: 30px;
  height: 30px;
}

.message-actions .icon-btn .icon {
  width: 15px;
  height: 15px;
}

/* reasoning --------------------------------------------------------- */

.reasoning {
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  /* 同 .md-code：clip 而不是 hidden，否则里面的 sticky 失效 */
  overflow: clip;
  overflow-clip-margin: 0;
}

/* 展开时「思考过程」这一行吸顶，滚动浏览长思考时始终能收起/展开 */
.reasoning[data-open='true'] .reasoning-toggle {
  position: sticky;
  top: var(--sticky-top);
  z-index: 3;
  background: var(--surface);
  border-radius: calc(var(--r-md) - 1px) calc(var(--r-md) - 1px) 0 0;
}

.reasoning-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 12px;
  font-size: var(--fs-xs);
  font-weight: 550;
  color: var(--text-3);
  will-change: transform;
}

.reasoning-toggle:hover {
  color: var(--text-2);
  background: var(--surface-3);
}

.reasoning-toggle .icon-caret {
  width: 13px;
  height: 13px;
  /* 用轻微过冲而不是 --ease-back（1.56 的过冲对 90° 旋转会转过头） */
  transition: transform var(--dur-base) cubic-bezier(0.34, 1.18, 0.64, 1);
}

.reasoning[data-open='false'] .reasoning-toggle .icon-caret {
  transform: rotate(-90deg);
}

.reasoning-body {
  display: none;
  padding: 2px 13px 11px;
  font-size: var(--fs-sm);
  line-height: 1.72;
  color: var(--text-2);
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* 虚拟滚动需要自己算高度：限高并自己滚动，而不是让它把整段撑开 */
  max-height: 62vh;
  overflow-y: auto;
  /*
   * 这里**不能**用 overscroll-behavior: contain。
   *
   * 它会让思考块内部滚到底之后不再把滚轮事件交给外层 —— 用户把鼠标停在
   * 展开的长思考上往下滚，滚到思考块底部就整个卡住，看起来就是
   * 「滚动到一半停了」。默认的链式滚动才是这里想要的行为。
   */
  overscroll-behavior: auto;
}

.reasoning-chars {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
}

/* 思考的 token 数：字符数右侧。估算值用「≈」标明，不冒充精确值 */
.reasoning-tokens {
  margin-left: 8px;
  padding: 1px 7px;
  font-family: var(--font-mono);
  font-size: 10px;
  color: #6d28d9;
  background: #ede9fe;
  border-radius: var(--r-full);
}

.reasoning-tokens[hidden] {
  display: none;
}

.reasoning-tokens[data-exact='0'] {
  color: var(--text-3);
  background: var(--surface-3);
}

/* 虚拟文本：只有视口附近的一小段真实存在，其余靠上下占位撑高度 */
.vtext {
  display: flow-root;
}

.vtext-pad {
  width: 1px;
  pointer-events: none;
}

.vtext-content {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.reasoning[data-open='true'] .reasoning-body {
  display: block;
}

/* 展开时给个明显的容器：思考阶段正文还没出现，它得撑住整个视线 */
.reasoning[data-open='true'] {
  background: #faf9ff;
  border-color: #ddd6fe;
}

.reasoning[data-open='true'] .reasoning-toggle {
  color: #6d28d9;
}

.reasoning[data-open='true'] .reasoning-body {
  border-top-color: #ede9fe;
}

/* tool call --------------------------------------------------------- */

.tool-call {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: 10px 0;
  padding: 10px 13px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-xs);
  will-change: transform, opacity;
}

.tool-call[data-state='running'] {
  border-color: #c7d2fe;
  background: linear-gradient(90deg, var(--accent-soft), var(--surface) 55%);
}

.tool-call[data-state='ok'] {
  border-color: #a7f3d0;
}

.tool-call[data-state='error'] {
  border-color: #fecaca;
  background: var(--danger-soft);
}

/*
 * 卡片挂上「大块内容」（组件 iframe / 文件正文）之后要换行。
 *
 * .tool-call 本身是横向 flex，iframe 作为第 4 个子元素会被排在同一行的
 * 下一列 —— 于是标签挤在左半边、组件占右半边，中间空出一大片，
 * 标签还被 align-items:center 垂直居中。让内容独占一整行即可，DOM 不用动。
 */
.tool-call[data-expanded='1'] {
  flex-wrap: wrap;
}

.tool-call[data-expanded='1'] > .widget,
.tool-call[data-expanded='1'] > .tool-file-view {
  flex: 0 0 100%;
  width: 100%;
  min-width: 0;
}

.tool-icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: none;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-sm);
}

.tool-call[data-state='ok'] .tool-icon {
  color: #047857;
  background: var(--ok-soft);
}

.tool-call[data-state='error'] .tool-icon {
  color: #b91c1c;
  background: #fee2e2;
}

.tool-icon .icon {
  width: 16px;
  height: 16px;
}

.tool-info {
  flex: 1;
  min-width: 0;
}

.tool-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}

.tool-detail {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tool-time {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
  min-width: 34px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
}

.tool-spinner {
  width: 14px;
  height: 14px;
  border: 2px solid rgba(99, 102, 241, 0.22);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.7s linear infinite;
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}

.stream-caret {
  display: inline-block;
  width: 2px;
  height: 1.05em;
  margin-left: 2px;
  vertical-align: text-bottom;
  background: var(--accent);
  border-radius: 1px;
  opacity: 0;
  will-change: opacity;
}

.message.is-streaming .stream-caret {
  opacity: 1;
}

.message-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
}

.foot-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 2px 7px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
}

/* 压缩标记 */
.compress-marker {
  display: flex;
  align-items: center;
  gap: 9px;
  margin: 4px 0 4px 43px;
  padding: 7px 13px;
  font-size: var(--fs-xs);
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-md);
  will-change: transform, opacity;
}

.compress-marker .icon {
  width: 14px;
  height: 14px;
  flex: none;
  color: var(--accent);
}

.compress-marker strong {
  color: var(--text-2);
  font-weight: 600;
}

.compress-marker button {
  margin-left: auto;
  font-size: 11px;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* notices ----------------------------------------------------------- */

.notice {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  margin: 10px 0;
  padding: 11px 14px;
  font-size: var(--fs-sm);
  line-height: 1.6;
  border-radius: var(--r-md);
  will-change: transform, opacity;
}

.notice-icon {
  flex: none;
  margin-top: 1px;
}

.notice-icon .icon {
  width: 16px;
  height: 16px;
}

.notice-error {
  color: #991b1b;
  background: var(--danger-soft);
  border: 1px solid #fecaca;
}

.notice-warn {
  color: #92400e;
  background: var(--warn-soft);
  border: 1px solid #fde68a;
}

.notice-body {
  flex: 1;
  min-width: 0;
}

.notice-retry {
  margin-top: 7px;
}

/* scroll to bottom -------------------------------------------------- */

.scroll-down {
  position: absolute;
  right: max(24px, calc(50% - var(--transcript-max) / 2 + 24px));
  bottom: 20px;
  z-index: 12;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 50%;
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  will-change: transform, opacity;
}

.scroll-down:hover {
  color: var(--text);
  border-color: var(--border-focus);
}

.scroll-down[hidden] {
  display: none;
}

/* ================================================================== */
/* 输入区                                                              */
/* ================================================================== */

.composer-wrap {
  flex: none;
  padding: 0 24px calc(14px + env(safe-area-inset-bottom));
  background: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.92) 34%, #fff 100%);
}

.composer {
  position: relative;
  max-width: var(--composer-max);
  margin: 0 auto;
}

/* 聚焦时用「白色内芯 + 渐变描边」实现渐变边框。
   这里不能用 ::before + z-index:-1 —— composer-box 上的 will-change: transform
   会创建层叠上下文，负 z-index 的伪元素会盖在白色背景之上而不是之下。 */
.composer-box {
  position: relative;
  padding: 14px 12px 10px 16px;
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    linear-gradient(var(--border), var(--border)) border-box;
  border: 1px solid transparent;
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-md);
  transition:
    background var(--dur-base) var(--ease-out),
    box-shadow var(--dur-base) var(--ease-out);
  will-change: transform;
}

.composer-box:focus-within {
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    var(--gradient) border-box;
  box-shadow: var(--shadow-xl);
}

.composer-box.is-dragging {
  background:
    linear-gradient(var(--surface), var(--surface)) padding-box,
    var(--gradient) border-box;
  box-shadow: 0 0 0 4px var(--accent-ring), var(--shadow-lg);
}

.composer-input-row {
  display: flex;
  align-items: flex-start;
}

.composer-input {
  flex: 1;
  min-width: 0;
  min-height: 26px;
  max-height: 220px;
  padding: 2px 4px;
  font-size: var(--fs-md);
  line-height: 1.65;
  color: var(--text);
  resize: none;
  overflow-y: auto;
  scrollbar-width: thin;
}

.composer-input::placeholder {
  color: #a6abbb;
}

.composer-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 10px;
}

.composer-toolbar {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  flex-wrap: wrap;
}

.composer-toolbar:empty {
  display: none;
}

.composer-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}

.toolbar-chip {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px 6px 9px;
  font-size: var(--fs-xs);
  font-weight: 550;
  color: var(--text-3);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: var(--r-full);
  overflow: hidden;
  white-space: nowrap;
  transition:
    color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.toolbar-chip:hover {
  color: var(--text-2);
  background: var(--surface-2);
}

.toolbar-chip .icon {
  width: 14px;
  height: 14px;
}

.toolbar-chip.is-on {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: #d5dbff;
}

.toolbar-chip.is-model {
  color: var(--text-2);
  background: var(--surface-2);
  font-weight: 600;
}

.toolbar-chip.is-model:hover {
  color: var(--accent);
  border-color: var(--border-focus);
}

.toolbar-chip .chip-label {
  max-width: 140px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.attach-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  flex: none;
  color: var(--text-3);
  border-radius: 50%;
  overflow: hidden;
  transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.attach-btn:hover {
  color: var(--text);
  background: var(--surface-2);
}

.attach-btn.is-hot {
  color: var(--warn);
  background: var(--warn-soft);
}

.attach-btn.is-full {
  color: var(--danger);
  background: var(--danger-soft);
}

.attach-btn .icon {
  width: 17px;
  height: 17px;
}

.attach-btn .ctx-badge {
  position: absolute;
  right: -1px;
  bottom: -1px;
  min-width: 15px;
  height: 15px;
  padding: 0 3px;
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 700;
  line-height: 15px;
  text-align: center;
  color: #fff;
  background: var(--accent);
  border: 2px solid #fff;
  border-radius: 8px;
  z-index: 1;
}

.send-btn {
  position: relative;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  flex: none;
  color: #fff;
  background: linear-gradient(140deg, #6366f1, #4f46e5 55%, #3b82f6);
  border-radius: 50%;
  box-shadow: 0 6px 18px rgba(79, 70, 229, 0.3);
  will-change: transform;
  overflow: hidden;
  transition: box-shadow var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}

.send-btn:hover:not([disabled]) {
  box-shadow: 0 9px 26px rgba(79, 70, 229, 0.4);
}

.send-btn[disabled] {
  color: #c3c7d3;
  background: var(--surface-3);
  box-shadow: none;
}

.send-btn .icon {
  width: 18px;
  height: 18px;
  position: relative;
  z-index: 1;
}

.send-btn .icon-stop {
  position: absolute;
  opacity: 0;
  transform: scale(0.5);
  transition: opacity var(--dur-fast) var(--ease-out), transform var(--dur-base) var(--ease-back);
}

.send-btn[data-mode='stop'] .icon-send {
  opacity: 0;
  transform: scale(0.5);
}

.send-btn[data-mode='stop'] .icon-stop {
  opacity: 1;
  transform: scale(1);
}

.send-btn[data-mode='stop'] {
  background: linear-gradient(140deg, #fb7185, #ef4444);
  box-shadow: 0 6px 18px rgba(239, 68, 68, 0.3);
}

.disclaimer {
  margin-top: 9px;
  font-size: 11px;
  color: var(--text-3);
  text-align: center;
}

.disclaimer.is-ok {
  color: #047857;
}

.disclaimer.is-error {
  color: #b91c1c;
}

/* ================================================================== */
/* 上下文用量条 / 面板                                                 */
/* ================================================================== */

.ctx-meter {
  margin: -2px 0 10px -6px;
}

.ctx-meter[hidden] {
  display: none;
}

.ctx-bar {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 3px 6px;
  border-radius: var(--r-full);
  will-change: transform;
}

.ctx-bar:hover {
  background: var(--surface-2);
}

.ctx-track {
  position: relative;
  flex: 1;
  height: 4px;
  background: var(--surface-3);
  border-radius: var(--r-full);
  overflow: hidden;
}

.ctx-fill {
  position: absolute;
  inset: 0 auto 0 0;
  width: 0;
  background: var(--gradient);
  border-radius: var(--r-full);
  transition: width var(--dur-slow) var(--ease-out), background-color var(--dur-base) var(--ease-out);
}

.ctx-meter[data-state='warn'] .ctx-fill {
  background: linear-gradient(90deg, #f59e0b, #f97316);
}

.ctx-meter[data-state='critical'] .ctx-fill {
  background: linear-gradient(90deg, #ef4444, #f43f5e);
}

.ctx-label {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
  white-space: nowrap;
}

.ctx-chevron {
  width: 12px;
  height: 12px;
  color: var(--text-3);
  transition: transform var(--dur-base) var(--ease-back);
}

.ctx-bar[aria-expanded='true'] .ctx-chevron {
  transform: rotate(180deg);
}

.ctx-popover {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(100% + 8px);
  height: 0;
  overflow: hidden;
  opacity: 0;
  will-change: height, opacity;
  pointer-events: none;
}

.ctx-popover[data-open='true'] {
  pointer-events: auto;
}

.ctx-panel-body {
  padding: 16px;
  max-height: 58vh;
  overflow-y: auto;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
}

.ctx-overview {
  display: flex;
  align-items: center;
  gap: 18px;
  margin-bottom: 14px;
}

.ctx-ring-wrap {
  position: relative;
  display: grid;
  place-items: center;
  width: 66px;
  height: 66px;
  flex: none;
}

.ctx-ring {
  position: absolute;
  inset: 0;
  width: 66px;
  height: 66px;
  transform: rotate(-90deg);
}

.ctx-ring-track {
  fill: none;
  stroke: var(--surface-3);
  stroke-width: 3;
}

.ctx-ring-fill {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  will-change: stroke-dashoffset;
}

.ctx-ring-percent {
  position: relative;
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-2);
}

.ctx-facts {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex: 1;
  min-width: 0;
}

.ctx-fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  font-size: 11.5px;
}

.ctx-fact-label {
  color: var(--text-3);
  flex: none;
}

.ctx-fact-value {
  font-family: var(--font-mono);
  color: var(--text-2);
  text-align: right;
  overflow-wrap: anywhere;
}

.ctx-control {
  padding: 4px 0 14px;
  border-bottom: 1px solid var(--border);
}

.ctx-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}

.ctx-actions .ghost-btn {
  flex: 1;
  justify-content: center;
}

.ctx-list {
  display: flex;
  flex-direction: column;
  gap: 5px;
  max-height: 168px;
  overflow-y: auto;
  padding: 12px 2px 2px;
}

.ctx-row {
  display: flex;
  align-items: center;
  gap: 10px;
  will-change: transform;
}

.ctx-role {
  width: 34px;
  flex: none;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-3);
  text-align: right;
}

.ctx-row.is-compressed .ctx-role {
  color: var(--accent);
}

.ctx-row-bar {
  flex: 1;
  height: 5px;
  background: var(--surface-3);
  border-radius: var(--r-full);
  overflow: hidden;
}

.ctx-row-fill {
  display: block;
  height: 100%;
  background: var(--accent);
  opacity: 0.42;
  border-radius: var(--r-full);
  transition: width var(--dur-slow) var(--ease-out);
}

.ctx-row.is-compressed .ctx-row-fill {
  background: var(--gradient);
  opacity: 0.9;
}

.ctx-tokens {
  width: 44px;
  flex: none;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
  text-align: right;
}

.ctx-empty {
  padding: 16px 0;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--text-3);
}

/* ================================================================== */
/* 附件托盘 / 拖放提示                                                 */
/* ================================================================== */

.attachment-tray {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin: -2px 0 10px;
}

.attachment-tray[hidden] {
  display: none;
}

.attachment {
  position: relative;
  display: flex;
  align-items: center;
  gap: 8px;
  max-width: 220px;
  padding: 5px 8px 5px 6px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  will-change: transform, opacity;
}

.attachment-image {
  padding: 3px;
  padding-right: 8px;
}

.attachment-image img {
  width: 40px;
  height: 40px;
  object-fit: cover;
  border-radius: var(--r-sm);
  border: 1px solid var(--border);
  background: #fff;
}

.attachment-dims {
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--text-3);
  line-height: 1.35;
  max-width: 116px;
  overflow-wrap: anywhere;
}

.attachment-icon {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  flex: none;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-sm);
}

.attachment-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.attachment-text strong {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-text small {
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--text-3);
}

.attachment-remove {
  position: absolute;
  top: -6px;
  right: -6px;
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  color: var(--text-inverse);
  background: var(--text-3);
  border: 2px solid #fff;
  border-radius: 50%;
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out), transform var(--dur-base) var(--ease-back);
  will-change: transform;
}

.attachment:hover .attachment-remove,
.attachment-remove:focus-visible {
  opacity: 1;
}

.attachment-remove:hover {
  background: var(--danger);
  transform: scale(1.15);
}

/* 拖放高亮由 .composer-box.is-dragging 的渐变描边负责 */
.drop-hint {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 8px;
  padding: 9px 14px;
  font-size: var(--fs-sm);
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px dashed #c7d2fe;
  border-radius: var(--r-md);
}

.drop-hint[hidden] {
  display: none;
}

.drop-hint-icon {
  display: grid;
  place-items: center;
}

.drop-hint-icon .icon {
  width: 16px;
  height: 16px;
}

/* 消息里的附件回显 */
.message-attachments {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 9px;
}

.message-attachments img {
  max-width: 240px;
  max-height: 200px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
  background: #fff;
}

.message-file-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  font-size: 11.5px;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-full);
}

.message-file-chip .icon {
  width: 13px;
  height: 13px;
  color: var(--accent);
}

/* ================================================================== */
/* 供应商面板                                                          */
/* ================================================================== */

.settings-input {
  width: 100%;
  padding: 9px 12px;
  font-size: var(--fs-sm);
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}

.settings-input:focus {
  background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.settings-input::placeholder {
  color: var(--text-3);
}

.settings-input:disabled {
  color: var(--text-3);
  cursor: not-allowed;
}

.link-btn {
  font-size: 11.5px;
  font-weight: 600;
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.provider-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.provider-row {
  padding: 10px 12px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}

.provider-row.is-active {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.provider-head {
  display: flex;
  align-items: center;
  gap: 8px;
}

.provider-pick {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: 1;
  min-width: 0;
  text-align: left;
  padding: 2px 0;
}

.provider-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  flex: none;
}

.provider-url {
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.provider-row.is-active .provider-url {
  color: var(--accent);
}

.provider-note {
  margin-top: 5px;
  padding-left: 26px;
  font-size: 11px;
  line-height: 1.55;
  color: var(--text-3);
}

.provider-editor {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px dashed var(--border-strong);
}

.provider-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 4px;
}

.provider-actions .ghost-btn {
  flex: 1;
  min-width: 110px;
  justify-content: center;
  font-size: 11.5px;
  padding: 8px 10px;
}

.provider-add {
  width: 100%;
  justify-content: center;
}

/* 思考模式有 7 种方言，两列排布。
   用复合选择器而不是单独的 .segmented-wrap —— 后者定义在 .segmented 之前，
   同优先级下会被 .segmented 的 grid-auto-flow: column 覆盖掉。 */
.segmented.segmented-wrap {
  grid-auto-flow: row;
  grid-template-columns: repeat(2, 1fr);
  gap: 4px;
}

.capability-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 7px;
}

.capability-chip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 9px 8px;
  font-size: 12px;
  font-weight: 550;
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: all var(--dur-fast) var(--ease-out);
}

.capability-chip:hover {
  color: var(--text-2);
  border-color: var(--border-strong);
}

.capability-chip.is-on {
  color: var(--accent);
  background: var(--accent-soft);
  border-color: #c7d2fe;
}

.capability-chip .icon {
  width: 14px;
  height: 14px;
}

.level-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.level-row {
  display: flex;
  align-items: center;
  gap: 9px;
}

.level-name {
  width: 44px;
  flex: none;
  font-size: 12px;
  color: var(--text-2);
}

.level-input {
  width: 88px;
  padding: 5px 9px;
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
}

.level-input-wide {
  flex: 1;
  min-width: 0;
}

.level-input:focus {
  background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.level-unit {
  font-size: 10.5px;
  color: var(--text-3);
}

/* 自实现的模型下拉（替代原生 select） ------------------------------- */

.model-picker {
  position: relative;
  margin-bottom: 8px;
}

.model-picker-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  width: 100%;
  padding: 9px 12px;
  font-size: var(--fs-sm);
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}

.model-picker-trigger:hover {
  border-color: var(--border-strong);
}

.model-picker.is-open .model-picker-trigger {
  background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.model-picker-value {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.model-picker-value.is-placeholder {
  font-family: var(--font-sans);
  color: var(--text-3);
}

.model-picker-caret {
  flex: none;
  color: var(--text-3);
  transition: transform var(--dur-base) var(--ease-back);
}

.model-picker.is-open .model-picker-caret {
  transform: rotate(180deg);
}

.model-picker-list {
  position: absolute;
  left: 0;
  right: 0;
  top: calc(100% + 6px);
  z-index: 20;
  display: flex;
  flex-direction: column;
  max-height: 260px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  animation: picker-drop 180ms var(--ease-out);
}

.model-picker-list[hidden] {
  display: none;
}

@keyframes picker-drop {
  from {
    opacity: 0;
    transform: translateY(-6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.model-picker-search {
  flex: none;
  padding: 9px 12px;
  font-size: 12px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.model-picker-search::placeholder {
  color: var(--text-3);
}

.model-picker-options {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 4px;
}

.model-option {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 8px;
  border-radius: var(--r-sm);
  transition: background-color var(--dur-fast) var(--ease-out);
}

.model-option.is-active {
  background: var(--surface-2);
}

.model-option.is-selected {
  background: var(--accent-soft);
}

.model-option-mark {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--text-3);
}

.model-option.is-selected .model-option-mark {
  color: var(--accent);
}

.model-option-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
  gap: 1px;
}

.model-option-label {
  font-size: 11.5px;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.model-option.is-selected .model-option-label {
  color: var(--accent);
  font-weight: 600;
}

.model-option-id {
  font-family: var(--font-mono);
  font-size: 9.5px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.model-option-action {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--text-3);
  border-radius: var(--r-xs);
  opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out);
}

.model-option:hover .model-option-action,
.model-option-action:focus-visible {
  opacity: 1;
}

.model-option-action:hover {
  color: var(--accent);
  background: var(--accent-soft);
}

.model-option-remove:hover {
  color: var(--danger);
  background: var(--danger-soft);
}

/* 行内别名编辑器：占满整行，避免挤在右侧 */
.model-label-editor {
  display: flex;
  align-items: center;
  gap: 6px;
  width: 100%;
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed var(--border-strong);
}

.model-option {
  flex-wrap: wrap;
}

.model-label-editor .settings-input {
  flex: 1;
  min-width: 0;
  padding: 6px 10px;
  font-size: 11.5px;
}

.model-label-save,
.model-label-cancel {
  flex: none;
  padding: 6px 11px;
  font-size: 11px;
}

.model-picker-empty {
  padding: 18px 10px;
  text-align: center;
  font-size: 12px;
  color: var(--text-3);
}

/* 手动添加模型 ------------------------------------------------------ */

.model-add-row {
  display: flex;
  align-items: center;
  gap: 7px;
}

.model-add-input {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 11.5px;
}

.model-add-btn {
  flex: none;
  padding: 9px 13px;
}

/* 长度上限 ---------------------------------------------------------- */

.limit-value {
  padding: 2px 8px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-full);
}

.limit-value.is-auto {
  color: var(--text-3);
  background: var(--surface-2);
}

.limit-segmented {
  display: grid;
  /* 三列：与思考方言那种两列长列表区分开，这里的项都很短 */
  grid-template-columns: repeat(3, 1fr);
  grid-auto-flow: row;
  gap: 4px;
}

.limit-custom {
  display: flex;
  align-items: center;
  gap: 7px;
  margin-top: 6px;
}

.limit-input {
  flex: 1;
  min-width: 0;
  padding: 7px 10px;
  font-family: var(--font-mono);
  font-size: 11.5px;
}

.limit-apply {
  flex: none;
  padding: 7px 13px;
}

/* 诊断结果 ---------------------------------------------------------- */

.diag-result {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: 12px;
  padding: 12px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.diag-result[hidden] {
  display: none;
}

.diag-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-size: 11.5px;
  line-height: 1.55;
}

.diag-row-label {
  width: 92px;
  flex: none;
  color: var(--text-3);
}

.diag-row-value {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  color: var(--text-2);
  overflow-wrap: anywhere;
}

.diag-row.is-ok .diag-row-value {
  color: #047857;
}

.diag-row.is-error .diag-row-value {
  color: #b91c1c;
}

.diag-row.is-warn .diag-row-value {
  color: #92400e;
}

.diag-row.is-pending .diag-row-value {
  color: var(--accent);
}

/* ================================================================== */
/* markdown                                                            */
/* ================================================================== */

.md {
  font-size: var(--fs-base);
  line-height: 1.75;
  overflow-wrap: anywhere;
}

.md > *:first-child {
  margin-top: 0 !important;
}

.md > *:last-child {
  margin-bottom: 0 !important;
}

.md-paragraph {
  margin: 0.62em 0;
}

.md-heading {
  margin: 1.5em 0 0.5em;
  font-weight: 650;
  line-height: 1.35;
  letter-spacing: -0.015em;
  scroll-margin-top: 20px;
}

h1.md-heading { font-size: 1.42em; }
h2.md-heading { font-size: 1.26em; padding-bottom: 0.3em; border-bottom: 1px solid var(--border); }
h3.md-heading { font-size: 1.12em; }
h4.md-heading,
h5.md-heading,
h6.md-heading { font-size: 1em; color: var(--text-2); }

.md-list {
  margin: 0.6em 0;
  padding-left: 1.35em;
}

ul.md-list {
  list-style: none;
}

ul.md-list > li {
  position: relative;
  margin: 0.3em 0;
}

ul.md-list > li::before {
  content: '';
  position: absolute;
  left: -0.95em;
  top: 0.72em;
  width: 4.5px;
  height: 4.5px;
  background: var(--text-3);
  border-radius: 50%;
  transition: transform var(--dur-base) var(--ease-back), background-color var(--dur-base) var(--ease-out);
}

ul.md-list > li:hover::before {
  background: var(--accent);
  transform: scale(1.35);
}

ol.md-list {
  list-style: decimal;
}

ol.md-list > li {
  margin: 0.3em 0;
  padding-left: 0.2em;
}

ol.md-list > li::marker {
  color: var(--accent);
  font-weight: 600;
  font-size: 0.92em;
}

.md-list .md-list {
  margin: 0.2em 0;
}

.md-list-item.is-task {
  display: flex;
  align-items: flex-start;
  gap: 0.55em;
  padding-left: 0;
}

.md-list-item.is-task::before {
  display: none;
}

.task-box {
  display: grid;
  place-items: center;
  width: 16px;
  height: 16px;
  flex: none;
  margin-top: 0.28em;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  background: var(--surface);
  border: 1.5px solid var(--border-strong);
  border-radius: 5px;
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}

.md-list-item.is-checked .task-box {
  background: var(--accent);
  border-color: var(--accent);
}

.md-list-item.is-checked .md-list-content {
  color: var(--text-3);
  text-decoration: line-through;
  text-decoration-color: var(--border-strong);
}

.md-quote {
  margin: 0.75em 0;
  padding: 0.15em 0 0.15em 1.05em;
  color: var(--text-2);
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--r-sm) var(--r-sm) 0;
  background: linear-gradient(90deg, var(--accent-soft), transparent 55%);
}

.md-quote > *:first-child {
  margin-top: 0;
}

.md-hr {
  margin: 1.5em 0;
}

.md-link {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: rgba(79, 70, 229, 0.32);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2.5px;
  transition: text-decoration-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.md-link:hover {
  color: var(--accent-hover);
  text-decoration-color: currentColor;
}

.md-link.is-autolink {
  font-family: var(--font-mono);
  font-size: 0.92em;
}

.md-link.is-blocked {
  color: var(--text-3);
  text-decoration: line-through;
  cursor: not-allowed;
}

.md-inline-code {
  padding: 0.14em 0.4em;
  font-size: 0.87em;
  color: #b4236b;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  overflow-wrap: anywhere;
}

.md strong {
  font-weight: 650;
  color: var(--text);
}

.md del {
  color: var(--text-3);
}

.md mark {
  padding: 0.06em 0.26em;
  color: inherit;
  background: linear-gradient(180deg, transparent 56%, rgba(250, 204, 21, 0.38) 56%);
  border-radius: 3px;
}

.md-image {
  display: inline-block;
  max-width: 100%;
}

.md-image img {
  max-width: 100%;
  height: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
}

.md-image.is-broken img {
  display: none;
}

.md-image.is-broken::after {
  content: 'image unavailable';
  padding: 6px 10px;
  font-size: var(--fs-xs);
  color: var(--text-3);
  background: var(--surface-2);
  border: 1px dashed var(--border-strong);
  border-radius: var(--r-sm);
}

.md-code {
  margin: 0.85em 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  /* 用 clip 而不是 hidden。
     hidden 会让 .md-code 成为滚动容器，里面的 sticky 就只相对它定位，
     而它自己并不滚动，于是吸顶完全失效。clip 一样能裁掉圆角外的内容，
     但不建立滚动容器 —— sticky 相对真正的滚动容器（.transcript）生效，
     同时仍被限制在 .md-code 的盒子里，正好是「脱离代码块就松手」。 */
  overflow: clip;
  overflow-clip-margin: 0;
  box-shadow: var(--shadow-sm);
}

.code-bar {
  /* 语言与复制按钮一直悬在代码块顶部，直到整个代码块滚出视野 */
  position: sticky;
  top: var(--sticky-top);
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 6px 8px 6px 14px;
  /* 吸顶后必须是不透明背景，否则代码会从下面透上来 */
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  border-radius: calc(var(--r-lg) - 1px) calc(var(--r-lg) - 1px) 0 0;
}

.code-lang {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--text-3);
}

/* 代码块右上角的操作组：预览 / Copy / 下载 */
.code-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  flex: none;
}

.code-preview.is-active {
  color: var(--accent);
  border-color: var(--border-focus);
  background: var(--accent-soft);
}

/* 未写完的代码块：按钮置灰不可用 ------------------------------- */

/*
 * 流式输出时代码块还没长完，此时复制/下载/预览拿到的都是半截内容。
 * message.js 会给「正在写的最后一块」打上 data-incomplete。
 */
.md-code[data-incomplete] .code-copy {
  opacity: 0.4;
  cursor: not-allowed;
  pointer-events: none;
}

.md-code[data-incomplete] .code-bar::after {
  content: '写入中…';
  margin-left: auto;
  padding-right: 8px;
  font-size: 10.5px;
  color: var(--text-3);
}

.code-copy {
  position: relative;
  padding: 3px 9px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  overflow: hidden;
  transition: all var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.code-copy:hover {
  color: var(--accent);
  border-color: var(--border-focus);
  background: var(--accent-soft);
}

.code-copy.is-copied {
  color: #047857;
  background: var(--ok-soft);
  border-color: #a7f3d0;
}

.md-code pre {
  margin: 0;
  padding: 14px 16px;
  /* 只允许横向滚动。这里必须显式写 overflow-y: hidden ——
     按规范，一个轴设成非 visible 时，另一个 visible 的轴会被计算成 auto，
     于是 pre 会变成纵向滚动容器并把滚轮吞掉，长代码块里的鼠标滚轮
     就再也滚不动外层会话了。 */
  overflow-x: auto;
  overflow-y: hidden;
  background: var(--surface);
}

.md-code code {
  font-family: var(--font-mono);
  font-size: 12.8px;
  line-height: 1.72;
  color: var(--text);
  tab-size: 2;
  white-space: pre;
}

.tok-k { color: #7c3aed; font-weight: 600; }
.tok-b { color: #0891b2; font-weight: 500; }
.tok-s { color: #0f766e; }
.tok-n { color: #c2410c; }
.tok-c { color: #94a3b8; font-style: italic; }
.tok-f { color: #2563eb; }
.tok-t { color: #db2777; }
.tok-a { color: #ca8a04; }
.tok-p { color: #64748b; }

.md-table-wrap {
  margin: 0.9em 0;
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-xs);
}

.md-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 0.92em;
}

.md-table th,
.md-table td {
  padding: 9px 13px;
  text-align: left;
  border-bottom: 1px solid var(--border);
}

.md-table th {
  font-weight: 620;
  color: var(--text);
  background: var(--surface-2);
  white-space: nowrap;
}

.md-table tr:last-child td {
  border-bottom: none;
}

.md-table tbody tr {
  transition: background-color var(--dur-fast) var(--ease-out);
}

.md-table tbody tr:hover {
  background: var(--bg-tint);
}

.md-math-display {
  margin: 0.9em 0;
  padding: 14px 16px;
  overflow-x: auto;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

/* ================================================================== */
/* 设置抽屉                                                            */
/* ================================================================== */

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(15, 23, 42, 0.28);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  will-change: opacity;
}

.drawer {
  position: fixed;
  top: 12px;
  right: 12px;
  bottom: 12px;
  z-index: 61;
  display: flex;
  flex-direction: column;
  width: min(420px, calc(100vw - 24px));
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-xl);
  transform: translate3d(102%, 0, 0);
  will-change: transform;
  visibility: hidden;
  overflow: hidden;
}

.drawer[data-open='true'] {
  visibility: visible;
}

.drawer-grip {
  display: none;
}

.drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 58px;
  flex: none;
  padding: 0 14px 0 22px;
  border-bottom: 1px solid var(--border);
}

.drawer-head h2 {
  font-size: var(--fs-lg);
  font-weight: 650;
  letter-spacing: -0.015em;
}

.drawer-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px 22px 26px;
}

.drawer-foot {
  flex: none;
  padding: 12px 22px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

.drawer-foot .ghost-btn {
  width: 100%;
  justify-content: center;
}

.settings-group {
  padding: 20px 0;
  border-bottom: 1px solid var(--border);
}

.settings-group:last-child {
  border-bottom: none;
}

.settings-heading {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 12px;
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: 0.075em;
  text-transform: uppercase;
  color: var(--text-3);
}

.settings-heading-icon {
  display: grid;
  place-items: center;
  color: var(--accent);
}

.settings-heading-icon .icon {
  width: 15px;
  height: 15px;
}

.settings-note {
  margin-bottom: 11px;
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--text-3);
}

.settings-textarea {
  width: 100%;
  padding: 11px 13px;
  font-size: var(--fs-sm);
  line-height: 1.65;
  color: var(--text);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  resize: vertical;
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}

.settings-textarea:focus {
  background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* model list -------------------------------------------------------- */

.model-list {
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.model-item {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  padding: 11px 13px;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition:
    border-color var(--dur-fast) var(--ease-out),
    background-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.model-item:hover {
  border-color: var(--border-focus);
  background: var(--bg-tint);
  box-shadow: var(--shadow-sm);
}

.model-item.is-selected {
  border-color: var(--accent);
  background: var(--accent-soft);
}

.model-radio {
  display: grid;
  place-items: center;
  width: 17px;
  height: 17px;
  flex: none;
  margin-top: 2px;
  border: 1.8px solid var(--border-strong);
  border-radius: 50%;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}

/* 正在使用的供应商：实心红点。
   只改圆点，名称保持原色 —— 名字变红容易被读成「这家出错了」。 */
.provider-pick[aria-pressed='true'] .model-radio {
  border-color: #ef4444;
  box-shadow: inset 0 0 0 4px #ef4444, 0 0 0 3px rgba(239, 68, 68, 0.16);
}

/* list 里的模型项仍用主题色，避免和「正在使用的供应商」混淆 */
.model-item.is-selected .model-radio {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 4px var(--accent);
}

.model-text {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

.model-name {
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}

.model-id {
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 400;
  color: var(--text-3);
}

.model-badge {
  padding: 1px 6px;
  font-size: 10px;
  font-weight: 650;
  letter-spacing: 0.02em;
  color: var(--accent);
  background: rgba(99, 102, 241, 0.12);
  border-radius: var(--r-full);
}

.model-blurb {
  margin-top: 3px;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--text-3);
}

/* field / slider ---------------------------------------------------- */

.field {
  margin-bottom: 14px;
}

.field-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 7px;
}

.field-label {
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--text-2);
}

.field-value {
  font-family: var(--font-mono);
  font-size: 11.5px;
  color: var(--accent);
  padding: 1px 7px;
  background: var(--accent-soft);
  border-radius: var(--r-xs);
}

.field-hint {
  margin-top: 5px;
  font-size: 11px;
  line-height: 1.55;
  color: var(--text-3);
}

/* 滑块：拖动手感相关的一整套修正
   - touch-action: none      防止在可滚动容器里拖动被滚动劫持
   - user-select: none       防止拖动时选中文字（浏览器会弹出「松开鼠标以搜索」）
   - 不给 thumb 加 transition  位移由布局驱动，加过渡只会让它看起来在打滑 */
.field input[type='range'] {
  width: 100%;
  height: 22px;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: grab;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}

.field input[type='range']:active {
  cursor: grabbing;
}

.field input[type='range']::-webkit-slider-runnable-track {
  height: 5px;
  background: var(--surface-3);
  border-radius: var(--r-full);
  border: 1px solid var(--border);
}

.field input[type='range']::-moz-range-track {
  height: 5px;
  background: var(--surface-3);
  border-radius: var(--r-full);
  border: 1px solid var(--border);
}

.field input[type='range']::-webkit-slider-thumb {
  appearance: none;
  -webkit-appearance: none;
  width: 16px;
  height: 16px;
  margin-top: -6.5px;
  background: var(--surface);
  border: 2px solid var(--accent);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
}

.field input[type='range']::-moz-range-thumb {
  width: 14px;
  height: 14px;
  background: var(--surface);
  border: 2px solid var(--accent);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
}

/* 悬停/按下的放大只用 box-shadow 与 border，不动 transform ——
   transform 会让 thumb 的中心偏离轨道计算出来的位置。 */
.field input[type='range']:hover::-webkit-slider-thumb {
  border-color: var(--accent-hover);
  box-shadow: 0 0 0 4px var(--accent-ring);
}

.field input[type='range']:active::-webkit-slider-thumb {
  border-color: var(--accent-hover);
  box-shadow: 0 0 0 6px var(--accent-ring);
}

.field input[type='range']:focus-visible::-webkit-slider-thumb {
  box-shadow: 0 0 0 5px var(--accent-ring);
}

/* 拖动期间整页禁止选中，作为最后一道保险 */
body.is-dragging-range,
body.is-dragging-range * {
  user-select: none !important;
  -webkit-user-select: none !important;
  cursor: grabbing !important;
}

.segmented {
  display: grid;
  grid-auto-flow: column;
  gap: 3px;
  padding: 3px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.segmented button {
  padding: 6px 4px;
  font-size: 11.5px;
  font-weight: 550;
  color: var(--text-3);
  border-radius: var(--r-sm);
  transition: color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.segmented button:hover {
  color: var(--text-2);
}

.segmented button.is-active {
  color: var(--accent);
  background: var(--surface);
  box-shadow: var(--shadow-xs);
}

/* switch ------------------------------------------------------------ */

.switch-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  padding: 9px 0;
}

.switch-copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.switch-copy strong {
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--text);
}

.switch-copy span {
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-3);
}

.switch {
  position: relative;
  flex: none;
  cursor: pointer;
}

.switch input {
  position: absolute;
  opacity: 0;
  width: 100%;
  height: 100%;
  margin: 0;
  cursor: pointer;
}

.switch-track {
  display: block;
  width: 42px;
  height: 24px;
  padding: 3px;
  background: var(--surface-3);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-full);
  transition: background-color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}

.switch-thumb {
  display: block;
  width: 16px;
  height: 16px;
  background: var(--surface);
  border-radius: 50%;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-slow) var(--ease-back);
  will-change: transform;
}

.switch input:checked + .switch-track {
  background: var(--accent);
  border-color: var(--accent);
}

.switch input:checked + .switch-track .switch-thumb {
  transform: translateX(18px);
}

.switch input:focus-visible + .switch-track {
  box-shadow: 0 0 0 3px var(--accent-ring);
}

/* tool list --------------------------------------------------------- */

.tool-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 10px;
}

.tool-toggle {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease-out), opacity var(--dur-base) var(--ease-out);
  will-change: transform;
}

.tool-toggle.is-on {
  background: var(--surface);
  border-color: #d5dbff;
}

.tool-toggle.is-off {
  opacity: 0.55;
}

.tool-toggle-icon {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  flex: none;
  color: var(--accent);
  background: var(--accent-soft);
  border-radius: var(--r-sm);
}

.tool-toggle-icon .icon {
  width: 15px;
  height: 15px;
}

.tool-toggle-copy {
  flex: 1;
  min-width: 0;
}

.tool-toggle-copy strong {
  display: block;
  font-size: var(--fs-sm);
  font-weight: 600;
}

.tool-toggle-copy span {
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
}

/* identity card + diagnostics ---------------------------------------- */

.identity-card {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin-bottom: 12px;
  padding: 13px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
}

.identity-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  font-size: 11.5px;
}

.identity-row dt {
  color: var(--text-3);
  flex: none;
}

.identity-row dd {
  font-family: var(--font-mono);
  color: var(--text-2);
  text-align: right;
  overflow-wrap: anywhere;
}

.diag {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 5px 14px;
  font-size: 11.5px;
}

.diag dt {
  color: var(--text-3);
}

.diag dd {
  font-family: var(--font-mono);
  color: var(--text-2);
  text-align: right;
  overflow-wrap: anywhere;
}

/* ================================================================== */
/* 模型选择器                                                          */
/* ================================================================== */

.picker-scrim {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(15, 23, 42, 0.2);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  opacity: 0;
  will-change: opacity;
}

.picker {
  position: fixed;
  top: 76px;
  left: 50%;
  z-index: 71;
  display: flex;
  flex-direction: column;
  width: min(460px, calc(100vw - 28px));
  max-height: min(460px, 70vh);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  transform: translate(-50%, -14px);
  opacity: 0;
  will-change: transform, opacity;
  visibility: hidden;
  overflow: hidden;
}

.picker[data-open='true'] {
  visibility: visible;
}

.picker-head {
  flex: none;
  padding: 12px 12px 10px;
  border-bottom: 1px solid var(--border);
}

.picker-title {
  display: block;
  margin-bottom: 8px;
  font-size: var(--fs-xs);
  font-weight: 650;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-3);
}

.picker-search {
  width: 100%;
  padding: 8px 12px;
  font-size: var(--fs-sm);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  transition: border-color var(--dur-fast) var(--ease-out), background-color var(--dur-fast) var(--ease-out);
}

.picker-search:focus {
  background: var(--surface);
  border-color: var(--border-focus);
  box-shadow: 0 0 0 3px var(--accent-ring);
}

.picker-search::-webkit-search-cancel-button {
  cursor: pointer;
}

.picker-body {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.picker-item {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 9px 10px;
  text-align: left;
  border-radius: var(--r-md);
  border: 1px solid transparent;
  transition: background-color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.picker-item.is-active {
  background: var(--surface-2);
}

.picker-item:hover,
.picker-item.is-active {
  background: var(--surface-2);
}

.picker-item.is-selected {
  background: var(--accent-soft);
  border-color: #d5dbff;
}

.picker-mark {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex: none;
  margin-top: 1px;
  color: var(--text-3);
  border-radius: var(--r-xs);
}

.picker-item.is-selected .picker-mark {
  color: var(--accent);
}

.picker-text {
  display: flex;
  flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.picker-name {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}

.picker-blurb {
  font-size: 11px;
  line-height: 1.5;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.picker-item .model-badge {
  flex: none;
  margin-top: 3px;
}

.picker-empty {
  padding: 26px 12px;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--text-3);
}

/* 树状模型选择器：供应商 → 模型 ------------------------------------- */

.picker-group {
  border-radius: var(--r-md);
  margin-bottom: 2px;
}

.picker-group-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 9px;
  border-radius: var(--r-md);
  text-align: left;
  transition: background-color var(--dur-fast) var(--ease-out);
}

.picker-group-head:hover:not(:disabled) {
  background: var(--surface-2);
}

.picker-group-head:disabled {
  cursor: not-allowed;
}

.picker-group-caret {
  flex: none;
  width: 14px;
  height: 14px;
  color: var(--text-3);
  transition: transform var(--dur-base) var(--ease-back);
}

.picker-group.is-open .picker-group-caret {
  transform: rotate(90deg);
}

.picker-group.is-disabled .picker-group-caret {
  opacity: 0.35;
}

.picker-group-name {
  flex: none;
  font-size: var(--fs-sm);
  font-weight: 620;
  color: var(--text);
}

.picker-group.is-disabled .picker-group-name {
  color: var(--text-3);
}

.picker-group-count {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 10px;
  color: var(--text-3);
  text-align: right;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.picker-group-lock {
  flex: none;
  width: 13px;
  height: 13px;
  color: var(--text-3);
  opacity: 0.7;
}

.picker-badge {
  flex: none;
  padding: 1px 6px;
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.02em;
  color: var(--accent);
  background: rgba(99, 102, 241, 0.12);
  border-radius: var(--r-full);
}

.picker-group-reason {
  padding: 0 9px 8px 31px;
  font-size: 10.5px;
  line-height: 1.5;
  color: var(--text-3);
}

.picker-group-hint {
  padding: 6px 9px 10px 31px;
  font-size: 10.5px;
  color: var(--text-3);
}

.picker-group-hint.is-error {
  color: #b91c1c;
}

.picker-fetch {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  font-size: 11px;
  font-weight: 550;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid #c7d2fe;
  border-radius: var(--r-full);
  transition: background-color var(--dur-fast) var(--ease-out);
}

.picker-fetch:hover {
  background: #e0e7ff;
}

.picker-fetch .icon {
  width: 13px;
  height: 13px;
}

/* 模型行缩进到供应商下面，形成层级 */
.picker-group .picker-item {
  margin-left: 18px;
  position: relative;
}

/* 连接线，让树形关系可见 */
.picker-group .picker-item::before {
  content: '';
  position: absolute;
  left: -9px;
  top: 50%;
  width: 7px;
  height: 1px;
  background: var(--border-strong);
}

/* 等待状态行：请求发出到第一个字之间的唯一反馈 ---------------- */

.message-status {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 8px;
  padding: 8px 12px;
  font-size: 12.5px;
  color: var(--text-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  animation: status-in 240ms var(--ease-out);
}

.message-status[hidden] {
  display: none;
}

@keyframes status-in {
  from {
    opacity: 0;
    transform: translateY(-4px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.status-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  animation: status-pulse 1.15s var(--ease-in-out) infinite;
}

.message-status[data-tone='thinking'] .status-dot {
  background: #8b5cf6;
}

.message-status[data-tone='tool'] .status-dot {
  background: #0ea5e9;
}

@keyframes status-pulse {
  0%,
  100% {
    opacity: 1;
    transform: scale(1);
  }
  50% {
    opacity: 0.4;
    transform: scale(0.72);
  }
}

.status-label {
  min-width: 0;
}

/* 截断后的续写入口 ------------------------------------------------ */

.continue-btn {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin-top: 10px;
  padding: 7px 13px;
  font-size: var(--fs-xs);
  font-weight: 600;
  color: var(--accent);
  background: var(--accent-soft);
  border: 1px solid #c7d2fe;
  border-radius: var(--r-full);
  transition: background-color var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}

.continue-btn:hover {
  background: #e0e7ff;
  border-color: var(--accent);
}

.continue-hint {
  padding-left: 7px;
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 500;
  color: var(--text-3);
  border-left: 1px solid #c7d2fe;
}

/* 沙箱组件 ---------------------------------------------------------- */

.widget {
  margin: 8px 0 0;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface);
}

.widget-source-btn {
  flex: none;
  margin-left: auto;
  padding: 3px 9px;
  font-size: 10.5px;
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

.widget-source-btn:hover,
.widget-source-btn.is-active {
  color: var(--accent);
  border-color: var(--border-focus);
}

.widget-source {
  margin: 0;
  padding: 12px 14px;
  max-height: 46vh;
  overflow: auto;
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
  color: var(--text-2);
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
  white-space: pre-wrap;
  word-break: break-word;
}

.tool-detail.is-error {
  color: var(--danger);
}

.widget-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: var(--surface-2);
  border-bottom: 1px solid var(--border);
}

.widget-icon {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--accent);
}

.widget-title {
  flex: 1;
  min-width: 0;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.widget-badge {
  flex: none;
  padding: 1px 7px;
  font-size: 10px;
  font-weight: 600;
  color: #6d28d9;
  background: #ede9fe;
  border-radius: var(--r-full);
  cursor: help;
}

/* 组件本身：沙箱 iframe。白底是为了不让宿主的暗色/纹理透进组件里，
   否则组件作者按默认白底设计的样式会显得脏。 */
.widget-frame {
  display: block;
  width: 100%;
  border: 0;
  background: #fff;
  color-scheme: light;
}

.widget-console {
  margin-top: 6px;
  border-top: 1px dashed var(--border-strong);
  font-family: var(--font-mono);
  font-size: 10.5px;
  color: var(--text-3);
}

.widget-console summary {
  padding: 4px 0;
  cursor: pointer;
}

.widget-console-body {
  max-height: 140px;
  overflow-y: auto;
  padding-bottom: 4px;
}

.widget-console-line {
  padding: 1px 0;
  overflow-wrap: anywhere;
}

/* 会话重命名输入框：直接顶替标题文本的位置 */
.session-rename {
  flex: 1;
  min-width: 0;
  padding: 2px 6px;
  font-size: var(--fs-sm);
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border-focus);
  border-radius: var(--r-xs);
  outline: none;
}

/* 自动生成的标题：给个微妙的标记，让用户知道这是模型起的、可以双击改 */
.session-item-text[data-generated='1']::after {
  content: '·AI';
  margin-left: 5px;
  font-size: 9.5px;
  color: var(--text-3);
  opacity: 0.75;
}

/* 预览面板：主区域向左避让，面板从右滑入 --------------------------- */

/*
 * 两边用同一条缓动与时长，读起来才是「一个动作」：
 *   .main / .composer-wrap 宽度 100% → 50%（右边缘向左扫过去）
 *   .preview-pane 从 translateX(100%) → 0（从右侧滑进来）
 * 关闭时整套反向。
 */
.app-shell {
  --preview-duration: 440ms;
  --preview-ease: cubic-bezier(0.22, 1, 0.36, 1);
}

.main,
.composer-wrap {
  width: 100%;
  transition: width var(--preview-duration) var(--preview-ease);
}

.app-shell.is-previewing .main,
.app-shell.is-previewing .composer-wrap {
  /* 让出右半边，并留出与浮起卡片相同的 12px 边距 */
  width: calc(50% - 12px);
}

.preview-pane {
  position: fixed;
  /* 与设置抽屉同一层级、同一形态：浮起的圆角卡片，而不是整边贴死的面板。
     两者视觉语言一致，切换时不会觉得是两个不同的东西。 */
  top: 12px;
  right: 12px;
  bottom: 12px;
  z-index: 61;
  display: flex;
  flex-direction: column;
  width: calc(50% - 20px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  transform: translate3d(calc(100% + 20px), 0, 0);
  visibility: hidden;
  transition: transform var(--preview-duration) var(--preview-ease),
    visibility 0s linear var(--preview-duration);
}

.app-shell.is-previewing .preview-pane {
  transform: translate3d(0, 0, 0);
  visibility: visible;
  /* 打开时立刻可见，不等动画结束 */
  transition: transform var(--preview-duration) var(--preview-ease), visibility 0s;
}

.preview-bar {
  display: flex;
  align-items: center;
  gap: 9px;
  flex: none;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border);
}

.preview-icon {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--accent);
}

.preview-title {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-sm);
  font-weight: 620;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.preview-badge {
  flex: none;
  padding: 1px 7px;
  font-size: 10px;
  font-weight: 600;
  color: #6d28d9;
  background: #ede9fe;
  border-radius: var(--r-full);
  cursor: help;
}

.preview-action {
  flex: none;
  padding: 4px 10px;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  transition: color var(--dur-fast) var(--ease-out), border-color var(--dur-fast) var(--ease-out);
}

.preview-action:hover {
  color: var(--accent);
  border-color: var(--border-focus);
}

.preview-body {
  flex: 1;
  min-height: 0;
  background: #fff;
}

/* 沙箱 iframe 填满面板，而不是靠 height:auto —— iframe 的 auto 高度
   会退到内核默认值，内容看起来就是一片空白 */
.preview-body .widget-frame {
  width: 100%;
  height: 100%;
  border: 0;
  background: #fff;
  color-scheme: light;
}

/* 窄屏放不下两栏：面板改为整屏覆盖，主区域不动 */
@media (max-width: 900px) {
  .preview-pane {
    width: 100%;
  }

  .app-shell.is-previewing .main,
  .app-shell.is-previewing .composer-wrap {
    width: 100%;
  }
}

/* ================================================================== */
/* 持久化文件面板                                                      */
/* ================================================================== */

.files-drawer {
  /* 复用设置抽屉的形态与层级：两者是同级的东西 */
  width: min(560px, calc(100vw - 24px));
  /* 自己带一段带一点回弹的滑入。这里用 CSS 而不是弹簧：
     面板是整块的布局位移，交给合成器更稳，也不会和设置抽屉的弹簧抢 inline 样式。 */
  transition: transform 420ms cubic-bezier(0.22, 1.15, 0.36, 1), visibility 0s linear 420ms;
}

/*
 * 设置抽屉的位移是由 JS 弹簧写 inline transform 驱动的，所以 .drawer 本身
 * 一直停在 translate3d(102%)。文件面板走的是类名切换，必须自己补上这个
 * 「打开」状态 —— 否则 dataset.open 已经是 true，面板却还在屏幕外。
 */
.files-drawer[data-open='true'] {
  transform: translate3d(0, 0, 0);
  visibility: visible;
  transition: transform 420ms cubic-bezier(0.22, 1.15, 0.36, 1), visibility 0s;
}

/* 标题、说明、空态一律居中 */
.files-drawer .drawer-head {
  position: relative;
  justify-content: center;
  gap: 0;
}

/*
 * 标题要**真正**居中，两个图标就不能留在 flex 流里 ——
 * 否则左边图标占的宽度会把标题往右推（实测偏 16px）。
 * 都改为绝对定位，标题独占整行再文字居中。
 */
.files-drawer .drawer-icon {
  position: absolute;
  left: 14px;
  top: 50%;
  transform: translateY(-50%);
}

.files-drawer .drawer-title {
  flex: 1;
  text-align: center;
}

.files-drawer .drawer-head .icon-btn {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
}

.files-hint {
  margin: 0 0 12px;
  padding: 0 6px;
  text-align: center;
  font-size: 11.5px;
  line-height: 1.65;
  color: var(--text-3);
}

/* 列表逐行浮现：给每行一点延迟，读起来像「依次出现」而不是整块闪出 */
@keyframes file-row-in {
  from {
    opacity: 0;
    transform: translateY(10px) scale(0.985);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

.file-row {
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--surface-2);
  /* hidden 在这里是安全的：行高由内容撑开，只用于裁圆角 */
  overflow: hidden;
  animation: file-row-in 380ms cubic-bezier(0.22, 1.15, 0.36, 1) backwards;
  transition: border-color 180ms ease-out, box-shadow 180ms ease-out, transform 180ms ease-out;
}

.file-row:hover {
  border-color: var(--border-focus);
  box-shadow: 0 6px 18px rgba(15, 23, 42, 0.06);
  transform: translateY(-1px);
}

/* 第八行之后不再累加延迟，否则长列表要等很久才出现 */
.file-row:nth-child(1) { animation-delay: 20ms; }
.file-row:nth-child(2) { animation-delay: 55ms; }
.file-row:nth-child(3) { animation-delay: 90ms; }
.file-row:nth-child(4) { animation-delay: 125ms; }
.file-row:nth-child(5) { animation-delay: 160ms; }
.file-row:nth-child(6) { animation-delay: 195ms; }
.file-row:nth-child(7) { animation-delay: 230ms; }
.file-row:nth-child(n + 8) { animation-delay: 250ms; }

.files-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 2px 2px 8px;
}

.files-empty {
  padding: 32px 12px;
  text-align: center;
  font-size: 12.5px;
  line-height: 1.7;
  color: var(--text-3);
}

.files-empty.is-error {
  color: var(--danger);
}

.file-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 9px 11px;
}

.file-icon {
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  flex: none;
  color: var(--accent);
}

.file-path {
  flex: 1;
  min-width: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.file-meta {
  flex: none;
  font-size: 10.5px;
  color: var(--text-3);
}

.file-actions {
  display: flex;
  gap: 6px;
  padding: 0 9px 9px;
}

.file-btn {
  padding: 5px 10px;
  font-size: 11px;
}

.file-confirm-text {
  align-self: center;
  margin-right: auto;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--danger);
}

.file-btn.is-danger {
  color: var(--danger);
  border-color: #fecaca;
}

.file-btn.is-danger:hover {
  background: #fef2f2;
}

/* 组件自己截的图 ------------------------------------------------- */

.shot-card {
  margin: 8px 0 0;
  padding: 0 10px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  overflow: hidden;
  background: var(--surface);
  animation: file-row-in 320ms cubic-bezier(0.22, 1.15, 0.36, 1);
}

.shot-image {
  display: block;
  /* 缩小展示：截图是拿来核对效果的，不是拿来看像素的，占满整屏反而
     把它下面真正有用的内容挤走了 */
  width: auto;
  max-width: min(100%, 420px);
  margin: 10px auto 0;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  max-height: 32vh;
  object-fit: contain;
  background: var(--surface-2);
  cursor: zoom-in;
}

.shot-image.is-zoomed {
  max-height: none;
  cursor: zoom-out;
}

.shot-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border-top: 1px solid var(--border);
  background: var(--surface-2);
}

.shot-label {
  flex: 1;
  min-width: 0;
  font-size: 11px;
  color: var(--text-3);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.shot-save {
  flex: none;
  padding: 3px 9px;
  font-size: 10.5px;
}

/* 对话里由 file_show 展开的文件内容 ------------------------------- */

.tool-file-view {
  margin-top: 8px;
  border-top: 1px solid var(--border);
  animation: file-content-in 260ms cubic-bezier(0.22, 1.15, 0.36, 1);
}

.tool-file-view[data-state='loading'],
.tool-file-view[data-state='error'] {
  padding: 10px 2px;
  font-size: 11.5px;
  color: var(--text-3);
}

.tool-file-view[data-state='error'] {
  color: var(--danger);
}

.tool-file-view .md-code {
  margin: 8px 0 0;
}

/* 对话里的展示要能一路看下去，同样解除 pre 的高度与纵向裁剪 */
.tool-file-view .md-code pre {
  max-height: none;
  overflow-y: visible;
}

/* 展开的正文：复用 Markdown 渲染出的代码块，自带高亮与复制 */
@keyframes file-content-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.file-content {
  border-top: 1px solid var(--border);
  background: var(--surface);
  animation: file-content-in 260ms cubic-bezier(0.22, 1.15, 0.36, 1);
  transform-origin: top center;
}

/* 面板头需要相对定位，关闭按钮才能绝对定位到右侧 */
.files-drawer .drawer-head {
  position: relative;
}

.file-content .md-code {
  margin: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

/*
 * 展开的正文要能一路看下去。
 *
 * 全局那条 .md-code pre { overflow-y: hidden } 是为了不让长代码块吞掉会话的
 * 滚轮而加的；但在这里它配合 max-height 会把超出部分变成**永远够不到**的内容。
 * 所以面板内解除这两个限制，交给外层 .files-list 统一滚动。
 */
.file-content .md-code pre {
  max-height: none;
  overflow-y: visible;
}

/* 展开的正文本身不设高度上限，让 .files-list 统一滚 */
.file-content {
  overflow: visible;
}

/* ================================================================== */
/* 会话搜索                                                            */
/* ================================================================== */

.search-scrim {
  position: fixed;
  inset: 0;
  z-index: 74;
  background: rgba(15, 23, 42, 0.2);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  will-change: opacity;
}

.search-dialog {
  position: fixed;
  top: 92px;
  left: 50%;
  z-index: 75;
  display: flex;
  flex-direction: column;
  width: min(540px, calc(100vw - 28px));
  max-height: min(460px, 64vh);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-xl);
  transform: translate(-50%, -12px);
  opacity: 0;
  will-change: transform, opacity;
  visibility: hidden;
  overflow: hidden;
}

.search-dialog[data-open='true'] {
  visibility: visible;
}

.search-input-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 12px 12px 16px;
  border-bottom: 1px solid var(--border);
}

.search-icon {
  display: grid;
  place-items: center;
  color: var(--text-3);
}

.search-icon .icon {
  width: 17px;
  height: 17px;
}

.search-input {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-base);
}

.search-input::placeholder {
  color: var(--text-3);
}

.search-results {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.search-result {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 9px 11px;
  text-align: left;
  border-radius: var(--r-md);
  transition: background-color var(--dur-fast) var(--ease-out);
  will-change: transform;
}

.search-result:hover,
.search-result.is-active {
  background: var(--surface-2);
}

.search-result-title {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
}

.search-result-snippet {
  font-size: 11.5px;
  line-height: 1.5;
  color: var(--text-3);
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.search-result-snippet mark {
  background: rgba(250, 204, 21, 0.3);
  color: inherit;
  border-radius: 2px;
}

.search-empty {
  padding: 26px 12px;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--text-3);
}

/* ================================================================== */
/* toasts                                                              */
/* ================================================================== */

.toasts {
  position: fixed;
  right: 18px;
  bottom: calc(18px + env(safe-area-inset-bottom));
  z-index: 90;
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-end;
  pointer-events: none;
}

.toast {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(380px, calc(100vw - 36px));
  padding: 11px 15px;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--text);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
  pointer-events: auto;
  will-change: transform, opacity;
}

.toast .icon {
  flex: none;
  width: 17px;
  height: 17px;
}

.toast-success .icon { color: var(--ok); }
.toast-error .icon { color: var(--danger); }
.toast-warn .icon { color: var(--warn); }
.toast-info .icon { color: var(--accent); }

/* ================================================================== */
/* responsive                                                          */
/* ================================================================== */

@media (max-width: 900px) {
  .transcript {
    padding-inline: 16px;
  }

  .composer-wrap {
    padding-inline: 14px;
  }

  .drawer {
    top: auto;
    left: 8px;
    right: 8px;
    bottom: 8px;
    width: auto;
    max-height: 88dvh;
    border-radius: var(--r-xl);
    transform: translate3d(0, 102%, 0);
  }

  .drawer-grip {
    display: block;
    width: 38px;
    height: 4px;
    margin: 8px auto 0;
    background: var(--border-strong);
    border-radius: var(--r-full);
  }

  .scroll-down {
    right: 16px;
  }
}

@media (max-width: 620px) {
  .topbar {
    padding-inline: 10px;
  }

  .hero {
    padding: 64px 16px 16px;
  }

  .suggestions {
    grid-template-columns: 1fr;
  }

  .message {
    gap: 10px;
  }

  .composer-box {
    padding: 12px 10px 8px 14px;
  }

  .toolbar-chip .chip-label {
    max-width: 84px;
  }

  .toasts {
    left: 14px;
    right: 14px;
    align-items: stretch;
  }

  .toast {
    max-width: none;
  }

  .ctx-list {
    max-height: 120px;
  }
}

@media (min-width: 1500px) {
  :root {
    --composer-max: 900px;
    --transcript-max: 900px;
  }
}
