:root {
  color-scheme: dark;
  --font-ui: Inter, "Noto Sans SC", "Microsoft YaHei", system-ui, sans-serif;
  --font-mono: "JetBrains Mono", "Cascadia Code", "SFMono-Regular", Consolas, "Liberation Mono", monospace;
  --serif: "Source Han Serif SC", "Noto Serif CJK SC", "Noto Serif SC", "Songti SC", "SimSun", Georgia, serif;
  --ui-scale: 1.1;
  --artifact-content-scale: calc(1.2 / var(--ui-scale));
  --sidebar-width: 252px;

  /* 窗边 r8 字号阶梯:正文 15 / UI 13 / meta 12 / micro 11 */
  --fs-chat: 15px;
  --fs-ui: 13px;
  --fs-meta: 12px;
  --fs-micro: 11px;
  --fs-artifact-chat: 16.3636px;

  /*
   * 圆角。原来散着 22 种取值（4/5/6/7/9/10/11/12/14/16px…），同一类控件在
   * 不同地方不一样宽。收敛成三个：矩形一律 --radius；12px 以下的小色块
   * （热力图格子、图例方块、柱状图顶）用 --radius-sm，那个尺寸上 8px 会圆成
   * 一个点；--radius-pill 只留给「靠圆头表达形状」的东西：开关轨道（38×22，
   * 圆角就是高度的一半，给 8px 会压成方块）、进度条与滑块轨道、圆头像、
   * 语音悬浮球。标签、按钮、浮层一律跟 --radius 走。
   * 圆形 50% 是形状不是圆角，仍写死；气泡那一角刻意留尖（--radius-sm），
   * 是尾巴，不是没统一。
   */
  --radius: 8px;
  --radius-sm: 3px;
  --radius-pill: 999px;

  /*
   * 夜阑 (dusk) —— 默认暗色主题。
   * MD3 system tokens;matugen 生成的 /theme.css 可整套覆盖。
   * 种子色取自 miyu-logo:primary=瞳色减淡的雾蓝,secondary=发色暖金,
   * tertiary=丝带酒红,surface=傍晚蓝紫。
   */
  --md-sys-color-primary: #aebde8;
  --md-sys-color-on-primary: #1f2c55;
  --md-sys-color-primary-container: #394877;
  --md-sys-color-on-primary-container: #dce3f9;
  --md-sys-color-secondary: #e4bf79;
  --md-sys-color-on-secondary: #402d02;
  --md-sys-color-secondary-container: #443716;
  --md-sys-color-on-secondary-container: #f6e7c4;
  --md-sys-color-tertiary: #e38c9a;
  --md-sys-color-on-tertiary: #55212e;
  --md-sys-color-tertiary-container: #4e242d;
  --md-sys-color-on-tertiary-container: #fadde3;
  --md-sys-color-error: #ec7a6e;
  --md-sys-color-on-error: #3f1210;
  --md-sys-color-error-container: #47231f;
  --md-sys-color-on-error-container: #f8dad4;
  --md-sys-color-surface: #171821;
  --md-sys-color-surface-container-lowest: #101117;
  --md-sys-color-surface-container-low: #12131b;
  --md-sys-color-surface-container: #1f212c;
  --md-sys-color-surface-container-high: #282b38;
  --md-sys-color-surface-container-highest: #323648;
  --md-sys-color-on-surface: #e9e6ef;
  --md-sys-color-on-surface-variant: #9993a5;
  --md-sys-color-outline: #4c5065;
  --md-sys-color-outline-variant: #303341;
  /* 扩展语义色:在线状态(不属于 MD3 标准 token) */
  --md-ext-color-online: #7ccb96;
}

/*
 * 旧变量层 —— 组件规则引用这些别名,一律从 MD3 token 派生。
 * 同时挂在 :root 和亮色 body 上:var() 在声明元素上解析,
 * 只挂 :root 的话亮色主题重定义 token 不会生效。
 */
:root,
body[data-theme="linen"] {
  --app-bg: var(--md-sys-color-surface);
  --sidebar-bg: var(--md-sys-color-surface-container-low);
  --topbar-bg: var(--md-sys-color-surface);
  --surface-1: var(--md-sys-color-surface-container);
  --surface-2: var(--md-sys-color-surface-container-high);
  --surface-3: var(--md-sys-color-surface-container-highest);
  --surface-soft: color-mix(in srgb, var(--md-sys-color-surface-container) 55%, var(--md-sys-color-surface));
  --line: var(--md-sys-color-outline-variant);
  --line-strong: var(--md-sys-color-outline);
  --text: var(--md-sys-color-on-surface);
  --text-soft: var(--md-sys-color-on-surface-variant);
  --text-faint: color-mix(in srgb, var(--md-sys-color-on-surface-variant) 70%, var(--md-sys-color-surface));
  --inverse-text: var(--md-sys-color-on-primary);
  --accent: var(--md-sys-color-primary);
  --accent-strong: color-mix(in srgb, var(--md-sys-color-primary) 82%, #ffffff);
  --accent-soft: var(--md-sys-color-primary-container);
  --cyan: var(--md-sys-color-primary);
  --cyan-soft: var(--md-sys-color-primary-container);
  --gold: var(--md-sys-color-secondary);
  --gold-soft: var(--md-sys-color-secondary-container);
  --coral: var(--md-sys-color-tertiary);
  --coral-soft: var(--md-sys-color-tertiary-container);
  --danger: var(--md-sys-color-error);
  --danger-soft: var(--md-sys-color-error-container);
  --online: var(--md-ext-color-online);
  --ribbon: var(--md-sys-color-tertiary);
  --ribbon-soft: var(--md-sys-color-tertiary-container);
  --user-bg: var(--md-sys-color-primary-container);
  --user-text: var(--md-sys-color-on-primary-container);
  /* 暗色:面板比气泡**亮**一档(One Dark 自己也是这么摆的),不是挖一个更黑的洞。 */
  --code-bg: var(--md-sys-color-surface-container-high);
  --code-ink: color-mix(in srgb, var(--md-sys-color-on-surface) 94%, var(--md-sys-color-primary));

  /* 正文高亮:暗色直接用 primary,亮色在 linen 块加深 */
  --hl: var(--md-sys-color-primary);

  /* 链接色**不**从主题派生(用户 09-09 裁定)。primary 跟着壁纸走,于是「链接」
     这件事在橄榄色壁纸下是橄榄色、在酒红壁纸下是酒红——而人对「蓝色带下划线
     = 可点」是有肌肉记忆的,那点主题一致性不值得拿它去换。深浅各一支柔和的蓝,
     终端那侧(src/render/style.rs 的 LINK_LABEL_STYLE)也是固定蓝,两端一致。 */
  --link: #8fb6ec;

  /* 三档软阴影(阴影 rgba 常量按主题,允许保留) */
  --bubble-shadow: 0 1px 4px rgba(0, 0, 0, 0.25);
  --card-shadow: 0 2px 8px rgba(0, 0, 0, 0.22);
  --float-shadow: 0 18px 50px rgba(0, 0, 0, 0.5), 0 4px 12px rgba(0, 0, 0, 0.35);
  --artifact-shadow: 0 0 10px rgba(0, 0, 0, 0.16), 0 2px 6px rgba(0, 0, 0, 0.1);
  --shadow: var(--float-shadow);

  /* 小签底色:身份用字形色,底色只表状态。中性签=页面背景色(白气泡上的「页面色凹陷」),
     live/fail 暗色淡混、亮色(linen 块)浓混。 */
  --chip-neutral: var(--app-bg);
  --chip-think: color-mix(in srgb, var(--accent-soft) 26%, transparent);
  --chip-live: color-mix(in srgb, var(--accent-soft) 48%, transparent);
  --chip-fail: color-mix(in srgb, var(--danger-soft) 55%, transparent);

  /*
   * 代码语法色。全部从 MD3 token 派生,一个 vendor 主题的十六进制都不抄:
   * MD3 保证同一个角色在亮色色板是深色调、在暗色色板是浅色调,所以同一条派生
   * 式在两套内置主题和 matugen 按壁纸生成的任意色板下,都朝着「跟代码底色拉开」
   * 的方向走(写死一套暗色主题的话,晨光下就是一片看不见的字)。
   * 每条再往 --code-ink 兑一点:压掉高饱和色在 12.5px 等宽字上的刺眼感,也把
   * matugen 偶尔给出的低对比色拽回来。
   * 角色只有九个,故意少——壁纸生成的色板未必有九种分得开的色相,少上色比上一
   * 堆分不清的色更好读。error 是三套色板下都必定是红的那个角色,给关键字;
   * online 明确「不跟壁纸走」的固定绿,给字符串;剩下的交给 primary/tertiary。
   */
  /* 语法高亮用固定的标准色板(One Dark),不从主题变量派生。
     派生版能跟着壁纸配色走,但代价是每换一张壁纸就换一套「关键字是什么颜色」——
     而看代码的人对紫关键字/绿字符串/橙数字/蓝函数是有肌肉记忆的,那点主题一致性
     不值得拿它去换(用户 09-09 裁定)。深浅两套各一份,见 linen 那块。 */
  --tok-c: #7f848e;
  --tok-p: #abb2bf;
  --tok-o: #56b6c2;
  --tok-k: #c678dd;
  --tok-s: #98c379;
  --tok-n: #d19a66;
  --tok-f: #61afef;
  --tok-t: #e5c07b;
  --tok-y: #e06c75;
}

body[data-theme="linen"] {
  color-scheme: light;

  /* 晨光 (dawn) —— 亮色主题。primary=发影藤紫,底色=窗边奶油白。 */
  --md-sys-color-primary: #7568b0;
  --md-sys-color-on-primary: #ffffff;
  --md-sys-color-primary-container: #e6e1f6;
  --md-sys-color-on-primary-container: #372e66;
  --md-sys-color-secondary: #8f6b1e;
  --md-sys-color-on-secondary: #ffffff;
  --md-sys-color-secondary-container: #f3e2bb;
  --md-sys-color-on-secondary-container: #4a3608;
  --md-sys-color-tertiary: #a5495a;
  --md-sys-color-on-tertiary: #ffffff;
  --md-sys-color-tertiary-container: #f6dce0;
  --md-sys-color-on-tertiary-container: #5e222c;
  --md-sys-color-error: #b3403a;
  --md-sys-color-on-error: #ffffff;
  --md-sys-color-error-container: #f6dcd6;
  --md-sys-color-on-error-container: #5f1d18;
  --md-sys-color-surface: #f6f0e2;
  --md-sys-color-surface-container-lowest: #fffdf6;
  --md-sys-color-surface-container-low: #efe7d3;
  --md-sys-color-surface-container: #fffdf6;
  --md-sys-color-surface-container-high: #f1eada;
  --md-sys-color-surface-container-highest: #e8dfc9;
  --md-sys-color-on-surface: #34303a;
  --md-sys-color-on-surface-variant: #797064;
  --md-sys-color-outline: #c6b795;
  --md-sys-color-outline-variant: #e3d8c1;
  --md-ext-color-online: #3e8e5c;

  /* 语法高亮的浅色一套(One Light)。注释比原版的 #a0a1a7 压暗了一档——那个值
     在浅底上只有 2.6:1,是「眯着眼找」的程度;注释该退到后面,但不该看不见。 */
  --tok-c: #81828a;
  --tok-p: #383a42;
  --tok-o: #017eb4;
  --tok-k: #a626a4;
  --tok-s: #3f8141;
  --tok-n: #986801;
  --tok-f: #3a6fe0;
  --tok-t: #a07001;
  --tok-y: #d3453b;

  /* 亮色下少数别名的映射不同:用户气泡用实心主色,代码块改暖纸浅底 */
  --user-bg: var(--md-sys-color-primary);
  --user-text: var(--md-sys-color-on-primary);
  /* 浅色的代码面板 = **页面自己那张纸**(surface),不是白纸。
     别再往 surface-container-lowest 上兑:壁纸生成的调色板(matugen)把它定成
     #ffffff,兑一成暖色只把 R-B 拉到 2,而同一页的气泡是 18、底是 19——量出来
     就是一块中性白补丁贴在暖奶油纸上,这正是「贴了张打印纸」的来源
     (09-09 实测 panel rgb(253,253,251) / bubble rgb(242,238,224))。
     用 surface 则天然跟着主题的色相走,且离气泡正好一档(matugen 亮色 +12、
     内置晨光 -9),和暗色那边「比气泡高一档」是同一个手法。
     顺带一提:浅色不能靠「压深」制造层次——One Light 那套色是照着近白底设计的,
     底色每压深一档就吃掉两成对比度,压到 surface-container-highest 时
     tok-o/t/y 会掉到 3.5:1 以下,而且 tok-t 补深之后会和 tok-n 撞成同一个色。 */
  --code-bg: var(--md-sys-color-surface);
  --code-ink: color-mix(in srgb, var(--md-sys-color-on-surface) 85%, var(--md-sys-color-surface));
  --hl: color-mix(in srgb, var(--md-sys-color-primary) 78%, var(--md-sys-color-on-surface));
  /* 亮色那支要压得住奶油纸:实测 4.65:1(近白的 matugen 亮色板上 4.87:1)。 */
  --link: #3a6ea8;
  --bubble-shadow: 0 1px 4px rgba(83, 64, 30, 0.07);
  --card-shadow: 0 2px 8px rgba(83, 64, 30, 0.06);
  --float-shadow: 0 18px 50px rgba(83, 64, 30, 0.2), 0 4px 12px rgba(83, 64, 30, 0.1);
  --artifact-shadow: 0 0 10px rgba(83, 64, 30, 0.1), 0 2px 6px rgba(83, 64, 30, 0.06);
  --chip-think: color-mix(in srgb, var(--accent-soft) 55%, transparent);
  --chip-live: color-mix(in srgb, var(--accent-soft) 85%, transparent);
  --chip-fail: color-mix(in srgb, var(--danger-soft) 78%, transparent);
}

* {
  box-sizing: border-box;
}

html,
body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
  overscroll-behavior: none;
}

/* Android Chrome:body 的 100% 是「工具栏收起」的大布局视口,而外壳只有可视视口那么高,
   文档比可见区域长出一截,到底后继续拖会把可视视口往下平移,外壳整体上移——输入框
   底部被推出屏幕、顶部也被切掉(09-11 手机端实测)。文档高度也钉在可视视口上。
   只在手机端钉:手机端 --ui-scale=1,--app-height 正好等于可视视口;桌面端
   --ui-scale=1.1,而 --app-height 已按 UI_SCALE 除过(那是给带 zoom 的 .app-shell
   用的),body 不带 zoom 再吃这个值就比窗口矮 1/1.1≈9%,底部露出一条 app 背景色的
   空带(09-11 桌面端实测)。桌面端 body 保持前面的 height:100%。 */
@media (max-width: 836px) {
  body {
    height: var(--app-height, 100%);
  }
}

body {
  background: var(--app-bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--fs-ui);
  letter-spacing: 0;
  -webkit-font-smoothing: antialiased;
}

/* 数字、ID、命令一律等宽 + tabular-nums */
.assistant-endpoint,
.character-count,
.session-time,
.capability-list dd,
.model-menu small,
.context-heading > span:last-child,
.settings-model small {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

button,
input,
textarea {
  color: inherit;
  font: inherit;
  letter-spacing: 0;
}

button {
  border: 0;
  appearance: none;
  -webkit-appearance: none;
}

button:focus-visible,
input:focus-visible,
textarea:focus-visible,
summary:focus-visible,
a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

button:disabled,
input:disabled,
textarea:disabled {
  cursor: not-allowed;
}

[hidden] {
  display: none !important;
}

/* 高度跟着可视视口走,而不是 100dvh。iOS Safari 不认 viewport meta 里的
   interactive-widget=resizes-content,软键盘弹出时 dvh 一动不动,外壳就比可见
   区域高出一个键盘,浏览器为了把输入框顶进视野只能滚动文档——表现是整页上移。
   --app-height 由 syncAppHeight() 写,JS 没跑起来时回落到 100dvh。 */
.app-shell {
  display: grid;
  grid-template-columns: var(--sidebar-width) minmax(0, 1fr);
  width: 100%;
  height: var(--app-height, calc(100dvh / var(--ui-scale)));
  zoom: var(--ui-scale);
}

.app-shell.is-sidebar-collapsed {
  grid-template-columns: minmax(0, 1fr);
}

.app-shell.is-sidebar-collapsed .sidebar {
  display: none;
}

.app-shell.is-sidebar-collapsed .sidebar-expand-button {
  display: inline-grid;
}

.icon-slot {
  display: inline-grid;
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
  place-items: center;
  line-height: 1;
}

.icon-slot svg {
  width: 100%;
  height: 100%;
  stroke-width: 1.8;
}

.icon-fallback {
  font-size: 14px;
  line-height: 1;
}

.icon-button {
  display: inline-grid;
  width: 34px;
  height: 34px;
  flex: 0 0 34px;
  place-items: center;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
}

.icon-button:hover:not(:disabled) {
  background: var(--surface-2);
  color: var(--text);
}

.icon-button:disabled {
  color: var(--text-faint);
  opacity: 0.55;
}

.status-dot {
  display: inline-block;
  width: 6px;
  height: 6px;
  flex: 0 0 6px;
  border-radius: 50%;
  color: var(--online);
  background: currentcolor;
  animation: status-pulse 2.4s ease-in-out infinite;
}

@keyframes status-pulse {
  0%,
  100% {
    box-shadow: 0 0 0 0 color-mix(in srgb, currentcolor 45%, transparent);
  }

  50% {
    box-shadow: 0 0 0 5px transparent;
  }
}

.status-dot.is-connecting {
  color: var(--gold);
}

.status-dot.is-offline,
.status-dot.is-blocked {
  color: var(--danger);
}

.sidebar {
  position: relative;
  z-index: 20;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-width: 0;
  min-height: 0;
  background: var(--sidebar-bg);
}

.brand-row {
  display: flex;
  min-height: 66px;
  align-items: center;
  padding: 13px 14px 11px;
  gap: 8px;
}

.brand-identity {
  display: flex;
  flex: 1;
  min-width: 0;
  align-items: center;
  gap: 10px;
}

.brand-avatar {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  border: 2px solid var(--gold);
  border-radius: 50%;
  object-fit: cover;
}

.brand-identity > div {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.brand-identity strong {
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.brand-identity > div > span,
.runtime-line > span:first-child {
  display: flex;
  min-width: 0;
  align-items: center;
  color: var(--text-soft);
  font-size: 11px;
  gap: 6px;
}

.sidebar-close,
.mobile-menu-button,
.sidebar-expand-button {
  display: none;
}

.sidebar-collapse-button {
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
}

.sidebar-collapse-button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.sidebar-collapse-button .icon-slot,
.sidebar-expand-button .icon-slot {
  width: 16px;
  height: 16px;
}

/* 新对话:brand-row 内 38px 图标方键 */
.new-chat-button {
  display: grid;
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  place-items: center;
  border: 0;
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--md-sys-color-on-primary-container);
  cursor: pointer;
  transition: filter 180ms ease, transform 150ms ease;
}

.new-chat-button:hover:not(:disabled) {
  filter: brightness(1.05);
  transform: translateY(-1px);
}

.new-chat-button:active:not(:disabled) {
  transform: scale(0.95);
}

.new-chat-button .icon-slot {
  width: 17px;
  height: 17px;
}

.new-chat-button:disabled {
  color: var(--text-faint);
  opacity: 0.58;
}

.session-list {
  min-height: 0;
  padding: 4px 8px 18px;
  overflow: auto;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

.session-items {
  display: grid;
  gap: 3px;
}

/* 侧栏拖拽排序:拖动中的行半透明,落点用主题色细线指示 */
.session-item.is-dragging {
  opacity: 0.45;
}

.session-item.drop-before {
  box-shadow: inset 0 2px 0 0 var(--accent);
}

.session-item.drop-after {
  box-shadow: inset 0 -2px 0 0 var(--accent);
}

.session-item {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  width: 100%;
  min-height: 30px;
  align-items: stretch;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  gap: 0;
  text-align: left;
  transition: background 180ms ease;
}

.session-item:hover,
.session-item:focus-within {
  background: color-mix(in srgb, var(--surface-1) 65%, transparent);
}

.session-item.active,
.session-item.active:hover {
  background: var(--surface-1);
  box-shadow: var(--bubble-shadow);
}

.session-item.active::before {
  position: absolute;
  top: 7px;
  bottom: 7px;
  left: 0;
  width: 3px;
  border-radius: var(--radius-sm);
  background: var(--ribbon);
  content: "";
}

.session-item-main {
  display: grid;
  grid-template-columns: 11px minmax(0, 1fr);
  min-width: 0;
  align-items: center;
  padding: 2px 7px 2px 11px;
  border-radius: var(--radius);
  background: transparent;
  color: inherit;
  cursor: pointer;
  gap: 7px;
  text-align: left;
}

/* 行首那一格:有状态就画,没有就空着。格子常驻,文字左缘才不会跟着动。 */
.session-lead {
  display: grid;
  width: 11px;
  height: 11px;
  place-items: center;
}

.session-item-main.is-renaming {
  cursor: default;
}



.session-copy {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.session-title-row {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 6px;
}

/* 会话名的字重定在 `.session-copy strong`(见下方);当前会话提半档到 500。
   原来写 600 是想要"略重",但本机字体栈没有 SemiBold 字面,600 会回退到
   Bold——12.5px 实测字面宽度 400=180.50 / 500=181.34 / 600=182.45 / 700=182.45,
   600 与 700 一模一样,于是当前会话整行变成真加粗(08-26 用户两次点名)。
   500 命中 Noto Sans CJK Medium,是真实存在的中间档。特异性要压过下面那条,
   否则被同特异性、位置更靠后的规则盖掉。 */
.session-item.active .session-copy strong {
  font-weight: 500;
}

.session-default-badge {
  flex: 0 0 auto;
  padding: 0 5px;
  border: 0;
  border-radius: var(--radius);
  background: var(--accent-soft);
  color: var(--md-sys-color-on-primary-container);
  font-size: 9px;
  font-weight: 500;
  line-height: 15px;
}

/* 运行中:转圈。动效表达「正在发生」——静态点和「有未读」看不出区别。 */
/* 盲文点阵转圈,和 REPL 里工具运行时那个同款(`wait_spinner.rs` 的
   BRAILLE_FRAMES)。同一件事在两个界面用同一个形状;圆环那种到处都是,
   这个一眼就认得出是 Miyu 在干活。

   换帧交给 JS(`startBrailleTicker`)。CSS 那两种做法都不可靠:动画
   `content` 只有 Chrome 认;十帧竖排靠 `steps()` 平移则要求行高和字形
   度量严丝合缝,盲文点阵一旦落到 fallback 字体就错位。 */
.session-run-spinner {
  display: grid;
  width: 11px;
  height: 14px;
  flex: 0 0 auto;
  place-items: center;
  color: var(--gold);
  font-family: var(--font-mono);
  /* 盲文点阵的字面比同号数字小一圈——点只占字身中间那一块,四周留白很多。
     要和旁边的未读圆点看着一样大,字号得往上顶。 */
  font-size: 17px;
  line-height: 1;
}

/* 未读:实心圆 + 呼吸。生命周期是「回合结束 → 用户切进来」,不是「已完成」。
   颜色用强调色:亮色主题(linen 的米色底)上金色和背景太接近,看不出来;
   matugen 取色主题同理,强调色是整套 token 里对比度最有保障的那个。只有
   graphite(默认暗色)保留亮金——深底上金点醒目,且和运行中的转圈同色系。
   呼吸动画复用 `status-pulse`,靠 currentcolor 自动取色。 */
.session-unread-dot {
  display: inline-block;
  flex: 0 0 auto;
  /* 外框与 spinner 同宽,两者互换时整行不抖;真正的点靠 radial-gradient 居中 */
  width: 11px;
  height: 11px;
  border-radius: 50%;
  color: var(--accent);
  background: radial-gradient(circle, currentcolor 0 3.5px, transparent 3.5px);
  animation: status-pulse 2.4s ease-in-out infinite;
}

body[data-theme="graphite"] .session-unread-dot {
  color: var(--gold);
}

@media (prefers-reduced-motion: reduce) {
  .session-run-spinner {
    animation-duration: 2.4s;
  }
}


.session-copy strong,
.session-copy small,
.session-time {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.session-copy strong {
  font-size: 12.5px;
  /* 语义上是 <strong>,视觉上不该整列粗体:层次交给背景与当前项的 500。 */
  font-weight: 400;
}

.session-copy small,
.session-time {
  color: var(--text-soft);
  font-size: 10.5px;
}

.session-time {
  color: var(--text-faint);
  font-size: 9.5px;
}

.session-rename-input {
  min-width: 0;
  padding: 2px 6px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  font-size: 12px;
}

.session-rename-input:focus {
  outline: none;
}

.session-trailing {
  display: flex;
  /* 横排:指示器与菜单按钮并排,各自垂直居中。竖排时指示器被顶到按钮上方,
     看着就是偏上的。 */
  flex-direction: row;
  align-items: center;
  justify-content: flex-end;
  padding: 5px 6px 5px 0;
  gap: 4px;
}

.session-time {
  max-width: 45px;
}

.session-menu-button {
  display: inline-grid;
  width: 22px;
  height: 22px;
  place-items: center;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  opacity: 0;
}

.session-menu-button .icon-slot {
  display: grid;
  place-items: center;
  width: 14px;
  height: 14px;
  line-height: 1;
}

.session-item:hover .session-menu-button,
.session-item:focus-within .session-menu-button,
.session-menu-button[aria-expanded="true"] {
  opacity: 1;
}

.session-menu-button:hover,
.session-menu-button[aria-expanded="true"] {
  background: var(--surface-3);
  color: var(--text);
}

.session-menu {
  position: absolute;
  top: calc(100% - 12px);
  right: 6px;
  z-index: 30;
  display: grid;
  min-width: 132px;
  padding: 4px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
  gap: 1px;
}

.session-menu.open-up {
  top: auto;
  bottom: calc(100% - 12px);
}

.session-menu button {
  padding: 7px 10px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font-size: 12px;
  text-align: left;
}

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

.session-menu button.is-danger {
  color: var(--danger);
}

.session-menu button.is-danger:hover {
  background: var(--danger-soft);
}

/* 批量删除的选择模式(09-24,web/sessionselect.js):行首指示格换成勾选框,
   列表顶上挂一条操作栏。按钮沿用会话菜单那套小字按钮,删除沿用危险色。 */
.session-select-box {
  display: grid;
  width: 11px;
  height: 11px;
  place-items: center;
  border: 1px solid var(--text-soft);
  border-radius: 3px;
  font-size: 9px;
  line-height: 1;
}

.session-item.is-selected .session-select-box {
  border-color: var(--accent);
  background: var(--accent);
  color: var(--md-sys-color-on-primary, #fff);
}

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

.session-bulk-bar {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0 4px 6px;
  padding: 4px;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
}

.session-bulk-count {
  flex: 1 1 auto;
  min-width: 0;
  padding: 0 6px;
  overflow: hidden;
  color: var(--text-soft);
  font-size: 11.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.session-bulk-button {
  flex: none;
  padding: 5px 8px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  cursor: pointer;
  font-size: 12px;
}

.session-bulk-button:hover:not(:disabled) {
  background: var(--surface-2);
}

.session-bulk-button.is-danger {
  color: var(--danger);
}

.session-bulk-button.is-danger:hover:not(:disabled) {
  background: var(--danger-soft);
}

.session-bulk-button:disabled {
  cursor: default;
  opacity: 0.45;
}


.sidebar-footer {
  padding: 11px 12px max(12px, env(safe-area-inset-bottom));
  background: var(--sidebar-bg);
}

.context-summary {
  display: grid;
  gap: 6px;
}

.context-heading {
  display: flex;
  justify-content: space-between;
  color: var(--text-soft);
  font-size: 10.5px;
  white-space: nowrap;
  gap: 6px;
}

.context-heading > span:last-child {
  font-size: 10px;
}

.context-track {
  height: 5px;
  overflow: hidden;
  border-radius: var(--radius-sm);
  background: var(--surface-2);
}

.context-track i {
  display: block;
  width: 0;
  height: 100%;
  border-radius: var(--radius-sm);
  background: linear-gradient(90deg, var(--gold), var(--accent));
  transition: width 500ms ease;
}

.context-track.is-high i {
  background: linear-gradient(90deg, var(--gold), var(--ribbon));
}

.context-track.is-critical i {
  background: var(--danger);
}

.sidebar-actions {
  display: flex;
  align-items: center;
  margin-top: 11px;
  gap: 2px;
}

.sidebar-actions > .sidebar-action:first-child {
  flex: 1 1 auto;
  min-width: 0;
}

.sidebar-action {
  display: inline-flex;
  min-width: 0;
  min-height: 32px;
  align-items: center;
  padding: 0 8px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  gap: 7px;
}

.sidebar-action:hover {
  background: var(--surface-2);
  color: var(--text);
}

.sidebar-action .icon-slot {
  width: 15px;
  height: 15px;
}

.settings-label {
  min-width: 0;
  white-space: nowrap;
}

.main-stage {
  --artifact-width: 45.4545vw;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  grid-template-rows: minmax(0, 1fr);
  min-width: 0;
  min-height: 0;
  background: var(--app-bg);
  /* 这里曾经是 container-type: inline-size，只为下面那条 @container 判断宽度。
     WebKit 在容器查询容器的后代被 replaceChildren 时会把 .chat-scroll 的
     scrollTop 同步归零（WebKitGTK 2.52 实测），于是流式渲染每帧都把视口拽回
     顶部，滚动跟随自我作废——Safari 独有的气泡抖动。宽度判断改由 app.js 的
     is-wide 类承担，见 syncArtifactLayout。 */
}

/* 顶栏没了,侧栏控制浮在正文左上角。正文有自己的左右留白,这两个按钮压在
   留白上,不占版面高度。 */
.stage-float {
  position: absolute;
  z-index: 15;
  top: 10px;
  left: 12px;
  display: flex;
  align-items: center;
  gap: 4px;
}

.stage-float:not(:has(button:not([hidden]))) {
  display: none;
}

/* 模式图标在这里出现一次,不在每一行会话前面重复。 */
.session-group-header {
  display: flex;
  align-items: center;
  margin: 12px 4px 3px;
  padding-left: 7px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 600;
  gap: 6px;
  letter-spacing: 0.04em;
  user-select: none;
}

.session-group-header .icon-slot {
  width: 12px;
  height: 12px;
  flex: 0 0 12px;
}

.mode-chooser-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  background: color-mix(in srgb, var(--md-sys-color-scrim, #000) 32%, transparent);
}

.mode-chooser {
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(340px, calc(100vw - 48px));
  padding: 16px;
  border-radius: var(--radius);
  background: var(--surface-1, var(--surface-2));
  box-shadow: 0 12px 40px color-mix(in srgb, #000 26%, transparent);
}

.mode-chooser > strong {
  font-size: 14px;
}

.mode-chooser > small {
  color: var(--text-soft);
  font-size: 11.5px;
}

.mode-chooser-option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  cursor: pointer;
  text-align: left;
}

.mode-chooser-option:hover {
  background: var(--surface-3);
}

.mode-chooser-option[data-mode="dev"]:hover {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--md-sys-color-tertiary) 40%, transparent);
}

.mode-chooser-option .icon-slot {
  width: 18px;
  height: 18px;
  flex: 0 0 18px;
}

.mode-chooser-copy {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.mode-chooser-copy small {
  color: var(--text-soft);
  font-size: 11px;
}

.model-menu-wrap {
  position: relative;
}

/* 模型按钮:金底小签 */
.model-button {
  display: inline-flex;
  min-width: 0;
  height: 28px;
  align-items: center;
  padding: 0 11px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-soft);
  cursor: pointer;
  gap: 7px;
  transition: background 180ms ease, color 180ms ease;
}

.model-button:hover:not(:disabled),
.model-button[aria-expanded="true"] {
  background: var(--surface-3, var(--surface-2));
  color: var(--text);
}

/* 菜单开着的时候箭头翻过来——不翻的话按钮看不出自己是开是关。 */
.model-button[aria-expanded="true"] > .icon-slot {
  transform: rotate(180deg);
}

.model-button:disabled {
  color: var(--text-faint);
  opacity: 0.58;
}

.model-button > .icon-slot {
  width: 12px;
  height: 12px;
  flex-basis: 12px;
  opacity: 0.7;
  transition: transform 160ms ease;
}

.model-label {
  max-width: 150px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: var(--fs-meta);
  font-weight: 600;
}

/* 设置页摘要那颗小圆点。模型菜单和输入框那个按钮上的都去掉了——颜色不
   表达任何信息,纯噪点;这里留着是因为摘要行没有别的图形锚点。 */
.model-mark {
  display: inline-grid;
  width: 7px;
  height: 7px;
  flex: 0 0 7px;
  place-items: center;
  overflow: hidden;
  border-radius: 50%;
  background: var(--gold);
  color: transparent;
  font-size: 0;
  font-style: normal;
}

/* 模型按钮从顶栏搬到了输入框那排,菜单往上开(往下开会掉出视口)。
   left/bottom/max-height 由 positionModelMenu() 写在 style 上:菜单挂在
   composer-dock 上而不是按钮旁边,纯 CSS 算不出按钮的位置。 */
.model-menu {
  position: absolute;
  z-index: 40;
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  width: min(286px, calc(calc(100vw / var(--ui-scale)) - 24px));
  overflow: hidden;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
}

.model-menu-list {
  min-height: 0;
  padding: 5px;
  overflow-y: auto;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

.model-menu-item {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 16px;
  min-height: 46px;
  width: 100%;
  align-items: center;
  padding: 6px 9px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  gap: 8px;
  text-align: left;
}

.model-menu-item:hover:not(:disabled),
.model-menu-item.selected {
  background: var(--surface-2);
  color: var(--text);
}

.model-menu-item:disabled {
  opacity: 0.52;
}

.model-menu-follow {
  margin-bottom: 5px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  border-radius: var(--radius) var(--radius) 0 0;
}

.model-menu-item.from-global {
  color: var(--text-soft);
}

.model-menu-item.from-global .check-slot {
  color: var(--text-faint);
}

.model-menu-copy {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.model-menu strong,
.model-menu small {
  overflow-wrap: anywhere;
}

.model-menu strong {
  font-size: var(--fs-ui);
  font-weight: 600;
  line-height: 1.35;
}

.model-menu small {
  color: var(--text-soft);
  font-size: 10.5px;
}

.model-menu .check-slot {
  width: 14px;
  height: 14px;
  color: var(--accent);
}

.model-menu-footer {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  padding: 8px;
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  background: transparent;
  gap: 7px;
}

.model-menu-feedback {
  grid-column: 1 / -1;
  min-height: 16px;
  color: var(--text-faint);
  font-size: 10px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.model-menu-feedback.is-error {
  color: var(--danger);
}

.model-menu-footer button {
  min-height: 32px;
  padding: 0 8px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-soft);
  cursor: pointer;
  font-size: 10.5px;
  font-weight: 500;
}

.model-menu-footer button:hover:not(:disabled) {
  color: var(--text);
  filter: brightness(1.04);
}

.model-menu-footer .model-confirm {
  background: var(--accent);
  color: var(--inverse-text);
}

.model-menu-footer .model-confirm:hover:not(:disabled) {
  background: var(--accent-strong);
  color: var(--inverse-text);
}

.model-menu-footer button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.conversation-stage {
  position: relative;
  display: grid;
  grid-row: 1;
  grid-column: 1;
  grid-template-rows: auto minmax(0, 1fr) auto;
  min-width: 0;
  min-height: 0;
}

/* 切换会话时铺一层加载动画(09-12「先切后加载」):目标标签已高亮,大会话拉取
   期间这里转圈,而不是像卡在旧会话上。 */
/* 切换会话的遮罩与圆环:**延迟 220ms 再淡入**。小会话几十毫秒就拉回来了,
   立刻画一层遮罩再撤掉,看着就是闪一下(用户 09-14)。两者都从 opacity:0 起步,
   动画带 220ms delay + forwards——没到 220ms 就加载完,类一摘,它压根没出现过。 */
.conversation-stage.is-switching::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 5;
  background: color-mix(in srgb, var(--surface-2) 60%, transparent);
  opacity: 0;
  animation: conv-switch-fade 160ms ease 220ms forwards;
}

@keyframes conv-switch-fade {
  to { opacity: 1; }
}
.conversation-stage.is-switching::before {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 6;
  width: 30px;
  height: 30px;
  margin: -15px 0 0 -15px;
  border-radius: 50%;
  border: 3px solid color-mix(in srgb, var(--accent) 28%, transparent);
  border-top-color: var(--accent);
  opacity: 0;
  animation:
    conv-switch-spin 0.7s linear 220ms infinite,
    conv-switch-fade 160ms ease 220ms forwards;
}
@keyframes conv-switch-spin {
  to { transform: rotate(360deg); }
}
@media (prefers-reduced-motion: reduce) {
  .conversation-stage.is-switching::before {
    animation: conv-switch-fade 160ms ease 220ms forwards;
  }
}

.inline-error {
  grid-row: 1;
  width: min(100% - 28px, 940px);
  margin: 8px auto 0;
  padding: 9px 12px;
  border: 0;
  border-left: 3px solid var(--danger);
  border-radius: var(--radius);
  background: var(--danger-soft);
  color: var(--md-sys-color-on-error-container);
  font-size: var(--fs-meta);
  line-height: 1.45;
  overflow-wrap: anywhere;
}

.chat-scroll {
  grid-row: 2;
  min-width: 0;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

.timeline {
  width: min(100%, 980px);
  min-height: 100%;
  margin: 0 auto;
  padding: 24px 30px 42px;
}

.day-divider {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 0 22px;
  color: var(--text-soft);
  font-size: var(--fs-micro);
}

.day-divider:not(:first-child) {
  margin-top: 28px;
}

.day-divider > span {
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: 3px 12px;
}

.system-event {
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 0 18px;
  color: var(--text-soft);
  font-size: var(--fs-micro);
}

.system-event > span {
  border-radius: var(--radius);
  background: var(--surface-2);
  padding: 3px 12px;
  max-width: 80%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 跨会话消息（09-23）：另一个会话里的 AI 发来的那条。铃铛 +「从 xxx 收到消息」，
   底下一根竖线串着正文，先露 --xs-rows 行，点开看全文——和终端里 `│` 串着的那
   一块同一个样子。竖线画成背景（同 .reasoning-window），不随内容滚走。 */
.xs-message {
  --proc-col: 16px;
  /* 与时间线的 --proc-soft 同一个配方(这一块不在 .proc-line 里,要自己定义)。 */
  --xs-soft: color-mix(in srgb, var(--text) 62%, var(--app-bg));
  margin: 0 0 18px;
}

.xs-head {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--text-soft);
  font-size: var(--fs-meta);
}

.xs-head .icon-slot {
  width: var(--proc-col);
  height: var(--proc-col);
  flex-basis: var(--proc-col);
}

/* 截到第几行由 crosssession.js 量出来填 --xs-clip(按实际行盒量,行内代码与中文
   回退字体会把行盒撑高);量出来之前先按十行估。 */
.xs-body {
  max-height: var(--xs-clip, 17em);
  overflow: hidden;
  line-height: 1.7;
  overflow-wrap: anywhere;
}

.xs-message > .xs-body {
  margin: 4px 0 0;
  padding-left: calc(var(--proc-col) + 6px);
  background-image: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--line-strong) 75%, var(--line)),
    color-mix(in srgb, var(--line-strong) 75%, var(--line))
  );
  background-repeat: no-repeat;
  background-size: 1px 100%;
  background-position: calc(var(--proc-col) / 2 - 0.5px) 0;
}

.xs-body > :first-child {
  margin-top: 0;
}


.xs-body > :last-child {
  margin-bottom: 0;
}

.xs-message.is-expanded > .xs-body {
  max-height: none;
}

/* 收着时露的那几行是附注,跟抬头一起淡;点开的全文才是正常色(和命令预览同一个
   规矩,用户 09-24:「消息预览的颜色不对」)。里面的加粗、代码、链接跟着淡。 */
.xs-message:not(.is-expanded) > .xs-body,
.xs-message:not(.is-expanded) > .xs-body *,
.tool-card.is-xs-send > .xs-send-preview * {
  color: var(--xs-soft, var(--proc-soft, var(--text-soft)));
}

.xs-more {
  display: block;
  color: var(--text-faint);
  line-height: 1.7;
  letter-spacing: 0.1em;
}

.xs-message > .xs-more {
  padding-left: calc(var(--proc-col) + 6px);
}

.xs-message.is-clipped,
.xs-message.is-expanded {
  cursor: pointer;
}

/* 并进 AI 回复之后（09-24 定的版式）：是这段回复的第一步，正文用附注字号，
   和时间线里点开的步同一个量级；离下面的「Worked for」/正文留一点空。 */
.assistant-blocks > .xs-message {
  margin: 2px 0 10px;
}

.assistant-blocks > .xs-message > .xs-body,
.assistant-blocks > .xs-message > .xs-more {
  font-size: var(--fs-meta);
}

/* 发出去的那张工具签：正文前几行排在抬头底下，缩进到文字列（同命令签）；展开后
   它退场，全文在展开区顶上。 */
.tool-card.is-xs-send > .xs-send-preview,
.tool-card.is-xs-send > .xs-send-more {
  margin: 0 0 4px var(--proc-indent, 0);
  color: var(--proc-soft, var(--text-soft));
  font-size: var(--fs-meta);
}

.tool-card.is-xs-send:not(.collapsed) > .xs-send-preview,
.tool-card.is-xs-send:not(.collapsed) > .xs-send-more {
  display: none;
}

.assistant-blocks .proc-steps > .tool-card > .xs-send-preview,
.assistant-blocks .proc-steps > .tool-card > .xs-send-more {
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.assistant-blocks .proc-steps > .tool-card > .xs-send-preview:hover,
.assistant-blocks .proc-steps > .tool-card > .xs-send-more:hover,
.assistant-blocks .proc-steps > .tool-card:has(> .xs-send-preview:hover, > .xs-send-more:hover) > .tool-head,
.assistant-blocks .proc-steps > .tool-card:has(> .tool-head:hover) > .xs-send-preview,
.assistant-blocks .proc-steps > .tool-card:has(> .tool-head:hover) > .xs-send-more {
  background: var(--surface-2);
}

.xs-send-full {
  margin: 0 0 8px;
  line-height: 1.7;
  overflow-wrap: anywhere;
}

/* 目标状态行：贴在输入框上方，跟着阶段变样。目标是会话级的长期状态，
   放在对话流里会被后面几十轮顶到看不见的地方。 */
.goal-bar {
  display: flex;
  align-items: center;
  margin-bottom: 6px;
  padding: 7px 9px 7px 11px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  gap: 9px;
  background: var(--surface-1);
}

.goal-bar[hidden] {
  display: none;
}

.goal-bar-mark {
  display: grid;
  width: 15px;
  height: 15px;
  flex: 0 0 15px;
  place-items: center;
  color: var(--text-faint);
}

.goal-bar[data-phase="active"] .goal-bar-mark {
  color: var(--gold);
}

.goal-bar[data-phase="blocked"] .goal-bar-mark {
  color: var(--danger, #e5484d);
}

/* 一行装下：目标占满剩余宽度，状态贴在它后面。 */
.goal-bar-objective {
  overflow: hidden;
  min-width: 0;
  flex: 1 1 auto;
  border-radius: var(--radius);
  cursor: text;
  font-size: 12px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.goal-bar-objective:hover {
  background: var(--surface-2);
  box-shadow: 0 0 0 3px var(--surface-2);
}

.goal-bar-meta {
  flex: 0 0 auto;
  color: var(--text-faint);
  font-size: 10.5px;
  white-space: nowrap;
}

.goal-bar[data-phase="blocked"] .goal-bar-meta {
  color: var(--danger, #e5484d);
}

.goal-bar-edit {
  min-width: 0;
  flex: 1 1 auto;
  padding: 4px 7px;
  border: 1px solid var(--accent);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  /* 多行文本框(09-12):自动撑高,不手动拉伸,换行随内容走 */
  resize: none;
  line-height: 1.45;
  overflow-y: auto;
  white-space: pre-wrap;
  word-break: break-word;
}

.goal-bar-edit:focus {
  outline: none;
}

.goal-bar-actions {
  display: flex;
  flex: 0 0 auto;
  gap: 2px;
}

.goal-bar-button {
  display: grid;
  width: 26px;
  height: 26px;
  place-items: center;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
}

.goal-bar-button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.goal-bar-button .icon-slot {
  width: 13px;
  height: 13px;
}

.jobs-strip {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 6px 14px 0;
  margin-bottom: 8px;
}

/* 在子代理的会话里回主会话(会话项目第 4 段):和任务条的折叠头一个样子。 */
.subagent-parent-bar {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  margin: 6px 14px 0;
  border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
  background: color-mix(in srgb, var(--accent-soft) 30%, var(--surface-2));
  color: var(--text);
  font-size: var(--fs-meta);
  border-radius: var(--radius);
  padding: 4px 12px;
  cursor: pointer;
}

.subagent-parent-bar[hidden] {
  display: none;
}

.subagent-parent-bar:hover {
  color: var(--accent);
}

.tool-card.has-child-session > .tool-head {
  cursor: pointer;
}

.jobs-strip-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: flex-start;
  border: none;
  background: var(--surface-2);
  color: var(--text-soft);
  font-size: var(--fs-micro);
  border-radius: var(--radius);
  padding: 4px 10px;
  cursor: pointer;
}

.jobs-strip-toggle:hover {
  color: var(--text);
}

/* 桌面端折叠头更醒目：手机端保持紧凑（836px 断点与整体缩放一致）。 */
@media (min-width: 837px) {
  .jobs-strip-toggle {
    font-size: var(--fs-meta);
    padding: 6px 14px;
    color: var(--text);
    border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
    background: color-mix(in srgb, var(--accent-soft) 30%, var(--surface-2));
  }
}

.job-chip {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 8px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-soft);
  font-size: var(--fs-micro);
  padding: 4px 10px;
}

.job-chip.is-done .job-chip-marker {
  color: var(--ok, #7fb069);
}

.job-chip.is-failed .job-chip-marker {
  color: var(--danger, #d08080);
}

.job-chip-marker {
  flex: none;
  width: 1.2em;
  text-align: center;
}

.job-chip-marker.is-spinning {
  animation: job-chip-spin 0.8s linear infinite;
}

@keyframes job-chip-spin {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

.job-chip-label {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.job-chip-time {
  flex: none;
  font-variant-numeric: tabular-nums;
}

/* 后台子代理任务行:可点开看流式子过程。收起时标题行里带一条单行窥视。 */
.job-chip-wrap {
  width: 100%;
}
.job-chip.is-expandable {
  cursor: pointer;
  transition: background 140ms ease;
}
/* 可点开的任务行悬浮要有「选中」反馈(#5:悬浮没有选中效果)——chip 本身已是
   surface-2,再叠一层正文色兑亮一档,和工具行整行悬浮同一套语言。 */
.job-chip.is-expandable:hover {
  background: color-mix(in srgb, var(--text) 8%, var(--surface-2));
}
.job-chip-label {
  flex: 1 1 auto;
}
/* 左侧标记槽:spinner 与展开箭头叠在同一格,平时显 spinner,悬浮显箭头
   (09-12 #8b)。 */
.job-chip-marker-slot {
  position: relative;
  flex: none;
  width: 1.3em;
  height: 1.3em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.job-chip-marker-slot .job-chip-chevron {
  display: none;
  position: absolute;
  inset: 0;
  margin: auto;
  width: 15px;
  height: 15px;
  opacity: 0.7;
  transition: transform 140ms ease;
}
.job-chip:hover > .job-chip-marker-slot > .job-braille {
  visibility: hidden;
}
.job-chip:hover > .job-chip-marker-slot > .job-chip-chevron {
  display: block;
}
/* 「后台任务 ×N」合并行是收起/展开控件,不是某个在跑的任务:一直显箭头(提示可展开/收起),
   不显盲文转圈(#138)。展开态由下面的 is-open 旋 180°。 */
.job-chip.is-toggle > .job-chip-marker-slot > .job-braille {
  display: none;
}
.job-chip.is-toggle > .job-chip-marker-slot > .job-chip-chevron {
  display: block;
}
.job-chip.is-open > .job-chip-marker-slot > .job-chip-chevron {
  transform: rotate(180deg);
}
/* 展开后的子过程流:限高可滚,不许顶满全屏(09-11 用户报)。 */
/* 后台【子代理】展开面板(不含命令日志面板,它自带一层框、别叠成两层框 #134):
   不要左侧竖线(#116);给一层柔和暖底做外框(和前台活区域同款),节点遮线块用的就是
   这暖底,面板不上底时节点暖色会浮在纯页面底上露方块(#122)。左缩进从 24 收到 6(#133)。 */
.job-stream-panel:not(.job-log-panel) {
  margin: 2px 0 8px 8px;
  padding: 5px 8px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--text) 5%, transparent);
  /* 后台子代理展开区约 5 行高就够,超出滚动(#4:限高丢了顶到全屏)。
     这条 :not() 特异度比下面那条裸 .job-stream-panel 高,所以限高得写在这里,
     不然那条 150px 压不过来、又退回了大高度。 */
  max-height: 150px;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-gutter: stable;
}

.job-chip-stop {
  flex: none;
  border: none;
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  padding: 0 2px;
  font-size: inherit;
}

.job-chip-stop:hover {
  color: var(--text);
}

/* 09-12 任务条重做:合并行=单行 job-chip 外观;盲文点阵 spinner(JS 驱动,不转);
   行窥视(跑到工具/思考单行刷新)+ token 显示;展开箭头悬在状态行之后。 */
.job-chip.is-toggle {
  cursor: pointer;
}
.job-chip.is-toggle .job-chip-label {
  flex: 1 1 auto;
}
.job-braille {
  animation: none;
  color: var(--accent, currentColor);
}
.job-chip-label {
  flex: 0 1 auto;
}
/* .reasoning-peek(文件后段)会用同特异度的 flex:0 1 auto 盖掉这里,
   所以用 .job-chip 前缀提高特异度,确保窥视撑开、把 token/时间/✕ 顶到最右
   (09-12 #8c:命令行 token/时间/✕ 没右对齐)。 */
.job-chip .job-chip-peek {
  display: flex;
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  margin-left: 2px;
  color: var(--proc-think, var(--text-soft));
  font-size: var(--fs-micro);
  line-height: 1.5;
}
.job-chip-peek > span {
  flex: none;
  white-space: nowrap;
}
/* 用户改主意(#2「窥视右对齐不合理」):任务行窥视改左对齐、紧跟时间,超长向右淡出。
   .job-chip 前缀把特异度抬到 0,3,0,压过文件后段的 `.reasoning-peek.is-overflow`
   (0,2,0,那条是给主对话「已思考」尾巴用的右对齐+左淡出,保持不动)。 */
.job-chip .job-chip-peek.is-overflow {
  justify-content: flex-start;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 28px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 28px), transparent);
}
.job-chip-token {
  flex: none;
  color: var(--text-soft);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-micro);
  opacity: 0.85;
}
.job-chip-token:empty {
  display: none;
}
/* 后台命令展开:拉日志尾巴,限高约 5 行可滚(09-12)。 */
.job-log-panel {
  margin: 2px 0 8px 8px;
}
.job-log-pre {
  margin: 0;
  max-height: 9em;
  overflow: auto;
  overscroll-behavior: contain;
  white-space: pre-wrap;
  word-break: break-word;
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--fs-micro);
  color: var(--text-soft);
  background: color-mix(in srgb, var(--text) 6%, transparent);
  border-radius: 6px;
  padding: 6px 8px;
}
/* 09-12 item 6:展开的子过程区约 5 行就够,不再 42vh 顶到全屏。 */
.job-stream-panel {
  /* 后台子代理展开区也固定约 5 行高(#10,和前台的活区域一个量级),超出滚动。 */
  max-height: 150px;
}

/* 09-12 二轮修 #2/#4/#5/#10:标题永远优先(至少放得下「开发中/子代理/命令」),
   窥视只是次要、可缩、定宽 token 槽减少抖动;展开(is-open)只显标题不显窥视;
   命令日志面板去掉左侧竖线。用 `.job-chip >` 直接子选择器压过前面几条同名规则。 */
/* 标题撑开占左边、优先完整显示;窥视靠右、只占一小块、和标题之间留足间距,
   永远不压标题(09-12 #1 后台标题被窥视覆盖)。token/时间/✕ 被撑开的标题顶到最右。 */
.job-chip > .job-chip-label {
  /* 标题优先完整显示(#3/#10:不被窥视盖住/挤掉):不缩、最多占 60%,超了才省略。 */
  flex: 0 0 auto;
  max-width: 60%;
  min-width: 3.6em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.job-chip > .job-chip-token,
.job-chip > .job-chip-time {
  flex: none;
}
.job-chip > .job-chip-peek {
  /* 窥视填右边余下空间,左对齐紧跟秒数。淡出只在真的放不下时才加(见 .is-overflow),
     内容短、空间够时不加遮罩(#132:短内容被无谓地虚掉了)。 */
  flex: 1 1 0;
  min-width: 0;
  justify-content: flex-start;
}
.job-chip.is-open > .job-chip-peek {
  display: none;
}
.job-chip > .job-chip-token {
  flex: none;
  min-width: 3.4em;
  text-align: right;
  margin-left: 6px;
}
.job-chip > .job-chip-time {
  margin-left: 6px;
}
/* 后台命令展开的日志面板不要那条左竖线(用户嫌丑,09-12)。 */
.job-log-panel {
  border-left: none;
  padding-left: 0;
}


.message {
  width: 100%;
  min-width: 0;
}

.user-message {
  display: grid;
  justify-items: end;
  margin-bottom: 27px;
}

.user-bubble {
  max-width: min(62%, 640px);
  padding: 10px 16px;
  border-radius: var(--radius) var(--radius) var(--radius-sm) var(--radius);
  background: var(--user-bg);
  color: var(--user-text);
  font-size: var(--fs-chat);
  line-height: 1.7;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.user-bubble p {
  margin: 0;
  line-height: 1.7;
}

/* 自己发的消息里只会出现三样东西:段落、代码块、链接。段落之间要有气口,
   代码块贴着气泡边会闷。 */
.user-bubble > * + * {
  margin-top: 9px;
}

/* 自己发的消息里的代码块跟着**气泡**走,不再借用正文那套 --code-bg。
   借用的写法在亮色主题下必翻车:晨光的气泡是实心主色(深),而 --code-bg 是页面
   那张奶油纸(浅)——深气泡上贴一张浅纸,谁看都不合理(用户 09-09 裁定)。
   两套主题的用户气泡都是「深底浅字」(暗色 primary-container / 亮色 primary),
   所以一条规则通吃:底色 = 气泡色兑进近黑,既比气泡深一档、又留着气泡的色相;
   字色 = 气泡前景色。语法色跟着钉死在 One Dark 那套上——面板永远是深的,
   就不该再跟主题的深浅走。 */
.user-bubble .code-block {
  margin: 0;
  --code-bg: color-mix(in srgb, var(--user-bg) 34%, #14141a);
  --code-ink: var(--user-text);
  --tok-c: #7f848e;
  --tok-p: #abb2bf;
  --tok-o: #56b6c2;
  --tok-k: #c678dd;
  --tok-s: #98c379;
  --tok-n: #d19a66;
  --tok-f: #61afef;
  --tok-t: #e5c07b;
  --tok-y: #e06c75;
  border-radius: var(--radius);
  white-space: normal;
}

.user-bubble .code-block pre {
  max-height: 320px;
}

.user-bubble > p > code {
  padding: 1px 5px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--user-text) 16%, transparent);
  font-family: var(--font-mono);
  font-size: 0.9em;
}

.user-bubble a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  overflow-wrap: anywhere;
}

.revision-editor {
  display: grid;
  width: min(86%, 640px);
  gap: 8px;
}

.revision-editor textarea {
  width: 100%;
  min-height: 96px;
  max-height: calc(40vh / var(--ui-scale));
  resize: vertical;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius) var(--radius) var(--radius-sm) var(--radius);
  outline: none;
  /* 和当前用户气泡同底色(中性 surface-1),不再是那块强调色(09-12 #12)。 */
  background: var(--surface-1);
  color: var(--text);
  padding: 10px 16px;
  font: inherit;
  font-size: var(--fs-chat);
  line-height: 1.7;
}

.revision-editor textarea:focus-visible {
  /* 聚焦高亮改中性(09-12 #14):不再是那圈强调色边线,和消息气泡一致。 */
  border-color: var(--line-strong);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--text) 10%, transparent);
}

.revision-editor-footer {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 7px;
}

.revision-editor-footer button {
  min-height: 34px;
  border-radius: var(--radius);
  padding: 5px 12px;
  background: var(--surface-2);
  color: var(--text);
}

.revision-editor-footer button[type="submit"] {
  background: var(--accent);
  color: var(--inverse-text);
}

.revision-editor-error {
  color: var(--danger);
  font-size: var(--fs-meta);
}

.user-attachments {
  display: flex;
  justify-content: flex-end;
  flex-wrap: wrap;
  width: fit-content;
  max-width: 100%;
  margin-bottom: 5px;
  gap: 5px;
}

.user-attachment-image {
  display: block;
  width: 96px;
  height: 96px;
  flex: 0 0 96px;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-2);
}

.user-attachment-image img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.user-attachment-file {
  display: grid;
  grid-template-columns: 28px minmax(0, 1fr) 18px;
  width: fit-content;
  min-width: 140px;
  max-width: min(280px, 100%);
  flex: 0 1 auto;
  min-height: 48px;
  align-items: center;
  padding: 6px 9px;
  border-radius: var(--radius);
  border: 1px solid color-mix(in srgb, var(--line) 65%, transparent);
  background: var(--surface-2);
  color: var(--text);
  gap: 7px;
}

.user-attachment-file > .icon-slot:first-child {
  width: 18px;
  height: 18px;
  color: var(--accent);
}

.user-attachment-file > .icon-slot:last-child {
  width: 14px;
  height: 14px;
  opacity: 0.7;
}

/* 能预览的芯片:整块点开预览,右下角箭头单独负责下载。 */
.user-attachment-file.is-previewable {
  cursor: pointer;
  transition: border-color 140ms ease, background-color 140ms ease;
}

.user-attachment-file.is-previewable:hover,
.user-attachment-file.is-previewable:focus-visible {
  border-color: color-mix(in srgb, var(--accent) 45%, var(--line));
  background: color-mix(in srgb, var(--accent) 8%, var(--surface-2));
}

.user-attachment-download {
  display: grid;
  width: 18px;
  height: 18px;
  align-content: center;
  justify-items: center;
  border-radius: var(--radius);
  color: inherit;
  opacity: 0.65;
}

.user-attachment-download:hover {
  opacity: 1;
}

.user-attachment-download .icon-slot {
  width: 14px;
  height: 14px;
}

.user-attachment-file > span:nth-child(2) {
  display: grid;
  min-width: 0;
  width: max-content;
  max-width: 210px;
}

.user-attachment-file strong,
.user-attachment-file small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.user-attachment-file strong {
  font-size: 12px;
  font-weight: 600;
}

.user-attachment-file small {
  font-size: 10px;
  opacity: 0.72;
}

.message-actions,
.assistant-meta {
  display: flex;
  min-height: 24px;
  align-items: center;
  margin-top: 3px;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  gap: 5px;
}

.assistant-stream-rail {
  display: flex;
  width: 100%;
  min-height: 24px;
  align-items: center;
  padding-left: 2px;
}

.assistant-stream-rail[hidden] {
  display: none;
}

.message-actions:hover,
.assistant-meta:hover {
  color: var(--text-soft);
}

.assistant-endpoint {
  color: inherit;
  font-size: inherit;
}

/* 回复末尾那行 ✻(09-26,与终端同一种写法):跟 meta 行一样的灰与等宽字。 */
.turn-end {
  margin-top: 2px;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

.message-actions button,
.assistant-meta button,
.code-copy-button {
  display: grid;
  width: 25px;
  height: 23px;
  place-items: center;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.message-actions button,
.assistant-meta button {
  opacity: 0;
}

.message:hover .message-actions button,
.assistant-message:hover .assistant-meta button,
.message-actions button:focus-visible,
.assistant-meta button:focus-visible {
  opacity: 1;
}

.message-actions button:hover,
.assistant-meta button:hover,
.code-copy-button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.message-actions .icon-slot,
.assistant-meta .icon-slot,
.code-copy-button .icon-slot {
  width: 13px;
  height: 13px;
}

/* 助手消息:92% 列宽的气泡行,30px 金圈头像固定在消息顶部 */
.assistant-message {
  position: relative;
  max-width: 92%;
  margin-bottom: 30px;
  padding-left: 40px;
}

.assistant-message.is-muted {
  opacity: 0.7;
}

.assistant-label {
  display: flex;
  min-width: 0;
  align-items: center;
  margin-bottom: 5px;
  gap: 8px;
}

.assistant-label img {
  position: absolute;
  top: 0;
  bottom: auto;
  left: 0;
  width: 30px;
  height: 30px;
  border: 1.5px solid var(--gold);
  border-radius: 50%;
  object-fit: cover;
}

.assistant-label > div {
  display: flex;
  min-width: 0;
  align-items: baseline;
  gap: 7px;
}

.assistant-label strong {
  color: var(--text-soft);
  font-size: var(--fs-micro);
  font-weight: 600;
}

.assistant-label span {
  color: var(--text-faint);
  font-size: var(--fs-micro);
  overflow-wrap: anywhere;
}

.assistant-label .live-indicator {
  color: var(--accent);
}

/* 助手气泡:surface-1 无边框 + 软阴影,左下角 3px 收尾 */
.assistant-content {
  position: relative;
  min-width: 0;
  padding: 12px 16px;
  border-radius: var(--radius) var(--radius) var(--radius) var(--radius-sm);
  background: var(--surface-1);
  box-shadow: var(--bubble-shadow);
  color: var(--text);
  font-size: var(--fs-chat);
  line-height: 1.75;
}

/* 普通正文和小签按内容收缩；长文本仍受消息列最大宽度约束并正常换行。 */
.assistant-content.is-slim {
  width: fit-content;
  max-width: 100%;
}

.assistant-bubble {
  position: relative;
  min-width: 0;
}

.assistant-bubble:has(.assistant-content.is-slim) {
  width: fit-content;
  max-width: 100%;
}

.assistant-blocks {
  min-width: 0;
}

.avatar-path-row { display: flex; align-items: center; gap: 6px; min-width: 0; }
.avatar-path-row .config-input { flex: 1 1 auto; min-width: 0; }
.avatar-path-row .icon-button { flex: 0 0 34px; }
.persona-avatar-preview { display: block; width: 38px; height: 38px; flex: 0 0 38px; border-radius: 50%; object-fit: cover; border: 1px solid var(--outline); }
.persona-board-preview { border-radius: var(--radius); }
.persona-avatar-preview.is-missing { background: var(--surface-3); }
.persona-starter-fields { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }

.assistant-blocks > * {
  margin-top: 0;
  margin-bottom: 10px;
}

.assistant-blocks > .tool-card,
.assistant-blocks > .reasoning-block {
  margin-bottom: 7px;
}

.assistant-blocks > *:last-child {
  margin-bottom: 0;
}

.assistant-meta {
  min-height: 25px;
  padding-left: 2px;
  justify-content: flex-start;
}

.assistant-meta .meta-spacer {
  flex: 1;
}

.turn-status-line {
  display: flex;
  min-height: 31px;
  align-items: center;
  margin: -18px 0 28px;
  padding-left: 40px;
  color: var(--text-faint);
  font-size: var(--fs-meta);
  gap: 7px;
}

.turn-status-line.is-interrupted,
.run-notice.is-error {
  color: var(--coral);
}

.turn-status-line .icon-slot {
  width: 14px;
  height: 14px;
}

.context-state-badge {
  display: inline-flex;
  min-height: 20px;
  align-items: center;
  padding: 0 6px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-2) 70%, transparent);
  color: var(--text-faint);
  font-size: var(--fs-micro);
}

.markdown-body {
  min-width: 0;
  overflow-wrap: anywhere;
}

.markdown-body > :first-child {
  margin-top: 0;
}

.markdown-body > :last-child {
  margin-bottom: 0;
}

.markdown-body p {
  margin: 0 0 10px;
}

.markdown-body .hl {
  color: var(--hl);
  font-weight: 600;
}

.markdown-body h2,
.markdown-body h3,
.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  margin: 18px 0 8px;
  color: var(--text);
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: 0;
}

.markdown-body h2 {
  font-size: 17px;
}

.markdown-body h3 {
  margin: 14px 0 6px;
  font-size: 15.5px;
}

.markdown-body h4,
.markdown-body h5,
.markdown-body h6 {
  margin: 12px 0 5px;
  font-size: var(--fs-chat);
}

.markdown-body ul,
.markdown-body ol {
  display: grid;
  margin: 0 0 10px;
  padding-left: 20px;
  gap: 3px;
}

.markdown-body li::marker {
  color: var(--text-soft);
}

.markdown-body .task-list {
  padding-left: 2px;
}

.markdown-body .task-list-item {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr);
  align-items: start;
  column-gap: 8px;
  list-style: none;
}

.markdown-body .task-list-item input {
  width: 15px;
  height: 15px;
  margin: 3px 0 0;
  accent-color: var(--accent);
  opacity: 1;
}

.markdown-body blockquote {
  margin: 0 0 10px;
  padding: 7px 13px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: color-mix(in srgb, var(--accent-soft) 35%, transparent);
  color: var(--text-soft);
  font-size: 14px;
}

.markdown-body blockquote p:last-child {
  margin-bottom: 0;
}

.markdown-body hr {
  height: 1px;
  margin: 14px 0;
  border: 0;
  background: var(--line);
}

.markdown-body del {
  color: var(--text-faint);
}

/* 表格:去外框与竖线,只留淡横线,整块坐在淡底容器里 */
.markdown-body .markdown-table-scroll {
  max-width: 100%;
  margin: 0 0 10px;
  overflow-x: auto;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-2) 45%, transparent);
  scrollbar-color: var(--line-strong) transparent;
}

.markdown-body table {
  width: max-content;
  min-width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

.markdown-body th,
.markdown-body td {
  max-width: 360px;
  padding: 7px 14px;
  border: 0;
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
}

.markdown-body th {
  border-bottom: 1px solid var(--line);
  color: var(--text-soft);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.07em;
}

.markdown-body td {
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
}

.markdown-body tbody tr:last-child td {
  border-bottom: 0;
}

.markdown-body .align-center {
  text-align: center;
}

.markdown-body .align-right {
  text-align: right;
}

.markdown-body code:not(pre code) {
  padding: 1px 6px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  font-family: var(--font-mono);
  font-size: 0.86em;
  overflow-wrap: anywhere;
}

.markdown-body a {
  color: var(--link);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: color-mix(in srgb, var(--link) 35%, transparent);
  text-underline-offset: 3px;
  overflow-wrap: anywhere;
}

.markdown-body a:hover {
  text-decoration-color: var(--link);
}

/* 「标题 (地址)」整行成链时,地址那半截退半档:标题仍然是主角,但两截同属一个
   链接,点哪儿都能走。 */
.link-url {
  font-weight: 400;
  opacity: 0.72;
}

/* 本地路径链接。浏览器不让 http 页面跳 file://,所以这里点一下是复制路径——
   光标形状先把这件事说清楚,免得点完以为链接坏了。 */
a.path-link {
  cursor: copy;
}

/* 代码块必须一眼看出是「一块面板」,但**不靠描边**(用户 09-09 裁定):层次
   交给底色,一条线只是把「底色分得不够开」这件事糊过去。
   两条约束缺一不可:底色跟着主题的色相走(要符合网页背景),同时跟气泡差开一档。
   走查里 check_surfaces 就是钉这两条的(testkit/webui-links/syntax.py)。 */
.code-block {
  margin: 2px 0 12px;
  overflow: hidden;
  border: 0;
  border-radius: var(--radius);
  background: var(--code-bg);
  color: var(--code-ink);
}

/* ```mermaid 卡片：图直接画在回复里，源码折在后面（用户 09-20 拍板：卡片式
   内联，不走 artifact——聊天里的图是回答的一部分）。 */
.mermaid-figure {
  display: flex;
  justify-content: center;
  padding: 10px 14px 14px;
  overflow-x: auto;
  color: color-mix(in srgb, var(--code-ink) 55%, transparent);
  font-size: 12px;
}

/* 图的配色由服务端换成主题变量（09-22），底是透明的，卡片自己的底透上来——
   所以这里不再衬白。
   限高：聊天流里一张几千像素高的图会把整段对话挤没，而这里**点一下就能在
   灯箱里看原图**（终端那边没有灯箱，所以那边反过来不限高）。SVG 是矢量，
   缩着看不掉精度。 */
.mermaid-figure svg {
  max-width: 100%;
  max-height: min(60vh, 520px);
  height: auto;
  border-radius: calc(var(--radius) - 4px);
}

.mermaid-figure.is-zoomable {
  cursor: zoom-in;
}

.mermaid-figure.is-zoomable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* 折在卡片里的源码块：外层已经有底色和圆角了，别再套一层。 */
.mermaid-block .mermaid-source {
  margin: 0;
  border-radius: 0;
}

.mermaid-block .mermaid-source .code-toolbar {
  display: none;
}

/* 「源码」开关 + 复制按钮成一组靠右。 */
.mermaid-actions {
  display: flex;
  align-items: center;
  gap: 2px;
}

/* 文字按钮：`.code-copy-button` 那套是 25×23 的图标格子，中文会被挤断行。 */
.mermaid-source-toggle {
  height: 23px;
  padding: 0 8px;
  border-radius: var(--radius);
  background: transparent;
  color: color-mix(in srgb, var(--code-ink) 60%, transparent);
  font-family: inherit;
  font-size: inherit;
  letter-spacing: inherit;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.mermaid-source-toggle:hover,
.mermaid-source-toggle.is-active {
  background: color-mix(in srgb, var(--code-ink) 12%, transparent);
  color: var(--code-ink);
}

.code-toolbar {
  display: flex;
  min-height: 30px;
  align-items: center;
  justify-content: space-between;
  padding: 3px 6px 0 14px;
  color: color-mix(in srgb, var(--code-ink) 50%, transparent);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

.code-copy-button {
  color: color-mix(in srgb, var(--code-ink) 60%, transparent);
}

.code-copy-button:hover {
  background: color-mix(in srgb, var(--code-ink) 12%, transparent);
  color: var(--code-ink);
}

.code-block pre {
  max-height: 420px;
  margin: 0;
  padding: 4px 16px 13px;
  overflow: auto;
  color: var(--code-ink);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.7;
  tab-size: 2;
}

.code-block code {
  white-space: pre;
}

/* 代码语法色。类名由 highlight.js 从 Prism 的 token 类型映射过来,九个角色:
   c 注释 / p 标点 / o 运算符 / k 关键字 / s 字符串 / n 数值 / f 函数 /
   t 类型标签 / y 属性变量,外加 diff 的增删行与 markdown 的粗斜体。 */
.tok-c {
  color: var(--tok-c);
  font-style: italic;
}

.tok-p {
  color: var(--tok-p);
}

.tok-o {
  color: var(--tok-o);
}

.tok-k {
  color: var(--tok-k);
}

.tok-s {
  color: var(--tok-s);
}

.tok-n {
  color: var(--tok-n);
}

.tok-f {
  color: var(--tok-f);
}

.tok-t {
  color: var(--tok-t);
}

.tok-y {
  color: var(--tok-y);
}

.tok-b {
  font-weight: 650;
}

.tok-i {
  font-style: italic;
}

/* diff 的增删行:颜色之外再垫一层极淡的底,整行扫过去比只认颜色快。 */
.tok-ins {
  background: color-mix(in srgb, var(--tok-s) 15%, transparent);
  color: var(--tok-s);
}

/* 删除行用红,不是关键字那个紫——补丁里紫色的「删掉」没人认得。 */
.tok-del {
  background: color-mix(in srgb, var(--tok-y) 15%, transparent);
  color: var(--tok-y);
}

/* 文件编辑工具(edit/kb/artifact)的 diff(web/diff.js):把 patchText 画成分文件、
   带增删配色的 diff。极简、无描边——只靠一行标题 + 改动行的整行底色区分,和过程
   时间线那套克制观感一致。增删色不沿用代码高亮那套(在暖米底上发闷),另起一套
   更干净的绿/红,两个主题各调一档。 */
:root {
  --diff-add: #1a7f37;
  --diff-del: #cf222e;
}
body[data-theme="graphite"] {
  --diff-add: #3fb950;
  --diff-del: #f85149;
}
.diff-view {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-width: 0;
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: var(--fs-micro);
}
.diff-file {
  min-width: 0;
  /* 不要描边(用户 #156):改用柔和阴影 + 一层浅表面把 diff 抬成一张卡。
     阴影收到 --bubble-shadow 那档(0 1px 4px,随主题),artifact 那档太散(用户嫌大)。 */
  background: var(--surface-1);
  border-radius: var(--radius);
  box-shadow: var(--bubble-shadow);
  overflow: hidden;
}
.diff-file-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 12px 7px;
}
.diff-op {
  flex: none;
  font-weight: 600;
  color: var(--text-soft);
}
.diff-file.is-add .diff-op { color: var(--diff-add); }
.diff-file.is-delete .diff-op { color: var(--diff-del); }
.diff-ns {
  flex: none;
  font-size: 10px;
  padding: 0 5px;
  border-radius: 4px;
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
}
.diff-path {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.diff-stat {
  flex: none;
  display: flex;
  gap: 8px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.diff-stat-add { color: var(--diff-add); }
.diff-stat-del { color: var(--diff-del); }
.diff-lines {
  margin: 0;
  max-height: 320px;
  overflow: hidden auto;
  overscroll-behavior: contain;
  line-height: 1.6;
  padding-bottom: 4px;
}
.diff-hunk {
  padding: 3px 12px;
  color: var(--text-faint);
  white-space: pre-wrap;
  word-break: break-word;
}
.diff-line {
  display: flex;
  white-space: pre-wrap;
  word-break: break-word;
}
.diff-gutter {
  flex: none;
  width: 1.9em;
  text-align: center;
  user-select: none;
  opacity: 0.65;
}
.diff-text {
  flex: 1 1 auto;
  min-width: 0;
  padding-right: 12px;
}
.diff-line.is-ctx .diff-text { color: var(--text-soft); }
.diff-line.is-add {
  background: color-mix(in srgb, var(--diff-add) 13%, transparent);
}
.diff-line.is-add .diff-gutter { color: var(--diff-add); opacity: 1; }
.diff-line.is-del {
  background: color-mix(in srgb, var(--diff-del) 12%, transparent);
}
.diff-line.is-del .diff-gutter { color: var(--diff-del); opacity: 1; }

/* 思考签:气泡内小签,常驻极浅紫底;直播时换 live 底 + 标题流光 */
.reasoning-block {
  min-width: 0;
  border-left: 0;
}

.reasoning-block summary {
  display: flex;
  width: fit-content;
  max-width: 100%;
  align-items: center;
  /* 标题不再可压缩,极端长度只能靠芯片自己裁边——正好裁在圆角上。 */
  overflow: hidden;
  padding: 4px 11px;
  border-radius: var(--radius);
  background: var(--chip-think);
  color: var(--text);
  cursor: pointer;
  gap: 7px;
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.5;
  list-style: none;
  user-select: none;
  transition: background-color 180ms ease;
}

.reasoning-block summary::-webkit-details-marker {
  display: none;
}

.reasoning-block summary:hover {
  background: var(--chip-live);
}

.reasoning-block summary .reasoning-icon {
  width: 13px;
  height: 13px;
  color: var(--accent);
}

/* 直播态字形位:迷你三点弹跳(4px,金 / accent / ribbon);完成后回到静态 ◈ */
.reasoning-icon i {
  display: none;
}

.reasoning-block.is-live summary .reasoning-icon {
  display: inline-flex;
  width: auto;
  height: 13px;
  align-items: center;
  gap: 3px;
}

.reasoning-block.is-live summary .reasoning-icon svg {
  display: none;
}

.reasoning-block.is-live summary .reasoning-icon i {
  display: block;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  animation: typing-bounce 1.2s ease-in-out infinite;
}

.reasoning-block.is-live summary .reasoning-icon i:nth-of-type(1) {
  background: var(--gold);
}

.reasoning-block.is-live summary .reasoning-icon i:nth-of-type(2) {
  background: var(--accent);
  animation-delay: 0.15s;
}

.reasoning-block.is-live summary .reasoning-icon i:nth-of-type(3) {
  background: var(--ribbon);
  animation-delay: 0.3s;
}

@media (prefers-reduced-motion: reduce) {
  .reasoning-block.is-live summary .reasoning-icon {
    display: inline-grid;
    width: 13px;
    gap: 0;
  }

  .reasoning-block.is-live summary .reasoning-icon svg {
    display: block;
  }

  .reasoning-block.is-live summary .reasoning-icon i {
    display: none;
  }
}

.reasoning-block summary .reasoning-chevron {
  width: 11px;
  height: 11px;
  opacity: 0.7;
  transition: transform 160ms ease;
}

.reasoning-live-status {
  flex: 0 0 auto;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  font-weight: 400;
  white-space: nowrap;
}

.reasoning-progress {
  display: none;
}

.reasoning-block.is-live summary {
  background: var(--chip-live);
}

.reasoning-block.is-live .reasoning-title {
  animation: shimmer 1.6s linear infinite;
  background: linear-gradient(90deg, var(--text) 30%, var(--accent) 50%, var(--text) 70%);
  background-size: 200% 100%;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

@keyframes shimmer {
  to {
    background-position: -200% 0;
  }
}

.reasoning-block[open] summary .reasoning-chevron {
  transform: rotate(90deg);
}

/* 这一段**不参与压缩**(`flex: 0 0 auto`)。
   上一版给它 `flex: 0 1 auto` + `overflow: hidden`,结果 09-09 用户实拍到
   「已思考」被压成「已…」——`overflow: hidden` 会把 flex 子项的自动最小尺寸压
   成 0,一旦哪层祖先按 min-content 定宽,这段文字就先被牺牲掉。我在无头环境
   里没能复现那个具体条件,所以不去猜是哪一层,直接断掉「可以被压缩」这件事:
   长度改由 max-width 封顶、由芯片自己裁边,不再依赖任何容器的宽度算法。 */
.reasoning-title {
  flex: 0 0 auto;
  max-width: 24em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tool-preparing-tag {
  display: inline-flex;
  width: fit-content;
  max-width: 100%;
  align-items: center;
  gap: 7px;
  padding: 4px 11px;
  border-radius: var(--radius);
  background: var(--chip-live);
  color: var(--text);
  font-size: 11.5px;
  font-weight: 600;
  line-height: 1.5;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tool-preparing-tag .icon-slot {
  width: 13px;
  height: 13px;
  flex: 0 0 13px;
  color: var(--accent);
}

.tool-preparing-tag .is-spinning svg {
  animation: spin 900ms linear infinite;
}

/* 展开:浅紫底面板 */
.reasoning-text {
  margin: 6px 0 2px;
  padding: 8px 12px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent-soft) 38%, transparent);
  color: var(--text-soft);
  font-size: var(--fs-meta);
  line-height: 1.75;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.conversation-media {
  display: grid;
  width: fit-content;
  max-width: min(100%, 250px);
  margin: 3px 0 18px;
  gap: 7px;
}

.conversation-media-visual {
  position: relative;
  display: grid;
  width: fit-content;
  max-width: min(100%, 250px);
  min-height: 0;
  place-items: center;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-soft);
}

.conversation-media img {
  display: block;
  width: auto;
  max-width: min(100%, 250px);
  height: auto;
  max-height: 250px;
  object-fit: contain;
}

.conversation-media-fallback {
  display: grid;
  min-height: 120px;
  place-items: center;
  padding: 18px;
  color: var(--text-faint);
  font-size: 12px;
  gap: 7px;
  text-align: center;
}

.conversation-media-fallback .icon-slot {
  width: 22px;
  height: 22px;
  color: var(--accent);
}

/* 图片是入口:点开灯箱。原先那三个按钮铺在图下面一行,现在跟着浮层走。 */
.conversation-media-visual.is-zoomable {
  cursor: zoom-in;
}

.conversation-media-visual.is-zoomable::after {
  position: absolute;
  border-radius: inherit;
  content: "";
  inset: 0;
  opacity: 0;
  pointer-events: none;
  transition: opacity 120ms ease;
  background: rgb(0 0 0 / 18%);
}

.conversation-media-visual.is-zoomable:hover::after {
  opacity: 1;
}

.conversation-media-visual.is-zoomable:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.lightbox {
  position: fixed;
  z-index: 90;
  display: grid;
  align-items: center;
  justify-items: center;
  padding: clamp(16px, 4vw, 48px);
  inset: 0;
  opacity: 0;
  transition: opacity 140ms ease;
}

.lightbox.is-open {
  opacity: 1;
}

.lightbox-scrim {
  position: absolute;
  border: 0;
  cursor: zoom-out;
  inset: 0;
  background: rgb(0 0 0 / 68%);
  backdrop-filter: blur(3px);
}

.lightbox-frame {
  position: relative;
  display: grid;
  max-width: 100%;
  max-height: 100%;
  justify-items: center;
  gap: 10px;
  transform: scale(0.97);
  transition: transform 140ms ease;
}

.lightbox.is-open .lightbox-frame {
  transform: scale(1);
}

.lightbox-image {
  display: block;
  max-width: 100%;
  max-height: calc(100dvh - clamp(96px, 12vw, 160px));
  border-radius: var(--radius);
  object-fit: contain;
  box-shadow: 0 18px 48px rgb(0 0 0 / 45%);
}

.lightbox-bar {
  display: flex;
  max-width: 100%;
  align-items: center;
  padding: 5px 6px 5px 12px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  gap: 4px;
  background: var(--surface-1);
  box-shadow: var(--artifact-shadow);
}

/* ── 正文链接卡片 ───────────────────────────────────────────────
   独占一行的链接升级成的卡片。宽度封在 520px:再宽在窄侧栏里会撑破气泡,
   再窄图就没意义了。抓不到元数据时这些规则一条都不生效,正文保持原样。 */
p.has-link-card {
  margin: 10px 0;
}

.link-card {
  display: block;
  max-width: 520px;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: inherit;
  text-decoration: none;
  transition: border-color 160ms ease, background-color 160ms ease, transform 160ms ease;
}

.link-card:hover,
.link-card:focus-visible {
  border-color: color-mix(in srgb, var(--accent) 50%, var(--line));
  background: color-mix(in srgb, var(--accent) 7%, var(--surface-2));
  transform: translateY(-1px);
}

.link-card-media {
  display: block;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  background: var(--surface-3, var(--surface-1));
  aspect-ratio: 1.91 / 1;
}

.link-card-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.link-card-body {
  display: grid;
  padding: 11px 13px 10px;
  gap: 5px;
}

.link-card-head {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 7px;
}

.link-card-icon {
  display: grid;
  width: 16px;
  height: 16px;
  flex: 0 0 auto;
  border-radius: var(--radius);
  object-fit: contain;
}

.link-card-icon.is-letter {
  place-items: center;
  background: color-mix(in srgb, var(--accent) 20%, transparent);
  color: var(--accent);
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
}

.link-card-title {
  display: -webkit-box;
  overflow: hidden;
  font-size: 13.5px;
  font-weight: 650;
  line-height: 1.4;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.link-card-desc {
  display: -webkit-box;
  overflow: hidden;
  margin: 0;
  color: var(--text-soft);
  font-size: 12px;
  line-height: 1.55;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.link-card-foot {
  display: flex;
  align-items: center;
  margin-top: 1px;
  gap: 6px;
}

.link-card-site {
  overflow: hidden;
  flex: 1 1 auto;
  color: var(--text-faint);
  font-size: 11.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.link-card-arrow {
  width: 12px;
  height: 12px;
  flex: 0 0 auto;
  color: var(--text-faint);
}

@media (max-width: 836px) {
  .link-card {
    max-width: 100%;
  }
}

/* 自动成链的裸地址会很长,别把气泡撑破。 */
.markdown-body a.auto-link {
  overflow-wrap: anywhere;
}

/* ── 附件预览浮层 ───────────────────────────────────────────────
   自己发出去的附件点开后看内容。和 .lightbox 同一套遮罩语言,但内容区是
   一块可滚动的面板而不是一张图。 */
.attachment-preview {
  position: fixed;
  z-index: 90;
  display: grid;
  align-items: center;
  justify-items: center;
  padding: clamp(16px, 4vw, 48px);
  inset: 0;
  opacity: 0;
  transition: opacity 140ms ease;
}

.attachment-preview.is-open {
  opacity: 1;
}

.attachment-preview-scrim {
  position: absolute;
  border: 0;
  cursor: zoom-out;
  inset: 0;
  background: rgb(0 0 0 / 68%);
  backdrop-filter: blur(3px);
}

.attachment-preview-frame {
  position: relative;
  display: grid;
  width: min(920px, 100%);
  max-height: 100%;
  grid-template-rows: auto minmax(0, 1fr);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--artifact-shadow);
  transform: scale(0.97);
  transition: transform 140ms ease;
}

.attachment-preview.is-open .attachment-preview-frame {
  transform: scale(1);
}

.attachment-preview-bar {
  display: flex;
  align-items: center;
  padding: 6px 8px 6px 14px;
  border-bottom: 1px solid var(--line);
  gap: 4px;
}

.attachment-preview-title {
  display: flex;
  min-width: 0;
  flex: 1 1 auto;
  align-items: baseline;
  overflow: hidden;
  gap: 8px;
}

.attachment-preview-title strong {
  overflow: hidden;
  font-size: 13px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-preview-title small {
  flex: 0 0 auto;
  color: var(--text-soft);
  font-size: 11px;
}

.attachment-preview-body {
  overflow: auto;
  min-height: 0;
  padding: 14px 16px;
}

.attachment-preview-text {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

.attachment-preview-video {
  display: block;
  width: 100%;
  max-height: min(72dvh, 900px);
  border-radius: var(--radius);
  background: #000;
}

.attachment-preview-audio {
  display: block;
  width: 100%;
}

.attachment-preview-pdf {
  display: block;
  width: 100%;
  height: min(72dvh, 900px);
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
}

.attachment-preview-note {
  margin: 10px 0 0;
  color: var(--text-soft);
  font-size: 12px;
}

.attachment-preview-body > .attachment-preview-note:only-child {
  margin: 0;
}

body.has-attachment-preview {
  overflow: hidden;
}

.lightbox-caption {
  overflow: hidden;
  max-width: min(46vw, 420px);
  margin-right: 6px;
  color: var(--text-soft);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.lightbox-caption:empty {
  display: none;
}

.lightbox-action,
.preview-action {
  display: grid;
  width: 30px;
  height: 30px;
  place-items: center;
  border-radius: var(--radius);
  color: var(--text-faint);
}

.lightbox-action:hover,
.preview-action:hover {
  background: var(--surface-2);
  color: var(--text);
}

.lightbox-action .icon-slot,
.preview-action .icon-slot {
  width: 15px;
  height: 15px;
}

body.has-lightbox {
  overflow: hidden;
}

/* 常驻任务面板。
   正文固定 980px 居中,宽屏两侧本来就空着一大片。默认不显示——窄屏它会盖住
   正文;`.is-wide` 由 app.js 按 `.main-stage` 的实际宽度挂上,这样预览工作区
   展开、侧栏收起都能自动跟上。这里不用容器查询:容器查询容器会让 WebKit 在
   后代被 replaceChildren 时归零 scrollTop(见 .main-stage 的注释)。 */
.stage-todos {
  position: absolute;
  z-index: 6;
  /* 贴着正文左缘往左排,而不是贴侧栏——正文固定 980px 居中,`right` 从
     stage 中线量出去正好落在正文左边,面板跟着正文走而不是跟着窗口走。 */
  top: 46px;
  right: calc(50% + 490px + 24px);
  display: none;
  width: 250px;
  max-height: calc(100% - 210px);
  overflow-y: auto;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

/* artifact 分栏后正文缩到左半,而下面的 `right` 仍从整个舞台的中线量,面板会
   落到正文头上;容器(主舞台)也没变窄,容器查询不会把它收掉。所以直接不让它
   在 artifact 打开时显示。这条 `:not(.artifact-open)` 必须写进**显示**规则本身:
   原来另写一条 `.main-stage.artifact-open .stage-todos{display:none}` 想盖掉它,
   但显示规则带 `:not([hidden])` 特异度(0,4,0)高于那条(0,3,0),隐藏规则打不过,
   浮层照样冒出来盖住对话(09-11 实测)。气泡里那份任务列表仍在。 */
.main-stage.is-wide:not(.artifact-open) .stage-todos:not([hidden]) {
  display: block;
}

/* 侧边这份去框：它悬在留白里,描边和底色反而显得突兀,也和正文抢注意力。
   气泡里那份仍是卡片——那个嵌在一段对话中间,需要边界把自己划出来。 */
.stage-todos .todo-panel {
  margin-top: 0;
  padding: 0;
  border: 0;
  background: transparent;
}

.stage-todos .todo-panel-head strong {
  color: var(--text-soft);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.stage-todos .todo-progress {
  margin-bottom: 14px;
  background: color-mix(in srgb, var(--line) 60%, transparent);
}

/* 左侧一条竖线把这几行归拢成一组,代替原来的方框。 */
.stage-todos .todo-list {
  padding-left: 13px;
  border-left: 1px solid var(--line);
  gap: 9px;
}

.stage-todos .todo-text {
  font-size: 12px;
}

/* 任务列表:AI 列的待办是给人看的产出,所以挂在工具签外面,收起态也可见。
   状态一律靠左边那个标记表达,不写字——每行挂个「待办」是纯噪点。 */
.todo-panel {
  margin-top: 5px;
  padding: 12px 14px 13px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}

.todo-panel-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
  gap: 8px;
}

.todo-panel-head strong {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.01em;
}

.todo-panel-head small {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10px;
  font-variant-numeric: tabular-nums;
}

.todo-progress {
  overflow: hidden;
  height: 3px;
  margin-bottom: 11px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
}

.todo-progress > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: color-mix(in srgb, var(--text-soft) 55%, transparent);
  transition: width 240ms ease;
}

.todo-list {
  display: grid;
  margin: 0;
  padding: 0;
  gap: 7px;
  list-style: none;
}

.todo-item {
  display: grid;
  grid-template-columns: 13px minmax(0, 1fr) auto;
  align-items: start;
  font-size: 12.5px;
  gap: 9px;
  line-height: 1.45;
}

.todo-mark {
  position: relative;
  width: 11px;
  height: 11px;
  margin-top: 3px;
  border: 1.5px solid var(--line-strong);
  border-radius: 50%;
}

.todo-text {
  min-width: 0;
  color: var(--text-soft);
  overflow-wrap: anywhere;
}

/* 右侧状态字。跟着所在行的那档灰走,不自己上色——一张表里已完成的往往最多,
   给它一块彩色就成了主角,而它恰恰最不需要注意。 */
.todo-status {
  align-self: center;
  color: var(--text-faint);
  font-size: 9.5px;
  white-space: nowrap;
}

.todo-item.is-in_progress .todo-status {
  color: var(--text-soft);
}

/* 整张表不上色。三种状态靠标记的形状分:空心圈、实心圆、圈里一个对勾;
   轻重靠文字的明暗分。加颜色只会让「已完成」这种最不需要注意的行反而最亮。 */
.todo-item.is-in_progress .todo-mark {
  border-color: var(--text-soft);
  background: var(--text-soft);
}

/* 三档灰阶:待办 --text-soft、进行中 --text、已完成 --text-faint+划掉。
   进行中只靠「最深的那一档灰」站出来,不再加粗到 600——那和实心黑点是同一个
   毛病,一行里两处都在使劲。 */
.todo-item.is-in_progress .todo-text {
  color: var(--text);
  font-weight: 500;
}

/* 已完成:空心圈里一个淡对勾。实心色块太抢——一张表里完成的往往最多,
   全都点亮就成了主角,而它们恰恰是最不需要注意的。 */
.todo-item.is-completed .todo-mark {
  border-color: color-mix(in srgb, var(--line-strong) 70%, transparent);
  background: transparent;
}

.todo-item.is-completed .todo-mark::after {
  position: absolute;
  top: 0.5px;
  left: 2.5px;
  width: 3px;
  height: 6px;
  border: solid var(--text-faint);
  border-width: 0 1.5px 1.5px 0;
  content: "";
  transform: rotate(42deg);
}

.todo-item.is-completed .todo-text {
  color: var(--text-faint);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--text-faint) 55%, transparent);
}

.todo-item.is-cancelled .todo-mark {
  border-style: dashed;
}

.todo-item.is-cancelled .todo-text {
  color: var(--text-faint);
  text-decoration: line-through;
  opacity: 0.7;
}

/* 工具签:气泡内小签。身份用字形色(⚙/$ 金),底色只表状态——
   运行中浅紫(默认态)、成功中性、失败浅红。 */
.tool-card {
  min-width: 0;
  max-width: 100%;
  border: 0;
  border-radius: 0;
  background: none;
}

.tool-card.is-command {
  --command-preview-bg: color-mix(in srgb, var(--gold-soft) 62%, transparent);
  --command-preview-ink: var(--md-sys-color-on-secondary-container);
  --command-preview-accent: var(--gold);
  width: fit-content;
}

body[data-color-scheme="matugen"] .tool-card.is-command {
  --command-preview-bg: color-mix(in srgb, var(--md-sys-color-tertiary-container) 70%, var(--surface-1));
  --command-preview-ink: var(--md-sys-color-on-tertiary-container);
  --command-preview-accent: var(--md-sys-color-tertiary);
}

.tool-head {
  display: flex;
  width: fit-content;
  max-width: 100%;
  min-height: 0;
  align-items: center;
  padding: 4px 9px;
  border-radius: var(--radius);
  background: var(--chip-live);
  color: var(--text);
  cursor: pointer;
  gap: 5px;
  font-size: 11.5px;
  font-weight: 600;
  text-align: left;
  transition: background-color 180ms ease;
}

.is-success .tool-head {
  background: var(--chip-neutral);
}

.is-success .tool-head:hover {
  background: var(--surface-2);
}

.is-failure .tool-head {
  background: var(--chip-fail);
}

.tool-card.is-command .tool-head {
  background: var(--command-preview-bg);
  color: var(--command-preview-ink);
}

.tool-card.is-command.is-failure .tool-head {
  background: var(--chip-fail);
  color: var(--md-sys-color-on-error-container);
}

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

.tool-icon .icon-slot {
  width: 13px;
  height: 13px;
}

.is-success .tool-icon {
  color: var(--gold);
}

.is-failure .tool-icon {
  color: var(--danger);
}

.tool-card.is-command .tool-icon {
  color: var(--command-preview-accent);
}

.tool-card.is-command.is-failure .tool-icon {
  color: var(--danger);
}

/* 芯片被压窄时,标题这层必须自己截断:没有 overflow 的话
   flex 只是把这个盒子挤小,里面的粗体名照样画到圆角背景外面去。 */
.tool-title {
  display: flex;
  min-width: 0;
  flex: 0 1 auto;
  overflow: hidden;
  align-items: baseline;
  gap: 6px;
}

.tool-title strong,
.tool-title small {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.tool-title strong {
  /* 工具名优先完整显示、不被主语挤没(#110):不缩(flex 0 0),靠下面的主语先让位
     腾空间。不再封 62%——那会在窄面板里把「后台任务」截成「后」(#123);极长的
     load_tools 名超出时由 .tool-title 的 overflow 兜底裁掉,不会画到圆角外。 */
  flex: 0 0 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: 11.5px;
  font-weight: 600;
}

.tool-title .tool-technical-name {
  display: none;
}

/* 参数 / 命令外显:等宽小字,填名字右边余下空间,先于名字让位、超长省略号(不加淡出
   遮罩——那会把还没溢出的主语文字也虚掉,读不清 #121)。 */
.tool-title .tool-summary {
  flex: 1 1 0;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-soft);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 400;
}

.tool-status {
  display: inline-flex;
  min-width: 0;
  align-items: center;
  color: var(--accent);
  font-size: 10.5px;
  gap: 4px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* 状态只留字形:✓ / ✕ / 转圈 */
.tool-status > span:not(.icon-slot) {
  display: none;
}

.is-success .tool-status {
  color: var(--online);
}

.is-failure .tool-status {
  color: var(--danger);
}

.tool-status .icon-slot {
  width: 12px;
  height: 12px;
}

.tool-chevron {
  width: 11px;
  height: 11px;
  flex: 0 0 11px;
  color: var(--text-soft);
  opacity: 0.7;
  transition: transform 160ms ease;
}

.tool-status .is-spinning svg {
  animation: spin 900ms linear infinite;
}

.tool-card.collapsed .tool-chevron {
  transform: rotate(-90deg);
}

.tool-card.collapsed .tool-body {
  display: none;
}

.tool-card.is-command:not(.collapsed) .tool-command-preview,
.tool-card.is-command:not(.collapsed) .tool-command-output-preview {
  display: none;
}

.tool-artifact-preview {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) 14px;
  width: fit-content;
  max-width: 100%;
  min-height: 34px;
  align-items: center;
  margin-top: 6px;
  padding: 5px 9px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-soft);
  cursor: pointer;
  font-size: 11px;
  gap: 7px;
}

.tool-artifact-preview:hover {
  background: var(--surface-3);
  color: var(--text);
}

.tool-artifact-preview .icon-slot {
  width: 14px;
  height: 14px;
  color: var(--accent);
}

.tool-artifact-preview .icon-slot:last-child {
  color: var(--text-faint);
}

.tool-artifact-preview > span:not(.icon-slot) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 收起时展示命令与最近输出；展开后由完整详情替代这两个预览。 */
/* 命令本身：抬头底下按行排开，缩进到文字列，时间线那根竖线从左边穿过。
   不再是一块粉底圆角框——那是 09-10 时间线重做之前的形态，重做时整个关掉了
   （只在抬头里留一截命令窥视）；现在抬头右边改放 short_title，命令回到下面，
   形状对齐 TUI 的 `│ <命令的一行>`。行数跟 `display.command_output_lines`。 */
.tool-command-preview {
  display: flex;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  flex-direction: column;
  margin: 0 0 4px var(--proc-indent, 0);
  padding: 0;
  border: 0;
  background: none;
  max-height: calc(var(--command-rows, 8) * 1.7em);
  overflow: hidden;
  color: var(--proc-soft, var(--text-soft));
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.7;
  tab-size: 2;
}

/* `⋮` 挂在裁剪容器**外面**，不然它自己也会被裁掉。 */
.tool-command-more {
  display: block;
  margin: 0 0 4px var(--proc-indent, 0);
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.7;
  letter-spacing: 0.1em;
}

/* 命令行**软换行**：一条很长的单行命令该把配置给的那几行空间用满，而不是
   截成一行加省略号（用户 09-20）。行数的账因此按「屏幕上占几行」算，不按
   「命令有几行」算——容器按 `--command-rows` 卡高度，超出的裁掉、底下给 `⋮`。 */
.tool-command-line,
.tool-command-omitted {
  display: block;
  min-width: 0;
  max-width: 100%;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
}

.tool-command-omitted {
  color: var(--text-faint);
  letter-spacing: 0.1em;
}

/* 抬头里的读秒：工具名和 short_title 之间。 */
.tool-command-seconds {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.tool-command-output-preview {
  display: inline-grid;
  width: fit-content;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  margin-top: 6px;
  padding: 8px 12px;
  max-height: min(calc(var(--command-output-lines, 8) * 1.6em + 16px), 34.5455dvh);
  overflow-x: hidden;
  overflow-y: auto;
  border-left: 2px solid var(--command-preview-accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: color-mix(in srgb, var(--command-preview-bg) 58%, var(--surface-1));
  color: var(--text-soft);
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.6;
}

.tool-command-output-line,
.tool-command-output-omitted {
  display: block;
  min-width: 0;
  max-width: 100%;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  word-break: break-word;
}

.tool-command-output-line.is-stderr {
  color: var(--danger);
}

.tool-command-output-omitted {
  color: var(--text-faint);
}

/* 子代理(task)签:标题行只留 字形 + task:标题 + 状态 */
/* 子代理行显示任务标题(#2:子代理 · title),用「·」和「子代理」隔开、常规字体不用等宽。 */
.tool-card.is-task .tool-title .tool-summary {
  display: inline;
  font-family: inherit;
  color: var(--text-soft);
}
.tool-card.is-task .tool-title .tool-summary::before {
  content: "· ";
  color: var(--text-faint);
}
.tool-card.is-task .tool-title .tool-summary:empty {
  display: none;
}
.tool-card.is-task .tool-title .tool-summary:empty::before {
  content: "";
}

/* 子代理实时进度面板:签正下方常驻(收起态也可见),tool.progress 原地刷新;
   完成后隐藏(完整信息进展开详情),失败保留最后状态并红字 */
/* 单行起步,内容长了自动换行撑开 */
.tool-live-progress {
  max-width: 640px;
  width: fit-content;
  margin-top: 6px;
  padding: 8px 12px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-2) 70%, transparent);
  color: var(--text-soft);
  font-family: var(--font-mono);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  line-height: 1.6;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

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

/* 展开:浅底面板;各小节 pre/正文各自坐进更深一档的色块,滚动边界一眼可辨 */
.tool-body {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  width: 100%;
  min-width: 0;
  max-width: 100%;
  margin-top: 6px;
  padding: 10px 12px;
  overflow: hidden;
  border: 0;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-2) 70%, transparent);
  gap: 9px;
}

.tool-detail {
  min-width: 0;
  max-width: 100%;
}

.tool-detail[hidden] {
  display: none;
}

.tool-detail-label {
  display: block;
  margin-bottom: 4px;
  color: var(--text-faint);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.tool-detail p {
  margin: 0;
  padding: 8px 10px;
  border-radius: var(--radius);
  /* 展开详情面板统一用柔和暖色(用户 #82/#83:原来 code-bg 亮色下太白) */
  background: color-mix(in srgb, var(--text) 5%, transparent);
  color: var(--text-soft);
  font-size: 11.5px;
  line-height: 1.6;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
}

.tool-detail pre {
  width: 100%;
  max-width: 100%;
  max-height: 300px;
  margin: 0;
  padding: 9px 10px;
  overflow: auto;
  border: 0;
  border-radius: var(--radius);
  /* 展开详情面板统一用柔和暖色(用户 #82/#83:原来 code-bg 亮色下太白) */
  background: color-mix(in srgb, var(--text) 5%, transparent);
  color: var(--text-soft);
  font-family: var(--font-mono);
  font-size: 11.5px;
  line-height: 1.65;
  overflow-wrap: normal;
  tab-size: 2;
  white-space: pre;
}

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

.question-card,
.answered-question-card {
  min-width: 0;
  overflow: hidden;
  border: 0;
  border-left: 3px solid var(--gold);
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
}

.persisted-question-wrap {
  margin: -7px 0 28px;
  padding-left: 40px;
}

.question-card.is-answered,
.answered-question-card {
  border-left-color: var(--accent);
}

.question-card.is-error {
  border-left-color: var(--danger);
}

.question-card > header,
.answered-question-card > header {
  display: flex;
  min-width: 0;
  align-items: center;
  padding: 11px 12px 9px;
  gap: 9px;
}

.question-icon {
  display: grid;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  place-items: center;
  border-radius: var(--radius);
  background: var(--gold-soft);
  color: var(--gold);
}

.is-answered .question-icon,
.answered-question-card .question-icon {
  background: var(--accent-soft);
  color: var(--accent);
}

.question-icon .icon-slot {
  width: 16px;
  height: 16px;
}

.question-card > header > div,
.answered-question-card > header > div {
  display: grid;
  min-width: 0;
  gap: 1px;
}

.question-card header small,
.answered-question-card header small {
  color: var(--gold);
  font-size: 9px;
  font-weight: 500;
}

.question-card.is-answered header small,
.answered-question-card header small {
  color: var(--accent);
}

.question-card header strong,
.answered-question-card header strong {
  font-size: 12px;
  font-weight: 600;
  overflow-wrap: anywhere;
}

.question-heading {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  min-width: 0;
  align-items: start;
  padding: 12px 16px 0 12px;
  gap: 14px;
}

.question-prompt {
  min-width: 0;
  margin: 0;
  color: var(--text);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.5;
  overflow-wrap: anywhere;
}

.question-navigation {
  display: grid;
  grid-template-columns: 26px minmax(46px, auto) 26px 30px;
  flex: 0 0 auto;
  align-items: center;
  justify-self: end;
  margin-right: 2px;
  gap: 2px;
  white-space: nowrap;
}

.question-position {
  color: var(--text-faint);
  font-size: 11px;
  line-height: 26px;
  text-align: center;
  white-space: nowrap;
}

.question-fieldset {
  position: relative;
  min-width: 0;
  margin: 0;
  padding: 9px 12px 12px;
  border: 0;
}

.question-legend {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.question-options {
  display: grid;
  margin-top: 0;
  gap: 6px;
}

.question-option {
  display: grid;
  grid-template-columns: 17px minmax(0, 1fr);
  min-width: 0;
  min-height: 40px;
  align-items: center;
  padding: 7px 9px;
  border: 0;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-2) 70%, transparent);
  color: var(--text-soft);
  cursor: pointer;
  gap: 8px;
}

.question-option:hover {
  background: var(--surface-2);
  color: var(--text);
}

.question-option.selected {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1.5px var(--accent);
  color: var(--text);
}

.question-option input {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--accent);
}

.question-option-copy {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.question-option-copy strong {
  font-size: 11px;
  font-weight: 500;
  overflow-wrap: anywhere;
}

.question-option-copy small {
  color: var(--text-faint);
  font-size: 9px;
  line-height: 1.4;
  overflow-wrap: anywhere;
}

.custom-answer {
  display: grid;
  grid-template-columns: 17px minmax(0, 1fr) auto;
  align-items: start;
  margin-top: 6px;
  padding: 8px 9px;
  border: 0;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-2) 70%, transparent);
  gap: 8px;
}

.custom-answer.selected {
  background: var(--accent-soft);
  box-shadow: inset 0 0 0 1.5px var(--accent);
}

.custom-answer > input {
  width: 15px;
  height: 15px;
  margin: 7px 0 0;
  accent-color: var(--accent);
}

.custom-answer textarea {
  width: 100%;
  min-height: 34px;
  max-height: 110px;
  resize: vertical;
  padding: 7px 8px;
  border: 0;
  border-radius: var(--radius);
  outline: 0;
  background: var(--surface-1);
  color: var(--text);
  font-size: 12px;
  line-height: 1.45;
  transition: box-shadow 180ms ease;
}

.custom-answer textarea:focus {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
}

.custom-answer-next {
  display: grid;
  width: 34px;
  height: 34px;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-3);
  color: var(--text-soft);
  cursor: pointer;
}

.custom-answer-next.is-ready {
  background: var(--accent);
  color: var(--inverse-text);
}

.custom-answer-next:hover:not(:disabled) {
  background: var(--accent-strong);
}

.custom-answer-next:disabled {
  cursor: default;
  opacity: 0.45;
}

.custom-answer-next .icon-slot {
  width: 14px;
  height: 14px;
}

.question-error {
  margin: 0;
  padding: 2px 12px 10px;
  border: 0;
  color: var(--danger);
  font-size: 10px;
  overflow-wrap: anywhere;
}

.question-page-button {
  display: grid;
  width: 26px;
  height: 26px;
  flex: 0 0 26px;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
}

.question-page-button:hover:not(:disabled) {
  color: var(--text);
  filter: brightness(1.05);
}

.question-page-button:hover:not(:disabled):not(.is-ready) {
  background: var(--surface-2);
}

.question-page-button:disabled {
  color: var(--text-faint);
  cursor: default;
  opacity: 0.45;
}

.question-page-button.is-ready {
  background: var(--accent);
  color: var(--inverse-text);
}

.question-page-button.is-previous .icon-slot {
  transform: rotate(180deg);
}

.question-page-button .icon-slot {
  width: 14px;
  height: 14px;
}

.question-submit {
  padding: 0;
}

.question-close-button {
  justify-self: end;
  color: var(--text-faint);
}

.question-close-button:hover:not(:disabled) {
  background: var(--danger-soft);
  color: var(--danger);
}

.question-card.is-answered .question-form {
  display: none;
}

.question-answer-summary,
.answered-question-list {
  display: grid;
  margin: 0;
  /* 左内边距对齐页眉文字(12px)。原来是 51px——那是给页眉左侧那枚 30px 图标
     让位的(12+30+9),而已回答卡的大对钩早已去掉(#143),列表却还缩在右边,
     和「已回答/N 项补充确认」不对齐(#166)。 */
  padding: 0 12px 11px 12px;
  gap: 7px;
}

.question-answer-summary div,
.answered-question-list div {
  display: grid;
  gap: 1px;
}

.question-answer-summary dt,
.answered-question-list dt {
  color: var(--text-faint);
  font-size: 9px;
}

.question-answer-summary dd,
.answered-question-list dd {
  margin: 0;
  color: var(--text-soft);
  font-size: 11px;
  overflow-wrap: anywhere;
}

.question-card.is-answered header small,
.answered-question-card header small {
  font-size: 11px;
}

.question-card.is-answered header strong,
.answered-question-card header strong {
  font-size: 15px;
}

.question-card.is-answered .question-answer-summary,
.answered-question-card .answered-question-list {
  gap: 10px;
  padding-bottom: 14px;
}

.question-card.is-answered .question-answer-summary dt,
.answered-question-card .answered-question-list dt {
  color: var(--text-soft);
  font-size: 13px;
  line-height: 1.5;
}

.question-card.is-answered .question-answer-summary dd,
.answered-question-card .answered-question-list dd {
  color: var(--text);
  font-size: 14px;
  line-height: 1.5;
}

.context-operation {
  display: grid;
  padding: 9px 12px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: color-mix(in srgb, var(--surface-2) 55%, transparent);
  color: var(--text-soft);
  gap: 5px;
}

.context-operation strong {
  display: flex;
  align-items: center;
  color: var(--accent);
  font-size: 10.5px;
  font-weight: 500;
  gap: 6px;
}

.context-operation.is-error {
  border-left-color: var(--danger);
}

.context-operation.is-error strong {
  color: var(--danger);
}

.context-operation .icon-slot {
  width: 13px;
  height: 13px;
}

.context-operation pre {
  max-height: 150px;
  margin: 0;
  overflow: auto;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  line-height: 1.55;
  white-space: pre-wrap;
}

.run-notice {
  display: flex;
  min-height: 34px;
  align-items: center;
  padding: 7px 11px;
  border-left: 3px solid var(--gold);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: color-mix(in srgb, var(--surface-2) 55%, transparent);
  color: var(--gold);
  font-size: 11px;
  line-height: 1.45;
  overflow-wrap: anywhere;
  gap: 7px;
}

.run-notice.is-error {
  border-left-color: var(--danger);
}

/* 多行报错：换行要留着（一句结论 + 每个端点一行 + 一句该怎么办），图标顶对齐。 */
.run-notice.is-multiline {
  align-items: flex-start;
  white-space: pre-wrap;
}

.run-notice.is-multiline .icon-slot {
  margin-top: 2px;
}

.run-notice .icon-slot {
  width: 14px;
  height: 14px;
}

.loading-state,
.blocked-state,
.empty-state {
  width: min(100%, 760px);
  min-height: 100%;
  align-content: center;
  justify-items: center;
  margin: 0 auto;
  text-align: center;
}

.loading-state {
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 11px;
  gap: 9px;
}

/* 打字 / 载入指示:三点弹跳(金 / accent / ribbon) */
.loading-mark {
  position: relative;
  width: 7px;
  height: 7px;
  margin: 0 14px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  animation: typing-bounce 1.2s ease-in-out 0.15s infinite;
}

.loading-mark::before,
.loading-mark::after {
  position: absolute;
  top: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  content: "";
}

.loading-mark::before {
  left: -12px;
  background: var(--gold);
  animation: typing-bounce 1.2s ease-in-out infinite;
}

.loading-mark::after {
  left: 12px;
  background: var(--ribbon);
  animation: typing-bounce 1.2s ease-in-out 0.3s infinite;
}

@keyframes typing-bounce {
  0%,
  60%,
  100% {
    transform: translateY(0);
  }

  30% {
    transform: translateY(-5px);
  }
}

/* 等待回复:气泡内三点弹跳(金 / accent / ribbon) */
.typing-indicator {
  display: inline-flex;
  align-items: center;
  padding: 5px 2px 3px;
  gap: 5px;
}

.typing-indicator.is-streaming {
  padding: 4px 2px;
}

/* 输入框那排的运行指示器。原来它在气泡左下角，且只在「第一个块到达前」出现
   ——推理和工具阶段反而没有，而那两段恰恰最需要「它还在动」。现在整个回合
   期间都在，位置固定，不随气泡内容跳来跳去。 */
.typing-indicator.is-composer {
  padding: 0 2px;
  gap: 4px;
  align-self: center;
}

.typing-indicator.is-composer i {
  width: 5px;
  height: 5px;
}

.typing-indicator.is-streaming i {
  width: 5px;
  height: 5px;
}

/* AI 输出「加载中」的编排动效(输入框那份是下面 typing-indicator 的旧匀速三点,
   两套 keyframes 零交集):三颗点摆成三角,顺时针转一圈 → 聚合到中心 → 展开成三角
   → 逆时针转一圈 → 聚合 → 展开成三角,6s/圈循环。没有「水平一行」这个姿态
   (用户 09-18:水平展开也不用了,连尾段的水平弹跳一起去掉),100% 与 0% 同姿态,
   接缝无跳变。三色用 Miyu logo 三原色(发金/丝带/瞳蓝)。无光效。 */
.miyu-run {
  --mrun: 6s;
  display: inline-block;
  width: 34px;
  height: 20px;
  position: relative;
  align-self: center;
}
.miyu-run .mr-spin {
  position: absolute;
  inset: 0;
  animation: mr-spin var(--mrun) ease-in-out infinite;
}
.miyu-run i {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 6px;
  height: 6px;
  margin: -3px;
  border-radius: 50%;
}
.miyu-run .mr1 { background: var(--gold); animation: mr1 var(--mrun) ease-in-out infinite; }
.miyu-run .mr2 { background: var(--ribbon); animation: mr2 var(--mrun) ease-in-out infinite; }
.miyu-run .mr3 { background: var(--accent); animation: mr3 var(--mrun) ease-in-out infinite; }
/* 0-25% 顺时针一圈(三角展开着),25-50% 保持在 360°(聚合/展开期间不转),
   50-75% 逆时针转回 0°,75-100% 保持(聚合/展开)。 */
@keyframes mr-spin { 0%{transform:rotate(0)} 25%{transform:rotate(360deg)} 50%{transform:rotate(360deg)} 75%{transform:rotate(0)} 100%{transform:rotate(0)} }
/* 三角 TL(-8,5) TOP(0,-7) TR(8,5);聚合 中心 scale .72。
   0-25% 三角(转圈) → 37% 聚合 → 50% 三角 → 75% 三角(转圈) → 87% 聚合 → 100% 三角 */
@keyframes mr1 {
  0%,25%{transform:translate(-8px,5px)} 37%{transform:translate(0,0) scale(.72)} 50%,75%{transform:translate(-8px,5px)}
  87%{transform:translate(0,0) scale(.72)} 100%{transform:translate(-8px,5px)} }
@keyframes mr2 {
  0%,25%{transform:translate(0,-7px)} 37%{transform:translate(0,0) scale(.72)} 50%,75%{transform:translate(0,-7px)}
  87%{transform:translate(0,0) scale(.72)} 100%{transform:translate(0,-7px)} }
@keyframes mr3 {
  0%,25%{transform:translate(8px,5px)} 37%{transform:translate(0,0) scale(.72)} 50%,75%{transform:translate(8px,5px)}
  87%{transform:translate(0,0) scale(.72)} 100%{transform:translate(8px,5px)} }
@media (prefers-reduced-motion: reduce) {
  .miyu-run .mr-spin, .miyu-run i { animation-duration: 0s; }
}
/* AI 输出气泡里那份「加载中」:留一点上下留白,别贴着头像行。
   整体缩小一点(用户觉得偏大):等比缩到 0.7,左对齐锚点不动。 */
.miyu-run.typing-run { margin: 3px 0 5px 2px; transform: scale(0.7); transform-origin: left center; }

.artifact-toggle-button {
  position: relative;
}

.artifact-toggle-button.has-new-artifact::after {
  position: absolute;
  top: 6px;
  right: 6px;
  width: 6px;
  height: 6px;
  border: 1px solid var(--topbar-bg);
  border-radius: 50%;
  background: var(--accent);
  content: "";
}

.artifact-workspace {
  --artifact-bg: var(--surface-1);
  --artifact-highlight: color-mix(in srgb, var(--artifact-bg) 84%, var(--md-sys-color-surface-container-highest) 16%);
  --artifact-highlight-hover: color-mix(in srgb, var(--artifact-highlight) 84%, white 16%);
  position: absolute;
  top: 10px;
  right: 10px;
  /* 非分栏桌面浮层态:bottom 停在输入框页脚上方(高度由 app.js 量了喂进来),
     不然绝对定位的面板会盖住页脚、输入框点不到(#2)。分栏/最大化/手机三态各自
     用 position:relative 或 fixed inset 覆盖这条,不受影响。 */
  bottom: calc(var(--composer-dock-height, 96px) + 10px);
  z-index: 12;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
  width: var(--artifact-width);
  min-width: 0;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--line) 50%, transparent);
  border-radius: var(--radius);
  background: var(--artifact-bg);
  box-shadow: var(--artifact-shadow);
}

.artifact-resize-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: -6px;
  z-index: 2;
  width: 12px;
  cursor: col-resize;
  touch-action: none;
}

.artifact-header {
  display: flex;
  min-width: 0;
  min-height: 58px;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px 8px 12px;
  gap: 10px;
  background: var(--artifact-bg);
}

.artifact-leading,
.artifact-actions {
  display: flex;
  min-width: 0;
  align-items: center;
}

.artifact-leading {
  flex: 1 1 auto;
  gap: 7px;
}

.artifact-mode-switch {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  padding: 0;
  background: transparent;
  gap: 4px;
}

.artifact-mode-switch button {
  display: grid;
  width: 30px;
  height: 30px;
  place-items: center;
  border-radius: var(--radius);
  background: var(--artifact-highlight);
  color: var(--text-faint);
  cursor: pointer;
}

.artifact-mode-switch button:hover {
  background: var(--artifact-highlight-hover);
  color: var(--text);
}

.artifact-mode-switch button.active {
  background: var(--artifact-highlight-hover);
  color: var(--accent);
  box-shadow: var(--bubble-shadow);
}

.artifact-mode-switch .icon-slot {
  width: 15px;
  height: 15px;
}

.artifact-image-actions {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  gap: 4px;
}

.artifact-image-actions a,
.artifact-image-actions button {
  display: grid;
  width: 30px;
  height: 30px;
  place-items: center;
  border-radius: var(--radius);
  background: var(--artifact-highlight);
  color: var(--text-faint);
  cursor: pointer;
}

.artifact-image-actions a:hover,
.artifact-image-actions button:hover {
  background: var(--artifact-highlight-hover);
  color: var(--text);
}

.artifact-image-actions button:disabled {
  opacity: 0.45;
}

.artifact-image-actions .icon-slot {
  width: 15px;
  height: 15px;
}

.artifact-resource-wrap {
  position: relative;
  min-width: 0;
  flex: 1 1 auto;
}

.artifact-title-button {
  display: flex;
  max-width: 100%;
  min-width: 0;
  min-height: 34px;
  align-items: center;
  padding: 0 7px;
  border-radius: var(--radius);
  color: var(--text);
  cursor: pointer;
  gap: 5px;
  background: var(--artifact-highlight);
}

.artifact-title-button:hover:not(:disabled),
.artifact-title-button[aria-expanded="true"] {
  background: var(--artifact-highlight-hover);
}

.artifact-title-button:disabled {
  cursor: default;
}

.artifact-title-button strong {
  min-width: 0;
  overflow: hidden;
  font-size: 13px;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.artifact-title-button small {
  flex: 0 0 auto;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 9px;
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.artifact-title-button > .icon-slot {
  width: 12px;
  height: 12px;
  flex: 0 0 12px;
  color: var(--text-faint);
}

.artifact-title-button:disabled > .icon-slot {
  display: none;
}

.artifact-resource-menu {
  position: absolute;
  top: calc(100% + 7px);
  left: 0;
  z-index: 8;
  display: grid;
  width: min(320px, calc(calc(100vw / var(--ui-scale)) - 36px));
  max-height: min(360px, 50dvh);
  padding: 5px;
  overflow-y: auto;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--artifact-bg);
  box-shadow: var(--artifact-shadow);
}

.artifact-resource-row {
  display: flex;
  align-items: center;
  gap: 2px;
}

.artifact-resource-row > button:first-child {
  flex: 1 1 auto;
  min-width: 0;
}

.artifact-resource-menu button {
  display: grid;
  grid-template-columns: 16px minmax(0, 1fr) auto 14px;
  min-height: 38px;
  align-items: center;
  padding: 5px 8px;
  border-radius: var(--radius);
  color: var(--text-soft);
  cursor: pointer;
  gap: 7px;
  text-align: left;
  background: transparent;
}

.artifact-resource-menu button:hover,
.artifact-resource-menu button.active {
  background: var(--artifact-highlight);
  color: var(--text);
}

.artifact-resource-menu button:hover {
  background: var(--artifact-highlight-hover);
}

.artifact-resource-menu button > span:not(.icon-slot) {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.artifact-resource-menu button > small {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.artifact-resource-menu .icon-slot {
  width: 14px;
  height: 14px;
}

.artifact-resource-menu .icon-slot:last-child {
  color: var(--accent);
}

/* 删除按钮要压过上面那批 `.artifact-resource-menu button` 的网格布局，
   所以写在后面并带上菜单前缀。上面那条 `.icon-slot:last-child` 是给「当前
   项」的对勾用的，叉正好也是最后一个 icon-slot，会被染成强调色。 */
.artifact-resource-menu .artifact-resource-remove {
  display: flex;
  flex: 0 0 auto;
  width: 26px;
  min-height: 26px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: var(--radius);
  color: var(--text-faint);
  opacity: 0;
}

.artifact-resource-row:hover .artifact-resource-remove,
.artifact-resource-menu .artifact-resource-remove:focus-visible {
  opacity: 1;
}

.artifact-resource-menu .artifact-resource-remove:hover {
  color: var(--danger, #e5484d);
  background: var(--artifact-highlight-hover);
}

.artifact-resource-menu .artifact-resource-remove .icon-slot:last-child {
  color: inherit;
}

.artifact-actions {
  flex: 0 0 auto;
  gap: 3px;
}

.artifact-actions .icon-button {
  width: 32px;
  height: 32px;
  flex-basis: 32px;
}

.artifact-actions .icon-button:hover {
  background: var(--artifact-highlight-hover);
  color: var(--text);
}

.artifact-download-button {
  display: inline-flex;
  width: 32px;
  min-width: 32px;
  height: 32px;
  align-items: center;
  justify-content: center;
  padding: 0;
  border-radius: var(--radius);
  background: var(--artifact-highlight);
  color: var(--text);
}

.artifact-download-button:hover {
  background: var(--artifact-highlight-hover);
}

.artifact-actions .icon-slot {
  width: 15px;
  height: 15px;
}

.artifact-view {
  min-width: 0;
  min-height: 0;
  overflow: auto;
  overscroll-behavior: contain;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
  background: var(--artifact-bg);
}

.artifact-image-stage {
  position: relative;
  display: flex;
  width: 100%;
  height: 100%;
  min-width: 0;
  min-height: 0;
  align-items: flex-start;
  justify-content: center;
  place-items: center;
  padding: 0;
  overflow: hidden;
  background: var(--artifact-bg);
  cursor: default;
  touch-action: none;
}

.artifact-image-stage > img {
  grid-area: 1 / 1;
  display: block;
  width: auto;
  max-width: 100%;
  height: auto;
  max-height: 100%;
  object-fit: contain;
  /* JS 用内联 transform 直接写 translate()+scale(),这里不再引用早已没人注入的
     --artifact-zoom(09-12 用户/AI 指出是死定义)。默认写 none,免得内联生效前闪一下。 */
  transform: none;
  transform-origin: center top;
  /* 缩放(滚轮)平滑过渡(09-12 用户要「边缘加过渡」);拖拽平移时必须关掉,
     否则每次 pointermove 都动画一遍 → 迟滞、图像追着指针错位(用户报)。 */
  transition: transform 160ms cubic-bezier(0.2, 0, 0, 1);
}

.artifact-image-stage.is-dragging > img {
  transition: none;
}

.artifact-image-stage.is-zoomed {
  cursor: grab;
}

.artifact-image-stage.is-dragging {
  cursor: grabbing;
}

.artifact-frame {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  background: white;
  zoom: var(--artifact-content-scale);
}

.artifact-markdown {
  width: min(100%, 820px);
  margin: 0 auto;
  padding: 28px 32px 64px;
  font-size: 14.1818px;
}

.artifact-markdown h2 {
  font-size: 18.5455px;
}

.artifact-markdown h3 {
  font-size: 16.9091px;
}

.artifact-markdown h4,
.artifact-markdown h5,
.artifact-markdown h6 {
  font-size: var(--fs-artifact-chat);
}

.artifact-markdown blockquote {
  font-size: 15.2727px;
}

.artifact-markdown table {
  font-size: 14.7273px;
}

.artifact-markdown th {
  font-size: 12px;
}

/* 表太长时那句「只画了前 N 行」——是旁注不是正文，压下去。 */
.artifact-markdown .artifact-table-note {
  margin-top: 14px;
  font-size: 12.7273px;
  opacity: 0.62;
}

.artifact-markdown .code-toolbar {
  font-size: 10.9091px;
}

.artifact-markdown .code-block pre {
  font-size: 13.6364px;
}

.artifact-source {
  display: grid;
  grid-template-columns: auto minmax(max-content, 1fr);
  width: max-content;
  min-width: 100%;
  min-height: 100%;
  background: var(--artifact-bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 13.6364px;
  line-height: 1.7;
}

.artifact-line-numbers {
  position: sticky;
  left: 0;
  z-index: 1;
  display: grid;
  min-width: 48px;
  align-content: start;
  padding: 22px 11px 48px 8px;
  background: var(--artifact-bg);
  color: var(--text-faint);
  text-align: right;
  user-select: none;
}

.artifact-line-numbers span {
  display: block;
  height: 1.7em;
  font-variant-numeric: tabular-nums;
}

.artifact-code {
  margin: 0;
  padding: 22px 22px 48px 18px;
  background: var(--artifact-bg);
  color: var(--text);
  font-family: var(--font-mono);
  font: inherit;
  tab-size: 2;
  white-space: pre;
}

.artifact-loading,
.artifact-failure {
  display: flex;
  min-height: 100%;
  align-items: center;
  justify-content: center;
  color: var(--text-faint);
  font-size: 13.0909px;
  gap: 8px;
}

.artifact-loading .is-spinning svg {
  animation: spin 900ms linear infinite;
}

.artifact-failure .icon-slot {
  width: 18px;
  height: 18px;
  color: var(--accent);
}

.main-stage.artifact-open.artifact-split {
  grid-template-columns: minmax(0, 1fr) calc(var(--artifact-width) + 26px);
}

.main-stage.artifact-open.artifact-split .artifact-workspace {
  position: relative;
  top: auto;
  right: auto;
  bottom: auto;
  grid-column: 2;
  grid-row: 1;
  width: var(--artifact-width);
  margin: 8px 10px 10px 16px;
  box-shadow: var(--artifact-shadow);
}

.main-stage.artifact-maximized .artifact-workspace {
  position: fixed;
  inset: 8px;
  z-index: 50;
  width: auto;
  margin: 0;
}

@media (max-width: 836px) {
  .stage-float {
    top: max(8px, env(safe-area-inset-top));
    left: 8px;
    gap: 4px;
  }

  :root {
    --ui-scale: 1;
  }

  .artifact-resize-handle {
    display: none;
  }

  .artifact-workspace {
    position: fixed;
    inset: 8px;
    z-index: 30;
    width: auto;
  }

  .artifact-header {
    min-height: 58px;
    padding: max(8px, env(safe-area-inset-top)) 8px 8px;
  }

  .artifact-mode-switch button {
    width: 28px;
    height: 28px;
  }

  .artifact-actions .icon-button {
    width: 30px;
    height: 30px;
    flex-basis: 30px;
  }

  .artifact-download-button {
    width: 30px;
    min-width: 30px;
    height: 30px;
    padding: 0;
  }

  .artifact-markdown {
    padding: 22px 16px 48px;
  }

  .artifact-image-stage {
    padding: 0;
  }
}

.typing-indicator i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  animation: typing-bounce 1.2s ease-in-out infinite;
}

.typing-indicator i:nth-child(1) {
  background: var(--gold);
}

.typing-indicator i:nth-child(2) {
  background: var(--accent);
  animation-delay: 0.15s;
}

.typing-indicator i:nth-child(3) {
  background: var(--ribbon);
  animation-delay: 0.3s;
}

.blocked-state {
  display: grid;
  padding: 32px 24px;
}

.blocked-state img {
  width: 64px;
  height: 64px;
  margin-bottom: 16px;
  border: 2px solid var(--gold);
  border-radius: 50%;
  object-fit: cover;
}

.blocked-state h1 {
  margin: 0;
  font-size: 19px;
  font-weight: 600;
}

.blocked-state p {
  max-width: 430px;
  margin: 8px 0 18px;
  color: var(--text-soft);
  font-size: 12px;
  line-height: 1.6;
  overflow-wrap: anywhere;
}

.login-form {
  display: grid;
  width: min(100%, 360px);
  margin-top: 4px;
  padding: 18px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
  gap: 8px;
  text-align: left;
}

.login-form > label {
  color: var(--text-soft);
  font-size: 12px;
  font-weight: 500;
}

.login-input {
  display: grid;
  grid-template-columns: 20px minmax(0, 1fr);
  min-height: 44px;
  align-items: center;
  padding: 0 11px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-faint);
  gap: 8px;
  transition: box-shadow 180ms ease;
}

.login-input:focus-within {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
  color: var(--accent);
}

.login-input .icon-slot {
  width: 16px;
  height: 16px;
}

.login-input input {
  width: 100%;
  min-width: 0;
  height: 42px;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--fs-chat);
}

.login-error {
  max-width: none !important;
  margin: 1px 0 0 !important;
  color: var(--danger) !important;
  font-size: 11px !important;
  line-height: 1.45 !important;
  text-align: left;
}

.login-submit {
  display: inline-flex;
  min-height: 40px;
  align-items: center;
  justify-content: center;
  margin-top: 5px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--inverse-text);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  gap: 7px;
}

.login-submit:hover:not(:disabled) {
  background: var(--accent-strong);
}

.login-submit:disabled {
  opacity: 0.62;
}

.login-submit .icon-slot {
  width: 15px;
  height: 15px;
}

.login-submit.is-loading .icon-slot svg {
  animation: spin 850ms linear infinite;
}

.empty-state {
  display: grid;
  padding: 30px 24px 48px;
}

.empty-visual {
  width: min(330px, 69.0909vw);
  height: 178px;
  overflow: hidden;
  margin-bottom: 20px;
  border-radius: var(--radius);
}

.empty-visual img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 55% 42%;
  filter: saturate(0.82) contrast(0.96);
}

.empty-copy {
  display: grid;
  justify-items: center;
  gap: 7px;
}

.empty-kicker {
  display: inline-flex;
  align-items: center;
  color: var(--text-soft);
  font-size: 10px;
  gap: 7px;
}

.empty-copy h1 {
  margin: 0;
  font-size: 22px;
  font-weight: 600;
}

.empty-copy p {
  margin: 0;
  color: var(--text-soft);
  font-size: 12px;
}

.prompt-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  width: min(100%, 580px);
  margin-top: 23px;
  gap: 8px;
}

.prompt-grid button {
  display: grid;
  grid-template-columns: 24px minmax(0, 1fr);
  min-height: 45px;
  align-items: center;
  padding: 7px 12px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--bubble-shadow);
  color: var(--text-soft);
  cursor: pointer;
  gap: 8px;
  text-align: left;
  transition: transform 150ms ease, box-shadow 150ms ease;
}

.prompt-grid button:hover:not(:disabled) {
  box-shadow: var(--card-shadow);
  color: var(--text);
  transform: translateY(-1px);
}

.prompt-grid button:disabled {
  opacity: 0.48;
}

.prompt-grid .icon-slot {
  width: 16px;
  height: 16px;
  color: var(--accent);
}

.prompt-grid button > span:last-child {
  font-size: var(--fs-meta);
  overflow-wrap: anywhere;
}

.jump-bottom-button {
  position: absolute;
  right: max(18px, calc((100% - 960px) / 2));
  bottom: 116px;
  z-index: 11;
  display: grid;
  width: 34px;
  height: 34px;
  place-items: center;
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text-soft);
  box-shadow: var(--float-shadow);
  cursor: pointer;
}

.jump-bottom-button:hover {
  color: var(--text);
}

.jump-bottom-button .icon-slot {
  width: 14px;
  height: 14px;
}

.composer-dock {
  grid-row: 3;
  position: relative;
  /* 桌面浮层态(非分栏)的 artifact 面板是 z-index:12 的绝对定位,页脚(和它同在
     main-stage 栈上下文里)得压过它,否则输入框被盖住点不到(#2)。手机全屏 artifact
     是 z-index:30,仍盖在页脚上——那是全屏预览的既定行为,不受影响。 */
  z-index: 13;
  min-width: 0;
  padding: 8px max(18px, calc((100% - 940px) / 2)) 12px;
  background: var(--app-bg);
}

.question-dock {
  width: 100%;
  max-height: min(calc(50dvh / var(--ui-scale)), max(0px, calc(var(--app-height, calc(100dvh / var(--ui-scale))) - 220px)));
  margin-bottom: 8px;
  overflow-y: auto;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

.question-dock .question-card {
  width: 100%;
  box-shadow: var(--card-shadow);
}

.question-dock .question-card header strong,
.question-dock .question-prompt {
  font-size: 14px;
}

.question-dock .question-card header small {
  font-size: 10px;
}

.question-dock .question-option-copy strong,
.question-dock .custom-answer textarea {
  font-size: 13px;
}

.question-dock .question-option-copy small {
  font-size: 11px;
}

.composer {
  width: 100%;
  min-width: 0;
  max-width: 100%;
  overflow: hidden;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
  transition: box-shadow 200ms ease;
}

.composer:focus-within {
  box-shadow: var(--card-shadow), 0 0 0 3px color-mix(in srgb, var(--accent) 15%, transparent);
}

.composer.is-disabled {
  box-shadow: var(--bubble-shadow);
}

.composer textarea {
  display: block;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  /* 输入框两行高(用户要求再矮一行)。 */
  min-height: 60px;
  max-height: 200px;
  resize: none;
  padding: 10px 15px 6px;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--text);
  font-size: var(--fs-chat);
  line-height: 1.5;
}

.composer textarea::placeholder {
  color: var(--text-faint);
}

.composer textarea:disabled {
  color: var(--text-soft);
}

/* ── 输入框:三行文本区 + 底部一栏(附件左下角,面板/语音/发送右下角);信息移到框下(#99) ── */
.composer-input-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  width: 100%;
  min-width: 0;
}
.composer-input-row > textarea {
  width: 100%;
}
.composer-inbox-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 10px 8px 10px;
}
.composer-inbox-right {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 4px;
  /* 停止按钮浮在发送按钮正上方(用户要求),需要相对定位作锚。 */
  position: relative;
}
/* 框内按钮统一一套:副按钮幽灵(透明+悬浮底色),发送圆形强调色作主操作,停止红调;
   36px 圆角、图标 18px。 */
.composer-inbox-bar button {
  width: 36px;
  height: 36px;
  flex: 0 0 36px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: 10px;
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease, transform 0.12s ease;
}
.composer-inbox-bar button > .icon-slot,
.composer-inbox-bar button > .icon-slot svg {
  width: 18px;
  height: 18px;
}
.composer-inbox-bar button:hover:not(:disabled) {
  background: var(--surface-2);
  color: var(--text);
}
.composer-inbox-bar button:active:not(:disabled) {
  transform: scale(0.9);
}
.composer-inbox-bar button:disabled {
  color: var(--text-faint);
  cursor: not-allowed;
}
.composer-inbox-bar .send-button {
  border-radius: 50%;
  background: var(--accent);
  color: var(--md-sys-color-on-primary, #12131b);
}
.composer-inbox-bar .send-button:hover:not(:disabled) {
  background: var(--accent);
  color: var(--md-sys-color-on-primary, #12131b);
  filter: brightness(1.1);
}
.composer-inbox-bar .send-button:disabled {
  background: var(--surface-2);
  color: var(--text-faint);
}
.composer-inbox-bar .live-stop-button {
  background: color-mix(in srgb, var(--ribbon) 20%, transparent);
  color: var(--ribbon);
  border: 0;
}
.composer-inbox-bar .live-stop-button:hover:not(:disabled) {
  background: color-mix(in srgb, var(--ribbon) 34%, transparent);
  color: var(--ribbon);
}
.composer-info {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
  padding: 8px 12px 2px;
  font-size: var(--fs-micro);
  color: var(--text-soft);
}
.composer-info-spacer {
  flex: 1 1 auto;
  min-width: 8px;
}
/* 模型选择器不被挤没:不收缩,标题过长才在自己内部省略(#2 手机端只剩「▾」的真因)。 */
.composer-info .model-menu-wrap {
  flex: 0 0 auto;
  min-width: 0;
}
.composer-info .model-button {
  /* 覆盖旧的手机端「只显 ▾」规则(那是模型还在框内时为省地方做的;现在模型移到
     框下信息行、有空间,手机端也要看得到模型名,#2)。 */
  width: auto;
  max-width: 46vw;
  justify-content: flex-start;
  padding: 4px 10px;
}
.composer-info .model-label {
  display: inline;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 100%;
}
.composer-info .k {
  /* 标签和数值同色(#111:不加粗后颜色还不一样),整行统一用 --text-soft。 */
  color: inherit;
}
.composer-info b {
  /* 数值不加粗、也不换色(#1/#111):和标签一个色,只靠等宽字形和位置区分。 */
  font-weight: 400;
  color: inherit;
  font-variant-numeric: tabular-nums;
  font-family: var(--font-mono);
}
.composer-speed,
.composer-cumulative,
.composer-timer {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  flex: none;
  white-space: nowrap;
}
/* 上下文:小圆环 + 数字(替代原来的长条,用户觉得不美观) */
.composer-info .composer-context {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
}
/* ---------- 选中文字右键菜单(web/selectionmenu.js) ---------- */
.sel-menu {
  position: fixed;
  z-index: 70;
  display: grid;
  min-width: 168px;
  padding: 5px;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
  font-size: var(--fs-meta);
}
.sel-menu-item {
  display: flex;
  align-items: center;
  padding: 7px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}
.sel-menu-item:hover:not(:disabled),
.sel-menu-item:focus-visible { background: var(--surface-2); outline: 0; }
.sel-menu-item:disabled { color: var(--text-faint); cursor: not-allowed; }
.sel-menu-sep { height: 1px; margin: 4px 6px; background: var(--line); }
.sel-menu-hint { padding: 4px 10px 3px; color: var(--text-faint); font-size: 10.5px; }

.sel-pop {
  position: fixed;
  z-index: 65;
  display: grid;
  grid-template-rows: auto minmax(0, 1fr) auto;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
  color: var(--text);
  font-size: var(--fs-meta);
  animation: ctx-pop-in 0.14s cubic-bezier(0.2, 0, 0, 1);
}
.sel-pop-head { display: flex; align-items: center; gap: 6px; padding: 9px 10px 8px 12px; border-bottom: 1px solid var(--line); }
/* 标题栏是拖动把手(selectionmenu.js makeDraggable);手机宽度是底部面板,不拖。 */
.sel-pop-head { cursor: grab; touch-action: none; user-select: none; }
.sel-pop.is-dragging { animation: none; box-shadow: var(--float-shadow), 0 0 0 1px var(--line-strong); }
.sel-pop.is-dragging .sel-pop-head { cursor: grabbing; }
@media (max-width: 640px) {
  .sel-pop-head { cursor: default; touch-action: auto; }
}
.sel-pop-head strong { flex: none; font-size: var(--fs-ui); font-weight: 600; }
.sel-pop-quote { flex: 1; min-width: 0; overflow: hidden; color: var(--text-soft); text-overflow: ellipsis; white-space: nowrap; }
.sel-icon,
.sel-chip {
  flex: none;
  padding: 3px 7px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  font-size: var(--fs-micro);
  cursor: pointer;
}
.sel-chip { background: var(--surface-2); }
.sel-icon:hover,
.sel-chip:hover { background: var(--surface-2); color: var(--text); }
.sel-icon.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: var(--accent); }
.sel-pop-body {
  min-height: 0;
  padding: 10px 12px;
  overflow-y: auto;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}
.sel-output { font-size: 13.5px; line-height: 1.65; }
/* 溢出(2026-09-14 用户报):浮窗是 grid,隐式列宽是 auto,一段不可断的长串(URL、路径、
   长英文词、报错原文)会把列撑得比浮窗还宽,文字就画到外面去了。列钉成 minmax(0, 1fr),
   子项 min-width 归零,长串允许在任意处折行;代码块保留原样,改成块内横向滚动。 */
.sel-pop { grid-template-columns: minmax(0, 1fr); }
.sel-pop > *,
.sel-pop-body > *,
.sel-section,
.sel-section-body { min-width: 0; }
.sel-output,
.sel-note,
.sel-result-snippet,
.sel-empty { overflow-wrap: anywhere; word-break: break-word; }
.sel-output pre,
.sel-output .code-block,
.sel-output .markdown-table-scroll { max-width: 100%; overflow-x: auto; }
.sel-output pre { white-space: pre; }
.sel-output img,
.sel-output table { max-width: 100%; }
.sel-result { grid-template-columns: minmax(0, 1fr); }
.sel-status { display: flex; align-items: center; gap: 8px; color: var(--text-soft); }
.sel-spinner {
  width: 12px;
  height: 12px;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: ctx-spin 0.8s linear infinite;
}
.sel-note { margin-bottom: 8px; padding: 6px 8px; border-radius: var(--radius); background: var(--surface-2); color: var(--text-soft); font-size: var(--fs-micro); line-height: 1.5; }
.sel-note.is-error { color: var(--danger); }
.sel-pop-foot { display: flex; justify-content: flex-end; gap: 6px; padding: 8px 10px; border-top: 1px solid var(--line); }
.sel-pop-foot:empty { display: none; }
.sel-btn { padding: 5px 10px; border: 0; border-radius: var(--radius); background: var(--surface-2); color: var(--text); font-size: var(--fs-meta); cursor: pointer; }
.sel-btn:hover:not(:disabled) { background: var(--surface-3); }
.sel-btn:disabled { opacity: 0.5; cursor: not-allowed; }
.sel-section + .sel-section { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.sel-section-head { margin-bottom: 6px; color: var(--text-faint); font-size: var(--fs-micro); }
.sel-result {
  display: grid;
  width: 100%;
  gap: 2px;
  padding: 6px 8px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text);
  text-align: left;
  text-decoration: none;
  cursor: pointer;
}
.sel-result:hover { background: var(--surface-2); }
.sel-result-title { overflow: hidden; font-weight: 500; text-overflow: ellipsis; white-space: nowrap; }
.sel-result-snippet { color: var(--text-soft); font-size: var(--fs-micro); line-height: 1.5; }
.sel-result-url { overflow: hidden; color: var(--link); font-size: 10.5px; text-overflow: ellipsis; white-space: nowrap; }
.sel-empty { color: var(--text-faint); font-size: var(--fs-micro); }

/* 手机:选区下方的工具条;浮窗改成底部面板(覆盖 JS 写的内联位置)。 */
.sel-toolbar {
  position: fixed;
  z-index: 70;
  display: flex;
  gap: 2px;
  padding: 4px;
  border-radius: var(--radius);
  background: var(--surface-3);
  box-shadow: var(--float-shadow);
}
.sel-toolbar[hidden] { display: none; }
.sel-toolbar-item { padding: 8px 10px; border: 0; border-radius: 6px; background: transparent; color: var(--text); font-size: var(--fs-meta); }
@media (max-width: 640px) {
  .sel-pop {
    top: auto !important;
    right: 0;
    bottom: 0 !important;
    left: 0 !important;
    width: auto !important;
    max-height: 70vh !important;
    border-radius: calc(var(--radius) * 2) calc(var(--radius) * 2) 0 0;
  }
}

.composer-info .ctx-ring {
  width: 16px;
  height: 16px;
  flex: none;
  transform: rotate(-90deg);
}
.composer-info .ctx-ring-bg {
  fill: none;
  stroke: color-mix(in srgb, var(--text) 14%, transparent);
  stroke-width: 3;
}
.composer-info .ctx-ring-fg {
  fill: none;
  stroke: var(--accent);
  stroke-width: 3;
  stroke-linecap: round;
  transition: stroke-dashoffset 0.4s ease, stroke 0.3s ease;
}
.composer-info .composer-context.is-high .ctx-ring-fg {
  stroke: var(--gold, #e9b64a);
}
.composer-info .composer-context.is-critical .ctx-ring-fg {
  stroke: var(--danger);
}
.composer-info .ctx-nums {
  display: inline-flex;
  gap: 5px;
  align-items: baseline;
}
.composer-info .ctx-nums #contextNumbers {
  font-family: var(--font-mono);
  /* 和「上下文」三个字同色(#130),整行统一。 */
  color: inherit;
  font-variant-numeric: tabular-nums;
}
/* 窄屏:累计/速度可省,模型和上下文优先(#2 手机端要能看到模型)。
   模型名很长时,右边的上下文与「用时」(09-24)会被挤出屏幕:这时让模型那块收窄、名字
   在自己里面省略,但至少留 96px——整个缩成「▾」正是 #2 的毛病。 */
@media (max-width: 640px) {
  .composer-cumulative,
  .composer-speed { display: none; }
  .composer-info { gap: 8px; }
  .composer-info .model-menu-wrap { flex: 0 1 auto; min-width: 96px; max-width: 60vw; }
  .composer-info .model-button { max-width: 100%; }
}

.attachment-tray {
  display: flex;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  box-sizing: border-box;
  align-items: flex-start;
  padding: 12px 14px 4px;
  overflow-x: auto;
  gap: 7px;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

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

.attachment-item {
  position: relative;
  display: grid;
  grid-template-columns: 38px minmax(78px, 1fr) 24px 24px;
  width: 224px;
  min-width: 224px;
  height: 54px;
  align-items: center;
  padding: 5px 5px 5px 6px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-soft);
  gap: 7px;
  flex: 0 0 auto;
}

.attachment-item.is-image {
  display: block;
  width: 96px;
  min-width: 96px;
  height: 96px;
  padding: 0;
  overflow: hidden;
  background: var(--surface-2);
}

.attachment-item.is-file {
  display: flex;
  width: fit-content;
  min-width: 140px;
  max-width: 280px;
  padding: 6px;
}

.attachment-item.is-error {
  color: var(--danger);
}

.attachment-item.is-image > img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.attachment-image-fallback {
  display: grid;
  width: 100%;
  height: 100%;
  place-items: center;
  color: var(--danger);
}

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

.attachment-image-fallback .icon-slot {
  width: 20px;
  height: 20px;
}

.attachment-file-icon {
  display: grid;
  width: 40px;
  height: 40px;
  place-items: center;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-3);
  color: var(--accent);
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 700;
}

.attachment-file-icon .icon-slot {
  width: 18px;
  height: 18px;
}

.attachment-item-copy {
  display: grid;
  min-width: 0;
  width: max-content;
  max-width: 176px;
  flex: 0 1 auto;
  line-height: 1.3;
}

.attachment-item-copy strong,
.attachment-item-copy small {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.attachment-item-copy strong {
  color: var(--text);
  font-size: 11.5px;
  font-weight: 600;
}

.attachment-item-copy small {
  color: inherit;
  font-size: 10px;
}

.attachment-action,
.attach-button {
  display: grid;
  place-items: center;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
}

.attachment-action {
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
}

.attachment-action:hover,
.attach-button:hover:not(:disabled) {
  background: var(--surface-3);
  color: var(--text);
}

/* 语音输入:听写中按钮变红并呼吸;状态行显示「在听」和电平条。 */
.mic-button.is-recording {
  color: #fff;
  background: var(--danger);
  animation: mic-pulse 1.2s ease-in-out infinite;
}

/* 听写中悬浮在输入框上方的电平指示:只有麦克风图标和一条电平,没有文字。 */
.voice-float {
  position: absolute;
  left: 50%;
  top: -34px;
  transform: translateX(-50%);
  z-index: 12;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 6px 14px;
  border-radius: var(--radius-pill);
  color: var(--danger);
  background: color-mix(in srgb, var(--app-bg) 82%, transparent);
  backdrop-filter: blur(10px);
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
  pointer-events: none;
}

.voice-float .icon-slot {
  width: 16px;
  height: 16px;
  animation: mic-pulse 1.2s ease-in-out infinite;
}

.voice-level {
  display: inline-block;
  width: 96px;
  height: 6px;
  border-radius: var(--radius-sm);
  background: color-mix(in srgb, var(--danger) 18%, transparent);
  overflow: hidden;
}

.voice-level b {
  display: block;
  height: 100%;
  width: 0;
  border-radius: var(--radius-sm);
  background: var(--danger);
  transition: width 80ms linear;
}

@keyframes mic-pulse {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.35); }
}

.attachment-remove:hover {
  color: var(--danger);
}

.attachment-remove {
  grid-column: 4;
  flex: 0 0 24px;
}

.attachment-item.is-image .attachment-remove {
  position: absolute;
  top: 5px;
  right: 5px;
  z-index: 1;
  background: color-mix(in srgb, var(--surface-1) 84%, transparent);
  color: var(--text);
  box-shadow: var(--bubble-shadow);
}

.attachment-item.is-image > .attachment-spinner,
.attachment-item.is-image > .attachment-action:not(.attachment-remove) {
  position: absolute;
  right: 5px;
  bottom: 5px;
  z-index: 1;
  display: grid;
  width: 26px;
  height: 26px;
  place-items: center;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--surface-1) 84%, transparent);
  box-shadow: var(--bubble-shadow);
}

.attachment-action .icon-slot,
.attachment-spinner {
  width: 13px;
  height: 13px;
}

.attachment-spinner svg {
  animation: spin 900ms linear infinite;
}

.attach-button {
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-soft);
  transition: transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1), background 150ms ease, filter 200ms ease;
}

.attach-button:disabled {
  cursor: not-allowed;
  opacity: 0.4;
}

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

.attach-button:hover:not(:disabled) {
  filter: brightness(1.04);
  transform: scale(1.08) rotate(8deg);
}

.attach-button:active:not(:disabled) {
  transform: scale(0.92);
}

.composer.is-dragging {
  box-shadow: var(--card-shadow), 0 0 0 3px color-mix(in srgb, var(--accent) 32%, transparent);
}

.composer-footer {
  display: flex;
  width: 100%;
  min-width: 0;
  max-width: 100%;
  min-height: 40px;
  align-items: center;
  justify-content: space-between;
  padding: 4px 7px 6px 12px;
  gap: 10px;
}

.composer-controls {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 9px;
}

/* 思考档位并进了模型菜单：每行模型右边一个小片,点开就地铺开档位选项。
   原先它是独立按钮 + 独立浮层,和模型按钮并排占两个位置,而两者常常要一起
   调(换了模型往往就要换档位)。 */
.model-menu-row {
  position: relative;
  display: flex;
  align-items: center;
  padding-right: 9px;
  border-radius: var(--radius);
  gap: 3px;
}

/* 高亮由行来画,行内那个按钮不再自己上色——否则背景在按钮右缘就断了,
   档位小片被甩在高亮之外,一行看着是两块。 */
.model-menu-row > .model-menu-item {
  flex: 1 1 auto;
  min-width: 0;
  background: transparent;
}

.model-menu-row:hover,
.model-menu-row:has(> .model-menu-item.selected) {
  background: var(--surface-2);
}

.model-menu-row:hover > .model-menu-item,
.model-menu-row > .model-menu-item.selected {
  color: var(--text);
}

/* 行内的档位控件。行已经有整块底色了,静息态只要比它高一档就看得出来;
   点上去/展开时才转成强调色。 */
.model-level-chip {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  height: 24px;
  padding: 0 6px 0 9px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-3);
  color: var(--text-soft);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 600;
  gap: 2px;
  white-space: nowrap;
}

.model-level-chip:hover,
.model-level-chip[aria-expanded="true"] {
  background: var(--accent);
  color: var(--md-sys-color-on-primary);
}

/* 这个会话钉住的档位(09-24):字用强调色,和跟随全局的灰字分得开。 */
.model-level-chip.is-pinned:not(:hover):not([aria-expanded="true"]) {
  color: var(--accent);
}

.model-level-chip .icon-slot {
  width: 11px;
  height: 11px;
  opacity: 0.7;
  transition: transform 160ms ease;
}

.model-level-chip[aria-expanded="true"] .icon-slot {
  transform: rotate(180deg);
}

.model-level-menu {
  position: absolute;
  z-index: 41;
  display: grid;
  min-width: 132px;
  padding: 4px;
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  gap: 1px;
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
}

.model-level-menu[hidden] {
  display: none;
}

.model-level-option {
  display: flex;
  min-height: 28px;
  align-items: center;
  padding: 0 10px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  font-family: var(--font-mono);
  font-size: 11px;
  text-align: left;
}

.model-level-option:hover {
  background: var(--surface-2);
  color: var(--text);
}

.model-level-option.selected {
  background: var(--accent);
  color: var(--md-sys-color-on-primary);
  font-weight: 600;
}


.composer-submit {
  min-width: 0;
  max-width: 100%;
  align-items: center;
}

/* 队列在输入框上方:排队的消息紧贴对话流,是「即将发生的下一条」 */
.queue-tray {
  display: grid;
  padding: 0 0 10px;
  gap: 5px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  margin-bottom: 10px;
}

.queue-item {
  display: flex;
  min-width: 0;
  align-items: center;
  justify-content: space-between;
  padding: 7px 11px;
  border-left: 3px solid var(--accent);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: color-mix(in srgb, var(--accent-soft) 30%, transparent);
  color: var(--text-soft);
  font-size: var(--fs-meta);
  line-height: 1.45;
  gap: 8px;
}

.queue-item > span {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.queue-remove {
  display: grid;
  width: 24px;
  height: 24px;
  flex: 0 0 24px;
  place-items: center;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
}

.queue-remove:hover {
  background: var(--surface-2);
  color: var(--danger);
}

.composer-context {
  display: grid;
  overflow: hidden;
  width: 132px;
  min-width: 92px;
  margin-right: 2px;
  gap: 4px;
}

/* 数字过长时省略号截断,不允许伸到发送按钮底下 */
.composer-context .context-heading {
  min-width: 0;
}

.composer-context .context-heading > span:last-child {
  overflow: hidden;
  min-width: 0;
  text-overflow: ellipsis;
}

.composer-context .context-heading {
  color: var(--text-soft);
  font-size: 10.5px;
}

.composer-context .context-track {
  height: 5px;
  margin-top: 1px;
}

.composer-state,
.character-count {
  color: var(--text-faint);
  font-size: var(--fs-micro);
  overflow-wrap: anywhere;
}

.composer-state.is-error,
.character-count.is-error {
  color: var(--danger);
}

.composer-submit {
  display: flex;
  position: relative;
  min-width: 0;
  flex: 0 1 auto;
  align-items: center;
  gap: 8px;
}

/* 发送键:38px 方形 r8 */
.send-button {
  display: grid;
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  place-items: center;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--md-sys-color-on-primary);
  cursor: pointer;
  transition: transform 180ms cubic-bezier(0.34, 1.56, 0.64, 1), background 150ms ease, filter 200ms ease;
}

.send-button:hover:not(:disabled) {
  filter: brightness(1.06);
  transform: scale(1.08) rotate(-8deg);
}

.send-button:active:not(:disabled) {
  transform: scale(0.92);
}

/* Compact per-reply stop controls above the composer send button. */
.live-stop-rail {
  /* 停止按钮浮在发送按钮正上方(用户要求):绝对定位、右缘对齐发送键、贴其上方一点。 */
  position: absolute;
  right: 0;
  bottom: calc(100% + 8px);
  display: flex;
  align-items: center;
  gap: 4px;
  z-index: 3;
}
.live-stop-rail[hidden] { display: none; }

.live-stop-button {
  position: relative;
  display: grid;
  width: 38px;
  height: 38px;
  flex: 0 0 38px;
  place-items: center;
  border: 1px solid color-mix(in srgb, var(--ribbon) 42%, transparent);
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--ribbon) 18%, var(--surface-1));
  color: var(--ribbon);
  cursor: pointer;
  transition: background 150ms ease, color 150ms ease, transform 150ms ease;
}

.live-stop-button .icon-slot {
  width: 20px;
  height: 20px;
}

.live-stop-button:hover:not(:disabled) {
  background: color-mix(in srgb, var(--ribbon) 30%, var(--surface-1));
}

.live-stop-button:active:not(:disabled) {
  transform: scale(0.92);
}

.live-stop-button:disabled {
  cursor: not-allowed;
  opacity: 0.55;
}

.send-button:disabled {
  background: var(--surface-3);
  color: var(--text-faint);
}

/* 停止态:ribbon */
.send-button.is-cancel {
  background: var(--ribbon);
  color: var(--md-sys-color-on-tertiary);
}

.send-button.is-cancel:hover:not(:disabled) {
  filter: brightness(1.06);
}

.send-button .icon-slot {
  width: 17px;
  height: 17px;
}

.page-scrim {
  position: fixed;
  inset: 0;
  z-index: 18;
  display: none;
  background: rgba(0, 0, 0, 0.46);
}

.page-scrim.visible {
  display: block;
}

/* 设置进了控制台,原来那个从右侧滑出的抽屉和它的遮罩都没了。
   `.settings-layout` / `.settings-nav` / `.settings-content` 本来就没绑在
   抽屉上,搬进控制台面板后原样生效。 */
.con-panel {
  min-height: 0;
}

.con-panel[data-console-panel="settings"] {
  display: grid;
  height: 100%;
  grid-template-rows: minmax(0, 1fr) auto;
}

.settings-content {
  min-height: 0;
  padding-bottom: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-color: var(--line-strong) transparent;
  scrollbar-width: thin;
}

.settings-section {
  padding: 20px 26px 6px;
}

.settings-section:last-child {
  padding-bottom: 26px;
}

.settings-layout {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
  min-height: 0;
  /* 和 .con-inner 一样居中：导航 168 + 内容左右各 26 内边距 + .st-root 960 = 1180，
     正好让内容列填满而不留白；导航和内容整块一起居中，footer 保持通栏。 */
  width: 100%;
  max-width: 1180px;
  margin: 0 auto;
}

.settings-nav {
  display: grid;
  align-content: start;
  padding: 10px 10px 10px 14px;
  background: transparent;
  gap: 2px;
}

.settings-nav button {
  position: relative;
  min-height: 40px;
  padding: 0 12px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  font-size: var(--fs-ui);
  text-align: left;
  transition: background 180ms ease, color 180ms ease;
}

.settings-nav button:hover {
  background: var(--surface-2);
  color: var(--text);
}

.settings-nav button.active {
  background: var(--surface-1);
  box-shadow: var(--bubble-shadow);
  color: var(--text);
  font-weight: 600;
}

.settings-nav button.active::before {
  position: absolute;
  top: 9px;
  bottom: 9px;
  left: 0;
  width: 3px;
  border-radius: var(--radius-sm);
  background: var(--ribbon);
  content: "";
}

.settings-section-heading {
  display: flex;
  min-height: 30px;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 11px;
  gap: 10px;
}

.settings-section-heading h2 {
  margin: 0;
}

.settings-description,
.settings-empty {
  margin: 0 0 12px;
  color: var(--text-faint);
  font-size: 13px;
  line-height: 1.6;
}

.settings-footer {
  display: flex;
  min-height: 58px;
  align-items: center;
  justify-content: space-between;
  padding: 9px 20px max(9px, env(safe-area-inset-bottom));
  background: var(--app-bg);
  gap: 10px;
}

.settings-footer > span {
  min-width: 0;
  color: var(--text-faint);
  font-size: 12px;
  overflow-wrap: anywhere;
}

.settings-footer > div {
  display: inline-flex;
  flex: 0 0 auto;
  gap: 7px;
}

.primary-button {
  display: inline-flex;
  min-height: 36px;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--inverse-text);
  cursor: pointer;
  font-weight: 600;
}

.primary-button:hover:not(:disabled) {
  background: var(--accent-strong);
}

.primary-button:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

.compact-button {
  min-height: 34px;
  padding: 0 11px;
  font-size: 12px;
}

.config-form,
.provider-editor,
.model-pool-editor,
.plugin-editor,
.prompt-editor {
  display: grid;
  gap: 11px;
}

.config-group {
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
}

.config-group > header {
  padding: 12px 14px 9px;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}

.config-group h3 {
  margin: 0;
  color: var(--text);
  font-size: var(--fs-ui);
  font-weight: 600;
}

.config-group > header p {
  margin: 4px 0 0;
  color: var(--text-faint);
  font-size: 12px;
  line-height: 1.55;
}

.config-group-body {
  display: grid;
  padding: 11px 14px 14px;
  gap: 10px;
}

.config-field {
  display: grid;
  min-width: 0;
  gap: 4px;
}

.config-field-label {
  color: var(--text-soft);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.08em;
}

.config-field-hint,
.secret-status,
.config-field-error {
  color: var(--text-faint);
  font-size: var(--fs-micro);
  line-height: 1.5;
}

.config-field-error {
  color: var(--danger);
}

.config-input {
  width: 100%;
  min-width: 0;
  min-height: 38px;
  padding: 8px 11px;
  border: 0;
  border-radius: var(--radius);
  outline: 0;
  background: var(--surface-2);
  color: var(--text);
  font-size: var(--fs-ui);
  line-height: 1.5;
  transition: box-shadow 180ms ease;
}

textarea.config-input {
  min-height: 92px;
  resize: vertical;
  font-family: var(--font-mono);
  font-size: 12px;
  line-height: 1.7;
}

.config-input:focus {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
}

.config-input.is-invalid {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 55%, transparent);
}

.config-toggle {
  display: grid;
  grid-template-columns: 38px minmax(0, 1fr);
  min-height: 42px;
  align-items: center;
  cursor: pointer;
  gap: 9px;
}

.config-toggle input {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
}

/* 开关:胶囊轨道 + 圆钮属语义圆形,保留 */
.toggle-track {
  position: relative;
  width: 38px;
  height: 22px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  transition: background 200ms ease;
}

.toggle-track::after {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-faint);
  content: "";
  transition: transform 200ms ease, background 200ms ease;
}

.config-toggle input:checked + .toggle-track {
  background: var(--accent);
}

.config-toggle input:checked + .toggle-track::after {
  background: var(--md-sys-color-on-primary);
  transform: translateX(16px);
}

.config-toggle-copy {
  display: grid;
  min-width: 0;
  gap: 1px;
}

.config-toggle-copy strong {
  color: var(--text);
  font-size: var(--fs-ui);
  font-weight: 500;
}

.config-toggle-copy small {
  color: var(--text-faint);
  font-size: var(--fs-meta);
}

.plugin-subsection {
  border-top: 1px solid var(--line);
}

.plugin-subsection > summary {
  padding: 10px 0;
  color: var(--text);
  cursor: pointer;
  font-size: var(--fs-ui);
  font-weight: 600;
}

.plugin-subsection-body {
  display: grid;
  padding: 0 0 10px 14px;
  gap: 10px;
}

.quota-accounts {
  display: grid;
  gap: 8px;
}

.quota-account {
  border-left: 2px solid var(--line);
  padding-left: 10px;
}

.quota-account > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: var(--text-soft);
  cursor: pointer;
  font-size: var(--fs-ui);
  font-weight: 600;
}

.quota-account-body {
  display: grid;
  padding: 8px 0 4px;
  gap: 8px;
}

.provider-card,
.plugin-card {
  overflow: hidden;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
}

.provider-card > summary,
.plugin-card > summary {
  display: flex;
  min-height: 46px;
  align-items: center;
  justify-content: space-between;
  padding: 8px 14px;
  cursor: pointer;
  gap: 8px;
  list-style: none;
}

.provider-card > summary::-webkit-details-marker,
.plugin-card > summary::-webkit-details-marker {
  display: none;
}

.provider-card > summary > span,
.plugin-card > summary > span:first-child {
  display: grid;
  min-width: 0;
  gap: 1px;
}

.provider-card summary strong,
.plugin-card summary strong {
  overflow: hidden;
  color: var(--text);
  font-size: var(--fs-ui);
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.provider-card summary small,
.plugin-card summary small {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
}

.provider-card-body,
.plugin-card-body {
  display: grid;
  padding: 11px 14px 14px;
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  gap: 10px;
}

.text-button {
  min-height: 32px;
  padding: 0 8px;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-faint);
  cursor: pointer;
  font-size: 12px;
}

.text-button:hover:not(:disabled) {
  background: var(--surface-2);
  color: var(--text);
}

.danger-text:hover:not(:disabled) {
  color: var(--danger);
}

.secret-editor {
  grid-template-columns: minmax(0, 1fr) auto;
}

.secret-editor > .config-input {
  grid-column: 1 / -1;
}

.secret-actions {
  display: inline-flex;
  justify-self: end;
  gap: 2px;
}

.model-pool-option {
  display: grid;
  grid-template-columns: 17px minmax(0, 1fr);
  min-height: 46px;
  align-items: center;
  padding: 5px 11px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--bubble-shadow);
  cursor: pointer;
  gap: 9px;
}

.model-pool-option:hover {
  background: var(--surface-2);
}

.model-pool-option input {
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--accent);
}

.model-pool-option span {
  display: grid;
  min-width: 0;
  gap: 1px;
}

.model-pool-option strong {
  overflow: hidden;
  color: var(--text);
  font-size: var(--fs-ui);
  font-weight: 500;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.model-pool-option small {
  overflow: hidden;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.plugin-state {
  display: inline-flex;
  min-width: 32px;
  min-height: 20px;
  align-items: center;
  justify-content: center;
  padding: 0 7px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text-faint);
  font-size: var(--fs-micro);
}

.plugin-state.is-enabled {
  background: var(--accent-soft);
  color: var(--md-sys-color-on-primary-container);
}

.prompt-document {
  display: grid;
  padding: 13px 14px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
  gap: 8px;
}

.prompt-document > header {
  display: flex;
  min-width: 0;
  align-items: center;
  gap: 6px;
}

.prompt-document > header .config-input {
  min-width: 0;
}

.prompt-document > header .config-field {
  flex: 1 1 auto;
  min-width: 0;
}

.prompt-document > header .icon-button {
  flex: 0 0 34px;
  margin-top: 18px;
}

.prompt-content {
  min-height: 240px !important;
  font-family: var(--font-ui) !important;
}

.config-json-editor {
  display: block;
  width: 100%;
  min-height: min(54.5455vh, 500px);
  margin: 0 0 10px;
  padding: 12px 14px;
  border: 0;
  border-radius: var(--radius);
  outline: 0;
  resize: vertical;
  background: var(--code-bg);
  color: var(--code-ink);
  font-family: var(--font-mono);
  font-size: 12.5px;
  line-height: 1.7;
  transition: box-shadow 180ms ease;
}

.config-json-editor:focus {
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
}

.settings-section h2 {
  margin: 0 0 10px;
  color: var(--gold);
  font-size: var(--fs-micro);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* 设置卡:demo 定稿的 settings-card / settings-row / segmented / toggle 语言 */
.settings-card {
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
}

.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  gap: 16px;
}

.settings-row + .settings-row {
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
}

.settings-row .lbl {
  min-width: 0;
}

.settings-row .lbl strong {
  display: block;
  font-size: var(--fs-ui);
  font-weight: 600;
}

.settings-row .lbl small {
  display: block;
  color: var(--text-soft);
  font-size: var(--fs-meta);
  line-height: 1.55;
}














.segmented {
  display: inline-flex;
  flex: 0 0 auto;
  padding: 3px;
  border-radius: var(--radius);
  background: var(--surface-2);
  gap: 2px;
}

.segmented button {
  padding: 4px 12px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  font-size: var(--fs-meta);
  font-weight: 600;
  transition: background 180ms ease, color 180ms ease;
}

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

/* 开关:胶囊轨道 + 圆钮属语义圆形(独立按钮版,配 aria-checked) */
.toggle {
  position: relative;
  width: 38px;
  height: 22px;
  flex: 0 0 38px;
  border: 0;
  border-radius: var(--radius-pill);
  background: var(--surface-2);
  cursor: pointer;
  transition: background 200ms ease;
}

.toggle::after {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-faint);
  content: "";
  transition: transform 200ms ease, background 200ms ease;
}

.toggle[aria-checked="true"] {
  background: var(--accent);
}

.toggle[aria-checked="true"]::after {
  background: var(--md-sys-color-on-primary);
  transform: translateX(16px);
}

.theme-options {
  display: flex;
  padding: 14px 16px;
  gap: 10px;
}

.theme-options button {
  display: flex;
  flex: 1;
  min-height: 44px;
  align-items: center;
  padding: 8px 12px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  box-shadow: inset 0 0 0 1.5px transparent;
  color: var(--text-soft);
  cursor: pointer;
  gap: 10px;
  text-align: left;
  transition: box-shadow 180ms ease, color 180ms ease;
}

.theme-options button:hover,
.theme-options button.selected {
  color: var(--text);
}

.theme-options button.selected {
  box-shadow: inset 0 0 0 1.5px var(--accent);
}

.theme-options button span {
  font-size: var(--fs-ui);
  font-weight: 600;
}

.theme-swatch {
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: var(--radius);
}

.theme-swatch.linen {
  background: linear-gradient(135deg, #f6f0e2 55%, #7568b0 55%);
}

.theme-swatch.graphite {
  background: linear-gradient(135deg, #171821 55%, #aebde8 55%);
}

/* 配色方案色卡:窗边=预设藤紫/雾蓝(静态预览,同上两块的先例);
   Matugen=当前生效 token 的 MD3 四色点 */
.theme-swatch.hue-madobe {
  background: linear-gradient(135deg, #7568b0 50%, #aebde8 50%);
}

.theme-swatch.hue-matugen {
  background: conic-gradient(var(--accent) 0 25%, var(--gold) 25% 50%, var(--ribbon) 50% 75%, var(--online) 75% 100%);
}


.settings-model {
  display: grid;
  grid-template-columns: 14px minmax(0, 1fr);
  min-height: 48px;
  align-items: center;
  padding: 5px 13px;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
  color: var(--text);
  gap: 9px;
}

.settings-model > span:last-child {
  display: grid;
  min-width: 0;
  gap: 2px;
}

.settings-model strong,
.settings-model small {
  overflow-wrap: anywhere;
}

.settings-model strong {
  font-size: var(--fs-ui);
  font-weight: 600;
}

.settings-model small {
  color: var(--text-faint);
  font-size: 10.5px;
}

.capability-list {
  display: grid;
  margin: 0;
  padding: 2px 14px;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
  gap: 0;
}

.capability-list > div,
.about-row {
  display: flex;
  min-height: 37px;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  gap: 12px;
}

.capability-list > div:last-child {
  border-bottom: 0;
}

.capability-list dt,
.about-row span:first-child {
  color: var(--text);
  font-size: var(--fs-ui);
}

.capability-list dd,
.about-row span:last-child {
  margin: 0;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 10.5px;
  text-align: right;
  overflow-wrap: anywhere;
}

.about-section {
  border-bottom: 0;
}

.about-row {
  padding: 2px 14px;
  border-bottom: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--card-shadow);
}

.secondary-button,
.danger-button {
  display: inline-flex;
  white-space: nowrap;
  flex: none;
  min-height: 36px;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  border-radius: var(--radius);
  cursor: pointer;
  gap: 7px;
}

.secondary-button {
  border: 0;
  background: var(--surface-2);
  color: var(--text);
  font-weight: 600;
}

.secondary-button:hover:not(:disabled) {
  filter: brightness(1.05);
}

.secondary-button .icon-slot {
  width: 15px;
  height: 15px;
}

.danger-button {
  background: var(--danger);
  color: #fff;
  font-weight: 600;
}

.danger-button:hover:not(:disabled) {
  background: color-mix(in srgb, var(--danger) 84%, #ffffff);
}

.secondary-button:disabled,
.danger-button:disabled {
  opacity: 0.5;
}

.toast-region {
  position: fixed;
  top: 18px;
  left: 50%;
  z-index: 80;
  display: grid;
  width: auto;
  max-width: calc(calc(100vw / var(--ui-scale)) - 28px);
  transform: translateX(-50%);
  justify-items: center;
  pointer-events: none;
}

.toast {
  width: fit-content;
  max-width: min(340px, calc(calc(100vw / var(--ui-scale)) - 28px));
  margin-top: 7px;
  padding: 10px 14px;
  border: 0;
  border-left: 3px solid var(--online);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  box-shadow: var(--float-shadow);
  font-size: var(--fs-ui);
  line-height: 1.45;
  overflow-wrap: anywhere;
  animation: toast-in 250ms cubic-bezier(0.2, 0, 0, 1) both;
}

.toast.is-error {
  border-left-color: var(--danger);
}

.reset-dialog {
  width: min(440px, calc(calc(100vw / var(--ui-scale)) - 32px));
  padding: 0;
  border: 0;
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  box-shadow: var(--float-shadow);
}

.reset-dialog::backdrop {
  background: rgba(0, 0, 0, 0.58);
}

.reset-dialog form {
  margin: 0;
}

.reset-dialog header {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr);
  padding: 18px;
  gap: 12px;
}

.dialog-icon {
  display: grid;
  width: 36px;
  height: 36px;
  place-items: center;
  border-radius: var(--radius);
  background: var(--danger-soft);
  color: var(--danger);
}

.dialog-icon .icon-slot {
  width: 18px;
  height: 18px;
}

.reset-dialog h2 {
  margin: 1px 0 5px;
  font-size: 15px;
  font-weight: 600;
}

.reset-dialog p {
  margin: 0;
  color: var(--text-soft);
  font-size: var(--fs-meta);
  line-height: 1.6;
}

.reset-dialog footer {
  display: flex;
  justify-content: flex-end;
  padding: 11px 14px 14px;
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  gap: 8px;
}

/* /pop 的轮次多选列表:沿用 reset-dialog 的壳,中段是可滚动清单。 */
.pop-dialog {
  width: min(560px, calc(calc(100vw / var(--ui-scale)) - 32px));
}

.pop-dialog header {
  grid-template-columns: minmax(0, 1fr);
}

.pop-dialog-list {
  max-height: min(48vh, 420px);
  overflow-y: auto;
  border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  padding: 6px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.pop-dialog-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 7px 8px;
  border-radius: var(--radius);
  cursor: pointer;
  font-size: var(--fs-meta);
}

.pop-dialog-row:hover {
  background: var(--surface-2);
}

.pop-dialog-row .pop-row-preview {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}

.pop-dialog-row .pop-row-meta {
  color: var(--text-faint);
  white-space: nowrap;
}

.pop-dialog-all {
  margin-right: auto;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--text-soft);
  font-size: var(--fs-meta);
  cursor: pointer;
}

.pop-dialog-empty {
  padding: 18px;
  text-align: center;
  color: var(--text-soft);
  font-size: var(--fs-meta);
}

.noscript-state {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #111512;
  color: #e7ece8;
  font-family: system-ui, sans-serif;
}

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

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

@media (max-width: 1078px) {
  :root {
    --sidebar-width: 224px;
  }

  .model-label {
    max-width: 96px;
  }

}

@media (max-width: 836px) {


  .persona-starter-fields {
    grid-template-columns: 1fr;
  }

  .app-shell {
    display: block;
  }

  .sidebar {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(calc(86vw / var(--ui-scale)), 320px);
    padding-top: env(safe-area-inset-top);
    box-shadow: var(--float-shadow);
    transform: translateX(-102%);
    transition: transform 180ms ease;
  }

  .sidebar.open {
    transform: translateX(0);
  }

  .sidebar-close,
  .mobile-menu-button {
    display: inline-grid;
  }

  /* 窄屏上侧栏是抽屉,只有「关掉」一个语义。「收起」是宽屏那套(收成一条窄
     轨),两个一起出现就是两个长得不一样的关闭按钮。 */
  .sidebar-collapse-button {
    display: none;
  }

  .sidebar-close,
  .mobile-menu-button {
    width: 36px;
    height: 36px;
    flex-basis: 36px;
  }

  .main-stage {
    width: 100%;
    height: var(--app-height, calc(100dvh / var(--ui-scale)));
  }

  .model-button {
    justify-content: center;
    width: 42px;
    padding: 0;
  }

  .model-label {
    display: none;
  }

  .model-menu {
    width: min(286px, calc(calc(100vw / var(--ui-scale)) - 16px));
    max-height: min(430px, calc(calc(100dvh / var(--ui-scale)) - 140px));
  }

  .timeline {
    padding: 22px 13px 32px;
  }

  .conversation-media {
    max-width: min(100%, 190px);
  }

  .conversation-media-visual,
  .conversation-media img {
    max-width: min(100%, 190px);
  }

  .conversation-media img {
    max-height: 190px;
  }

  .user-bubble {
    max-width: 86%;
  }

  .revision-editor {
    width: 100%;
  }

  .user-attachments {
    max-width: 86%;
  }

  .assistant-message {
    max-width: 100%;
    padding-left: 38px;
  }

  .turn-status-line {
    padding-left: 38px;
  }

  .assistant-label img {
    width: 28px;
    height: 28px;
  }

  .tool-title .tool-summary {
    max-width: calc(40vw / var(--ui-scale));
  }

  .question-answer-summary,
  .answered-question-list {
    padding-left: 12px;
  }

  .persisted-question-wrap {
    padding-left: 0;
  }

  .composer-dock {
    padding: 7px 9px max(7px, env(safe-area-inset-bottom));
  }

  .composer textarea {
    min-height: 64px;
    max-height: 120px;
    padding-top: 10px;
  }

  .composer-footer {
    min-height: 39px;
  }

  .composer-controls {
    gap: 5px;
  }

  .attach-button {
    width: 36px;
    height: 36px;
    flex-basis: 36px;
  }

  .composer-context {
    width: auto;
    min-width: 0;
    max-width: 220px;
    flex: 1 1 auto;
  }

  .composer-submit {
    flex: 1 1 auto;
    justify-content: flex-end;
  }

  .send-button {
    width: 36px;
    height: 36px;
    flex-basis: 36px;
    border-radius: var(--radius);
  }

  .jump-bottom-button {
    right: 12px;
    bottom: 119px;
  }

  .empty-state {
    padding: 22px 13px 34px;
  }

  .empty-visual {
    height: 145px;
    margin-bottom: 15px;
  }

  .empty-copy h1 {
    font-size: 20px;
  }

  .prompt-grid {
    margin-top: 17px;
  }

  .settings-layout {
    grid-template-columns: 1fr;
    grid-template-rows: auto minmax(0, 1fr);
  }

  /* 横滚标签条:background-attachment: local 的遮罩随内容滚动,只在还有内容没露出来的那一侧显示渐隐 */
  .settings-nav {
    display: flex;
    overflow-x: auto;
    padding: 8px;
    gap: 5px;
    scrollbar-width: none;
    background:
      linear-gradient(to right, var(--app-bg) 40%, transparent) left / 36px 100% no-repeat local,
      linear-gradient(to left, var(--app-bg) 40%, transparent) right / 36px 100% no-repeat local,
      linear-gradient(to right, color-mix(in srgb, var(--text) 16%, transparent), transparent) left / 18px 100% no-repeat scroll,
      linear-gradient(to left, color-mix(in srgb, var(--text) 16%, transparent), transparent) right / 18px 100% no-repeat scroll;
  }

  .settings-nav::-webkit-scrollbar {
    display: none;
  }

  .settings-nav button {
    min-width: max-content;
    min-height: 38px;
    padding: 0 11px;
    font-size: 13px;
  }

  .settings-nav button.active::before {
    top: auto;
    right: 10px;
    bottom: 3px;
    left: 10px;
    width: auto;
    height: 3px;
  }

  .settings-section {
    padding: 18px 15px;
  }

  .settings-footer {
    align-items: stretch;
    flex-direction: column;
  }

  .settings-footer > div {
    width: 100%;
  }

  .settings-footer > div > button {
    flex: 1;
  }

  .toast-region {
    top: calc(12px + env(safe-area-inset-top));
    left: 50%;
  }
}

@media (max-width: 473px) {
  .stage-float .icon-button {
    width: 32px;
    height: 32px;
    flex-basis: 32px;
  }

  .tool-title strong,
  .tool-title small {
    white-space: normal;
    overflow-wrap: anywhere;
  }

  .question-heading {
    padding-right: 16px;
    gap: 8px;
  }

  .prompt-grid {
    grid-template-columns: 1fr;
    width: min(100%, 360px);
    gap: 6px;
  }

  .prompt-grid button {
    min-height: 41px;
  }

  .character-count {
    max-width: 100px;
  }

  /* 窄屏上进度条挤在一排控件中间,细得看不出刻度,数字本身已经说明问题。 */
  .composer-context .context-track {
    display: none;
  }

  .composer-context {
    display: grid;
    width: auto;
    min-width: 0;
    max-width: none;
    flex: 1 1 auto;
  }

  .composer-context .context-heading {
    justify-content: flex-end;
  }

  /* 窄屏下隐藏「上下文」标签,把宽度让给数字 */
  .composer-context .context-heading > span:first-child {
    display: none;
  }

  .composer-state {
    max-width: 58px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .composer-submit {
    gap: 4px;
  }

  .character-count {
    max-width: 70px;
    font-size: 9px;
  }

  .settings-layout {
    grid-template-columns: 1fr;
  }

  .settings-nav {
    display: flex;
    padding: 6px 8px;
    overflow-x: auto;
    gap: 3px;
  }

  .settings-nav button {
    min-width: max-content;
    min-height: 29px;
    padding: 0 8px;
  }

  .settings-footer {
    align-items: flex-end;
    flex-direction: column;
    padding: 8px 10px max(8px, env(safe-area-inset-bottom));
  }

  .settings-footer > span {
    width: 100%;
  }
}

@media (max-height: 360px) {
  .composer-dock.has-pending-question .composer {
    display: none;
  }

  .composer-dock.has-pending-question .question-dock {
    max-height: max(0px, calc(var(--app-height, calc(100dvh / var(--ui-scale))) - 88px));
    margin-bottom: 0;
  }
}

@media (hover: none) {
  .message-actions button,
  .assistant-meta button,
  .session-menu-button {
    opacity: 1;
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    transition-duration: 0.01ms !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ═══════════════════════════ 控制台(数据统计) ═══════════════════════════ */
/* 图表专用色阶:从主题三色派生,亮/暗各自过了色觉与对比度校验;
   --chart-4 是模型环形图第四色(蓝→金→紫→玫 的环邻组合校验通过)。 */
:root {
  --chart-1: #6b87d9; --chart-2: #b08427; --chart-3: #c65f7f; --chart-4: #8d7ce4;
  --heat-0: #262a3e; --heat-1: #303c66; --heat-2: #42549b; --heat-3: #5a71c4; --heat-4: #82a1ea;
}
body[data-theme="linen"] {
  --chart-1: #5d6cc4; --chart-2: #8f6b1e; --chart-3: #c2426e; --chart-4: #6d51c4;
  --heat-0: #ece4d1; --heat-1: #cdc7e8; --heat-2: #a8a0d6; --heat-3: #837ac0; --heat-4: #5b4fa0;
}

.console-view { position: fixed; inset: 0; z-index: 40; display: flex; background: var(--app-bg); }
.console-view[hidden] { display: none; }

.con-rail { width: 216px; flex: none; display: flex; flex-direction: column;
  background: var(--sidebar-bg); border-right: 1px solid var(--line); transition: width .18s; }
.con-rail-head { display: flex; align-items: center; gap: 8px; padding: 15px 14px 11px; }
.con-rail-head b { font-size: 14px; font-weight: 600; white-space: nowrap; }
.con-rail-head .icon-button { margin-left: auto; }
.con-rail-nav { flex: 1; padding: 6px 8px; display: flex; flex-direction: column; gap: 3px; }
.con-rail-item { display: flex; align-items: center; gap: 9px; padding: 8px 10px; border-radius: var(--radius);
  background: transparent; color: var(--text-soft); text-align: left; white-space: nowrap; width: 100%; cursor: pointer; }
.con-rail-item:hover { background: var(--surface-2); color: var(--text); }
.con-rail-item.active { background: var(--accent-soft); color: var(--md-sys-color-on-primary-container); }
.con-rail-item .icon-slot { width: 15px; height: 15px; flex: none; }
.con-rail-foot { padding: 8px; border-top: 1px solid var(--line); }
.console-view.rail-collapsed .con-rail { width: 56px; }
.console-view.rail-collapsed .con-rail b,
.console-view.rail-collapsed .con-rail-item span:not(.icon-slot) { display: none; }
.console-view.rail-collapsed .con-rail-item { justify-content: center; padding: 8px; }
.console-view.rail-collapsed .con-rail-head { justify-content: center; padding-inline: 0; }
.console-view.rail-collapsed .con-rail-head .icon-button { margin: 0; }

.con-main { flex: 1; min-width: 0; overflow-y: auto; }

/* 手机:216px 侧栏会把正文挤到一半宽,改成顶部横滚标签条,「返回」缩成箭头钉在最左 */
@media (max-width: 836px) {
  .console-view { flex-direction: column; }
  .con-rail, .console-view.rail-collapsed .con-rail {
    width: auto; flex-direction: row; align-items: stretch; border-right: 0;
    border-bottom: 1px solid var(--line); padding-top: env(safe-area-inset-top); transition: none;
  }
  .con-rail-head { display: none; }
  .con-rail-nav {
    flex: 1 1 auto; min-width: 0; flex-direction: row; align-items: center; gap: 2px; padding: 6px 8px;
    overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
  }
  .con-rail-nav::-webkit-scrollbar { display: none; }
  .con-rail-foot { order: -1; flex: none; display: flex; align-items: center; border-top: 0; border-right: 1px solid var(--line); padding: 6px 4px 6px 8px; }
  .con-rail-item, .console-view.rail-collapsed .con-rail-item {
    width: auto; flex: none; justify-content: flex-start; padding: 7px 10px; font-size: var(--fs-meta);
  }
  .console-view.rail-collapsed .con-rail-item span:not(.icon-slot) { display: inline; }
  .con-rail-foot .con-rail-item { padding: 7px 8px; }
  .con-rail-foot .con-rail-item > span:not(.icon-slot) { display: none; }
  .con-main { flex: 1 1 auto; min-height: 0; }
}
.con-inner { max-width: 1080px; margin: 0 auto; padding: 22px 26px 40px; }
.con-head { display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap; margin-bottom: 18px; }
.con-head h2 { margin: 0; font-family: var(--serif); font-size: 22px; font-weight: 600; letter-spacing: .01em; }
.con-head small { color: var(--text-soft); font-size: var(--fs-meta); }
.con-head .con-segmented { margin-left: auto; }
.con-segmented { display: inline-flex; background: var(--surface-soft); border-radius: var(--radius); padding: 2px; }
.con-segmented button { padding: 3px 12px; border-radius: var(--radius); font-size: var(--fs-meta); color: var(--text-soft);
  background: none; border: none; cursor: pointer; }
.con-segmented button.on { background: var(--surface-2); color: var(--text); box-shadow: var(--bubble-shadow); }

.u-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 12px; margin-bottom: 12px; }
.u-tile { background: var(--surface-1); border-radius: var(--radius); padding: 14px 16px 13px; box-shadow: var(--card-shadow);
  display: flex; flex-direction: column; }
.u-tile-label { display: flex; align-items: center; gap: 6px; font-size: var(--fs-meta);
  color: var(--text-soft); margin-bottom: 8px; }
.u-tile-label svg { width: 13px; height: 13px; stroke: currentColor; stroke-width: 1.8; fill: none;
  stroke-linecap: round; stroke-linejoin: round; color: var(--text-faint); flex: none; }
.u-tl-right { margin-left: auto; }
.u-tile-value { font-size: 25px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.u-tile-value small { font-size: 13px; font-weight: 400; color: var(--text-soft); margin-left: 2px; }
.u-tile-sub { display: flex; align-items: center; gap: 7px; margin-top: 5px;
  font-size: var(--fs-micro); color: var(--text-soft); }
.u-delta { font-size: var(--fs-micro); padding: 1px 7px; border-radius: var(--radius); font-variant-numeric: tabular-nums; }
.u-delta.up { background: color-mix(in srgb, var(--online) 18%, transparent); color: var(--online); }
.u-delta.down { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.u-tile-flex { flex-direction: row; align-items: center; gap: 14px; }
.u-tf-main { flex: 1; min-width: 0; }
.u-ring { width: 58px; height: 58px; flex: none; }

.u-card { background: var(--surface-1); border-radius: var(--radius); box-shadow: var(--card-shadow);
  padding: 15px 17px; margin-bottom: 12px; }
.u-card-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 12px; flex-wrap: wrap; }
.u-card-head h3 { margin: 0; font-size: 14px; font-weight: 600; }
.u-hint { font-size: var(--fs-micro); color: var(--text-faint); }
.u-legend { margin-left: auto; display: flex; gap: 13px; font-size: var(--fs-micro); color: var(--text-soft); }
.u-legend i { display: inline-block; width: 9px; height: 9px; border-radius: var(--radius-sm); margin-right: 5px; }

.u-heat-body { display: flex; gap: 8px; align-items: stretch; }
.u-heat-days { display: grid; grid-template-rows: repeat(7, 1fr); gap: 3px; width: 15px; flex: none; margin-top: 18px; }
.u-heat-days span { font-size: var(--fs-micro); color: var(--text-faint); line-height: 1; align-self: center; }
.u-heat-wrap { overflow-x: auto; flex: 1; min-width: 0; }
.u-heat-months { position: relative; height: 15px; margin-bottom: 3px; min-width: 680px; }
.u-heat-months span { position: absolute; top: 0; font-size: var(--fs-micro); color: var(--text-faint); white-space: nowrap; }
.u-heatmap { display: grid; grid-auto-flow: column; grid-template-rows: repeat(7, 1fr);
  grid-auto-columns: 1fr; gap: 3px; min-width: 680px; }
.u-heatmap i, .u-heat-scale i { border-radius: var(--radius-sm); background: var(--heat-0); }
.u-heatmap i { width: auto; height: auto; aspect-ratio: 1; }
.u-heatmap i:hover { outline: 1.5px solid var(--line-strong); outline-offset: 1px; }
.u-heatmap i[data-l="1"], .u-heat-scale i[data-l="1"] { background: var(--heat-1); }
.u-heatmap i[data-l="2"], .u-heat-scale i[data-l="2"] { background: var(--heat-2); }
.u-heatmap i[data-l="3"], .u-heat-scale i[data-l="3"] { background: var(--heat-3); }
.u-heatmap i[data-l="4"], .u-heat-scale i[data-l="4"] { background: var(--heat-4); }
.u-heat-scale { display: flex; align-items: center; gap: 4px; margin-top: 9px;
  font-size: var(--fs-micro); color: var(--text-faint); }
.u-heat-scale i { width: 11px; height: 11px; }

.u-chart-wrap { display: flex; }
.u-chart-y { position: relative; width: 44px; flex: none; height: 214px; }
.u-chart-y span { position: absolute; right: 10px; transform: translateY(50%);
  font-size: var(--fs-micro); color: var(--text-faint); font-family: var(--font-mono); }
.u-chart-plot { flex: 1; min-width: 0; }
.u-bars { position: relative; display: flex; align-items: flex-end; height: 214px;
  padding-top: 14px; border-bottom: 1px solid var(--line-strong); }
.u-gridline { position: absolute; left: 0; right: 0; border-top: 1px dashed var(--line); pointer-events: none; }
.u-bar-slot { flex: 1; min-width: 0; display: flex; justify-content: center; align-items: flex-end;
  position: relative; z-index: 1; height: 100%; }
.u-bar-col:hover { filter: brightness(1.12); }
.u-bar-col { width: 62%; max-width: 38px; min-width: 5px; min-height: 8px; display: flex; flex-direction: column-reverse; gap: 2px;
  transform-origin: bottom; animation: u-rise .35s ease; }
@keyframes u-rise { from { transform: scaleY(.35); opacity: .4; } }
.u-bar-col i:last-of-type { border-radius: var(--radius-sm) var(--radius-sm) 0 0; }
.u-bar-col i { width: 100%; display: block; }
.u-bar-col i.s1 { background: var(--chart-1); }
.u-bar-col i.s2 { background: var(--chart-2); }
.u-bar-col i.s3 { background: var(--chart-3); }
.u-bar-x { display: flex; margin-top: 6px; }
.u-bar-x span { flex: 1; min-width: 0; text-align: center; font-size: var(--fs-micro); color: var(--text-faint);
  font-family: var(--font-mono); overflow: visible; white-space: nowrap; }
.u-empty { padding: 26px 0; text-align: center; color: var(--text-faint); font-size: var(--fs-ui); }

.u-chart-tip { position: fixed; z-index: 80; pointer-events: none; background: var(--surface-3);
  border: 1px solid var(--line-strong); border-radius: var(--radius); padding: 8px 11px;
  font-size: var(--fs-meta); box-shadow: var(--float-shadow); display: none; min-width: 150px; }
.u-chart-tip b { display: block; margin-bottom: 4px; }
.u-chart-tip .row { display: flex; justify-content: space-between; gap: 14px; color: var(--text-soft); }
.u-chart-tip .row em { font-style: normal; font-family: var(--font-mono); color: var(--text);
  font-variant-numeric: tabular-nums; }
.u-chart-tip .row i { display: inline-block; width: 8px; height: 8px; border-radius: var(--radius-sm); margin-right: 5px; }

.u-model-body { display: flex; align-items: flex-start; gap: 26px; flex-wrap: wrap; }
/* 来源内细项条(主动回复判断等):整行占满,排在环形图与表格之下。 */
.u-kind-strip { flex-basis: 100%; display: flex; flex-wrap: wrap; gap: 8px; }
.u-kind-item { display: inline-flex; align-items: baseline; gap: 10px; padding: 6px 12px;
  border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface-2);
  font-size: 12px; color: var(--text-faint); }
.u-kind-item b { font-weight: 600; color: var(--text); }
.u-kind-item em { font-style: normal; font-family: var(--font-mono);
  font-variant-numeric: tabular-nums; }
/* 模型表里的细项行:同模型同色,空心点+徽章表明用途不同。 */
.u-dot-kind { position: relative; opacity: .5; }
.u-kind-tag { margin-left: 6px; padding: 1px 6px; border-radius: var(--radius);
  border: 1px solid var(--border); font-size: 10px; font-weight: 500;
  color: var(--text-faint); vertical-align: 1px; }
/* 环形图固定在卡片左上:模型行数一变,居中对齐会让整个环上下漂(08-26
   用户点名切标签页时饼图位置乱跳)。 */
.u-donut-wrap { position: relative; width: 188px; height: 188px; flex: none;
  margin-inline: 6px; align-self: flex-start; margin-top: 6px; }
.u-donut-wrap svg { width: 100%; height: 100%; display: block; }
.u-donut-wrap circle { transition: stroke-width .12s; }
.u-donut-center { position: absolute; inset: 0; display: grid; place-items: center;
  text-align: center; pointer-events: none; }
.u-donut-center b { display: block; font-size: 22px; font-variant-numeric: tabular-nums; }
.u-donut-center .u-donut-sub { display: block; margin-top: 2px; font-size: 11px;
  color: var(--text-faint); font-variant-numeric: tabular-nums; }
.u-donut-center small { color: var(--text-soft); font-size: var(--fs-micro); }
.u-table-scroll { overflow-x: auto; flex: 1; min-width: 340px; }
.u-table { width: 100%; border-collapse: collapse; font-size: var(--fs-ui); }
.u-table th { text-align: left; font-size: var(--fs-micro); color: var(--text-soft); font-weight: 500;
  padding: 4px 10px 8px; border-bottom: 1px solid var(--line); white-space: nowrap; }
.u-table th.num { text-align: right; }
.u-table td { padding: 9px 10px; border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums; white-space: nowrap; }
.u-table tbody tr:last-child td { border-bottom: none; }
.u-table tbody tr:hover td { background: var(--surface-2); }
.u-table tbody tr.hl td { background: var(--surface-2); }
.u-table tfoot td { border-top: 1px solid var(--line-strong); border-bottom: none;
  padding: 9px 10px; font-weight: 600; }
.u-table .num { text-align: right; font-family: var(--font-mono); font-size: var(--fs-meta); }
.u-model-name b { display: block; font-weight: 500; }
.u-model-name small { color: var(--text-faint); font-size: var(--fs-micro); }
.u-dot { display: inline-block; width: 9px; height: 9px; border-radius: var(--radius-sm); margin-right: 7px; }
.u-cache-pill { font-size: var(--fs-micro); padding: 1px 8px; border-radius: var(--radius);
  background: color-mix(in srgb, var(--online) 16%, transparent); color: var(--online); }
.u-records-table td { padding: 11px 10px; }
.u-records-table .time { font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--text-faint); width: 70px; }
.u-records-table .u-day-row td { padding: 16px 10px 7px; font-size: var(--fs-micro); color: var(--text-faint);
  border-bottom: none; }
.u-records-table tbody .u-day-row:hover td { background: none; }
.u-records-table tbody tr:first-child.u-day-row td { padding-top: 4px; }
.u-type-pill { font-size: var(--fs-micro); padding: 1px 9px; border-radius: var(--radius); }
.u-type-pill.t-chat { background: var(--surface-2); color: var(--text-soft); }
.u-type-pill.t-aux { background: var(--gold-soft); color: var(--gold); }
/* 细项(主动回复判断等)与普通辅助调用区分:同一栏里"判断"要一眼可辨。 */
.u-type-pill.t-kind { background: var(--accent-soft);
  color: var(--md-sys-color-on-primary-container); }
body[data-theme="linen"] .u-type-pill.t-aux { color: var(--md-sys-color-on-secondary-container); }
.u-src-pill { font-size: var(--fs-micro); padding: 1px 8px; border-radius: var(--radius);
  background: var(--surface-2); color: var(--text-soft); }

/* 与手机布局同一断点(836,侧栏抽屉/控制台顶部标签条那条线)。 */
@media (max-width: 836px) {
  .con-inner { padding: 16px 14px 32px; }
  /* 环形图不再站在表格左边:窄屏里两者并排放不下,表格被挤成一条。
     竖排:环形图居中在上,表格整行在下。 */
  .u-model-body { flex-direction: column; align-items: stretch; gap: 12px; }
  .u-donut-wrap { width: 160px; height: 160px; margin: 0 auto; align-self: center; }
  /* 手机端表格:滚动容器不再撑最小宽,列间距收紧,并裁掉次要列——
     整行塞不进屏幕时宁可少列也不让页面横向溢出。 */
  .u-table-scroll { min-width: 0; width: 100%; }
  .u-table th, .u-table td { padding-left: 6px; padding-right: 6px; }
  /* 模型消耗明细:留 模型/占比/消费/缓存命中,裁 请求/输入/输出。 */
  .u-models-table th:nth-child(3), .u-models-table td:nth-child(3),
  .u-models-table th:nth-child(4), .u-models-table td:nth-child(4),
  .u-models-table th:nth-child(5), .u-models-table td:nth-child(5) { display: none; }
  /* 最近调用:留 时间/模型/消费/缓存命中/类型,裁 来源/输入/输出。 */
  .u-records-table th:nth-child(2), .u-records-table td:nth-child(2),
  .u-records-table th:nth-child(4), .u-records-table td:nth-child(4),
  .u-records-table th:nth-child(5), .u-records-table td:nth-child(5) { display: none; }
  .u-donut-wrap { margin-inline: auto; }
}

/* ═ LaTeX 公式(KaTeX) ═ 块级横向滚动防溢出;颜色随 currentColor 跟主题。 */
.markdown-body .math-block { overflow-x: auto; overflow-y: hidden; padding: 6px 2px; margin: 10px 0; }
.markdown-body .math-block .katex-display { margin: 0; }
.markdown-body .math-inline .katex { font-size: 1.05em; }
.markdown-table-scroll .math-inline .katex { font-size: 1em; }
.u-rec-filters { margin-left: auto; display: flex; gap: 8px; }
.u-rec-filters select { font: inherit; font-size: var(--fs-meta); color: var(--text-soft);
  background: var(--surface-soft); border: 1px solid var(--line); border-radius: var(--radius); padding: 3px 8px; }
.u-rec-filters select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* CSP style-src 'self' 拦 HTML 解析期的内联样式:静态标注一律走 class。 */
.u-refresh { align-self: center; margin-left: -6px; }
/* 清空排在刷新右边;危险动作用弱化底色,悬停才显红。 */
.u-clear { align-self: center; margin-left: -2px; color: var(--text-faint); }
.u-clear:hover { color: var(--danger, #c0392b); }
.u-heat-days span:nth-child(1) { grid-row: 1; }
.u-heat-days span:nth-child(2) { grid-row: 3; }
.u-heat-days span:nth-child(3) { grid-row: 5; }
.u-legend .u-lg1 { background: var(--chart-1); }
.u-legend .u-lg2 { background: var(--chart-2); }
.u-legend .u-lg3 { background: var(--chart-3); }

/* ═ 视频消息 ═ 气泡内居中,不超视口;网页全屏铺满窗口(object-fit contain)。 */
.markdown-body .video-card { display: flex; flex-direction: column; align-items: center; margin: 10px 0 4px; }
.video-shell { position: relative; width: min(100%, 480px); }
.video-shell video { display: block; width: 100%; max-height: 56vh; border-radius: var(--radius);
  background: #000; box-shadow: var(--card-shadow); }
.vfs-btn { position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; border-radius: var(--radius);
  background: rgba(0, 0, 0, .48); color: #fff; border: none; cursor: pointer;
  display: grid; place-items: center; opacity: 0; transition: opacity .15s; }
.vfs-btn svg { width: 15px; height: 15px; stroke: currentColor; stroke-width: 1.8; fill: none;
  stroke-linecap: round; stroke-linejoin: round; }
.video-shell:hover .vfs-btn, .vfs-btn:focus-visible { opacity: 1; }
.video-shell.webfs { position: fixed; inset: 0; z-index: 70; width: auto; max-width: none;
  background: rgba(0, 0, 0, .93); display: grid; place-items: center; padding: 28px; }
.video-shell.webfs video { width: 100%; height: 100%; max-height: none;
  object-fit: contain; border-radius: var(--radius); box-shadow: none; }
.video-shell.webfs .vfs-btn { top: 16px; right: 16px; opacity: 1; }
.video-caption { margin-top: 7px; font-size: var(--fs-micro); color: var(--text-soft);
  max-width: min(100%, 480px); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* 斜杠命令的补全菜单。挂在 .composer-dock（position: relative）上，从输入框
   上方弹出——往下弹会被输入框自己盖住。 */
.commandMenu {
  position: absolute;
  /* 贴着输入框会看不出这是两个东西；留一段间距，并收窄到内容宽度， */
  /* 免得一条两行的菜单横贯整个对话区，比输入框还显眼。 */
  bottom: calc(100% - 2px);
  left: max(18px, calc((100% - 940px) / 2));
  z-index: 40;
  width: min(520px, calc(100% - 2 * max(18px, calc((100% - 940px) / 2))));
  max-height: min(320px, 50vh);
  margin-bottom: 10px;
  overflow-y: auto;
  padding: 6px;
  border: 1px solid var(--border-1, rgba(128, 128, 128, 0.22));
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--float-shadow);
}

.commandMenuItem {
  display: flex;
  gap: 14px;
  align-items: baseline;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.commandMenuItem:hover,
.commandMenuItem.isActive {
  background: var(--surface-2);
}

.commandMenuName {
  flex: 0 0 auto;
  font-family: var(--mono-font, monospace);
}

.commandMenuHelp {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  color: var(--text-muted, inherit);
  font-size: 0.86em;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 命令回执：复用系统事件那条居中小条（后台任务完成同款）。差别只有一点——
   系统事件是一行短标签，可以 nowrap + 省略号；命令回执常常是一句要读完的
   解释，截断了等于没说，所以允许换行。 */
/* 命令还在跑：文字变淡 + 呼吸，和跑完的结果区分开。 */
.system-event.is-command-result.is-pending > span {
  opacity: 0.62;
  animation: command-pending-pulse 1.4s ease-in-out infinite;
}

@keyframes command-pending-pulse {
  0%,
  100% {
    opacity: 0.62;
  }

  50% {
    opacity: 0.35;
  }
}

.system-event.is-command-result > span {
  max-width: min(560px, 80%);
  overflow: visible;
  text-overflow: clip;
  white-space: normal;
  line-height: 1.5;
  padding: 6px 12px;
  text-align: center;
}

.system-event.is-command-result.is-error > span {
  background: color-mix(in srgb, var(--danger) 14%, var(--surface-2));
  color: var(--danger);
}

/* ── 文件分享面板(shared.js) ── */

.shared-files-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--md-sys-color-surface) 45%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}

.shared-files-panel {
  width: min(680px, 100%);
  max-height: min(72vh, 640px);
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  color: var(--text);
  border: 1px solid color-mix(in srgb, var(--text-faint) 40%, transparent);
  border-radius: var(--radius);
  box-shadow: 0 18px 48px rgba(0, 0, 0, 0.35);
  overflow: hidden;
}

.shared-files-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 14px 18px;
  border-bottom: 1px solid color-mix(in srgb, var(--text-faint) 35%, transparent);
}

.shared-files-hint {
  flex: 1;
  font-size: 12px;
  color: var(--text-soft);
}

.shared-files-refresh,
.shared-files-close {
  border: none;
  background: transparent;
  color: var(--text-soft);
  font-size: 16px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: var(--radius);
}

.shared-files-refresh:hover,
.shared-files-close:hover {
  background: var(--surface-2);
  color: var(--text);
}

/* 批量操作工具条:与行内胶囊按钮同族,禁用态压暗提示不可点 */
.shared-files-toolbar {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 8px 18px;
  border-bottom: 1px solid color-mix(in srgb, var(--text-faint) 22%, transparent);
}

.shared-files-tool {
  display: inline-flex;
  align-items: center;
  flex: none;
  white-space: nowrap;
  gap: 6px;
  border: 1px solid color-mix(in srgb, var(--text-faint) 45%, transparent);
  background: var(--surface-2);
  color: var(--text);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: var(--radius);
  cursor: pointer;
}

.shared-files-tool svg {
  flex: none;
  width: 13px;
  height: 13px;
}

.shared-files-tool:hover:not(:disabled) {
  background: var(--surface-3);
}

.shared-files-tool:disabled {
  opacity: 0.45;
  cursor: default;
}

.shared-files-tool.is-danger {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
}

.shared-files-upload-status {
  margin-left: auto;
  font-size: 12px;
  color: var(--text-soft);
  max-width: 50%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.shared-files-panel.is-dropping {
  outline: 2px dashed var(--accent);
  outline-offset: -6px;
}

.shared-files-check {
  flex: none;
  width: 15px;
  height: 15px;
  margin: 0;
  accent-color: var(--accent);
  cursor: pointer;
}

.shared-files-list {
  overflow-y: auto;
  padding: 10px 14px 16px;
}

.shared-files-empty {
  margin: 18px 6px;
  color: var(--text-soft);
  font-size: 13px;
}

.shared-files-row {
  padding: 10px 8px;
  border-bottom: 1px solid color-mix(in srgb, var(--text-faint) 22%, transparent);
}

.shared-files-row:last-child {
  border-bottom: none;
}

.shared-files-row-head {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 0;
}

.shared-files-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  color: var(--text-soft);
}

.shared-files-icon svg {
  width: 16px;
  height: 16px;
}

.shared-files-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 14px;
}

.shared-files-meta {
  flex: none;
  font-size: 12px;
  color: var(--text-soft);
}

.shared-files-actions {
  display: flex;
  gap: 8px;
  margin-top: 8px;
  flex-wrap: wrap;
}

.shared-files-action {
  white-space: nowrap;
  border: 1px solid color-mix(in srgb, var(--text-faint) 45%, transparent);
  background: var(--surface-2);
  color: var(--text);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: var(--radius);
  cursor: pointer;
}

.shared-files-action:hover {
  background: var(--surface-3);
}

.shared-files-action.is-danger {
  color: var(--danger);
  border-color: color-mix(in srgb, var(--danger) 45%, transparent);
}

.shared-files-preview {
  margin-top: 10px;
}

.shared-files-preview img {
  max-width: 100%;
  max-height: 320px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  display: block;
}

/* hidden 属性必须赢过 display:flex,否则面板关不上 */
.shared-files-overlay[hidden] {
  display: none;
}

/* 手机:面板贴边、提示文案让位给按钮、行内胶囊加高到可点 */
@media (max-width: 836px) {
  .shared-files-overlay { padding: 12px; }
  .shared-files-panel { max-height: min(84vh, 720px); }
  .shared-files-header { padding: 12px 14px; }
  .shared-files-toolbar { padding: 8px 14px; }
  .shared-files-list { padding: 8px 10px 14px; }
  .shared-files-upload-status { flex: 1 1 100%; max-width: none; margin-left: 0; }
  .shared-files-action { padding: 6px 12px; }
}

@media (max-width: 473px) {
  .shared-files-hint { display: none; }
}

/* ── 气泡内分享附件卡片(音频/视频/文件是一个视觉家族:8px 圆角 + --line 边框 + 悬停染 accent) ── */

.shared-attachment {
  margin-top: 8px;
  max-width: 420px;
}

.shared-attachment-preview img {
  max-width: 100%;
  max-height: 300px;
  border-radius: var(--radius);
  border: 1px solid var(--line);
  display: block;
  margin-bottom: 6px;
}

/* 视频容器:黑底收边,原生控件保留 */
.media-video-shell {
  border-radius: var(--radius);
  border: 1px solid var(--line);
  overflow: hidden;
  background: var(--md-sys-color-surface-container-lowest);
  margin-bottom: 6px;
  transition: border-color 0.15s ease;
}

.media-video-shell:hover {
  border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
}

.media-video-shell video {
  display: block;
  width: 100%;
  max-height: 300px;
  background: #000;
}

.shared-files-preview .media-video-shell video {
  max-height: 320px;
}

.shared-attachment-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  text-decoration: none;
  min-width: 0;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.shared-attachment-row:hover {
  background: var(--surface-2);
  border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
}

.shared-attachment-icon {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius);
  background: color-mix(in srgb, var(--accent-soft) 55%, transparent);
  color: var(--accent);
}

.shared-attachment-icon svg {
  width: 16px;
  height: 16px;
}

.shared-attachment-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 13px;
}

.shared-attachment-meta {
  flex: none;
  font-size: 12px;
  color: var(--text-soft);
}

.shared-attachment-download {
  flex: none;
  display: inline-flex;
  align-items: center;
  color: var(--text-soft);
  transition: color 0.15s ease;
}

.shared-attachment-download svg {
  width: 15px;
  height: 15px;
}

.shared-attachment-row:hover .shared-attachment-download {
  color: var(--accent);
}

/* ── 自定义音频播放器 ── */

.media-audio-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 12px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  transition: border-color 0.15s ease;
}

.media-audio-card:hover,
.media-audio-card.is-playing {
  border-color: color-mix(in srgb, var(--accent) 40%, var(--line));
}

.media-audio-card audio {
  display: none;
}

.media-audio-head {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

.media-audio-cover {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: var(--radius);
  background: linear-gradient(135deg, var(--accent-soft), color-mix(in srgb, var(--coral-soft) 55%, var(--accent-soft)));
  color: var(--user-text);
}

.media-audio-cover svg {
  width: 20px;
  height: 20px;
}

.media-audio-card.is-playing .media-audio-cover {
  color: color-mix(in srgb, var(--user-text) 80%, var(--accent-strong));
}

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

.media-audio-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.media-audio-meta {
  margin-top: 2px;
  font-size: 12px;
  color: var(--text-soft);
}

.media-audio-card.is-error .media-audio-meta {
  color: var(--danger);
}

.media-audio-controls {
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
}

.media-audio-play {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
  color: var(--inverse-text);
  cursor: pointer;
  transition: background 0.15s ease, transform 0.1s ease;
}

.media-audio-play:hover {
  background: var(--accent-strong);
}

.media-audio-play:active {
  transform: scale(0.94);
}

.media-audio-play svg {
  width: 15px;
  height: 15px;
}

.media-audio-time {
  flex: none;
  font-size: 11px;
  font-variant-numeric: tabular-nums;
  color: var(--text-soft);
  min-width: 32px;
  text-align: center;
}

.media-audio-track {
  flex: 1;
  min-width: 48px;
  height: 16px;
  display: flex;
  align-items: center;
  cursor: pointer;
  touch-action: none;
  border-radius: var(--radius-pill);
  /* 轨道底色:内嵌渐变画一条 5px 细线,省一层元素 */
  background: linear-gradient(color-mix(in srgb, var(--text-faint) 45%, transparent) 0 0) center / 100% 5px no-repeat;
}

.media-audio-track-fill {
  position: relative;
  height: 5px;
  width: 0%;
  border-radius: var(--radius-pill);
  background: var(--accent);
  min-width: 0;
}

.media-audio-track-fill::after {
  content: "";
  position: absolute;
  right: -5px;
  top: 50%;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--accent-strong);
  transform: translateY(-50%) scale(0);
  transition: transform 0.12s ease;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

.media-audio-track:hover .media-audio-track-fill::after,
.media-audio-track.is-scrubbing .media-audio-track-fill::after,
.media-audio-track:focus-visible .media-audio-track-fill::after {
  transform: translateY(-50%) scale(1);
}

.media-audio-track:focus-visible {
  outline: 2px solid color-mix(in srgb, var(--accent) 60%, transparent);
  outline-offset: 2px;
}

.media-audio-track.is-static {
  cursor: default;
  opacity: 0.55;
}

.media-audio-icon-btn {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  border: none;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
  text-decoration: none;
  transition: background 0.15s ease, color 0.15s ease;
}

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

.media-audio-icon-btn svg {
  width: 15px;
  height: 15px;
}

/* 音量条:accent 已播 + 淡轨道,WebKit/Firefox 各写一份 */
.media-audio-volume {
  flex: none;
  width: 56px;
  height: 16px;
  margin: 0;
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  cursor: pointer;
}

.media-audio-volume::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--text-faint) 45%, transparent);
}

.media-audio-volume::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 10px;
  height: 10px;
  margin-top: -3px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
}

.media-audio-volume::-moz-range-track {
  height: 4px;
  border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--text-faint) 45%, transparent);
}

.media-audio-volume::-moz-range-progress {
  height: 4px;
  border-radius: var(--radius-pill);
  background: var(--accent);
}

.media-audio-volume::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border: none;
  border-radius: 50%;
  background: var(--accent);
}

/* 窄屏收起音量条,静音键仍在 */
@media (max-width: 480px) {
  .media-audio-volume {
    display: none;
  }
}

/* ── G2:不可见即暂停 ──
   页面隐藏(切标签/最小化)时由 app.js 挂 miyu-paused。所有无限动画
   (status-pulse/shimmer/typing-bounce/spin 等)暂停,恢复可见时原地续播,
   视觉零变化。实测隐藏窗口不暂停时合成负载与可见时相同。 */
body.miyu-paused *,
body.miyu-paused *::before,
body.miyu-paused *::after {
  animation-play-state: paused !important;
}

/* 生图点阵占位气泡(08-22):工具芯片隐藏,方形气泡内随机区域的小块点阵
   若隐若现(补丁元素由 app.js 生成,位置/大小/时长随机);tool.image 到达后
   原地换成图片;失败时占位变错误态并露出芯片。 */
.tool-card.image-tool-chip {
  display: none;
}
.image-gen-bubble {
  position: relative;
  width: min(320px, 70%);
  min-width: 220px; /* slim 收缩语境下的形状兜底 */
  aspect-ratio: 1 / 1;
  margin: 6px 0;
  border-radius: var(--radius);
  background: var(--surface-2);
  overflow: hidden;
}
.image-gen-bubble .image-gen-label {
  position: relative;
  z-index: 2;
  display: inline-block;
  white-space: nowrap; /* 任何退化宽度下 6 个字也不竖排 */
  margin: 14px 16px;
  font-size: 13px;
  color: var(--text-soft);
}
.image-gen-bubble .dot-patch {
  position: absolute;
  pointer-events: none;
  background-image: radial-gradient(circle, var(--text-faint) 1.4px, transparent 1.6px);
  background-size: 11px 11px;
  -webkit-mask-image: radial-gradient(closest-side, #000 30%, transparent 100%);
  mask-image: radial-gradient(closest-side, #000 30%, transparent 100%);
  opacity: 0;
  animation: imageGenDotPatch 2.8s ease-in-out forwards;
}
@keyframes imageGenDotPatch {
  0% { opacity: 0; }
  45% { opacity: 0.55; }
  100% { opacity: 0; }
}

/* ── 插件 dashboard 共享零件(09-03)──────────────────────────────────
   只用别名层变量,matugen 主题覆盖时跟着走。 */
.dash-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 18px;
}

.dash-select,
.dash-search {
  height: 32px;
  padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-ui);
}

.dash-search-box {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: auto;
  color: var(--text-faint);
}

.dash-search-box svg { width: 14px; height: 14px; }
.dash-search { min-width: 220px; }
.dash-search:focus,
.dash-select:focus { outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 1px; }

.dash-icon-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-soft);
  cursor: pointer;
}
.dash-icon-button svg { width: 15px; height: 15px; }
.dash-icon-button:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.dash-icon-button:disabled { opacity: .4; cursor: default; }
.dash-icon-button.is-danger:hover:not(:disabled) { color: var(--danger); }

.dash-button {
  white-space: nowrap;
  padding: 7px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-ui);
  cursor: pointer;
}
.dash-button:hover { background: var(--surface-3); }
.dash-button.is-danger { color: var(--danger); border-color: color-mix(in srgb, var(--danger) 45%, transparent); }
.dash-button.is-primary { background: var(--accent); border-color: var(--accent); color: var(--inverse-text, #fff); }
.dash-button.is-primary:hover { background: var(--accent-strong, var(--accent)); }
.dash-button svg { width: 14px; height: 14px; margin-right: 6px; vertical-align: -2px; }
.dash-button:disabled { opacity: .5; cursor: default; }

.dash-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 12px;
  margin-bottom: 20px;
}
.dash-card {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.dash-card-label { color: var(--text-soft); font-size: var(--fs-meta); letter-spacing: .04em; }
.dash-card-value { font-family: var(--serif); font-size: 24px; font-weight: 600; line-height: 1.1; }
/* 长文件名会撑破卡片:`How-to_verify_GPG_key_of_official_.ISO_images_en.md` 这种
   一个词就比卡片还宽,默认的断行规则不肯在词中间断,于是整段画到边框外面
   (09-09 用户实拍)。允许任意位置断行,再封两行、超出打省略号;全文挂 title。 */
.dash-card-hint {
  display: -webkit-box;
  overflow: hidden;
  color: var(--text-faint);
  font-size: var(--fs-micro);
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.dash-table-wrap { overflow-x: auto; }
.dash-table {
  display: grid;
  grid-template-columns: var(--dash-cols, minmax(260px, 3fr) minmax(90px, 1fr) 84px 110px 56px 128px 40px);
  min-width: var(--dash-min, 820px);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  overflow: hidden;
}
.dash-row {
  display: contents;
  cursor: pointer;
}
.dash-row > span {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 12px;
  border-bottom: 1px solid var(--line);
  font-size: var(--fs-ui);
  overflow: hidden;
}
.dash-row:last-child > span { border-bottom: 0; }
.dash-row:not(.is-head):hover > span { background: var(--surface-2); }
.dash-row:focus-visible > span { background: var(--surface-2); }
.dash-row.is-head > span {
  min-height: 36px;
  color: var(--text-soft);
  font-size: var(--fs-micro);
  letter-spacing: .05em;
  text-transform: uppercase;
  background: var(--surface-soft, var(--surface-2));
  cursor: default;
}
.dash-cell-main {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  line-height: 1.45;
}
.dash-cell-muted { color: var(--text-soft); }
.dash-cell-mono { font-family: var(--font-mono); font-size: var(--fs-meta); color: var(--text-soft); }
.dash-cell-actions { justify-content: flex-end; padding-right: 6px !important; }

.dash-chip {
  display: inline-block;
  padding: 2px 8px;
  border-radius: var(--radius);
  font-size: var(--fs-micro);
  background: var(--chip-neutral, var(--surface-3));
  color: var(--text-soft);
  /* 药丸不许内部折行:窄列里「index 覆盖」曾被挤成两行(09-05 用户截图)。 */
  white-space: nowrap;
  vertical-align: middle;
}
.dash-chip.is-active { background: color-mix(in srgb, var(--online) 22%, transparent); color: var(--online); }
.dash-chip.is-archived,
.dash-chip.is-muted { background: color-mix(in srgb, var(--text-faint) 25%, transparent); color: var(--text-faint); }
.dash-chip.is-warn { background: color-mix(in srgb, var(--gold, #d4a017) 22%, transparent); color: var(--gold, #d4a017); }
.dash-chip.is-danger { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); }
.dash-chip.is-builtin { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }

.dash-pager {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 6px;
  margin-top: 12px;
  color: var(--text-soft);
  font-size: var(--fs-meta);
}
.dash-pager-text { margin-right: 6px; }

.dash-empty {
  padding: 36px 0;
  text-align: center;
  color: var(--text-faint);
  font-size: var(--fs-ui);
}

.dash-drawer-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: color-mix(in srgb, var(--app-bg) 55%, transparent);
  backdrop-filter: blur(2px);
}
.dash-drawer {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(420px, 92vw);
  display: flex;
  flex-direction: column;
  background: var(--surface-1);
  border-left: 1px solid var(--line);
  box-shadow: var(--float-shadow, 0 12px 40px rgba(0,0,0,.35));
}
.dash-drawer-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px 12px;
  border-bottom: 1px solid var(--line);
}
.dash-drawer-body { flex: 1; overflow-y: auto; padding: 16px 18px; }
.dash-drawer-foot { display: flex; justify-content: flex-end; gap: 8px; padding: 12px 18px; border-top: 1px solid var(--line); }
.dash-detail-content {
  margin: 0 0 16px;
  padding: 12px 14px;
  border-radius: var(--radius);
  background: var(--surface-2);
  font-size: var(--fs-chat);
  line-height: 1.6;
  white-space: pre-wrap;
  word-break: break-word;
}
.dash-meta {
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: 6px 12px;
  margin: 0;
  font-size: var(--fs-meta);
}
.dash-meta dt { color: var(--text-soft); }
.dash-meta dd { margin: 0; word-break: break-word; }

.dash-confirm {
  max-width: 420px;
  padding: 20px 22px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  font: inherit;
}
.dash-confirm::backdrop { background: color-mix(in srgb, var(--app-bg) 60%, transparent); }
.dash-confirm p { margin: 0 0 16px; white-space: pre-wrap; line-height: 1.5; font-size: var(--fs-ui); }
.dash-confirm-actions { display: flex; justify-content: flex-end; gap: 8px; }

/* ── dashboard 零件二期(09-04):作用域、动作行、过滤条、表单、时间线、折线、toast ── */
.dash-scope { display: inline-flex; align-items: center; gap: 8px; margin-left: auto; }
.dash-scope-label { color: var(--text-soft); font-size: var(--fs-meta); }
.dash-actions { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin: -6px 0 18px; }
.dash-actions-gap { flex: 1; }
.dash-filters { display: inline-flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.dash-filter-sep { color: var(--text-faint); font-size: var(--fs-meta); }
.dash-tag-input { width: 110px; }
.dash-wide { width: 100%; }
.dash-textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-2);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-ui);
  line-height: 1.5;
  resize: vertical;
}
.dash-textarea:focus { outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 1px; }
/* 脚本面板(09-05):抽屉里的单行输入与描述段。 */
.dash-input {
  width: 100%;
  box-sizing: border-box;
  padding: 7px 10px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-body);
}
.dash-input:focus { outline: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); outline-offset: 1px; }
.dash-drawer-desc { margin: 0 0 12px; color: var(--text-soft); line-height: 1.55; white-space: pre-wrap; word-break: break-word; }
.dash-cell-main .dash-chip,
.dash-cell-main .dash-cell-muted { margin-left: 6px; }
.dash-cell-main .dash-chip { font-size: var(--fs-micro); line-height: 1.3; }
.dash-field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 12px; flex: 1; min-width: 0; }
.dash-field-label { color: var(--text-soft); font-size: var(--fs-meta); }
.dash-field-hint { color: var(--text-faint); font-size: var(--fs-micro); }
.dash-field .dash-select { width: 100%; }
.dash-field-row { display: flex; gap: 12px; }
.dash-section { margin: 18px 0 8px; font-size: var(--fs-meta); color: var(--text-soft); letter-spacing: .04em; text-transform: uppercase; }
.dash-detail-content.is-quote { font-size: var(--fs-ui); color: var(--text-soft); margin-bottom: 8px; }
.dash-timeline { list-style: none; margin: 0; padding: 0 0 0 14px; border-left: 2px solid var(--line); }
.dash-timeline-item { position: relative; padding: 0 0 14px 14px; }
.dash-timeline-item::before {
  content: ""; position: absolute; left: -20px; top: 4px; width: 8px; height: 8px; border-radius: 50%;
  background: var(--accent); box-shadow: 0 0 0 3px var(--surface-1);
}
.dash-timeline-time { display: block; color: var(--text-faint); font-size: var(--fs-micro); margin-bottom: 4px; }
.dash-timeline-card { display: flex; flex-direction: column; gap: 4px; }
.dash-timeline-title { font-size: var(--fs-ui); }
.dash-timeline-body { margin: 0; font-size: var(--fs-ui); line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.dash-timeline-body.is-old { color: var(--text-faint); text-decoration: line-through; }
.dash-linked { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }
.dash-linked li { display: flex; flex-direction: column; gap: 2px; padding: 8px 10px; border-radius: var(--radius); background: var(--surface-2); cursor: pointer; font-size: var(--fs-ui); }
.dash-linked li:hover { background: var(--surface-3); }
.dash-sparkline { width: 100%; height: 60px; display: block; }
.dash-sparkline-line { fill: none; stroke: var(--accent); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
.dash-sparkline-base { stroke: var(--line-strong, var(--line)); stroke-width: 1; stroke-dasharray: 3 3; vector-effect: non-scaling-stroke; }
.dash-toast {
  position: fixed; left: 50%; bottom: 28px; z-index: 80; transform: translateX(-50%);
  padding: 9px 16px; border-radius: var(--radius); background: var(--surface-3); color: var(--text);
  font-size: var(--fs-ui); box-shadow: var(--float-shadow, 0 8px 24px rgba(0,0,0,.3));
  animation: dash-toast-in .18s ease-out;
}
.dash-toast.is-error { background: color-mix(in srgb, var(--danger) 22%, var(--surface-3)); color: var(--danger); }
@keyframes dash-toast-in { from { opacity: 0; transform: translate(-50%, 8px); } to { opacity: 1; transform: translate(-50%, 0); } }
.dash-drawer { width: min(520px, 94vw); }

/* ── 知识库面板:宽版内容区、内联卡、目录树、代码预览、搜索结果、上传记录 ── */
.con-inner.is-wide { max-width: 1400px; }
.dash-banner {
  margin: 0 0 12px; padding: 10px 14px; border-radius: var(--radius);
  background: color-mix(in srgb, var(--gold, #d4a017) 14%, var(--surface-1)); color: var(--text-soft); font-size: var(--fs-ui);
}
.dash-card-actions { margin-top: 8px; }
.dash-card-actions .dash-button { padding: 4px 10px; font-size: var(--fs-meta); }
.dash-inline-card {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 10px 16px; margin-bottom: 18px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1);
  font-size: var(--fs-ui);
}
.dash-inline-main { font-weight: 600; white-space: nowrap; }
.dash-inline-card .dash-button { margin-left: auto; }
/* 紧凑版:一行装下,中段文字截断而不是换行。整条换行之后按钮独占一行,看着
   像一根进度条(09-09 用户反馈内置库那条「占地方太大」)。 */
.dash-inline-card.is-tight {
  flex-wrap: nowrap;
  gap: 10px;
  padding: 6px 12px;
  margin-bottom: 12px;
}
.dash-inline-card.is-tight .dash-cell-muted {
  min-width: 0;
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-inline-card.is-tight .dash-chip {
  /* 「上次失败:…」可以很长,给它一个上限,别把整行推歪。 */
  max-width: 18em;
  flex: 0 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.dash-inline-card.is-tight .dash-chip.is-builtin { flex: none; }
.dash-button.is-slim { padding: 4px 10px; }
@media (max-width: 700px) {
  .dash-inline-card.is-tight { flex-wrap: wrap; }
  .dash-inline-card.is-tight .dash-cell-muted { flex-basis: 100%; }
}
.dash-split { display: grid; grid-template-columns: minmax(260px, 1fr) minmax(0, 2.2fr); gap: 16px; align-items: start; }
@media (max-width: 900px) { .dash-split { grid-template-columns: 1fr; } }
.dash-tree-pane, .dash-main-pane {
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1); min-height: 320px; overflow: hidden;
}
.dash-tree-pane { max-height: 72vh; overflow-y: auto; padding: 6px 0; }
.dash-tree { list-style: none; margin: 0; padding: 0; }
.dash-tree-row {
  display: flex; align-items: center; gap: 6px; padding: 5px 10px 5px 8px; cursor: pointer; font-size: var(--fs-ui); user-select: none;
}
.dash-tree-row:hover { background: var(--surface-2); }
.dash-tree-row.is-selected { background: color-mix(in srgb, var(--accent) 16%, transparent); }
.dash-tree-row svg { width: 13px; height: 13px; color: var(--text-faint); flex: none; }
.dash-tree-indent { flex: none; display: inline-block; }
.dash-tree-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-tree-row.is-dir .dash-tree-name { color: var(--text-soft); }
.dash-tree-count, .dash-tree-size { color: var(--text-faint); font-size: var(--fs-micro); font-variant-numeric: tabular-nums; }
.dash-tree-row .dash-icon-button { width: 22px; height: 22px; opacity: 0; }
.dash-tree-row:hover .dash-icon-button { opacity: 1; }
.dash-index-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; background: var(--text-faint); }
.dash-index-dot.is-fresh { background: var(--online); }
.dash-index-dot.is-stale { background: var(--gold, #d4a017); }
.dash-preview-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; padding: 10px 14px; border-bottom: 1px solid var(--line); font-size: var(--fs-ui); }
.dash-preview-name { font-family: var(--font-mono); font-size: var(--fs-meta); word-break: break-all; }
.dash-code {
  margin: 0; padding: 8px 0; max-height: 66vh; overflow: auto; font-family: var(--font-mono); font-size: var(--fs-meta); line-height: 1.55; tab-size: 4;
}
.dash-code-line { display: flex; }
.dash-code-no { flex: none; width: 52px; padding-right: 12px; text-align: right; color: var(--text-faint); user-select: none; }
.dash-code-text { white-space: pre-wrap; word-break: break-word; padding-right: 14px; }
.dash-code-more { padding: 8px 14px 12px; }
.dash-results { display: flex; flex-direction: column; }
.dash-result { padding: 10px 14px; border-bottom: 1px solid var(--line); cursor: pointer; }
.dash-result:hover { background: var(--surface-2); }
.dash-result-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--fs-ui); }
.dash-snippet { margin: 6px 0 0; padding: 6px 10px; border-radius: var(--radius); background: var(--surface-2); font-size: var(--fs-meta); line-height: 1.5; white-space: pre-wrap; word-break: break-word; color: var(--text-soft); }
.dash-upload-log { margin-bottom: 14px; padding: 10px 14px; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1); }
.dash-upload-head { display: flex; align-items: center; gap: 8px; font-size: var(--fs-ui); }
.dash-upload-list { list-style: none; margin: 8px 0 0; padding: 0; max-height: 180px; overflow-y: auto; display: flex; flex-direction: column; gap: 4px; }
.dash-upload-list li { display: flex; align-items: center; gap: 10px; font-size: var(--fs-meta); }
.dash-upload-list .dash-cell-mono { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── 表情包面板:标签云、画廊、卡片、抽屉大图 ── */
.dash-scope-hint { color: var(--text-faint); font-size: var(--fs-micro); white-space: nowrap; }
.dash-tag-cloud { display: flex; flex-wrap: wrap; gap: 6px; margin: -8px 0 14px; }
.dash-chip.is-clickable { border: none; cursor: pointer; font: inherit; font-size: var(--fs-micro); }
.dash-chip.is-clickable:hover { background: var(--surface-3); color: var(--text); }
.dash-search-hint { margin: -6px 0 12px; color: var(--text-soft); font-size: var(--fs-meta); }
.dash-gallery { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
/* 瀑布流:行单位 1px,跨行数由 JS 按卡片实际高度算(见 dash-memes.js)。
   列还是自动填充,所以从左到右的顺序不变——搜索命中的前几张仍在最前。
   JS 没跑起来时靠这里的默认跨行数兜底,不至于塌成一条线。 */
.dash-gallery.is-masonry { grid-auto-rows: 1px; row-gap: 0; align-items: start; }
.dash-gallery.is-masonry .dash-meme { grid-row-end: span 212; margin-bottom: 12px; }
/* min-height:0 是关键:缩略图是列向 flex 的子项,它的「自动最小尺寸」会按
   <img> 的固有高度算,于是 aspect-ratio 定的高度被顶掉——一张 120×420 的图
   照样撑出 646px 的格子(实测)。 */
.dash-gallery.is-masonry .dash-meme-thumb { aspect-ratio: 1; min-height: 0; overflow: hidden; }
/* 手机:150px 一格会退成单列巨卡,收到三列;页头的「人格 → 库」提示与下拉里的「(当前人格)」重复,让位给上传按钮 */
@media (max-width: 473px) {
  .dash-gallery { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; }
  .dash-gallery.is-masonry { row-gap: 0; }
  .dash-gallery.is-masonry .dash-meme { grid-row-end: span 150; margin-bottom: 8px; }
  .dash-scope { flex-wrap: wrap; min-width: 0; }
  .dash-scope select { min-width: 0; max-width: 100%; }
  .dash-scope-hint { display: none; }
}
.dash-meme {
  margin: 0; border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-1); overflow: hidden; cursor: pointer;
  display: flex; flex-direction: column; transition: transform .12s ease, box-shadow .12s ease;
}
.dash-meme:hover, .dash-meme:focus-visible { transform: translateY(-2px); box-shadow: var(--card-shadow); outline: none; }
.dash-meme.is-disabled .dash-meme-thumb img { opacity: .35; filter: grayscale(1); }
.dash-meme-thumb { position: relative; background: var(--surface-2); display: flex; align-items: center; justify-content: center; }
.dash-meme-thumb img { width: 100%; height: 100%; object-fit: contain; }
.dash-meme-badge {
  position: absolute; right: 6px; top: 6px; padding: 1px 6px; border-radius: var(--radius);
  background: color-mix(in srgb, var(--app-bg) 70%, transparent); color: var(--text); font-size: var(--fs-micro); font-weight: 600;
}
.dash-meme-badge.is-count { right: auto; left: 6px; font-weight: 400; color: var(--text-soft); }
.dash-meme-cap { display: flex; align-items: center; gap: 6px; padding: 8px 10px; font-size: var(--fs-meta); }
.dash-meme-name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-meme-hero { display: flex; justify-content: center; margin-bottom: 14px; padding: 10px; border-radius: var(--radius); background: var(--surface-2); }
.dash-meme-full { max-width: 100%; max-height: 300px; object-fit: contain; }

/* ── 群聊 / 群管面板:发送者单元、媒体 chip、领奖台、横向条形、星期×小时热力、事件卡、危险区 ── */
.dash-sender { display: flex; align-items: center; gap: 6px; }
.dash-row > span > small { display: block; }
.dash-row.is-recalled .dash-cell-main { color: var(--text-faint); text-decoration: line-through; }
.dash-media-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.dash-podium { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 14px; }
.dash-podium-item { display: flex; flex-direction: column; gap: 3px; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2); font-size: var(--fs-ui); }
.dash-podium-rank { font-size: 20px; }
.dash-hbars { display: flex; flex-direction: column; gap: 6px; }
.dash-hbar { display: grid; grid-template-columns: minmax(120px, 1fr) minmax(0, 3fr) 48px; align-items: center; gap: 10px; font-size: var(--fs-meta); }
.dash-hbar-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-hbar-track { height: 10px; border-radius: var(--radius-pill); background: var(--surface-2); overflow: hidden; }
.dash-hbar-fill { display: block; height: 100%; border-radius: var(--radius-pill); background: var(--chart-1, var(--accent)); }
.dash-heat { display: grid; grid-template-columns: 22px repeat(24, 1fr); gap: 3px; align-items: center; }
.dash-heat i { display: block; aspect-ratio: 1; border-radius: var(--radius-sm); background: var(--heat-0, var(--surface-2)); }
.dash-heat i[data-l="1"] { background: var(--heat-1); }
.dash-heat i[data-l="2"] { background: var(--heat-2); }
.dash-heat i[data-l="3"] { background: var(--heat-3); }
.dash-heat i[data-l="4"] { background: var(--heat-4); }
.dash-heat-axis { font-size: var(--fs-micro); color: var(--text-faint); text-align: center; }
.dash-two-col { display: grid; grid-template-columns: minmax(0, 2fr) minmax(220px, 1fr); gap: 12px; }
@media (max-width: 900px) { .dash-two-col { grid-template-columns: 1fr; } }
.dash-kv { display: grid; grid-template-columns: auto 1fr; gap: 6px 14px; font-size: var(--fs-ui); }
.dash-kv strong { font-variant-numeric: tabular-nums; }
.dash-event { display: flex; flex-direction: column; gap: 4px; }
.dash-event-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--fs-ui); }
.dash-danger { margin-top: 26px; padding-top: 6px; border-top: 1px solid var(--line); }
.dash-timeline-card > .dash-chip { align-self: flex-start; }

/* ── 好感·情绪面板:等级分布条、分数头、复选行 ── */
.dash-level-bar { display: flex; gap: 3px; height: 26px; }
.dash-level-cell { display: flex; align-items: center; justify-content: center; min-width: 6px; border-radius: var(--radius); background: color-mix(in srgb, var(--accent) 28%, var(--surface-2)); overflow: hidden; }
.dash-level-cell.is-empty { background: var(--surface-2); }
.dash-level-cell i { font-style: normal; font-size: var(--fs-micro); color: var(--text); white-space: nowrap; padding: 0 6px; }
.dash-score-head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 8px; }
.dash-score-big { font-family: var(--serif); font-size: 30px; font-weight: 600; }
.dash-check { display: flex; align-items: center; gap: 8px; margin: 4px 0 12px; font-size: var(--fs-ui); }

/* ── 情绪标签:二维方格、点、区域标注、量表、表单 ── */
.dash-emo-layout { display: grid; grid-template-columns: minmax(220px, 300px) minmax(0, 1fr); gap: 18px; align-items: start; }
@media (max-width: 900px) { .dash-emo-layout { grid-template-columns: 1fr; } }
.dash-emo-grid {
  position: relative; aspect-ratio: 1; border-radius: var(--radius); overflow: hidden;
  background:
    linear-gradient(to right, transparent 49.5%, var(--line) 49.5%, var(--line) 50.5%, transparent 50.5%),
    linear-gradient(to bottom, transparent 49.5%, var(--line) 49.5%, var(--line) 50.5%, transparent 50.5%),
    linear-gradient(135deg, color-mix(in srgb, var(--danger) 14%, var(--surface-2)) 0%, var(--surface-2) 50%, color-mix(in srgb, var(--online) 16%, var(--surface-2)) 100%);
}
.dash-emo-region { position: absolute; transform: translate(-50%, -50%); font-size: var(--fs-micro); color: var(--text-faint); pointer-events: none; }
.dash-emo-axis { position: absolute; font-size: var(--fs-micro); color: var(--text-faint); }
.dash-emo-axis.is-x { right: 8px; bottom: 4px; }
.dash-emo-axis.is-y { left: 6px; top: 4px; }
.dash-emo-dot { position: absolute; width: 14px; height: 14px; border-radius: 50%; transform: translate(-50%, -50%); box-sizing: border-box; }
.dash-emo-dot.is-stored { border: 2px solid var(--accent); background: transparent; }
.dash-emo-dot.is-effective { background: var(--accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--accent) 25%, transparent); }
.dash-emo-side { display: flex; flex-direction: column; gap: 10px; }
.dash-meter { display: grid; grid-template-columns: 52px minmax(0, 1fr) 48px auto; align-items: center; gap: 10px; font-size: var(--fs-meta); }
.dash-meter-label { color: var(--text-soft); }
.dash-meter-track { position: relative; height: 10px; border-radius: var(--radius-pill); background: var(--surface-2); overflow: hidden; }
.dash-meter-fill { position: absolute; top: 0; height: 100%; background: var(--accent); border-radius: var(--radius-pill); }
.dash-meter-base { position: absolute; top: -2px; width: 2px; height: 14px; background: var(--text-faint); transform: translateX(-1px); }
.dash-emo-form { display: flex; flex-direction: column; gap: 10px; margin-bottom: 12px; }
.dash-emo-form label { display: grid; grid-template-columns: 52px minmax(0, 1fr) 48px; align-items: center; gap: 10px; font-size: var(--fs-meta); color: var(--text-soft); }
.dash-emo-form input[type="range"] { height: auto; padding: 0; border: none; background: transparent; accent-color: var(--accent); }

/* ── 动效层(09-04):进场淡入上浮、抽屉滑入、条形/量表生长、折线画出;
   全部短促克制,prefers-reduced-motion 一律关掉。 ── */
@keyframes dash-fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes dash-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes dash-slide-in { from { transform: translateX(28px); opacity: .4; } to { transform: none; opacity: 1; } }
@keyframes dash-grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes dash-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes dash-pop { 0% { transform: translate(-50%, -50%) scale(.6); } 70% { transform: translate(-50%, -50%) scale(1.15); } 100% { transform: translate(-50%, -50%) scale(1); } }

.con-panel:not([hidden]) > .con-inner { animation: dash-fade-up .26s ease-out both; }
.dash-card { animation: dash-fade-up .36s ease-out both; animation-delay: calc(var(--i, 0) * 45ms); transition: transform .16s ease, box-shadow .16s ease; }
.dash-card:hover { transform: translateY(-2px); box-shadow: var(--card-shadow); }
.dash-table, .dash-tree-pane, .dash-main-pane, .u-card, .dash-inline-card { animation: dash-fade-up .28s ease-out both; }
.dash-row > span { animation: dash-fade-in .3s ease-out both; }
.dash-row:nth-child(2) > span { animation-delay: 22ms; }
.dash-row:nth-child(3) > span { animation-delay: 44ms; }
.dash-row:nth-child(4) > span { animation-delay: 66ms; }
.dash-row:nth-child(5) > span { animation-delay: 88ms; }
.dash-row:nth-child(6) > span { animation-delay: 110ms; }
.dash-row:nth-child(7) > span { animation-delay: 132ms; }
.dash-row:nth-child(8) > span { animation-delay: 154ms; }
.dash-row:nth-child(9) > span { animation-delay: 176ms; }
.dash-row:nth-child(10) > span { animation-delay: 198ms; }
.dash-row:nth-child(11) > span { animation-delay: 220ms; }
.dash-row:nth-child(12) > span { animation-delay: 242ms; }
.dash-row:nth-child(13) > span { animation-delay: 264ms; }
.dash-row:nth-child(14) > span { animation-delay: 286ms; }
.dash-row:nth-child(15) > span { animation-delay: 308ms; }
.dash-row:not(.is-head) > span { transition: background-color .14s ease; }
.dash-meme { animation: dash-fade-up .34s ease-out both; }
.dash-meme:nth-child(1) { animation-delay: 0ms; }
.dash-meme:nth-child(2) { animation-delay: 18ms; }
.dash-meme:nth-child(3) { animation-delay: 36ms; }
.dash-meme:nth-child(4) { animation-delay: 54ms; }
.dash-meme:nth-child(5) { animation-delay: 72ms; }
.dash-meme:nth-child(6) { animation-delay: 90ms; }
.dash-meme:nth-child(7) { animation-delay: 108ms; }
.dash-meme:nth-child(8) { animation-delay: 126ms; }
.dash-meme:nth-child(9) { animation-delay: 144ms; }
.dash-meme:nth-child(10) { animation-delay: 162ms; }
.dash-meme:nth-child(11) { animation-delay: 180ms; }
.dash-meme:nth-child(12) { animation-delay: 198ms; }
.dash-meme:nth-child(13) { animation-delay: 216ms; }
.dash-meme:nth-child(14) { animation-delay: 234ms; }
.dash-meme:nth-child(15) { animation-delay: 252ms; }
.dash-meme:nth-child(16) { animation-delay: 270ms; }
.dash-meme:nth-child(17) { animation-delay: 288ms; }
.dash-meme:nth-child(18) { animation-delay: 306ms; }
.dash-meme:nth-child(19) { animation-delay: 324ms; }
.dash-meme:nth-child(20) { animation-delay: 342ms; }
.dash-meme:nth-child(21) { animation-delay: 360ms; }
.dash-meme:nth-child(22) { animation-delay: 378ms; }
.dash-meme:nth-child(23) { animation-delay: 396ms; }
.dash-meme:nth-child(24) { animation-delay: 414ms; }
.dash-timeline-item { animation: dash-fade-up .3s ease-out both; }
.dash-timeline-item:nth-child(1) { animation-delay: 0ms; }
.dash-timeline-item:nth-child(2) { animation-delay: 40ms; }
.dash-timeline-item:nth-child(3) { animation-delay: 80ms; }
.dash-timeline-item:nth-child(4) { animation-delay: 120ms; }
.dash-timeline-item:nth-child(5) { animation-delay: 160ms; }
.dash-timeline-item:nth-child(6) { animation-delay: 200ms; }
.dash-timeline-item:nth-child(7) { animation-delay: 240ms; }
.dash-timeline-item:nth-child(8) { animation-delay: 280ms; }
.dash-timeline-item:nth-child(9) { animation-delay: 320ms; }
.dash-timeline-item:nth-child(10) { animation-delay: 360ms; }
.dash-timeline-item:nth-child(11) { animation-delay: 400ms; }
.dash-timeline-item:nth-child(12) { animation-delay: 440ms; }
.dash-timeline-item::before { transition: transform .16s ease; }
.dash-timeline-item:hover::before { transform: scale(1.35); }
.dash-drawer-overlay { animation: dash-fade-in .18s ease-out both; }
.dash-drawer { animation: dash-slide-in .24s cubic-bezier(.2, .8, .2, 1) both; }
.dash-confirm[open] { animation: dash-fade-up .18s ease-out both; }
.dash-hbar-fill, .dash-meter-fill, .dash-level-cell { transform-origin: left center; animation: dash-grow-x .5s cubic-bezier(.2, .8, .2, 1) both; }
.dash-hbar-track, .dash-meter-track { overflow: hidden; }
.dash-level-bar .dash-level-cell:nth-child(n+2) { animation-delay: 60ms; }
.dash-sparkline-line { stroke-dasharray: 1; stroke-dashoffset: 1; animation: dash-draw .9s ease-out .1s both; }
.dash-heat i { animation: dash-fade-in .4s ease-out both; transition: transform .12s ease; }
.dash-heat i:hover { transform: scale(1.35); }
.dash-emo-dot { transition: left .5s cubic-bezier(.2, .8, .2, 1), top .5s cubic-bezier(.2, .8, .2, 1); }
.dash-emo-dot.is-effective { animation: dash-pop .45s ease-out both; }
.con-segmented button { transition: background-color .16s ease, color .16s ease, box-shadow .16s ease; }
.dash-chip.is-clickable, .dash-button, .dash-icon-button { transition: background-color .14s ease, color .14s ease, transform .12s ease; }
.dash-button:active, .dash-icon-button:active { transform: scale(.96); }
.dash-tree-row { transition: background-color .12s ease; }
.dash-index-dot.is-stale { animation: dash-fade-in 1.2s ease-in-out infinite alternate; }
.con-rail-item { transition: background-color .16s ease, color .16s ease, transform .12s ease; }
.con-rail-item:active { transform: scale(.98); }

/* ── 记账面板(09-09) ────────────────────────────────────────
 * 只用别名层变量,跟着主题与 matugen 走。金额同时靠符号与颜色区分方向——
 * 只用红绿的话,色觉差异的人看到的是两列一样的灰。
 */
.dash-led-block { margin-bottom: 6px; }
.dash-led-block .dash-section { margin-top: 0; }

/* 金额列:主金额一行,外币原值一行小字。整列右对齐、等宽,便于竖着比大小。 */
.dash-led-amount { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; min-width: 0; }
.dash-led-money { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--fs-ui); white-space: nowrap; }
.dash-led-money.is-expense { color: var(--danger); }
.dash-led-money.is-income { color: var(--md-ext-color-online, var(--online)); }
.dash-led-money.is-transfer { color: var(--text-soft); }
.dash-led-origin { color: var(--text-faint); font-size: var(--fs-micro); white-space: nowrap; }

/* 分类占比条:第三列放金额,比通用 hbar 的 48px 宽一些才装得下带小数的钱。 */
.dash-led-hbar { grid-template-columns: minmax(96px, 1fr) minmax(0, 2.4fr) 84px; }
.dash-led-hbar .dash-cell-mono { text-align: right; font-variant-numeric: tabular-nums; }

/* 预算行:名称 / 进度条 / 用量 / 删除。 */
.dash-led-budget { grid-template-columns: minmax(72px, 1fr) minmax(0, 2fr) auto auto; margin-bottom: 8px; }
.dash-led-budget .dash-cell-mono { white-space: nowrap; font-variant-numeric: tabular-nums; }
.dash-meter-fill.is-ok { background: var(--md-ext-color-online, var(--online)); }
.dash-meter-fill.is-near { background: var(--gold); }
.dash-meter-fill.is-exceeded { background: var(--danger); }

/* 图表区与下面的筛选条之间留一口气,否则折线紧贴分段按钮。 */
.dash-led-block { margin-bottom: 16px; }

/* 视图标签条:流水 / 账户 / 分类 / 预算 / 数据。 */
.dash-led-tabs { margin: 0 0 16px; }

/* 视图抬头:标题 + 一句说明 + 右侧的新建按钮。 */
.dash-led-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}
.dash-led-head .dash-section { margin: 0 0 4px; }
.dash-led-hint { margin: 0; max-width: 62ch; color: var(--text-soft); font-size: var(--fs-meta); line-height: 1.6; }

/*
 * 表单放大一档。原来 .dash-input 的字号写的是 var(--fs-body)——那个变量
 * 根本不存在,声明整条作废,于是控件字号退回继承(09-09 用户反馈「字体太小」
 * 的直接原因)。这里显式给足:标签用 UI 档,输入用正文档,高度 40px 保证
 * 手机上点得准。
 */
.dash-led-form .dash-field { gap: 7px; margin-bottom: 16px; }
.dash-led-form .dash-field-label { font-size: var(--fs-ui); color: var(--text); }
.dash-led-form .dash-field-hint { font-size: var(--fs-meta); }
.dash-led-form .dash-input,
.dash-led-form .dash-select {
  height: 40px;
  padding: 0 12px;
  font-size: var(--fs-chat);
}
.dash-led-form input[type="file"].dash-input { height: auto; padding: 9px 12px; }
.dash-led-form .con-segmented button { padding: 8px 16px; font-size: var(--fs-ui); }
.dash-led-currency { flex: 0 0 116px; }

/* 就地展开的新建表单,免去一层抽屉。 */
.dash-led-inline-form {
  width: min(420px, 100%);
  margin-bottom: 16px;
  padding: 14px 16px 4px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}

/* 自制的文件选择器:原生控件的英文标签盖不住,只好藏起来重做一个。 */
.dash-led-file { display: flex; align-items: center; gap: 10px; }
.dash-led-filename {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-soft);
  font-size: var(--fs-meta);
}

/* 账户 / 账本卡片。 */
.dash-led-cards { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 8px; }
.dash-led-card {
  display: flex;
  align-items: center;
  gap: 10px;
  min-width: 200px;
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--surface-1);
}
.dash-led-card.is-current { border-color: var(--accent); }
.dash-led-card-name { font-size: var(--fs-ui); }
.dash-led-card-value {
  margin-left: auto;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-ui);
}
.dash-led-chips { display: flex; flex-wrap: wrap; gap: 8px; }

/* 区块内部的行距:说明、按钮、表单各自留白,否则按钮会压到说明上。 */
.dash-led-block > .dash-led-hint { margin-bottom: 12px; }
.dash-led-block > .dash-actions { margin-top: 4px; }
.dash-led-block > .dash-led-form { max-width: 480px; margin-top: 14px; }

/*
 * 两块图各自成卡片。不给容器的话,左边占比条最右那列金额会紧贴右边的
 * 折线,读起来像是折线的纵轴刻度(09-09 桌面走查实测)。
 */
.dash-led-charts { gap: 16px; margin-bottom: 14px; }
.dash-led-chart {
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 12px 16px 14px;
}
.dash-led-chart .dash-section { margin: 0 0 10px; }
.dash-led-chart .dash-sparkline { height: 84px; }

@media (max-width: 640px) {
  /*
   * 窄屏收起备注列。四列在 390px 下挤不开,金额会被裁成「−128.」——
   * 钱看不全比看不见备注严重得多(09-09 手机走查实测)。备注点开行还在。
   * 列模板是 D.table 用 element.style 设的,这里必须 !important 才盖得住。
   */
  .dash-led-table { --dash-cols: 62px minmax(0, 1fr) minmax(96px, auto) !important; }
  .dash-led-table .dash-row > *:nth-child(3) { display: none; }
  .dash-led-hbar { grid-template-columns: minmax(72px, 1fr) minmax(0, 1.6fr) 72px; }
  .dash-led-budget { grid-template-columns: minmax(56px, 1fr) minmax(0, 1.2fr) auto auto; }
}

@media (prefers-reduced-motion: reduce) {
  .con-panel > .con-inner, .dash-card, .dash-table, .dash-tree-pane, .dash-main-pane, .u-card, .dash-inline-card,
  .dash-row > span, .dash-meme, .dash-timeline-item, .dash-drawer-overlay, .dash-drawer, .dash-confirm[open],
  .dash-hbar-fill, .dash-meter-fill, .dash-level-cell, .dash-sparkline-line, .dash-heat i, .dash-emo-dot, .dash-index-dot.is-stale {
    animation: none !important; transition: none !important;
  }
  .dash-sparkline-line { stroke-dasharray: none; stroke-dashoffset: 0; }
}

/* ── 可排序表头 ── */
.dash-row.is-head > span.is-sortable { cursor: pointer; user-select: none; gap: 4px; }
.dash-row.is-head > span.is-sortable:hover, .dash-row.is-head > span.is-sortable.is-active { color: var(--text); }
.dash-sort-arrow { font-style: normal; font-size: 9px; opacity: .45; transition: opacity .14s ease, transform .14s ease; }
.is-sortable.is-active .dash-sort-arrow { opacity: 1; color: var(--accent); }
.is-sortable:hover .dash-sort-arrow { opacity: .9; }

/* ═══════════════════════════════════════════════════════════════════════
   设置页重做(09-04):st-* 前缀。三层结构——页面卡片 / 右侧抽屉 / 弹出层。
   动效:卡片进场淡入上浮(按 --i 错峰)、抽屉滑入滑出、菜单与弹出框缩放淡入、
   标签指示条滑动、折叠区高度过渡、错误字段抖动、底栏有改动时升起。
   prefers-reduced-motion 一律关。
   ═══════════════════════════════════════════════════════════════════════ */

.st-page { padding-top: 16px; }
.st-root { display: grid; gap: 14px; max-width: 960px; }
.st-root.is-platform-off > .st-card:not(:first-of-type) { opacity: .72; }

.st-page-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; margin-bottom: 2px; animation: st-fade-up .3s ease-out both; }
.st-page-head h2 { margin: 0 0 4px; font-size: 17px; font-weight: 700; letter-spacing: -.01em; }
.st-page-desc { margin: 0; color: var(--text-soft); font-size: var(--fs-meta); line-height: 1.6; max-width: 62ch; }
.st-head-switch { display: inline-flex; align-items: center; gap: 10px; color: var(--text-soft); font-size: var(--fs-meta); flex: 0 0 auto; padding-top: 4px; }
.st-group-title { margin: 10px 0 -4px; color: var(--text-faint); font-size: var(--fs-micro); font-weight: 700; letter-spacing: .12em; text-transform: uppercase; }

.st-icon { width: 16px; height: 16px; flex: 0 0 auto; }

/* ── 按钮 ── */
.st-btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px; min-height: 34px; padding: 0 12px; border: 0; border-radius: var(--radius); background: var(--surface-2); color: var(--text); cursor: pointer; font-size: var(--fs-ui); font-weight: 600; white-space: nowrap; transition: background 160ms ease, color 160ms ease, transform 120ms ease, box-shadow 160ms ease; }
.st-btn:hover:not(:disabled) { background: var(--surface-3); }
.st-btn:active:not(:disabled) { transform: translateY(1px); }
.st-btn:disabled { opacity: .5; cursor: not-allowed; }
.st-btn.is-primary { background: var(--accent); color: var(--inverse-text); }
.st-btn.is-primary:hover:not(:disabled) { background: var(--accent-strong); }
.st-btn.is-primary.is-danger { background: var(--danger); color: var(--md-sys-color-on-error, #fff); }
.st-btn.is-text { background: transparent; color: var(--text-soft); padding: 0 8px; }
.st-btn.is-text:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.st-btn.is-text.is-danger { color: var(--danger); }
.st-btn.is-text.is-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 14%, transparent); }
.st-btn.is-small { min-height: 28px; padding: 0 9px; font-size: var(--fs-meta); }
.st-btn .st-icon { width: 15px; height: 15px; }
.st-btn.is-loading .st-icon { animation: spin .9s linear infinite; }
.st-icon-btn { display: inline-grid; place-items: center; width: 30px; height: 30px; flex: 0 0 30px; border: 0; border-radius: var(--radius); background: transparent; color: var(--text-soft); cursor: pointer; transition: background 140ms ease, color 140ms ease, transform 120ms ease; }
.st-icon-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--text); }
.st-icon-btn:active:not(:disabled) { transform: scale(.94); }
.st-icon-btn.is-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 16%, transparent); color: var(--danger); }
.st-icon-btn:disabled { opacity: .4; cursor: not-allowed; }
.st-icon-btn .st-icon { width: 16px; height: 16px; }

/* ── 芯片 / 标识 ── */
.st-chip { display: inline-flex; align-items: center; gap: 4px; min-height: 20px; padding: 0 7px; border-radius: var(--radius); background: var(--surface-2); color: var(--text-soft); font-size: var(--fs-micro); font-weight: 600; line-height: 1; white-space: nowrap; }
.st-chip.is-soft { background: color-mix(in srgb, var(--surface-3) 70%, transparent); }
.st-chip.is-accent { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); }
.st-chip.is-ok { background: color-mix(in srgb, var(--online) 18%, transparent); color: var(--online); }
.st-chip.is-warn { background: color-mix(in srgb, var(--gold) 20%, transparent); color: var(--gold); }
.st-chip.is-model { font-family: var(--font-mono); font-weight: 500; }
.st-mark { display: inline-grid; place-items: center; width: 38px; height: 38px; flex: 0 0 38px; border-radius: var(--radius); background: hsl(var(--mark-hue, 220) 42% 30% / .9); color: hsl(var(--mark-hue, 220) 80% 88%); font-size: 13px; font-weight: 800; letter-spacing: .02em; }
.st-mark.is-small { width: 24px; height: 24px; flex-basis: 24px; border-radius: var(--radius); font-size: 10px; }

/* ── 卡片 / 行 ── */
.st-card { overflow: visible; border-radius: var(--radius); background: var(--surface-1); box-shadow: var(--card-shadow); animation: st-fade-up .34s ease-out both; animation-delay: calc(var(--i, 0) * 40ms); }
.st-card.is-plain { background: transparent; box-shadow: none; }
.st-card.is-plain > .st-card-head { padding: 0 2px 10px; }
.st-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; padding: 14px 16px 10px; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.st-card.is-plain > .st-card-head { border-bottom: 0; }
.st-card-head h3 { margin: 0; font-size: var(--fs-ui); font-weight: 700; }
.st-card-head p { margin: 3px 0 0; color: var(--text-faint); font-size: var(--fs-meta); line-height: 1.55; }
.st-card-actions { display: inline-flex; gap: 6px; flex: 0 0 auto; }
.st-card-body { display: flex; flex-direction: column; }
.st-card-body.is-list { padding: 4px 0; }
.st-row { display: flex; align-items: center; justify-content: space-between; gap: 18px; padding: 11px 16px; }
.st-row + .st-row, .st-row + .st-disclosure, .st-disclosure + .st-row { border-top: 1px solid color-mix(in srgb, var(--line) 50%, transparent); }
.st-row.is-block { flex-direction: column; align-items: stretch; gap: 8px; }
.st-row .lbl { min-width: 0; flex: 1 1 auto; }
.st-row .lbl strong { display: block; font-size: var(--fs-ui); font-weight: 600; }
.st-row .lbl small { display: block; margin-top: 2px; color: var(--text-faint); font-size: var(--fs-meta); line-height: 1.5; }
.st-row-control { display: flex; align-items: center; justify-content: flex-end; gap: 8px; flex: 0 0 auto; max-width: 56%; min-width: 0; }
.st-row.is-block .st-row-control { max-width: none; justify-content: stretch; }
.st-row.is-block .st-row-control > * { flex: 1 1 auto; }
.st-row[hidden] { display: none; }
.st-error { flex: 1 0 100%; margin: -4px 0 0; color: var(--danger); font-size: var(--fs-micro); animation: st-fade-in .18s ease-out; }
.st-row:has(> .st-error) { flex-wrap: wrap; }
.st-hint { margin: 4px 0; color: var(--text-faint); font-size: var(--fs-meta); line-height: 1.55; }
.st-empty { display: grid; justify-items: center; gap: 10px; padding: 28px 16px; border-radius: var(--radius); border: 1px dashed var(--line-strong); color: var(--text-faint); font-size: var(--fs-meta); text-align: center; animation: st-fade-in .3s ease-out both; }
.st-empty p { margin: 0; }

/* ── 输入控件 ── */
.st-input, .st-textarea { min-width: 0; min-height: 34px; padding: 6px 10px; border: 0; border-radius: var(--radius); outline: 0; background: var(--surface-2); color: var(--text); font-size: var(--fs-ui); line-height: 1.45; transition: box-shadow 160ms ease, background 160ms ease; }
.st-input { width: 240px; max-width: 100%; }
.st-row.is-block .st-input, .st-textarea { width: 100%; }
.st-input.is-number { width: 120px; text-align: right; font-variant-numeric: tabular-nums; }
.st-input.is-mono, .st-textarea.is-mono { font-family: var(--font-mono); font-size: 12.5px; }
.st-textarea { resize: vertical; min-height: 90px; }
.st-input:focus, .st-textarea:focus, .st-select:focus, .st-chips:focus-within { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); }
.st-input.is-invalid, .st-textarea.is-invalid, .st-chips-input.is-invalid { box-shadow: 0 0 0 2px color-mix(in srgb, var(--danger) 60%, transparent); }
.st-input::placeholder, .st-textarea::placeholder, .st-chips-input::placeholder { color: var(--text-faint); }
.st-unit-wrap { display: inline-flex; align-items: center; gap: 6px; }
.st-unit { color: var(--text-faint); font-size: var(--fs-micro); white-space: nowrap; }
.st-link-value { min-width: 0; overflow: hidden; color: var(--text-soft); font-size: var(--fs-ui); white-space: nowrap; text-overflow: ellipsis; }
.st-card[data-section] { scroll-margin-top: 20px; }
.st-select-wrap { position: relative; display: inline-flex; min-width: 0; }
.st-select { appearance: none; min-height: 34px; padding: 6px 30px 6px 10px; border: 0; border-radius: var(--radius); outline: 0; background: var(--surface-2); color: var(--text); font-size: var(--fs-ui); cursor: pointer; max-width: 260px; transition: box-shadow 160ms ease; }
.st-select-caret { position: absolute; right: 9px; top: 50%; width: 14px; height: 14px; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; }
.st-inline-form { display: flex; gap: 8px; align-items: center; }
.st-inline-form .st-input { flex: 1 1 auto; width: auto; }
.st-inline-actions { display: inline-flex; gap: 6px; }

/* 芯片列表 */
.st-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; min-height: 40px; padding: 5px 7px; border-radius: var(--radius); background: var(--surface-2); cursor: text; transition: box-shadow 160ms ease; }
.st-chips.is-mono .st-chip-item { font-family: var(--font-mono); }
.st-chip-item { display: inline-flex; align-items: center; gap: 2px; padding: 3px 3px 3px 9px; border-radius: var(--radius); background: var(--surface-1); box-shadow: var(--bubble-shadow); font-size: var(--fs-meta); animation: st-pop .18s ease-out both; }
.st-chip-item .st-icon-btn { width: 20px; height: 20px; flex-basis: 20px; }
.st-chip-item .st-icon-btn .st-icon { width: 12px; height: 12px; }
.st-chips-input { flex: 1 1 120px; min-width: 100px; min-height: 26px; border: 0; outline: 0; background: transparent; color: var(--text); font-size: var(--fs-ui); }
.st-choice-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.st-choice-chip { display: inline-flex; align-items: center; gap: 5px; min-height: 28px; padding: 0 10px; border: 1px solid var(--line-strong); border-radius: var(--radius); background: transparent; color: var(--text-soft); cursor: pointer; font-size: var(--fs-meta); font-weight: 600; transition: background 140ms ease, color 140ms ease, border-color 140ms ease, transform 120ms ease; }
.st-choice-chip:hover { border-color: var(--accent); color: var(--text); }
.st-choice-chip:active { transform: scale(.96); }
.st-choice-chip[aria-pressed="true"] { border-color: transparent; background: color-mix(in srgb, var(--accent) 24%, transparent); color: var(--accent); }
.st-choice-chip .st-icon { width: 13px; height: 13px; }

/* 键值表 / 列表 */
.st-kv, .st-list { display: grid; gap: 6px; }
.st-kv-row, .st-list-row { display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1.4fr) auto; align-items: center; gap: 6px; animation: st-fade-in .2s ease-out both; }
.st-list-row { grid-template-columns: minmax(0, 1fr) auto auto; }
.st-kv-row .st-input, .st-list-row .st-input { width: 100%; }
.st-kv-eq { color: var(--text-faint); font-family: var(--font-mono); font-size: 12px; padding: 0 2px; }
.st-kv > .st-btn, .st-list > .st-btn { justify-self: start; }

/* 密钥 */
.st-secret { display: grid; gap: 6px; }
.st-secret-line { display: flex; align-items: center; gap: 8px; }
.st-secret-line .st-input, .st-secret-line .st-textarea { flex: 1 1 auto; width: auto; }
.st-secret-status { flex: 0 0 auto; color: var(--text-faint); font-size: var(--fs-micro); font-weight: 600; }
.st-secret-status.is-ok { color: var(--online); }
.st-secret-status.is-warn { color: var(--gold); }
.st-secret-actions { display: flex; gap: 4px; }

/* 选择器按钮(模型池/模型/限流) */
.st-picker { display: inline-flex; align-items: center; gap: 6px; min-height: 34px; max-width: 100%; padding: 4px 8px 4px 10px; border: 0; border-radius: var(--radius); background: var(--surface-2); color: var(--text); cursor: pointer; font-size: var(--fs-ui); text-align: left; transition: background 140ms ease, box-shadow 160ms ease; }
.st-picker:hover { background: var(--surface-3); }
.st-picker:focus-visible { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); outline: 0; }
.st-picker.is-compact { min-height: 30px; }
.st-picker-text { display: inline-flex; flex-direction: column; min-width: 0; line-height: 1.25; }
.st-picker-text strong { font-size: var(--fs-ui); font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-picker-text small { color: var(--text-faint); font-size: var(--fs-micro); }
.st-picker-text.is-muted { color: var(--text-faint); }
.st-picker-caret { width: 14px; height: 14px; color: var(--text-faint); margin-left: auto; flex: 0 0 auto; }
.st-picker .st-chip { max-width: 160px; overflow: hidden; text-overflow: ellipsis; display: inline-block; line-height: 20px; }
.st-pick-group { margin-top: 8px; }
.st-pick-group-title { padding: 6px 2px 2px; color: var(--text-faint); font-size: var(--fs-micro); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.st-check-row { display: flex; align-items: center; gap: 9px; min-height: 32px; padding: 3px 6px; border-radius: var(--radius); cursor: pointer; transition: background 120ms ease; }
.st-check-row:hover { background: var(--surface-2); }
.st-check-row input { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; }
.st-check-row > span { display: grid; min-width: 0; }
.st-check-row strong { font-size: var(--fs-ui); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-check-row small { color: var(--text-faint); font-size: var(--fs-micro); }
.st-check-row.is-strong { margin-bottom: 4px; padding-bottom: 8px; border-bottom: 1px solid var(--line); border-radius: 0; }
.st-check-row.is-strong strong { font-weight: 600; }

/* 折叠区:grid 0fr→1fr 做高度过渡 */
.st-disclosure { padding: 0; }
.st-disclosure-head { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 40px; padding: 6px 16px; border: 0; background: transparent; color: var(--text-soft); cursor: pointer; text-align: left; transition: color 140ms ease, background 140ms ease; }
.st-disclosure-head:hover { background: color-mix(in srgb, var(--surface-2) 60%, transparent); color: var(--text); }
.st-disclosure-head strong { font-size: var(--fs-ui); font-weight: 600; }
.st-disclosure-head small { color: var(--text-faint); font-size: var(--fs-micro); }
.st-disclosure-caret { width: 14px; height: 14px; transition: transform 200ms cubic-bezier(.2,.8,.2,1); }
.st-disclosure.is-open .st-disclosure-caret { transform: rotate(90deg); }
.st-disclosure-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 240ms cubic-bezier(.2,.8,.2,1); }
.st-disclosure.is-open .st-disclosure-body { grid-template-rows: 1fr; }
.st-disclosure-inner { min-height: 0; overflow: hidden; }
.st-disclosure.is-open .st-disclosure-inner { border-top: 1px solid color-mix(in srgb, var(--line) 50%, transparent); }

/* ── 卡片墙 ── */
.st-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 10px; }
.st-grid.is-personas { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.st-grid.is-plugins { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }
.st-provider-card, .st-persona-card, .st-plugin-card { position: relative; display: flex; align-items: center; gap: 12px; min-height: 68px; padding: 12px 12px 12px 14px; border: 0; border-radius: var(--radius); background: var(--surface-1); color: var(--text); text-align: left; box-shadow: var(--card-shadow); animation: st-fade-up .36s ease-out both; animation-delay: calc(var(--i, 0) * 38ms); transition: transform .16s ease, box-shadow .16s ease, background .16s ease; }
.st-provider-card, .st-persona-card { cursor: pointer; }
.st-provider-card:hover, .st-persona-card:hover, .st-plugin-card:hover { transform: translateY(-2px); box-shadow: var(--float-shadow); }
.st-provider-card:focus-visible, .st-persona-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.st-provider-copy, .st-persona-copy, .st-plugin-copy, .st-route-copy, .st-server-copy { display: grid; min-width: 0; flex: 1 1 auto; gap: 2px; }
.st-provider-copy strong, .st-persona-copy strong, .st-plugin-copy strong, .st-route-copy strong, .st-server-copy strong { font-size: var(--fs-ui); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-provider-copy small, .st-persona-copy small, .st-plugin-copy small, .st-route-copy small, .st-server-copy small { color: var(--text-faint); font-size: var(--fs-micro); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-server-copy small.is-mono { font-family: var(--font-mono); }
.st-provider-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.st-provider-copy .st-provider-chips { margin-top: 5px; }
.st-card-caret { width: 16px; height: 16px; color: var(--text-faint); flex: 0 0 auto; transition: transform .16s ease, color .16s ease; }
.st-provider-card:hover .st-card-caret, .st-persona-card:hover .st-card-caret, .st-route-row:hover .st-card-caret { transform: translateX(3px); color: var(--accent); }
.st-persona-card.is-active { box-shadow: 0 0 0 2px var(--accent), var(--card-shadow); }
.st-avatar { display: grid; place-items: center; width: 44px; height: 44px; flex: 0 0 44px; border-radius: var(--radius); overflow: hidden; background: var(--surface-2); }
.st-avatar img { width: 100%; height: 100%; object-fit: cover; }
.st-avatar .st-mark { width: 44px; height: 44px; border-radius: var(--radius); }
.st-avatar.is-default { background: color-mix(in srgb, var(--accent) 22%, transparent); color: var(--accent); }
.st-avatar.is-default .st-icon { width: 20px; height: 20px; }
.st-plugin-card { padding: 8px 12px 8px 8px; }
.st-plugin-card.is-off { opacity: .62; }
.st-plugin-card.is-off:hover { opacity: 1; }
.st-plugin-open { display: flex; flex: 1 1 auto; align-items: center; gap: 11px; min-width: 0; padding: 4px 6px; border: 0; border-radius: var(--radius); background: transparent; color: inherit; cursor: pointer; text-align: left; transition: background .14s ease; }
.st-plugin-open:hover { background: var(--surface-2); }
.st-plugin-open .st-mark { width: 34px; height: 34px; flex-basis: 34px; border-radius: var(--radius); font-size: 12px; }

/* 供应商抽屉:模型列表 */
.st-toolbar { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 12px; }
.st-toolbar .st-input { flex: 1 1 160px; width: auto; }
.st-toolbar-hint { color: var(--text-faint); font-size: var(--fs-micro); line-height: 1.5; flex: 1 1 100%; }
.st-model-list { display: grid; gap: 4px; }
.st-model-row { display: flex; align-items: center; gap: 8px; min-height: 44px; padding: 5px 6px 5px 4px; border-radius: var(--radius); background: var(--surface-1); box-shadow: var(--card-shadow); animation: st-fade-up .28s ease-out both; animation-delay: calc(var(--i, 0) * 22ms); transition: background .14s ease; }
.st-model-row:hover { background: var(--surface-2); }
.st-model-row.is-default { box-shadow: inset 2px 0 0 var(--gold), var(--card-shadow); }
.st-model-name { flex: 1 1 auto; min-width: 0; font-family: var(--font-mono); font-size: 12.5px; }
.st-model-name strong { font-weight: 600; overflow-wrap: anywhere; }
.st-model-badges { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 4px; flex: 0 1 auto; }
.st-modality { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: var(--radius); background: color-mix(in srgb, var(--surface-3) 70%, transparent); color: var(--text-soft); }
.st-modality .st-icon { width: 12px; height: 12px; }
.st-star { color: var(--text-faint); }
.st-star.is-on { color: var(--gold); }
.st-star.is-on .st-icon { fill: currentColor; }
.st-star-mini { width: 12px; height: 12px; color: var(--gold); fill: currentColor; margin-left: 4px; vertical-align: -1px; }
.st-cost-grid { display: grid; grid-template-columns: 90px repeat(3, minmax(0, 1fr)); gap: 6px; align-items: end; }
.st-cost-grid .st-select { max-width: none; width: 100%; }
.st-cost-cell { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.st-cost-cell .st-input { width: auto; min-width: 0; }
.st-cost-cell small { color: var(--text-faint); font-size: var(--fs-micro); }
.st-fetch-list { display: grid; gap: 2px; max-height: 52vh; overflow-y: auto; padding-right: 2px; scrollbar-width: thin; }
.st-fetch-row { display: flex; align-items: center; gap: 10px; min-height: 38px; padding: 4px 8px; border-radius: var(--radius); cursor: pointer; animation: st-fade-in .22s ease-out both; animation-delay: calc(var(--i, 0) * 14ms); transition: background .12s ease; }
.st-fetch-row:hover { background: var(--surface-2); }
.st-fetch-row input { accent-color: var(--accent); width: 15px; height: 15px; margin: 0; flex: 0 0 auto; }
.st-fetch-row strong { flex: 1 1 auto; min-width: 0; font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; overflow-wrap: anywhere; }

/* 服务器 / 路由 / 账号行 */
.st-server-row, .st-route-row { display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 8px 14px; border: 0; background: transparent; color: var(--text); text-align: left; animation: st-fade-in .24s ease-out both; animation-delay: calc(var(--i, 0) * 30ms); transition: background .12s ease; }
.st-route-row { cursor: pointer; }
.st-server-row + .st-server-row, .st-route-row + .st-route-row { border-top: 1px solid color-mix(in srgb, var(--line) 50%, transparent); }
.st-server-row:hover, .st-route-row:hover { background: color-mix(in srgb, var(--surface-2) 60%, transparent); }
.st-server-mark { display: grid; place-items: center; width: 34px; height: 34px; flex: 0 0 34px; border-radius: var(--radius); background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); }
.st-server-mark .st-icon { width: 16px; height: 16px; }
.st-server-copy { padding: 0; border: 0; background: transparent; color: inherit; cursor: pointer; text-align: left; }
.st-route-copy { gap: 5px; }
.st-accounts { display: grid; gap: 8px; padding: 12px 16px 4px; }
.st-account { display: grid; gap: 8px; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2); }
.st-account-head { display: flex; align-items: center; gap: 8px; }
.st-account-head .st-input { flex: 1 1 auto; width: auto; }
.st-account .st-secret-line .st-input { background: var(--surface-1); }
.st-account .st-textarea { background: var(--surface-1); }
.st-card > .st-card-body > .st-btn, .st-card-body > .st-btn { margin: 4px 16px 14px; align-self: flex-start; }

/* 图片字段 */
.st-image-field { display: flex; gap: 12px; align-items: flex-start; }
.st-image-controls { display: grid; gap: 6px; flex: 1 1 auto; min-width: 0; }
.st-image-controls .st-input { width: 100%; }
.st-avatar-preview, .st-board-preview { flex: 0 0 auto; width: 64px; height: 64px; border-radius: var(--radius); object-fit: cover; background: var(--surface-2); }
.st-board-preview { width: 120px; height: 68px; border-radius: var(--radius); }
.st-avatar-preview.is-missing, .st-board-preview.is-missing { background: repeating-linear-gradient(45deg, var(--surface-2) 0 6px, var(--surface-1) 6px 12px); }

/* ── 抽屉 ── */
.st-drawer-overlay { position: fixed; inset: 0; z-index: 70; display: flex; justify-content: flex-end; background: color-mix(in srgb, var(--app-bg) 52%, transparent); backdrop-filter: blur(2px); animation: st-fade-in .2s ease-out both; }
.st-drawer-overlay.is-closing { animation: st-fade-out .2s ease-in both; }
.st-drawer { --st-drawer-width: 560px; display: flex; flex-direction: column; width: min(var(--st-drawer-width), 94vw); height: 100%; background: var(--surface-1); border-left: 1px solid var(--line); box-shadow: var(--float-shadow); animation: st-slide-in .28s cubic-bezier(.2,.8,.2,1) both; }
.st-drawer-overlay.is-closing .st-drawer { animation: st-slide-out .22s cubic-bezier(.4,0,.8,.4) both; }
.st-drawer-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 18px 12px; }
.st-drawer-title { display: grid; min-width: 0; gap: 2px; }
.st-drawer-title strong { font-size: 15px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-drawer-title small { color: var(--text-faint); font-size: var(--fs-micro); font-family: var(--font-mono); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* flex: 0 0 auto 是必须的:抽屉是列向 flex,而这条 overflow-y: hidden 让本元素
   的自动最小尺寸变成 0——不锁住 flex-shrink,标签页内容一长就把整条标签栏压
   扁,里面 38px 高的按钮被自己的 overflow 从下面裁掉。 */
.st-tabs { position: relative; display: flex; flex: 0 0 auto; gap: 2px; padding: 0 14px; border-bottom: 1px solid var(--line); overflow-x: auto; overflow-y: hidden; scrollbar-width: none; }
.st-tab { position: relative; flex: 0 0 auto; min-height: 38px; padding: 0 11px; border: 0; background: transparent; color: var(--text-soft); cursor: pointer; font-size: var(--fs-ui); font-weight: 600; white-space: nowrap; transition: color .16s ease; }
.st-tab:hover { color: var(--text); }
.st-tab.is-active { color: var(--accent); }
.st-tabs-indicator { position: absolute; bottom: -1px; left: 0; width: var(--w, 0px); height: 2px; border-radius: var(--radius-sm); background: var(--accent); transform: translateX(var(--x, 0px)); transition: transform .24s cubic-bezier(.2,.8,.2,1), width .24s cubic-bezier(.2,.8,.2,1); }
.st-drawer-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; overscroll-behavior: contain; padding: 14px 18px 24px; display: grid; gap: 12px; align-content: start; scrollbar-width: thin; scrollbar-color: var(--line-strong) transparent; }
.st-drawer-body.st-tab-enter { animation: st-fade-up .22s ease-out both; }
.st-drawer-body .st-card { animation: none; }
.st-drawer-foot { display: flex; align-items: center; gap: 8px; padding: 10px 18px max(10px, env(safe-area-inset-bottom)); border-top: 1px solid var(--line); background: var(--surface-1); }
.st-foot-spacer { flex: 1 1 auto; }

/* ── 菜单 / 弹出框 ── */
.st-menu { position: fixed; z-index: 90; display: grid; gap: 1px; min-width: 200px; max-width: min(360px, 92vw); max-height: 70vh; overflow-y: auto; padding: 5px; border-radius: var(--radius); background: var(--surface-1); box-shadow: var(--float-shadow); transform-origin: top left; animation: st-pop-in .16s cubic-bezier(.2,.8,.2,1) both; scrollbar-width: thin; }
.st-menu.is-flipped { transform-origin: bottom left; }
.st-menu.is-closing { animation: st-pop-out .14s ease-in both; }
.st-menu-item { display: grid; grid-template-columns: 16px auto minmax(0, 1fr); align-items: center; gap: 8px; width: 100%; min-height: 34px; padding: 5px 9px 5px 6px; border: 0; border-radius: var(--radius); background: transparent; color: var(--text-soft); cursor: pointer; text-align: left; transition: background .12s ease, color .12s ease; }
.st-menu-item:hover:not(:disabled), .st-menu-item:focus-visible { background: var(--surface-2); color: var(--text); outline: 0; }
.st-menu-item:disabled { opacity: .45; cursor: not-allowed; }
.st-menu-item.is-danger { color: var(--danger); }
.st-menu-item.is-danger:hover:not(:disabled) { background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); }
.st-menu-item.is-checked { color: var(--text); }
.st-menu-check { display: grid; place-items: center; width: 16px; height: 16px; color: var(--accent); }
.st-menu-check .st-icon { width: 14px; height: 14px; }
.st-menu-icon { width: 15px; height: 15px; }
.st-menu-item:not(:has(.st-menu-icon)) { grid-template-columns: 16px minmax(0, 1fr); }
.st-menu-copy { display: grid; min-width: 0; gap: 1px; }
.st-menu-copy strong { font-size: var(--fs-ui); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-menu-copy small { color: var(--text-faint); font-size: var(--fs-micro); line-height: 1.4; }
.st-menu-sep { margin: 4px 6px; border: 0; border-top: 1px solid var(--line); }
.st-menu-heading { padding: 7px 8px 2px; color: var(--text-faint); font-size: var(--fs-micro); font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.st-popover { position: fixed; z-index: 88; display: flex; flex-direction: column; max-width: min(420px, 94vw); max-height: 76vh; border-radius: var(--radius); background: var(--surface-1); box-shadow: var(--float-shadow); transform-origin: top right; animation: st-pop-in .18s cubic-bezier(.2,.8,.2,1) both; }
.st-popover.is-flipped { transform-origin: bottom right; }
.st-popover.is-closing { animation: st-pop-out .14s ease-in both; }
.st-popover-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 8px 6px 14px; border-bottom: 1px solid var(--line); }
.st-popover-head strong { font-size: var(--fs-ui); font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-popover-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 8px 8px 10px; scrollbar-width: thin; }
.st-popover-body .st-row { padding: 8px 6px; }
.st-popover-body .st-row-control { max-width: 60%; }
.st-popover-body .st-input.is-number { width: 110px; }

/* ── 对话框 ── */
.st-dialog { --st-dialog-width: 520px; width: min(var(--st-dialog-width), calc(100vw / var(--ui-scale) - 32px)); max-height: calc(100vh / var(--ui-scale) - 48px); padding: 0; border: 0; border-radius: var(--radius); background: var(--surface-1); color: var(--text); box-shadow: var(--float-shadow); display: none; flex-direction: column; }
.st-dialog[open] { display: flex; animation: st-dialog-in .22s cubic-bezier(.2,.8,.2,1) both; }
.st-dialog::backdrop { background: rgba(0, 0, 0, .55); animation: st-fade-in .2s ease-out both; }
.st-dialog-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 16px 12px 10px 18px; border-bottom: 1px solid var(--line); }
.st-dialog-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 14px 18px; display: grid; gap: 12px; scrollbar-width: thin; }
.st-dialog-body .st-card { animation: none; }
.st-dialog-foot { display: flex; align-items: center; justify-content: flex-end; gap: 8px; padding: 10px 18px 14px; border-top: 1px solid var(--line); }
.st-dialog-text { margin: 0; color: var(--text-soft); font-size: var(--fs-ui); line-height: 1.6; }

/* ── 底栏:有改动时升起 ── */
.settings-footer { transition: background .2s ease, box-shadow .2s ease, transform .24s cubic-bezier(.2,.8,.2,1); }
.settings-footer.is-dirty { background: var(--surface-1); box-shadow: 0 -8px 24px rgba(0, 0, 0, .28); }
.settings-footer.is-dirty > span::before { content: "●"; margin-right: 6px; color: var(--gold); animation: status-pulse 1.6s ease-in-out infinite; }
.settings-footer.is-invalid > span { color: var(--danger); }
.settings-footer.is-dirty .primary-button:not(:disabled) { animation: st-pop .3s ease-out both; }

/* 模型池:池子装模型 */
.st-pool-section { display: grid; gap: 10px; }
.st-pool-section + .st-pool-section { margin-top: 18px; }
.st-pool-section-head { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; padding: 0 2px; }
.st-pool-section-head h3 { margin: 0; font-size: var(--fs-ui); font-weight: 700; }
.st-pool-section-head p { margin: 0; color: var(--text-faint); font-size: var(--fs-micro); line-height: 1.5; }
.st-pool-section-head p:empty { display: none; }
.st-pool-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 12px; }
.st-pool-grid.is-global { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.st-pool-grid.is-tiers { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.st-pool-grid.is-roles { grid-template-columns: minmax(0, 1fr); }
.st-pool-card.is-wide { min-height: 0; }
.st-pool-card.is-wide .st-pool-member-copy strong { font-family: inherit; font-size: var(--fs-ui); }
@media (max-width: 1180px) { .st-pool-grid.is-tiers { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 720px) { .st-pool-grid.is-global, .st-pool-grid.is-tiers { grid-template-columns: minmax(0, 1fr); } }
.st-pool-card { display: flex; flex-direction: column; min-height: 180px; border-radius: var(--radius); background: var(--surface-1); box-shadow: var(--card-shadow); animation: st-fade-up .34s ease-out both; animation-delay: calc(var(--i, 0) * 50ms); }
.st-pool-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; padding: 14px 16px 10px; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.st-pool-head h3 { margin: 0; font-size: var(--fs-ui); font-weight: 700; }
.st-pool-head p { margin: 3px 0 0; color: var(--text-faint); font-size: var(--fs-micro); line-height: 1.5; }
.st-pool-list { flex: 1 1 auto; display: grid; align-content: start; gap: 4px; padding: 8px; }
.st-pool-empty { margin: 0; padding: 18px 10px; color: var(--text-faint); font-size: var(--fs-meta); text-align: center; border: 1px dashed color-mix(in srgb, var(--line-strong) 70%, transparent); border-radius: var(--radius); }
.st-pool-member { display: flex; align-items: center; gap: 9px; min-height: 40px; padding: 4px 4px 4px 8px; border-radius: var(--radius); background: var(--surface-2); animation: st-pop .2s ease-out both; animation-delay: calc(var(--i, 0) * 25ms); transition: background .12s ease; }
.st-pool-member:hover { background: var(--surface-3); }
.st-pool-member-copy { display: grid; flex: 1 1 auto; min-width: 0; gap: 1px; }
.st-pool-member-copy strong { font-family: var(--font-mono); font-size: 12.5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.st-pool-member-copy small { color: var(--text-faint); font-size: var(--fs-micro); }
.st-pool-foot { padding: 6px 8px 10px; border-top: 1px solid color-mix(in srgb, var(--line) 45%, transparent); }

/* 局部重画不重放入场动画(rerender 打上 is-settled;切换导航时去掉) */
.st-root.is-settled .st-page-head, .st-root.is-settled .st-card, .st-root.is-settled .st-provider-card, .st-root.is-settled .st-persona-card, .st-root.is-settled .st-plugin-card,
.st-root.is-settled .st-server-row, .st-root.is-settled .st-route-row, .st-root.is-settled .st-empty, .st-root.is-settled .st-pool-card, .st-root.is-settled .st-pool-member,
.st-drawer-body.is-settled .st-model-row { animation: none; }

/* ── 动画 ── */
@keyframes st-fade-up { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes st-fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes st-fade-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes st-slide-in { from { transform: translateX(40px); opacity: .5; } to { transform: none; opacity: 1; } }
@keyframes st-slide-out { from { transform: none; opacity: 1; } to { transform: translateX(40px); opacity: 0; } }
@keyframes st-pop-in { from { opacity: 0; transform: scale(.94) translateY(-4px); } to { opacity: 1; transform: none; } }
@keyframes st-pop-out { from { opacity: 1; transform: none; } to { opacity: 0; transform: scale(.96); } }
@keyframes st-pop { 0% { transform: scale(.85); } 60% { transform: scale(1.06); } 100% { transform: scale(1); } }
@keyframes st-dialog-in { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes st-shake { 0%, 100% { transform: translateX(0); } 20% { transform: translateX(-4px); } 40% { transform: translateX(4px); } 60% { transform: translateX(-3px); } 80% { transform: translateX(3px); } }
.st-shake { animation: st-shake .32s ease-in-out; }

@media (prefers-reduced-motion: reduce) {
  .st-card, .st-page-head, .st-provider-card, .st-persona-card, .st-plugin-card, .st-model-row, .st-pool-card, .st-pool-member, .st-server-row, .st-route-row, .st-fetch-row, .st-chip-item, .st-empty, .st-error,
  .st-drawer-overlay, .st-drawer, .st-menu, .st-popover, .st-dialog[open], .st-dialog::backdrop, .st-drawer-body.st-tab-enter, .st-shake, .settings-footer.is-dirty .primary-button, .st-kv-row, .st-list-row { animation: none !important; }
  .st-disclosure-body, .st-tabs-indicator, .st-disclosure-caret, .st-provider-card, .st-persona-card, .st-plugin-card, .settings-footer { transition: none !important; }
}

@media (max-width: 836px) {
  .st-row { flex-wrap: wrap; }
  .st-row-control { max-width: none; flex: 1 1 100%; justify-content: flex-start; }
  .st-input { width: 100%; }
    .st-cost-grid { grid-template-columns: 1fr 1fr; }
}

/* ── 批量选择(09-04):表情包选择模式、记忆/知识库勾选列、批量操作条 ── */
.dash-bulk-bar { display: flex; align-items: center; flex-wrap: wrap; gap: 8px 10px; margin: 0 0 12px; padding: 8px 12px; border-radius: var(--radius); background: color-mix(in srgb, var(--accent) 14%, var(--surface-1)); box-shadow: var(--card-shadow); animation: dash-fade-up .22s ease-out both; }
.dash-bulk-bar strong { flex: none; font-size: var(--fs-ui); }
/* 按钮成组:窄了整组换行,不会散成三行。margin-left:auto 让宽容器里仍然右对齐。 */
.dash-bulk-actions { display: flex; flex-wrap: wrap; align-items: center; margin-left: auto; gap: 8px; }
/* compact:只剩两个按钮,不必再占一整条。 */
.dash-bulk-bar.is-compact { padding: 6px 8px; }
.dash-bulk-bar.is-compact .dash-bulk-actions { margin-left: 0; }
.dash-bulk-spacer { flex: 1 1 auto; }
.dash-row-check { width: 15px; height: 15px; margin: 0; accent-color: var(--accent); cursor: pointer; }
.dash-cell-check { justify-content: center; padding: 0 !important; }
.dash-tree-check { flex: none; }
.dash-meme.is-selectable { cursor: pointer; }
.dash-meme.is-selectable .dash-meme-thumb::after { content: ""; position: absolute; inset: 0; background: transparent; transition: background .12s ease; }
.dash-meme.is-selected { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }
.dash-meme.is-selected .dash-meme-thumb::after { background: color-mix(in srgb, var(--accent) 22%, transparent); }
.dash-meme-check { position: absolute; top: 6px; left: 6px; z-index: 1; display: grid; place-items: center; width: 22px; height: 22px; border-radius: var(--radius); border: 2px solid rgba(255, 255, 255, .85); background: rgba(0, 0, 0, .35); color: transparent; transition: background .12s ease, color .12s ease; }
.dash-meme-check svg { width: 14px; height: 14px; }
.dash-meme.is-selected .dash-meme-check { background: var(--accent); border-color: var(--accent); color: var(--inverse-text); }

/* 表情包「添加理由」:只给人看的乐子,模型看不到 */
.dash-meme-reason { margin: 0 0 14px; padding: 10px 12px 10px 14px; border-left: 3px solid var(--gold); border-radius: var(--radius); background: color-mix(in srgb, var(--gold) 12%, var(--surface-2)); }
.dash-meme-reason-label { display: block; margin-bottom: 4px; color: var(--gold); font-size: var(--fs-micro); font-weight: 700; letter-spacing: .08em; }
.dash-meme-reason p { margin: 0; font-size: var(--fs-ui); line-height: 1.6; }

/* ── 赞助面板(09-09):领奖台、名次条、首字头像 ──
   颜色全部由既有 token 混出(--gold / --accent),不新增色值。 */
.dash-avatar {
  flex: none; display: grid; place-items: center; width: 30px; height: 30px; border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--accent) 20%, var(--surface-2)); color: var(--text);
  font-size: var(--fs-meta); font-weight: 600; line-height: 1;
}
.dash-sponsor-podium { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.dash-sponsor-podium-item {
  display: flex; flex-direction: column; gap: 6px; min-width: 0; padding: 12px 14px;
  border: 1px solid var(--line); border-radius: var(--radius); background: var(--surface-2); cursor: pointer;
}
.dash-sponsor-podium-item:hover, .dash-sponsor-podium-item:focus-visible { border-color: var(--accent); }
/* 前三的强调只差在底色浓淡上：金 → 主色 → 淡金，冠军最实。 */
.dash-sponsor-podium-item.is-1 { background: color-mix(in srgb, var(--gold) 18%, var(--surface-1)); border-color: color-mix(in srgb, var(--gold) 45%, var(--line)); }
.dash-sponsor-podium-item.is-2 { background: color-mix(in srgb, var(--accent) 12%, var(--surface-1)); border-color: color-mix(in srgb, var(--accent) 30%, var(--line)); }
.dash-sponsor-podium-item.is-3 { background: color-mix(in srgb, var(--gold) 8%, var(--surface-1)); border-color: color-mix(in srgb, var(--gold) 20%, var(--line)); }
.dash-sponsor-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.dash-sponsor-medal { flex: none; font-size: 19px; line-height: 1; }
/* 会被挤的那个孩子必须 flex:0 1 auto + min-width:0，否则长名字把整行撑出去。 */
.dash-sponsor-name { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.dash-sponsor-amount { font-family: var(--serif); font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; }
.dash-sponsor-sub { display: flex; align-items: center; flex-wrap: wrap; gap: 4px 10px; min-width: 0; font-size: var(--fs-micro); color: var(--text-soft); }
.dash-sponsor-chips { display: flex; flex-wrap: wrap; gap: 4px; min-width: 0; }
.dash-sponsor-chips .dash-chip { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.dash-sponsor-list { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; }
.dash-sponsor-row {
  display: grid; grid-template-columns: 34px 30px minmax(0, 1.8fr) minmax(60px, 1.4fr) 100px 54px 84px;
  align-items: center; gap: 10px; padding: 6px 10px; border-radius: var(--radius); cursor: pointer; font-size: var(--fs-meta);
}
.dash-sponsor-row:hover, .dash-sponsor-row:focus-visible { background: var(--surface-2); }
.dash-sponsor-row > * { min-width: 0; }
.dash-sponsor-rank { color: var(--text-faint); font-variant-numeric: tabular-nums; }
.dash-sponsor-who { display: flex; flex-direction: column; min-width: 0; }
/* 会被挤的孩子:flex 里 0 1 auto + min-width 0,grid 里 block + min-width 0,两种容器同一个类兜住。 */
.dash-sponsor-cell { display: block; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dash-sponsor-total { text-align: right; font-variant-numeric: tabular-nums; }
.dash-chip.dash-sponsor-total, .dash-chip.dash-sponsor-amount { justify-self: end; align-self: start; }
/* 行 hover 时底色就是 --surface-2，进度槽得换一层才看得出来。 */
.dash-sponsor-row .dash-hbar-track { background: color-mix(in srgb, var(--text-faint) 18%, transparent); }
/* .dash-field 是 display:flex，会盖掉 [hidden] 的 UA 规则（币种切回人民币时那一格要真消失）。 */
.dash-field[hidden] { display: none; }
@media (max-width: 836px) {
  /* 手机上三个并排只剩几十像素宽，改成竖着排；名次条把进度条与笔数收起来。 */
  .dash-sponsor-podium { grid-template-columns: 1fr; }
  .dash-sponsor-row { grid-template-columns: 30px 30px minmax(0, 1fr) 96px; gap: 8px; }
  .dash-sponsor-row .dash-hbar-track, .dash-sponsor-row > :nth-last-child(-n+2) { display: none; }
}

/* ── 知识库拖放上传(09-09) ─────────────────────────────────────────── */
/* 投放区是整个知识库面板而不是右边的文件树:库空时文件树只剩一行提示,而那正是
   最想拖文件进来的时刻,把最小的目标留给最常见的动作说不过去。min-height 让面板
   即使内容很短也铺满正文区,不然拖到空白处会被浏览器当成「打开这个文件」。 */
.dash-drop-host { position: relative; min-height: 100%; }
.dash-drop-host.is-dropping { outline: 2px dashed var(--accent); outline-offset: -8px; border-radius: var(--radius); }
.dash-drop-veil {
  position: absolute; inset: 0; z-index: 5; display: flex; justify-content: center;
  background: color-mix(in srgb, var(--accent) 8%, transparent); border-radius: var(--radius);
  /* 不吃指针事件:遮罩自己一旦成为拖放目标,鼠标进它就等于离开下面的面板,
     指示层会随鼠标疯狂闪。 */
  pointer-events: none;
}
/* .dash-drop-veil 是 display:flex,会盖掉 [hidden] 的 UA 规则。 */
.dash-drop-veil[hidden] { display: none; }
/* 面板可能比视口高;标签 sticky 在滚动口顶部,滚到哪都看得见。sticky 要生效,
   flex 子项不能被拉伸,所以显式 align-self。 */
.dash-drop-label {
  position: sticky; top: 24px; align-self: flex-start; margin-top: 24px;
  display: flex; align-items: center; gap: 8px; padding: 10px 20px;
  border: 1px dashed var(--accent); border-radius: var(--radius);
  background: var(--surface-1); box-shadow: var(--card-shadow);
  color: var(--text); font-size: var(--fs-ui); font-weight: 600;
}
.dash-drop-label svg { width: 16px; height: 16px; color: var(--accent); }
/* 上传结果里的理由是服务端原话,可以很长(守卫那句拒绝有 100 多字符)。让它跟
   文件名争宽度而不是把整行撑出记录框;全文在 title 上。 */
.dash-upload-list .dash-chip { flex: 0 1 auto; min-width: 0; max-width: 62%; overflow: hidden; text-overflow: ellipsis; }

/* 重建卡的进度条:只在真跑着且知道总数时才出现,所以它不是常驻元素——
   高度与 .todo-progress 对齐(3px + 圆角),颜色用 accent 而不是 text-soft,
   因为它代表「正在发生的事」而不是「已完成比例的静态展示」。 */
.dash-card-progress {
  overflow: hidden;
  height: 3px;
  margin-top: 8px;
  border-radius: var(--radius-pill);
  background: var(--surface-3);
}

.dash-card-progress > i {
  display: block;
  height: 100%;
  border-radius: inherit;
  background: var(--accent);
  transition: width 240ms ease;
}

/* ── 账号(阶段 5 多用户) ── */
.login-switch { margin: 4px 0 0; font-size: 12px; color: var(--text-soft); text-align: center; }
.login-switch button { padding: 0 0 0 4px; border: 0; background: none; color: var(--accent); font-size: 12px; cursor: pointer; }
.acct-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px 14px; }
.acct-grid label { display: grid; gap: 4px; font-size: var(--fs-meta); color: var(--text-soft); }
.acct-grid input { min-height: 38px; padding: 0 10px; border: 0; border-radius: var(--radius);
  background: var(--surface-2); color: var(--text); font-size: var(--fs-ui); outline: 0; }
.acct-grid input:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); }
.acct-grid input:disabled { color: var(--text-soft); }
.acct-profile { display: grid; gap: 4px; margin-top: 12px; font-size: var(--fs-meta); color: var(--text-soft); }
.acct-profile textarea { min-height: 120px; padding: 10px; border: 0; border-radius: var(--radius); resize: vertical;
  background: var(--surface-2); color: var(--text); font-size: var(--fs-ui); font-family: inherit; outline: 0; }
.acct-profile textarea:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); }
.acct-actions { display: flex; align-items: center; gap: 10px; margin-top: 12px; flex-wrap: wrap; }
.acct-actions .login-submit { margin-top: 0; padding: 0 18px; }
.acct-head-action { margin-left: auto; flex: none; }
.u-card-head .u-hint { flex: 1 1 160px; min-width: 0; line-height: 1.5; }
.acct-actions .login-submit { white-space: nowrap; flex: none; }
.acct-grid input { box-sizing: border-box; width: 100%; }
.acct-profile textarea { box-sizing: border-box; width: 100%; line-height: 1.6; }
.acct-invite-code { display: inline-block; margin: 0 0 12px; padding: 10px 14px; border-radius: var(--radius);
  background: var(--surface-2); font-family: var(--mono); font-size: 20px; letter-spacing: .14em; user-select: all; }
.u-table .acct-row-action { min-height: 26px; padding: 2px 10px; font-size: var(--fs-micro); margin-right: 6px; }
.u-table .acct-muted { color: var(--text-faint); }

/* ── 登录页独立(阶段 5 多用户):没登录就只有登录面板 ── */
body.is-blocked .sidebar,
body.is-blocked .sidebar-scrim,
body.is-blocked .stage-float,
body.is-blocked .stage-todos,
body.is-blocked .composer-dock,
body.is-blocked .artifact-workspace,
body.is-blocked .console-view { display: none !important; }
body.is-blocked .main-stage { grid-column: 1 / -1; }
body.is-blocked .blocked-state {
  position: fixed; inset: 0; z-index: 60; display: grid; place-content: center; justify-items: center;
  padding: 32px 24px; background: var(--app-bg); text-align: center;
  animation: login-fade 320ms ease-out both;
}
body.is-login .blocked-state img { width: 84px; height: 84px; margin-bottom: 18px; }
body.is-login .blocked-state h1 { font-size: 24px; }
body.is-login .login-form { width: min(100%, 380px); padding: 22px; }
@keyframes login-fade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { body.is-blocked .blocked-state { animation: none; } }

/* ── 欢迎引导(OOBE,阶段 8) ── */
.oobe { position: fixed; inset: 0; z-index: 70; display: grid; place-items: center; padding: 20px; overflow: auto; }
.oobe[hidden] { display: none; }
.oobe-bg { position: absolute; inset: 0; background: var(--app-bg); overflow: hidden; }
.oobe-bg i { position: absolute; border-radius: 50%; filter: blur(60px); opacity: .55; animation: oobe-drift 18s ease-in-out infinite alternate; }
.oobe-bg i:nth-child(1) { width: 46vw; height: 46vw; left: -12vw; top: -14vw; background: color-mix(in srgb, var(--accent) 55%, transparent); }
.oobe-bg i:nth-child(2) { width: 38vw; height: 38vw; right: -10vw; bottom: -12vw; background: color-mix(in srgb, var(--gold, #d4a25a) 45%, transparent); animation-delay: -6s; }
.oobe-bg i:nth-child(3) { width: 26vw; height: 26vw; right: 20vw; top: 8vh; background: color-mix(in srgb, var(--accent) 30%, transparent); animation-delay: -12s; }
@keyframes oobe-drift { from { transform: translate3d(0, 0, 0) scale(1); } to { transform: translate3d(6vw, 4vh, 0) scale(1.15); } }
.oobe-card { position: relative; width: min(100%, 640px); max-height: calc(100dvh - 40px); display: grid; grid-template-rows: auto 1fr auto;
  background: color-mix(in srgb, var(--surface-1) 92%, transparent); border-radius: calc(var(--radius) * 1.6); box-shadow: var(--card-shadow), 0 30px 80px rgba(0,0,0,.35);
  backdrop-filter: blur(18px); overflow: hidden; animation: oobe-in 520ms cubic-bezier(.2,.8,.2,1) both; }
@keyframes oobe-in { from { opacity: 0; transform: translateY(18px) scale(.98); } to { opacity: 1; transform: none; } }
.oobe-head { display: flex; align-items: center; justify-content: space-between; padding: 18px 22px 0; }
.oobe-steps { display: flex; gap: 18px; margin: 0; padding: 0; list-style: none; font-size: var(--fs-meta); color: var(--text-faint); }
.oobe-steps li { display: flex; align-items: center; gap: 7px; transition: color 200ms; }
.oobe-steps li span { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 50%; background: var(--surface-2); font-size: 11px; transition: background 200ms, color 200ms; }
.oobe-steps li.on { color: var(--text); }
.oobe-steps li.on span { background: var(--accent); color: var(--inverse-text); }
.oobe-steps li.done span { background: color-mix(in srgb, var(--accent) 35%, var(--surface-2)); }
.oobe-skip { border: 0; background: none; color: var(--text-faint); font-size: var(--fs-meta); cursor: pointer; }
.oobe-skip:hover { color: var(--text); }
.oobe-panes { position: relative; overflow: auto; padding: 8px 22px 6px; }
.oobe-pane { display: none; animation: oobe-pane 360ms cubic-bezier(.2,.8,.2,1) both; }
.oobe-pane.is-active { display: block; }
@keyframes oobe-pane { from { opacity: 0; transform: translateX(28px); } to { opacity: 1; transform: none; } }
.oobe-pane h1 { margin: 14px 0 4px; font-family: var(--serif); font-size: 26px; font-weight: 600; letter-spacing: .01em; }
.oobe-pane > p { margin: 0 0 16px; color: var(--text-soft); font-size: var(--fs-ui); line-height: 1.6; }
.oobe-choice { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-bottom: 14px; }
.oobe-option { display: grid; gap: 4px; padding: 12px 14px; text-align: left; border: 2px solid transparent; border-radius: var(--radius);
  background: var(--surface-2); color: var(--text); cursor: pointer; transition: border-color 160ms, transform 160ms; }
.oobe-option:hover { transform: translateY(-1px); }
.oobe-option.is-on { border-color: var(--accent); }
.oobe-option b { font-size: var(--fs-ui); }
.oobe-option span { font-size: var(--fs-micro); color: var(--text-soft); line-height: 1.5; }
.oobe-persona { display: grid; gap: 12px; }
.oobe-persona[hidden] { display: none; }
.oobe-row { display: flex; gap: 14px; align-items: center; }
.oobe-avatar { position: relative; flex: none; width: 84px; height: 84px; display: grid; place-items: center; border-radius: 50%;
  background: var(--surface-2); border: 2px dashed color-mix(in srgb, var(--accent) 50%, transparent); cursor: pointer; overflow: hidden; color: var(--text-soft); font-size: var(--fs-micro); }
.oobe-avatar img { width: 100%; height: 100%; object-fit: cover; }
.oobe-avatar img:not([hidden]) + span { display: none; }
.oobe-fields { flex: 1; display: grid; gap: 8px; }
.oobe-fields label, .oobe-prompt, .oobe-toggle { display: grid; gap: 4px; font-size: var(--fs-meta); color: var(--text-soft); }
.oobe-fields input, .oobe-prompt textarea, .oobe-pane textarea { padding: 9px 10px; border: 0; border-radius: var(--radius); background: var(--surface-2);
  color: var(--text); font: inherit; font-size: var(--fs-ui); outline: 0; resize: vertical; }
.oobe-fields input:focus, .oobe-pane textarea:focus { box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent); }
.oobe-pane > textarea { width: 100%; min-height: 160px; box-sizing: border-box; }
.oobe-templates { display: flex; flex-wrap: wrap; gap: 6px; }
.oobe-templates button { padding: 5px 11px; border: 0; border-radius: 999px; background: var(--surface-2); color: var(--text-soft); font-size: var(--fs-micro); cursor: pointer; }
.oobe-templates button:hover, .oobe-templates button.is-on { background: color-mix(in srgb, var(--accent) 22%, var(--surface-2)); color: var(--text); }
.oobe-board { display: grid; gap: 6px; padding: 10px; border-radius: var(--radius); background: var(--surface-2); cursor: pointer; font-size: var(--fs-micro); color: var(--text-soft); }
.oobe-board img { width: 100%; max-height: 140px; object-fit: cover; border-radius: calc(var(--radius) * .7); }
.oobe-toggle { grid-template-columns: auto 1fr; grid-template-rows: auto auto; column-gap: 10px; align-items: center; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2); margin-bottom: 10px; cursor: pointer; }
.oobe-toggle input { grid-row: 1 / span 2; width: 18px; height: 18px; accent-color: var(--accent); }
.oobe-toggle b { color: var(--text); font-size: var(--fs-ui); }
.oobe-always { display: grid; gap: 4px; margin: 0 0 10px; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2); font-size: var(--fs-meta); color: var(--text-soft); }
.oobe-always b { color: var(--text); font-size: var(--fs-ui); }
.oobe-subhead { margin: 14px 0 8px; font-size: var(--fs-meta); font-weight: 600; color: var(--text-soft); }
.oobe-plugins { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 8px; }
.oobe-plugin { display: grid; grid-template-columns: auto 1fr; column-gap: 8px; align-items: start; padding: 9px 10px; border-radius: var(--radius); background: var(--surface-2); cursor: pointer; font-size: var(--fs-micro); color: var(--text-soft); }
.oobe-plugin input { margin-top: 2px; accent-color: var(--accent); }
.oobe-plugin b { display: block; color: var(--text); font-size: var(--fs-meta); }
.oobe-done { display: grid; justify-items: center; gap: 10px; padding: 34px 0 20px; text-align: center; }
.oobe-done img { width: 96px; height: 96px; border-radius: 50%; object-fit: cover; border: 3px solid var(--accent); animation: oobe-pop 600ms cubic-bezier(.2,.9,.2,1.2) both; }
@keyframes oobe-pop { from { transform: scale(.4); opacity: 0; } to { transform: none; opacity: 1; } }
.oobe-foot { display: flex; align-items: center; gap: 10px; padding: 12px 22px 18px; }
.oobe-foot .login-error { flex: 1; margin: 0 !important; }
.oobe-foot .login-submit { margin: 0 0 0 auto; padding: 0 20px; }
.oobe-foot .secondary-button[hidden] { display: none; }
@media (max-width: 640px) { .oobe { padding: 0; } .oobe-card { max-height: 100dvh; border-radius: 0; } .oobe-choice { grid-template-columns: 1fr; } }
@media (prefers-reduced-motion: reduce) { .oobe-bg i, .oobe-card, .oobe-pane, .oobe-done img { animation: none; } }
/* 账号页:人格卡 */
.persona-list { display: grid; gap: 8px; }
.persona-row { display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 12px; align-items: center; padding: 10px 12px; border-radius: var(--radius); background: var(--surface-2); }
.persona-row > div { min-width: 0; }
.persona-row b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (max-width: 560px) {
  .persona-row { grid-template-columns: 44px minmax(0, 1fr); }
  .persona-row-actions { grid-column: 1 / -1; justify-content: flex-start; }
}
.persona-row.is-active { box-shadow: inset 0 0 0 2px var(--accent); }
.persona-row img, .persona-row .persona-initial { width: 44px; height: 44px; border-radius: 50%; object-fit: cover; display: grid; place-items: center; background: var(--surface-1); font-weight: 600; }
.persona-row b { display: block; font-size: var(--fs-ui); }
.persona-row small { color: var(--text-soft); }
.persona-row .acct-row-action { margin-right: 0; }
.persona-row-actions { display: flex; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }

/* ═══════════════════════════ 过程时间线(思考 + 工具) ═══════════════════════════ */
/*
 * 连续的思考块和工具签串成一条时间线:一根 1px 细线穿过图标列的中心,图标处断开,
 * 图标就是节点。没有底板、边框、标签色——简洁靠形式,不靠把过程藏起来。
 * 线是独立元素(.proc-rail),起点终点由 JS 按可见节点算,高度走 transition,
 * 新出一行就平滑长到那个图标。动画只有一条曲线一组时长:行淡入/线生长 0.45s,开合 0.38s。
 * 次要色不用 --text-soft(亮色下是发棕的 on-surface-variant),改从正文色按比例兑底色得中性灰。
 */
.proc-line {
  position: relative;
  --proc-col: 16px;
  --proc-gap: 4px;
  --proc-ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --proc-soft: color-mix(in srgb, var(--text) 62%, var(--app-bg));
  --proc-think: color-mix(in srgb, var(--text) 74%, var(--app-bg));
  --proc-indent: calc(var(--proc-col) + var(--proc-gap) + 4px);
  margin: 2px 0;
}
.proc-rail {
  position: absolute;
  z-index: 0;
  top: 0;
  left: calc(var(--proc-col) / 2 - 0.5px);
  width: 1px;
  height: 0;
  background: color-mix(in srgb, var(--line-strong) 75%, var(--line));
  pointer-events: none;
  /* 不给线自己的过渡:它靠 ResizeObserver 在内容(grid-rows fold)动画的每一帧
     重量节点位置、瞬时贴着内容长/缩(#8 线拖后盖字的真因就是这条 0.45s 过渡在追赶)。
     新节点淡入时线瞬时到位、节点淡上来,观感也对。 */
}
.proc-head,
.proc-wrap {
  position: relative;
  z-index: 1;
}
@keyframes proc-fadein {
  from {
    opacity: 0;
    transform: translateY(4px);
  }
}

/* 节点:图标带上下两段页面色,把线遮出断口 */
.proc-node,
.assistant-blocks .proc-steps > .tool-card > .tool-head > .tool-icon,
.assistant-blocks .proc-steps > .reasoning-block > summary > .reasoning-icon {
  display: grid;
  box-sizing: border-box;
  width: var(--proc-col);
  height: var(--proc-col);
  flex: 0 0 var(--proc-col);
  margin: 0;
  place-items: center;
  border-radius: 0;
  background: var(--app-bg);
  box-shadow: 0 -2px 0 var(--app-bg), 0 2px 0 var(--app-bg);
  color: var(--proc-soft);
}
/* 子过程时间线在暖色面板里:节点遮线块要用面板的底色,不能用页面 app-bg(那样
   在暖底上露出一块深色方块),也不能没有背景(那样细线从图标里穿过去)。图标在
   什么背景上就是什么背景(#4)。 */
.sub-blocks .proc-steps > .tool-card > .tool-head > .tool-icon,
.sub-blocks .proc-steps > .reasoning-block > summary > .reasoning-icon,
.sub-blocks .proc-head > .proc-node {
  background: color-mix(in srgb, var(--text) 5%, var(--app-bg));
  box-shadow:
    0 -2px 0 color-mix(in srgb, var(--text) 5%, var(--app-bg)),
    0 2px 0 color-mix(in srgb, var(--text) 5%, var(--app-bg));
}
.assistant-blocks .proc-steps > .tool-card > .tool-head > .tool-icon .icon-slot,
.assistant-blocks .proc-steps > .reasoning-block > summary > .reasoning-icon svg,
.proc-node .icon-slot {
  width: 13px;
  height: 13px;
}

/* 总结行:只在「过程自动收起」开着、且时间线已切断时出现 */
.proc-head {
  display: flex;
  width: 100%;
  min-height: 30px;
  align-items: center;
  margin: 0;
  padding: 2px 0;
  border: 0;
  background: none;
  color: var(--proc-soft);
  font: 600 11.5px/1.5 var(--font-ui);
  text-align: left;
  cursor: pointer;
  gap: var(--proc-gap);
  pointer-events: none;
}
.proc-head > * {
  pointer-events: auto;
}
.proc-head[hidden] {
  display: none;
}
.proc-summary {
  display: inline-flex;
  align-items: baseline;
  padding: 0 4px;
  border-radius: 5px;
  font-variant-numeric: tabular-nums;
  transition: background-color 0.18s ease;
  animation: proc-fadein 0.45s var(--proc-ease) both;
}
.proc-head:hover .proc-summary {
  background: var(--surface-2);
}
.proc-summary b {
  /* 「Worked for x s」和后面的「1 tool · 1 thought」同色(#129),不再更深一档。 */
  color: inherit;
  font-weight: 600;
}
.proc-summary .proc-err {
  color: var(--danger);
}
.proc-summary .proc-dot {
  padding: 0 2px;
  opacity: 0.6;
}
.proc-chevron {
  width: 12px;
  height: 12px;
  transition: transform 0.38s var(--proc-ease);
}
.proc-line.is-open .proc-chevron {
  transform: rotate(90deg);
}
/* 开合是高度过渡:外层 grid 行高 0fr↔1fr,内层 overflow hidden */
.proc-wrap {
  display: grid;
  grid-template-rows: 0fr;
  opacity: 0;
  transition: grid-template-rows 0.38s var(--proc-ease), opacity 0.25s ease;
}
.proc-line.is-open .proc-wrap {
  grid-template-rows: 1fr;
  opacity: 1;
}
.proc-wrap > div {
  min-height: 0;
  overflow: hidden;
}
.proc-steps {
  display: flex;
  min-width: 0;
  flex-direction: column;
  padding: 0 0 2px;
  gap: 0;
}
.assistant-blocks .proc-steps > * {
  margin: 0;
  animation: proc-fadein 0.45s var(--proc-ease) both;
}
.proc-line.is-static .proc-steps > * {
  animation: none;
}
/* 思考中:节点保持原子图标,只让它轻轻呼吸;芯片形态那三个跳动点不进时间线 */
.assistant-blocks .proc-steps > .reasoning-block.is-live > summary > .reasoning-icon {
  display: grid;
  width: var(--proc-col);
  gap: 0;
}
.assistant-blocks .proc-steps > .reasoning-block.is-live > summary > .reasoning-icon svg {
  display: block;
  animation: proc-breathe 1.6s ease-in-out infinite;
}
.assistant-blocks .proc-steps > .reasoning-block.is-live > summary > .reasoning-icon i {
  display: none;
}
@keyframes proc-breathe {
  50% {
    opacity: 0.35;
  }
}

/* 「准备 xx」占位签:时间线上的一行,转圈图标就是节点,文字和工具行同款 */
.assistant-blocks .proc-steps > .tool-preparing-tag {
  /* 和其它节点一样走 proc-fadein 平滑滑入;顶替它的正式卡不再重放动画(#17) */
  display: flex;
  width: 100%;
  max-width: 100%;
  min-height: 30px;
  align-items: center;
  margin: 0;
  padding: 4px 0;
  border-radius: 0;
  background: none;
  color: var(--proc-soft);
  gap: var(--proc-gap);
  overflow: visible;
  white-space: normal;
}
.assistant-blocks .proc-steps > .tool-preparing-tag > .icon-slot {
  display: grid;
  box-sizing: border-box;
  width: var(--proc-col);
  height: var(--proc-col);
  flex: 0 0 var(--proc-col);
  place-items: center;
  background: var(--app-bg);
  box-shadow: 0 -2px 0 var(--app-bg), 0 2px 0 var(--app-bg);
  color: var(--proc-soft);
}
.assistant-blocks .proc-steps > .tool-preparing-tag > .icon-slot svg {
  width: 13px;
  height: 13px;
}
.assistant-blocks .proc-steps > .tool-preparing-tag > .tool-preparing-label {
  min-width: 0;
  padding: 1px 4px;
  overflow: hidden;
  color: var(--proc-soft);
  font-size: 11.5px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* 工具行:节点 + 名字 + 等宽主语,右侧耗时。不再是各自宽度的彩色芯片 */
.assistant-blocks .proc-steps > .tool-card {
  width: 100%;
  max-width: 100%;
  border: 0;
  border-radius: 0;
  background: none;
}
.assistant-blocks .proc-steps > .tool-card > .tool-head {
  display: flex;
  width: 100%;
  max-width: 100%;
  min-height: 30px;
  align-items: center;
  padding: 4px 0;
  border-radius: 0;
  background: none;
  color: var(--proc-soft);
  gap: var(--proc-gap);
  /* 整行可点展开(#11):不再只让 节点/文字/耗时 接指针 */
  cursor: pointer;
}
.assistant-blocks .proc-steps > .tool-card > .tool-head > .tool-title {
  min-width: 0;
  max-width: 100%;
  flex: 0 1 auto;
  align-items: baseline;
  padding: 1px 4px;
  border-radius: 5px;
  gap: 5px;
  transition: background-color 0.18s ease;
}
/* 悬浮高亮覆盖整行(#3),不再只高亮标题那一小块 tag;圆角贴合行,图标遮线块
   在 hover 时也跟成 surface-2,免得中间露出一块 app-bg 小方块。 */
.assistant-blocks .proc-steps > .tool-card > .tool-head {
  border-radius: 6px;
  transition: background-color 0.15s ease;
}
.assistant-blocks .proc-steps > .tool-card > .tool-head:hover {
  background: var(--surface-2);
}
/* 命令那几行也能点开，就得有同样的手感：悬浮时整条（抬头 + 命令行）一起亮，
   不然点得动但看不出来能点（用户 09-20）。`:has()` 让「鼠标在命令行上」也能
   把抬头点亮，反过来同理。 */
.assistant-blocks .proc-steps > .tool-card > .tool-command-preview,
.assistant-blocks .proc-steps > .tool-card > .tool-command-more {
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.assistant-blocks .proc-steps > .tool-card > .tool-command-preview:hover,
.assistant-blocks .proc-steps > .tool-card > .tool-command-more:hover,
.assistant-blocks
  .proc-steps
  > .tool-card:has(> .tool-command-preview:hover, > .tool-command-more:hover)
  > .tool-head,
.assistant-blocks .proc-steps > .tool-card:has(> .tool-head:hover) > .tool-command-preview,
.assistant-blocks .proc-steps > .tool-card:has(> .tool-head:hover) > .tool-command-more {
  background: var(--surface-2);
}
/* 抬头的图标是拿底色遮住时间线那根竖线的，整条一起亮时它也得跟上，
   否则中间露出一块 app-bg 的小方块。 */
.assistant-blocks
  .proc-steps
  > .tool-card:has(> .tool-command-preview:hover, > .tool-command-more:hover)
  > .tool-head
  > .tool-icon {
  background: var(--surface-2);
  box-shadow: 0 -2px 0 var(--surface-2), 0 2px 0 var(--surface-2);
}
.assistant-blocks .proc-steps > .tool-card > .tool-head:hover > .tool-icon {
  background: var(--surface-2);
  box-shadow: 0 -2px 0 var(--surface-2), 0 2px 0 var(--surface-2);
}
.assistant-blocks .proc-steps > .tool-card .tool-title strong {
  color: var(--text);
  transition: color 0.35s ease;
  /* 时间线全宽,工具名不必留 4em 下限(那让「Bash」这种短名后面空一截,#15)。 */
  min-width: 0;
}
.assistant-blocks .proc-steps > .tool-card .tool-title .tool-summary {
  color: var(--proc-soft);
  transition: color 0.35s ease;
}
.assistant-blocks .proc-steps > .tool-card > .tool-head > .tool-status {
  margin-left: 4px;
  color: var(--proc-soft);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  transition: color 0.35s ease;
}
/* 成功不打勾:右侧就是耗时 */
.assistant-blocks .proc-steps > .tool-card.is-success > .tool-head > .tool-status .icon-slot,
.assistant-blocks .proc-steps > .tool-card > .tool-head > .tool-chevron {
  display: none;
}
/* 颜色只给失败一处:那一行的节点、名字、主语、状态全红,线不变色 */
.assistant-blocks .proc-steps > .tool-card.is-failure > .tool-head > .tool-icon,
.assistant-blocks .proc-steps > .tool-card.is-failure .tool-title strong,
.assistant-blocks .proc-steps > .tool-card.is-failure .tool-title .tool-summary,
.assistant-blocks .proc-steps > .tool-card.is-failure > .tool-head > .tool-status {
  color: var(--danger);
}
/* 命令签:命令本身排在抬头底下(见 `.tool-command-preview`);命令**输出**仍然
   只在点开里,收起态不露 */
.assistant-blocks .proc-steps > .tool-card > .tool-command-output-preview {
  display: none;
}
.assistant-blocks .proc-steps > .tool-card > .tool-live-progress {
  margin: 0 0 6px var(--proc-indent);
}
/* 展开区平滑高度动画(#7/#9):tool-body 外套一层 grid 容器 .tool-fold,靠
   grid-template-rows 0fr↔1fr 过渡——所有现代浏览器双向都平滑(和「Worked for」的
   proc-wrap 同一招),不像 height:auto 那样不被支持时收起就瞬间。垂直外边距也一起
   过渡到 0,收起后不留空档。 */
.assistant-blocks .proc-steps > .tool-card > .tool-fold {
  display: grid;
  grid-template-rows: 1fr;
  margin: 2px 0 8px 0;
  transition: grid-template-rows 0.32s var(--proc-ease), margin 0.32s var(--proc-ease);
}
.assistant-blocks .proc-steps > .tool-card.collapsed > .tool-fold {
  grid-template-rows: 0fr;
  margin-top: 0;
  margin-bottom: 0;
}
.assistant-blocks .proc-steps > .tool-card > .tool-fold > .tool-body {
  min-height: 0;
  overflow: hidden;
}
/* 详情:一个面板,细边,参数在前、空一行、结果在后;不再有「参数 / 结果」小标。
   底色改暖柔(#82/#9b:原来 surface-1 亮色下是刺眼白)。 */
.assistant-blocks .proc-steps > .tool-card > .tool-fold > .tool-body {
  width: auto;
  margin: 0 0 0 var(--proc-indent);
  padding: 9px 10px;
  border: 0;
  background: color-mix(in srgb, var(--text) 5%, transparent);
  gap: 1em;
}
/* 旧的 collapsed display:none 只在没套 fold 的兜底路径生效;套了 fold 就靠 grid 收。 */
/* 展开之后「参数」和「结果」连成一坨，看不出哪儿是命令、哪儿是输出（用户
   09-20）。09-10 那版把标签整个藏了，这儿请回来，并给除第一块之外的每块加一道
   细分界线（哪一块是第一块由 JS 打 `.is-first-detail`——CSS 选不出「前一个可见
   兄弟」，中间那几块是 hidden 的）。 */
.assistant-blocks .proc-steps > .tool-card .tool-detail-label {
  display: block;
  margin-bottom: 3px;
  color: var(--text-faint);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.12em;
}
.assistant-blocks .proc-steps > .tool-card .tool-detail:not([hidden]):not(.is-first-detail) {
  margin-top: 9px;
  padding-top: 9px;
  border-top: 1px solid color-mix(in srgb, var(--text) 12%, transparent);
}
.assistant-blocks .proc-steps > .tool-card .tool-detail pre {
  padding: 0;
  overflow-x: hidden;
  background: none;
  color: var(--text);
  font-size: 11.5px;
  line-height: 1.65;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* 思考行:节点是原子,标题「已思考」,内容是一段淡色文字(没有底色) */
.assistant-blocks .proc-steps > .reasoning-block {
  border: 0;
}
.assistant-blocks .proc-steps > .reasoning-block > summary {
  width: 100%;
  max-width: 100%;
  min-height: 30px;
  padding: 4px 0;
  border-radius: 6px;
  background: none;
  color: var(--text);
  gap: var(--proc-gap);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
/* 整行 hover 高亮(#5:思考行原来悬浮无反馈);流光字标题在上层、自己带
   background-clip:text,行底色在它后面不影响。图标遮线块也跟色免得露出小方块。 */
.assistant-blocks .proc-steps > .reasoning-block > summary:hover {
  background: var(--surface-2);
}
.assistant-blocks .proc-steps > .reasoning-block > summary:hover > .reasoning-icon {
  background: var(--surface-2);
  box-shadow: 0 -2px 0 var(--surface-2), 0 2px 0 var(--surface-2);
}
.assistant-blocks .proc-steps > .reasoning-block > summary .reasoning-title {
  padding: 1px 4px;
  border-radius: 5px;
  transition: background-color 0.18s ease;
}
/* 正在思考的标题是 background-clip:text 的流光字,底色一换字就没了(09-11 todolist 截图):
   hover 底色只给想完的那种。 */
.assistant-blocks .proc-steps > .reasoning-block:not(.is-live) > summary .reasoning-title:hover {
  background: var(--surface-2);
}
.assistant-blocks .proc-steps > .reasoning-block > summary .reasoning-live-status,
.assistant-blocks .proc-steps > .reasoning-block > summary .reasoning-chevron {
  color: var(--proc-soft);
}
/* 窥视槽:思考收着时,思考的尾巴放在标题行剩下的空间里。正在想就跟着滚,想完了也留着;
   尾部对齐——文字比槽宽时从左边溢出被裁掉,再加一层左侧渐隐,看起来就是新字从右边推进来。
   展开时才藏(内容就在下面)。 */
.reasoning-peek {
  display: none;
  min-width: 0;
  /* 只占文字那么宽,展开箭头紧跟其后;放不下时才被压到剩余宽度 */
  flex: 0 1 auto;
  justify-content: flex-start;
  margin-left: 6px;
  overflow: hidden;
  color: var(--proc-think);
  font-size: var(--fs-meta);
  font-weight: 400;
  line-height: 1.5;
}
.reasoning-peek > span {
  flex: none;
  white-space: nowrap;
}
/* 子代理标题行的单行窥视:复用 reasoning-peek 的尾部对齐/左渐隐。收起态
   在标题行里显示当前子过程(和「已思考」尾巴同款);展开后让位给子过程时间线。 */
.tool-card.is-task.collapsed .tool-head .tool-peek {
  display: flex;
}
.tool-card.is-task:not(.collapsed) .tool-head .tool-peek {
  display: none;
}
/* 展开后的子过程时间线容器:proc-line(和主对话过程区同款)挂在里面;限高可滚,
   不许顶满全屏(09-11 用户报)。 */
.tool-card.is-task .sub-blocks {
  /* 前台子代理:一块约四行高的活区域,子过程在里面流式滚动/窥视(用户拍板)。 */
  margin-bottom: 2px;
  max-height: 124px;
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  scroll-behavior: smooth;
  /* 预留滚动条槽:思考流增长时滚动条忽隐忽现会让整块宽度一跳一跳,连带窥视抖(#3)。 */
  scrollbar-gutter: stable;
}
/* 前台子代理的活区域外框(tool-body)收紧内边距:刚开只有 1 行 brief 时,原来
   9px 上下 padding + 8px 外边距让这块看着有两行多(#113)。子过程区不是详情面板,
   不需要那么厚的留白。特异度对齐上面那条详情面板规则(0,5,0)才压得过。 */
.assistant-blocks .proc-steps > .tool-card.is-task > .tool-fold > .tool-body {
  padding: 5px 8px;
}
/* 子代理任务简介(展开区最上方,09-12 #6):标题 + 整段 prompt,不再让人读裸 JSON。 */
/* 任务简介:一个可展开 tag,收起只显任务标题,展开才看整段 prompt(prompt 太长会刷屏)。 */
/* 任务简介=时间线的开头(和其它步同构):summary 一行,无背景,marker 是坐在细线上的
   节点(平时 📋、悬浮换展开箭头),点开在下面缩进显整段 prompt。 */
.subagent-brief {
  margin: 0;
}
.subagent-brief > summary {
  display: flex;
  align-items: center;
  gap: var(--proc-gap, 4px);
  list-style: none;
  cursor: pointer;
  min-height: 26px;
  padding: 3px 0;
  font-weight: 600;
  font-size: 11.5px;
  color: var(--proc-soft);
  border-radius: 6px;
  transition: background-color 0.15s ease;
}
.subagent-brief > summary::-webkit-details-marker { display: none; }
.subagent-brief > summary:hover {
  background: var(--surface-2);
}
/* 节点:和时间线其它图标同一列、坐在细线上,遮线块用面板暖底(#4)。平时 📋,
   悬浮原地换成展开箭头(不在右侧另起,用户要求)。 */
.subagent-brief-marker {
  position: relative;
  flex: 0 0 var(--proc-col, 16px);
  width: var(--proc-col, 16px);
  height: var(--proc-col, 16px);
  display: grid;
  place-items: center;
  background: color-mix(in srgb, var(--text) 5%, var(--app-bg));
  box-shadow:
    0 -2px 0 color-mix(in srgb, var(--text) 5%, var(--app-bg)),
    0 2px 0 color-mix(in srgb, var(--text) 5%, var(--app-bg));
  color: var(--proc-soft);
}
.subagent-brief > summary:hover > .subagent-brief-marker {
  background: var(--surface-2);
  box-shadow: 0 -2px 0 var(--surface-2), 0 2px 0 var(--surface-2);
}
.subagent-brief-marker .subagent-brief-icon,
.subagent-brief-marker .subagent-brief-chevron {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 13px;
  height: 13px;
}
.subagent-brief-chevron {
  opacity: 0;
  transition: transform 0.25s ease, opacity 0.12s ease;
}
.subagent-brief > summary:hover .subagent-brief-icon {
  opacity: 0;
}
.subagent-brief > summary:hover .subagent-brief-chevron {
  opacity: 1;
}
.subagent-brief[open] > summary .subagent-brief-icon {
  opacity: 0;
}
.subagent-brief[open] > summary .subagent-brief-chevron {
  opacity: 1;
  transform: rotate(90deg);
}
.subagent-brief-name {
  flex: 1 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text);
}
.subagent-brief-prompt {
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 11.5px;
  line-height: 1.55;
  color: var(--proc-think, var(--text-soft));
  margin: 2px 8px 6px var(--proc-indent);
  padding: 0;
}
/* 子代理正文(#6):模型在工具轮之间/收尾说的话,流式累加并按 markdown 渲染。
   是正文不是思考,所以用常规正文色、和时间线内容左缘对齐。 */
.sub-content {
  font-size: 12px;
  line-height: 1.6;
  color: var(--text);
  margin: 2px 8px 8px var(--proc-indent);
  padding: 0;
}
.sub-content > :first-child { margin-top: 0; }
.sub-content > :last-child { margin-bottom: 0; }
/* 子代理正文里的代码块/表格底色:默认 --code-bg 在亮色主题是近白(255,253,246),
   落在暖米面板上像块白斑(#9「还是白色的底」)。统一改成和工具详情面板同款的柔和暖底。 */
.sub-content .code-block {
  --code-bg: color-mix(in srgb, var(--text) 6%, transparent);
  background: color-mix(in srgb, var(--text) 6%, transparent);
  box-shadow: none;
}
.sub-content .code-block pre,
.sub-content .markdown-table-scroll,
.sub-content table {
  background: color-mix(in srgb, var(--text) 6%, transparent);
}
/* 子过程时间线不再吸顶(#112/#117:吸顶行反复透出下面的文字、盖字,做了三版都不稳;
   这块本就只有约 5 行、滚不远,吸顶收益小于它带来的重叠问题)。行随内容正常滚动。
   留一层柔和暖底(和面板同视觉),纯为节点遮线用,不再靠它盖住透上来的字。 */
.sub-blocks .reasoning-block > summary,
.sub-blocks .tool-card > .tool-head {
  background: color-mix(in srgb, var(--text) 5%, var(--app-bg));
}
/* 不吸顶后横向仍用 clip 裁掉长思考文本(nowrap),纵向交给外层 .sub-blocks/.job-stream-panel
   的滚动容器(不再需要 overflow-y:visible 去让 sticky 吸到滚动容器)。 */
.sub-blocks .proc-wrap,
.sub-blocks .proc-wrap > div {
  overflow-x: clip;
  overflow-y: clip;
}
/* 前台子代理行在手机端太长(09-12 #8):收起时不显那条单行窥视,活动去展开区看;
   token/读秒也让位,标题+状态就够窄。 */
@media (max-width: 836px) {
  .tool-card.is-task .tool-head > .tool-peek,
  .tool-card.is-task .tool-head > .tool-task-token {
    display: none;
  }
}
/* 前台子代理行的 token 消耗 + 读秒(09-12 #6):等宽小字,贴在状态前面。 */
.tool-card.is-task .tool-head > .tool-task-token,
.tool-card.is-task .tool-head > .tool-task-seconds {
  flex: none;
  margin-left: 6px;
  color: var(--proc-soft, var(--text-soft));
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-variant-numeric: tabular-nums;
  pointer-events: auto;
}
.tool-card.is-task .tool-head > .tool-task-token:empty {
  display: none;
}
/* 前台子代理行布局(#2):子代理·title 贴左 hug、token/秒数紧跟,窥视占满余下、
   右对齐滚动、左侧淡出过渡;标题在左永远完整(#7),窥视不再压标题。 */
.tool-card.is-task .tool-head > .tool-title {
  /* 标题固定在左、封顶 60% 不缩,永远完整可见,超了才省略(#3/#7 不被窥视盖)。 */
  flex: 0 1 auto;
  max-width: 60%;
  min-width: 0;
}
.tool-card.is-task .tool-head > .tool-peek {
  flex: 1 1 0;
  min-width: 0;
  margin-left: 8px;
  /* 左对齐紧跟秒数;淡出只在放不下时加(#132)。 */
  justify-content: flex-start;
}
/* 真的放不下才加左右淡出(0,4,0 压过 .reasoning-peek.is-overflow 的 0,2,0)。 */
.tool-card.is-task .tool-head > .tool-peek.is-overflow {
  -webkit-mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 24px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 14px, #000 calc(100% - 24px), transparent);
}
/* 放不下了:尾部对齐(文字从左边溢出被裁),再加一层左侧渐隐,新字从右边推进来 */
.reasoning-peek.is-overflow {
  justify-content: flex-end;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 32px);
  mask-image: linear-gradient(to right, transparent, #000 32px);
}
.assistant-blocks .proc-steps > .reasoning-block:not([open]) > summary .reasoning-peek {
  display: flex;
}
/* 正在想 + 思考收着:标题底下那扇滚动窗(display.thinking_scroll_lines 行),露正文
   末尾几行(多出来的从顶上滚走);这时标题行里的窥视让位。想完(is-live 撤掉)或点开就藏。
   它在 <summary> 里(summary 换行铺满):合着的 <details> 不画 summary 之外的东西。 */
.reasoning-window {
  display: none;
  position: relative;
  flex: 1 0 100%;
  box-sizing: border-box;
  max-height: calc(var(--think-window-lines, 10) * 1.75em);
  /* 正文和展开后的思考正文一样退到时间线右边;左侧那根线画在**时间线那一列**
     (和 .proc-rail 同列同色),像终端里 `│` 穿过去那几行(用户 09-17:「线在
     timeline 的位置会更好看」)。 */
  margin: 2px 8px 2px 0;
  padding-left: var(--proc-indent, 0px);
  overflow: hidden;
  cursor: default;
  color: var(--proc-think);
  font-size: var(--fs-meta);
  line-height: 1.75;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  /* 这根线**必须画成背景**，不能用绝对定位的伪元素：这扇窗自己滚
     （`setReasoningWindow` 里 `scrollTop = scrollHeight`），而绝对定位的子元素
     会跟着内容一起滚走——线于是被滚上去、窗口顶上空一截（用户 09-20）。
     背景默认 `background-attachment: scroll`，是钉在元素盒子上的，不随内容动。 */
  background-image: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--line-strong) 75%, var(--line)),
    color-mix(in srgb, var(--line-strong) 75%, var(--line))
  );
  background-repeat: no-repeat;
  background-size: 1px 100%;
  background-position: calc(var(--proc-col, 16px) / 2 - 0.5px) 0;
}
.reasoning-block.is-live.has-window:not([open]) > summary {
  flex-wrap: wrap;
}
.reasoning-block.is-live.has-window:not([open]) > summary > .reasoning-window {
  display: block;
}
.assistant-blocks .proc-steps > .reasoning-block.is-live.has-window:not([open]) > summary .reasoning-peek,
.reasoning-block.is-live.has-window:not([open]) > summary .reasoning-peek {
  display: none;
}
.assistant-blocks .proc-steps > .reasoning-block > .reasoning-text {
  margin: 0 8px 6px var(--proc-indent);
  padding: 0;
  background: none;
  color: var(--proc-think);
}

/* ═══ 气泡:AI 不套气泡,正文直接铺在页面底色上;用户消息改用原先助手气泡的中性色 ═══ */
.assistant-content {
  padding: 2px 0 0;
  border-radius: 0;
  background: none;
  box-shadow: none;
}
.user-bubble {
  background: var(--surface-1);
  color: var(--text);
  box-shadow: var(--bubble-shadow);
}
/* 正文里的面原来都是对着气泡的 surface-1 调的,现在直接落在页面底色上:
   代码块用 surface-1 加软阴影(和用户气泡同一张卡),行内代码和表格底用
   正文色兑底色得到的中性灰,亮色下不再和米色底混成一片。 */
.assistant-content .code-block {
  --code-bg: var(--surface-1);
  box-shadow: var(--bubble-shadow);
}
.assistant-content .markdown-body code:not(pre code) {
  border-radius: 8px;
  background: color-mix(in srgb, var(--text) 9%, var(--app-bg));
}
.assistant-content .markdown-table-scroll {
  border-radius: var(--radius);
  background: var(--surface-1);
  box-shadow: var(--bubble-shadow);
}
.assistant-content .markdown-body table {
  background: none;
}
.assistant-content .markdown-body th {
  border-bottom: 1px solid var(--line);
  background: color-mix(in srgb, var(--text) 5%, var(--surface-1));
}
.assistant-content .markdown-body td {
  border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent);
}
.assistant-content .markdown-body tr:last-child td {
  border-bottom: 0;
}
/* 用户气泡现在是中性底,里面的代码块不再是那块深蓝:底色深一档、配色跟正文同一套 */
.user-bubble .code-block {
  --code-bg: color-mix(in srgb, var(--text) 7%, var(--surface-1));
  --code-ink: var(--text);
  --tok-c: inherit;
  --tok-p: inherit;
  --tok-o: inherit;
  --tok-k: inherit;
  --tok-s: inherit;
  --tok-n: inherit;
  --tok-f: inherit;
  --tok-t: inherit;
  --tok-y: inherit;
}
.user-bubble > p > code {
  border-radius: 8px;
  background: color-mix(in srgb, var(--text) 9%, var(--surface-1));
}

/* ═══ 排队消息:画在对话末尾的用户气泡,左边一枚「排队中」小签和撤下按钮 ═══ */
/* 网格两列会把气泡挤成最窄的一柱;改 flex,气泡照旧按 62% 上限自然铺开,小签贴在左边 */
.user-message.is-queued {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
}
.user-message.is-queued .user-attachments {
  flex: 0 0 100%;
}
.user-message.is-queued .user-bubble {
  opacity: 0.82;
}
.queue-badge {
  display: inline-flex;
  align-items: center;
  color: var(--text-soft);
  font-size: var(--fs-micro);
  white-space: nowrap;
  gap: 2px;
}
.queue-badge .queue-remove {
  width: 20px;
  height: 20px;
  flex-basis: 20px;
}

/* ---------- 09-14 划词菜单打磨(用户逐条) ---------- */

/* 菜单字号跟 AI 正文同一档:原来落在 UI 档,和它旁边被选中的正文两个字号。 */
.sel-menu { font-size: var(--fs-chat); }

/* 复制 / 重试 / 钉住 / 关闭 收成右上角一排图标(原来复制与重试在页脚)。 */
.sel-pop-actions {
  display: inline-flex;
  gap: 2px;
  align-items: center;
  margin-left: auto;
}
.sel-pop-actions .icon-slot {
  width: 15px;
  height: 15px;
}

/* 等模型那几秒的转圈:和会话列表、REPL 等待动画同一组盲文帧。 */
.sel-braille {
  font-family: var(--font-mono);
  color: var(--text-muted);
}

/* 头部那条分割线去掉(用户 09-14):浮窗本来就小,一条横线把它切成两截。 */
.sel-pop-head { border-bottom: 0; }

/* 收起之后底下要留一口气,不然总结行贴着浮窗底边。 */
.sel-pop-body { padding-top: 4px; padding-bottom: 14px; }

/* 时间线的节点靠 --app-bg 的底色+上下投影把那根细线遮断,而浮窗底色是
   --surface-1,于是图标底下露出一块深色方块。浮窗里一律换成浮窗自己的底色。 */
.sel-pop .proc-node,
.sel-pop .proc-steps > .reasoning-block > summary > .reasoning-icon,
.sel-pop .proc-steps > .tool-card > .tool-head > .tool-icon {
  background: var(--surface-1);
  box-shadow: 0 -2px 0 var(--surface-1), 0 2px 0 var(--surface-1);
}
/* 那一格底色本来是用来遮断时间线细线的。浮窗里这条线只有一个节点、没有要遮的
   线段,而「卡片底色」跟浮窗底色又不是同一个值——与其猜该填哪个,不如透明,
   永远和身后一致。正在思考与已思考两态一样办。 */
.sel-pop .proc-steps > .reasoning-block > summary > .reasoning-icon,
.sel-pop .proc-steps > .reasoning-block.is-live > summary > .reasoning-icon {
  background: transparent;
  box-shadow: none;
}

/* 容器带 assistant-blocks 是为了吃到时间线那套样式;主对话里的外边距在浮窗
   里太空,这里收掉。 */
.sel-blocks { margin: 0; }

/* 流式思考只给四行刷新空间,滚到底跟着新字走;想完自动收起,点标题行能展开。 */
.sel-pop .reasoning-block.sel-think.is-streaming .reasoning-text {
  max-height: calc(4 * 1.55em);
  overflow: hidden;
}

/* 窄窗下「上下文」被折成「上下 / 文」两行(8388 实拍)。标签不折行。 */
.composer-info .ctx-nums .k { white-space: nowrap; }
