:root {
  color-scheme: dark;
  /* Codex 式中性底色：层级主要依靠明暗和分隔线，青色只用于焦点、链接和当前指示。 */
  --bg: #0b0d10;
  --panel: #111418;
  --panel-2: #171a1f;
  --surface: var(--panel);
  --border: #2b3038;
  --text: #f2f4f7;
  --text-2: #a7adb7;
  /* --text-3 按「最暗的承载面」定标，而不是按 --panel。
     旧值 #737a85 对 --panel 是 4.27:1（勉强），但 muted 文字大量出现在卡片上，
     卡片底是更亮的 --elev-3 #1a2029 —— 那里只有 3.78:1，低于 AA 4.5。
     提到 #868d99 后：卡片上 4.90:1、panel 上 5.53:1，两个承载面同时达标，
     且与 --text-2 #a7adb7 仍有 1.57 倍亮度差，三级文字层级不塌。*/
  --text-3: #868d99;
  --primary: #67e8f9;
  --primary-2: #22d3ee;
  --accent: var(--primary);
  /* accent 之上的前景色（配对 token）。必须存在，因为 accent 在深色档是**亮色**
     (#67e8f9)、在浅色档是**暗色**(#005f87)——任何写死 color:#fff 的"accent 实底 + 白字"
     在深色档都会崩：白字压在亮青上只有 1.45:1，对勾图标基本看不见。
     深色档用近黑（13.1:1），浅色档用白（7.03:1），暖色档用暖白（7.87:1，见 sepia 块）。 */
  --accent-fg: #0b1114;
  --success: #4ade80;
  --warn: #fbbf24;
  --error: #fb7185;
  /* --danger 是 --error 的同义别名，必须定义在这里而不是靠调用处写 fallback。
     历史欠账：全站有 20+ 处var(--danger) 却从未有人定义过这个变量。
     带 fallback 的（var(--error)）表面正常，实际是绕开主题系统的硬编码红，
     三种主题共用同一个 #dc2626；**不带** fallback 的三处则是彻底失效——
     CSS 里 var() 解析不到会让整条声明 invalid at computed-value time，
     其后果不是"忽略这条"而是回退到 unset：color 变成继承色、background 变 transparent、
     border-color 变 currentColor。于是：
       · .ws-op-badge.is-delete（2539）——「删除」这个最高危操作的红色徽章完全无色，
         而写=琥珀/建=绿/读=青全都正常，唯独最需要警示的那个不显示；
       · .is-copy-fail（2499）——「复制失败」的红色反馈不存在，且因为带 !important，
         它赢下级联后再自废，把按钮原本的正常色一起顶掉；
       · .composer-attachment.failed（4228）——附件上传失败的红框红字不显示。
     指向 --error 而非沿用 #dc2626还顺带修了对比度：深色卡片底（--elev-3）上
     #dc2626 仅 3.39:1（不达 AA），--error #fb7185 为 6.08:1。各主题自动跟随。 */
  --danger: var(--error);
  --danger-a-45: var(--error-a-45);
  /*微信与「操作成功」脱钩：两者都是绿，但一个是**渠道身份**（这条会话来自微信）、
     一个是**操作结果**（刚才那步成功了）。同色同通道时，toast 左侧色条、状态点、
     徽章全都无法区分二者——用户看到绿色只能靠读文字判断是哪种含义，颜色白占位置。
     取微信品牌绿而非再造一个绿：渠道标识用品牌色是最省认知的一步（识别优于回忆）。
     深色档用品牌原色 #07C160（卡片上 6.87:1）；浅色/暖色档见各自主题块，
     品牌原色在亮底上只有 2.38:1，必须压暗才能承担文字色。 */
  --wechat: #07C160;
  --mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --input-bg: #0e1115;
  --btn-hover: #1b1f25;
  --term-bg: #080a0d;
  --surface-raised: color-mix(in srgb, var(--panel) 96%, transparent);
  --surface-tint: color-mix(in srgb, var(--text) 2.5%, transparent);
  --surface-tint-2: color-mix(in srgb, var(--text) 4.5%, transparent);
  --text-dim: var(--text-3);
  --primary-a-06: color-mix(in srgb, var(--primary) 6%, transparent);
  --primary-a-08: color-mix(in srgb, var(--primary) 8%, transparent);
  --primary-a-12: color-mix(in srgb, var(--primary) 12%, transparent);
  --primary-a-16: color-mix(in srgb, var(--primary) 16%, transparent);
  --primary-a-22: color-mix(in srgb, var(--primary) 22%, transparent);
  --primary-a-24: color-mix(in srgb, var(--primary) 24%, transparent);
  --primary-a-35: color-mix(in srgb, var(--primary) 35%, transparent);
  --primary-a-38: color-mix(in srgb, var(--primary) 38%, transparent);
  --primary-a-45: color-mix(in srgb, var(--primary) 45%, transparent);
  --primary-a-55: color-mix(in srgb, var(--primary) 55%, transparent);
  /*名字必须与实际比例一致：旧写法 --accent-a-18: var(--primary-a-16) 让"18"这个名字
     指向 16% 的值，任何按名字推断浓度的后续改动都会被误导（也无从发现自己被误导）。 */
  --accent-a-18: color-mix(in srgb, var(--primary) 18%, transparent);
  --accent-a-45: var(--primary-a-45);
  --success-a-06: color-mix(in srgb, var(--success) 6%, transparent);
  --success-a-08: color-mix(in srgb, var(--success) 8%, transparent);
  --success-a-12: color-mix(in srgb, var(--success) 12%, transparent);
  --success-a-22: color-mix(in srgb, var(--success) 22%, transparent);
  --success-a-35: color-mix(in srgb, var(--success) 35%, transparent);
  --success-a-42: color-mix(in srgb, var(--success) 42%, transparent);
  --success-a-45: color-mix(in srgb, var(--success) 45%, transparent);
  --error-a-06: color-mix(in srgb, var(--error) 6%, transparent);
  --error-a-08: color-mix(in srgb, var(--error) 8%, transparent);
  --error-a-12: color-mix(in srgb, var(--error) 12%, transparent);
  --error-a-16: color-mix(in srgb, var(--error) 16%, transparent);
  --error-a-22: color-mix(in srgb, var(--error) 22%, transparent);
  --error-a-28: color-mix(in srgb, var(--error) 28%, transparent);
  --error-a-35: color-mix(in srgb, var(--error) 35%, transparent);
  --error-a-45: color-mix(in srgb, var(--error) 45%, transparent);
  --warn-a-06: color-mix(in srgb, var(--warn) 6%, transparent);
  --warn-a-22: color-mix(in srgb, var(--warn) 22%, transparent);
  --warn-a-35: color-mix(in srgb, var(--warn) 35%, transparent);
  /* 微信的半透明派生量随 --wechat 走，不再借--success：借用会让脱钩只做了一半——
     字色分开了、底色和描边还是成功绿，同屏依然分不出渠道态和结果态。 */
  --wechat-a-06: color-mix(in srgb, var(--wechat) 6%, transparent);
  --wechat-a-08: color-mix(in srgb, var(--wechat) 8%, transparent);
  --wechat-a-12: color-mix(in srgb, var(--wechat) 12%, transparent);
  --wechat-a-15: color-mix(in srgb, var(--wechat) 15%, transparent);
  --wechat-a-18: color-mix(in srgb, var(--wechat) 18%, transparent);
  --wechat-a-35: color-mix(in srgb, var(--wechat) 35%, transparent);
  --wechat-a-38: color-mix(in srgb, var(--wechat) 38%, transparent);
  --wechat-a-45: color-mix(in srgb, var(--wechat) 45%, transparent);
  --overlay: color-mix(in srgb, var(--bg) 66%, transparent);
  --brand-gradient: var(--primary);
  /* 品牌墨色圆形固定配色：与 --ink/--ink-fg 分开定义，不随明暗主题翻转，
     确保 logo 圆形在任何主题下都是深色圆+白字，不会在深色页面下变成刺眼的浅色反色块。 */
  --brand-mark-bg: #3b3b37;
  --brand-mark-fg: #f7f7f4;
  /* ── 分类色（categorical，4 类）──
     与语义色（success/warn/error）职责不同：语义色表达"好/该注意/坏"，分类色只表达
     "属于第几类"，本身无褒贬。能力口径①②③④、工具来源等枚举必须用它，
     否则就会像以前那样，为了凑出四种颜色而直接抓 Tailwind 500 原色写进 JS 行内样式
     （#6366f1/#0ea5e9/#f59e0b/#10b981）——那批色既不跟随主题，又与语义色撞车
     （用户会把 amber 读成"警告"、把 emerald 读成"成功"，而它们其实只是"第③类""第④类"）。
     深色档取 300 档（深底上 8:1+），浅色档取 700 档（白底上 5:1+），暖色档暖化。 */
  --cat-1: #a5b4fc;
  --cat-2: #7dd3fc;
  --cat-3: #fcd34d;
  --cat-4: #6ee7b7;
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px;
  --r-sm: 8px; --r-md: 10px; --r-lg: 14px; --r-xl: 18px;
  --ease-standard: cubic-bezier(.4,0,.2,1);
  --ease-spring: cubic-bezier(.32,.72,0,1);
  --dur-fast: .12s; --dur-base: .18s;
  /* ──焦点环：全站唯一定义处 ──
     曾经被定义三次（这里、Apple 精致层5093、去蓝收敛层 6665），最后一处把它改成了
     中性灰 color-mix(text 16%)。焦点环是**无障碍设施**，不是装饰：键盘用户完全依赖它
     定位"我现在在哪个控件上"。16% 中性灰在深色卡片（--elev-3）上几乎不可见，
     等于把键盘可达性让给了"去蓝"的观感偏好——这个取舍不成立。
     恢复用 accent，也正是文件头声明的「青色只用于焦点、链接和当前指示」中的第一项：
     去蓝收敛的对象是**主操作按钮**的高饱和实底，从来不该包括焦点环。 */
  --focus-ring: 0 0 0 3px var(--primary-a-22);
  --shadow-1: 0 1px 2px rgba(0,0,0,.12);
  --shadow-2: 0 8px 28px rgba(0,0,0,.22);
  --shadow-3: 0 20px 64px rgba(0,0,0,.34);
  /* 海拔令牌：深色主题的层级用明度台阶表达（阴影在深底上不可见），
     抬升面再补一道极细顶部受光边；阴影只给真正悬浮的 popover/modal。 */
  --elev-0: #0b0d10;   /* 应用底 */
  --elev-1: #10141a;   /* 内容管理区（中栏，退后半档） */
  --elev-2: #151a21;   /* 会话主轨（右栏，抬半档） */
  --elev-3: #1a2029;   /* 卡片 */
  --elev-4: #202731;   /* hover / 浮起 */
  --elev-edge: inset 0 1px 0 rgba(255,255,255,.045);
  --card-border: color-mix(in srgb, var(--border) 55%, transparent);
  /* 深色不用投影：零值阴影占位（none 不能与其他阴影组成列表，会导致整条声明失效）。 */
  --card-shadow: 0 0 0 0 rgba(0,0,0,0);
  --card-shadow-hover: 0 0 0 0 rgba(0,0,0,0);
  /* 左边栏比应用底再暗半档：视觉锚点，让整个窗口像 native app 一样有"框体"。 */
  --side-bg: #08090c;
}

html.light {
  color-scheme: light;
  --bg: #f7f7f7;
  --panel: #ffffff;
  --panel-2: #f1f2f3;
  --surface: var(--panel);
  --border: #d9dce1;
  --text: #1f2328;
  --text-2: #59636f;
  --text-3: #6e7781;
  /* Codex 浅色强调色：深青色，确保在白底上有足够对比度。 */
  --primary: #005f87;
  --primary-2: #004c6d;
  --accent: var(--primary);
  --accent-fg: #ffffff;
  --success: #1a7f37;
  --warn: #9a6700;
  --error: #cf222e;
  /* 微信品牌绿压暗版：原色 #07C160 在白底只有 2.38:1，做文字色不可读。
     #04803e 保住品牌绿的色相识别，同时在白底达5.05:1（AA）。 */
  --wechat: #04803e;
  --input-bg: #ffffff;
  --btn-hover: #e9eaec;
  --term-bg: #f3f4f5;
  --surface-raised: color-mix(in srgb, var(--panel) 97%, transparent);
  --surface-tint: color-mix(in srgb, var(--text) 2.5%, transparent);
  --surface-tint-2: color-mix(in srgb, var(--text) 4.5%, transparent);
  --overlay: color-mix(in srgb, var(--text) 38%, transparent);
  --shadow-1: 0 1px 2px rgba(31,35,40,.06);
  --shadow-2: 0 8px 28px rgba(31,35,40,.10);
  --shadow-3: 0 20px 60px rgba(31,35,40,.16);
  /* 浅色主题的海拔：白面 + 环境阴影（浅色底上阴影才有效）。 */
  --elev-0: #f7f7f7;
  --elev-1: #f0f1f4;   /* 内容管理区，微沉 */
  --elev-2: #ffffff;   /* 会话主轨 */
  --elev-3: #ffffff;   /* 卡片（靠阴影浮起） */
  --elev-4: #ffffff;
  /* inset 高光在浅色白卡上不可见，但 none 不能与其他阴影组成列表，用零值占位。 */
  --elev-edge: inset 0 0 0 0 rgba(0,0,0,0);
  --card-border: color-mix(in srgb, var(--border) 70%, transparent);
  --card-shadow: 0 1px 2px rgba(31,35,40,.05), 0 2px 8px rgba(31,35,40,.04);
  --card-shadow-hover: 0 2px 6px rgba(31,35,40,.07), 0 8px 20px rgba(31,35,40,.09);
  /* 浅色左边栏：冷调浅灰蓝，比内容管理区略深一档，形成稳定框体感。 */
  --side-bg: #e9edf6;
  /* 分类色浅色档：700 档，白底上 5:1+（cat-1 实测 7.90:1）。 */
  --cat-1: #4338ca;
  --cat-2: #0369a1;
  --cat-3: #b45309;
  --cat-4: #047857;
}

/* ===== 暖阅读（sepia）=====
 * 行业标准的第三档阅读模式（Kindle / Apple Books / Instapaper 均称 Sepia），
 * 本质是「低色温暖白」：模拟 2700–3000K灯光下纸张的反射色，不是"给白色加黄"。
 *
 * 为什么长时间阅读用暖黄而不是中性灰或冷色：
 *  1) 色差：人眼晶状体对短波折射更强，冷底上黑字边缘会色散发虚；黄区（555–580nm）
 *     贴近明视觉光谱光视效率峰值（555nm），文字边缘成像最锐利——这条决定清晰度；
 *  2) 削减 460–480nm 短波，降低对 ipRGC/melanopsin 的刺激，夜间阅读不抑制褪黑素；
 *  3) 抑制 halation：纯白在高亮屏上峰值过高，与黑字形成过强边缘对比产生光晕；
 *  4) 与真实纸张（反射光谱本就偏暖）一致，符合既有阅读习惯。
 * 中性灰之所以没人用：饱和度 0 与暖黄互斥，既无白的干净也无暖的舒适，是最不讨好的一档。
 *
 * 关键：整套色板色温必须统一，文字要一起移到暖轴（棕黑）。若只改背景、文字仍用冷黑
 * #1f2328，视觉结果是"白纸被昏黄灯照着"而非"暖色的纸"——大脑会解读为照明有问题，
 * 反而更累。因此下面所有颜色的色相都锁在 38–42° 这条轴上，只让明度与饱和度变化。
 *
 * 复用策略：本档同时挂 light 类（见 app.js setTheme），因此那100+ 条
 * `html.light .xxx` 覆盖规则（阴影生效方式、亮底文字色、边框可见性）全部自动继承，
 * 这里只需覆盖变量。半透明派生量走 color-mix(var(--text))，会自动跟随暖化后的文字色。
 */
html.sepia {
  color-scheme: light;
  --bg: #efe7d6;        /* 桌面底L*≈92：比浅色档沉一档，形成"中间"层级 */
  --panel: #f7f1e3;     /* 纸面 L*≈95：比底更亮 = 纸浮在桌上 */
  --panel-2: #e8dfcb;
  --surface: var(--panel);
  --border: #d9cdb4;
  --text: #33291c;      /* 暖黑，对 panel 12.64:1 → WCAG AAA */
  --text-2: #645640;    /* 对 panel 6.31:1 → AA（对齐浅色档的 6.11，不让暖档更难读） */
  --text-3: #7a6848;    /* 对 panel 4.80:1 / 对 panel-2 4.08:1 → AA（对齐浅色档 4.55/4.06） */
  /* 强调色走"互补对比"：深青绿而非浅色档的冷青 #005f87。
   * 降低纯蓝的短波成分以消除与暖底的色温冲突，同时保留黄↔蓝紫的互补关系让强调更跳出。
   * 明度经实测校准：对 panel 6.99:1（浅色档 7.03，持平），其上白字 7.87:1。
   * 不取更深的值是为了保住强调色的活力——再深就与正文抢层级了。 */
  --primary: #0f596c;
  --primary-2: #0b4553;
  --accent: var(--primary);
  /*暖白而非纯白：纯白压在暖底页面的强调实底上会显出冷斑（注释开头已说明色温统一原则）。
     对 --primary #0f596c 为 7.87:1。 */
  --accent-fg: #f7f1e3;
  /* 语义色同步暖化：保持可辨识的前提下削去冷感，否则三个语义色会像贴在暖纸上的冷色贴纸。 */
  --success: #2e6b33;   /* 偏橄榄 */
  --warn: #8a5a00;      /* 本就是暖色，仅微调 */
  --error: #b33a2b;     /* 偏砖红 */
  /* 微信绿暖化并推向黄绿轴：既与暖底同色温，又和上面的橄榄绿 --success 拉开色相距离
     （两者都在绿区，若只差明度，脱钩在这一档就等于没做）。对 panel 4.95:1 → AA。 */
  --wechat: #45741c;
  --input-bg: #fbf7ec;
  --btn-hover: #e5dbc5;
  /* 终端/代码块刻意保持接近中性：强暖底会与语法高亮色互相污染。 */
  --term-bg: #f2ede4;
  --surface-raised: color-mix(in srgb, var(--panel) 97%, transparent);
  --surface-tint: color-mix(in srgb, var(--text) 2.5%, transparent);
  --surface-tint-2: color-mix(in srgb, var(--text) 4.5%, transparent);
  --overlay: color-mix(in srgb, var(--text) 38%, transparent);
  /* 阴影用棕调而非冷灰：冷灰阴影落在暖底上会发青，是"只改背景"最容易露馅的地方。 */
  --shadow-1: 0 1px 2px rgba(74,54,38,.08);
  --shadow-2: 0 8px 28px rgba(74,54,38,.12);
  --shadow-3: 0 20px 60px rgba(74,54,38,.18);
  --elev-0: #efe7d6;
  --elev-1: #eae1cd;   /* 内容管理区，微沉 */
  --elev-2: #f7f1e3;   /* 会话主轨 */
  --elev-3: #f9f4e8;   /* 卡片（靠阴影浮起，比主轨再亮一点） */
  --elev-4: #fbf7ee;
  --elev-edge: inset 0 0 0 0 rgba(0,0,0,0);
  --card-border: color-mix(in srgb, var(--border) 70%, transparent);
  --card-shadow: 0 1px 2px rgba(74,54,38,.06), 0 2px 8px rgba(74,54,38,.05);
  --card-shadow-hover: 0 2px 6px rgba(74,54,38,.09), 0 8px 20px rgba(74,54,38,.11);
  /* 暖调侧栏，与浅色档的冷调#e9edf6 对位。 */
  --side-bg: #e5d9c0;
  /* 分类色暖色档：色相压进暖轴，并与本档的 --warn #8a5a00 / --success #2e6b33
     刻意错开明度与饱和度，避免"分类色被读成语义色"。*/
  --cat-1: #4a3f8f;
  --cat-2: #1b5566;
  --cat-3: #8f5b16;
  --cat-4: #33683f;
}
/* ============================================================================
 * 语义标记（sem-*）—— JS 侧渲染状态标签的唯一着色入口
 *
 * 存在的理由：此前 app.js 里有 48+ 处内联 `style={{color:'#10b981'}}` 这类写法，
 * 用的是又一套（Tailwind 500 档）色板。内联样式**权重最高、任何主题规则都盖不过**，
 * 于是浅色/暖色档下这些 10px 小标签的对比度全面崩盘：
 *   #f59e0b on白 = 2.15:1、#10b981 = 2.54:1、#9ca3af = 2.54:1（AA 要求 4.5:1）
 * ——即"深色主题下看着挺好，切到浅色就成了隐形文字"。根因不是开发者选色随意，
 * 而是 JS 侧没有可用的着色出口，只能就手写 hex。这里补上这个出口。
 *
 * 用法：h('span', { class: 'sem-tag sem-ok' }, '已生效')
 * 底色统一用 color-mix 12%（而非拼接 hex alpha 后缀 '1f'）——后者要求色值必须是
 * 字面量 hex，正是逼着调用方硬编码的直接原因。
 * ========================================================================== */
.sem-tag {
  display: inline-flex; align-items: center;
  font-size: 11px; line-height: 1.5; padding: 1px 8px; border-radius: 999px;
  white-space: nowrap; flex-shrink: 0;
}
.sem-ok      { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.sem-warn    { color: var(--warn);    background: color-mix(in srgb, var(--warn) 12%, transparent); }
.sem-error   { color: var(--error);   background: color-mix(in srgb, var(--error) 12%, transparent); }
.sem-info    { color: var(--accent);  background: color-mix(in srgb, var(--accent) 12%, transparent); }
/* neutral = "未启用/未暴露"这类**无状态**，刻意不给色相：它们不是好也不是坏，
   给了色相就会被读成某种态度（灰色恰恰是"这里没什么可看的"最准确的表达）。 */
.sem-neutral { color: var(--text-3);  background: color-mix(in srgb, var(--text-3) 12%, transparent); }
.sem-cat-1   { color: var(--cat-1);   background: color-mix(in srgb, var(--cat-1) 12%, transparent); }
.sem-cat-2   { color: var(--cat-2);   background: color-mix(in srgb, var(--cat-2) 12%, transparent); }
.sem-cat-3   { color: var(--cat-3);   background: color-mix(in srgb, var(--cat-3) 12%, transparent); }
.sem-cat-4   { color: var(--cat-4);   background: color-mix(in srgb, var(--cat-4) 12%, transparent); }
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; background: var(--bg); color: var(--text);
  font: 14px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", sans-serif; }
body.drawer-open { overflow: hidden; }
a { color: var(--primary); text-decoration: none; }
button { font: inherit; }
/* 统一线性图标：随父级 color 着色，垂直居中、像素对齐 */
.icon { display: inline-flex; align-items: center; justify-content: center; line-height: 0; flex: 0 0 auto; }
.icon svg { display: block; }
input, select, textarea {
  width: 100%; padding: 8px 10px; background: var(--input-bg); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px; outline: none;
}
input:focus, textarea:focus, select:focus { border-color: var(--primary); }
textarea { font-family: var(--mono); resize: vertical; min-height: 80px; }
/* Safari 不重置 appearance 会保留系统原生下拉箭头（双层、粗大，与自定义背景/内距明显不协调）；
   统一去掉原生外观并换成与.topbar-agent-switcher 一致的细箭头图标，三端表现一致。 */
select {
  appearance: none; -webkit-appearance: none; -moz-appearance: none;
  cursor: pointer; padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%236b7280' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 10px center;
}
/* 复选框/单选框不应被全局 width:100% 撑满，否则会破坏行内排版 */
input[type="checkbox"], input[type="radio"] { width: auto; flex: none; margin: 0; }
label { display: block; margin: 8px 0 4px; color: var(--text-2); font-size: 12px; }

/* ===== 通用表单字段系统：标签 + 控件 + 说明，统一节奏与对齐 ===== */
.form-stack { display: flex; flex-direction: column; gap: 16px; }
.form-stack > p { color: var(--text-2); }
.field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.field > label { margin: 0; font-weight: 500; }
.field-hint { color: var(--text-2); font-size: 12px; line-height: 1.5; }
.field-row { display: flex; gap: 12px; align-items: flex-start; }
.field-row > .field { flex: 1 1 0; }
.field-row > .field-shrink { flex: 0 0 110px; }
.field-check { display: flex; align-items: center; gap: 8px; margin: 0; cursor: pointer; font-size: 13px; color: var(--text); }
.field-check span { line-height: 1; }
.upload-box { display: flex; align-items: center; gap: 10px; padding: 10px; background: var(--input-bg); border: 1px dashed var(--border); border-radius: 8px; }
.upload-status { min-width: 0; color: var(--text-2); font-size: 12px; line-height: 1.4; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.upload-status.success { color: var(--success); }
.upload-status.error { color: var(--error); }
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  flex: 0 0 auto; white-space: nowrap;
  padding: 6px 12px; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); border-radius: 6px; cursor: pointer; }
.btn:hover { background: var(--btn-hover); }
.btn.primary { background: var(--text); border-color: var(--text); color: var(--bg); }
.btn.primary:hover { background: var(--text-2); border-color: var(--text-2); }
.btn.danger { background: transparent; border-color: var(--error); color: var(--error); }
.btn.ghost { background: transparent; border-color: transparent; color: var(--text-2); }
.btn:disabled { opacity: .5; cursor: not-allowed; }
.row { display: flex; gap: 8px; align-items: center; }
.col { display: flex; flex-direction: column; gap: 8px; }
.muted { color: var(--text-2); }
.tag { display: inline-block; padding: 2px 8px; border-radius: 999px; font-size: 12px; border: 1px solid var(--border); }
.tag.queued { color: var(--text-2); }
.tag.running { color: var(--primary); border-color: var(--primary); }
.tag.reviewing { color: var(--warn); border-color: var(--warn); }
.tag.interacting { color: var(--accent); border-color: var(--accent); }
.tag.committing, .tag.starting { color: var(--primary); }
.tag.done { color: var(--success); border-color: var(--success); }
.tag.failed { color: var(--error); border-color: var(--error); }
.tag.blocked, .tag.paused, .tag.incomplete { color: var(--warn); border-color: var(--warn); }
.tag.canceled { color: var(--text-3); border-color: var(--border); }

/* layout */
.shell { display: grid; grid-template-rows: 1fr; height: 100vh; height: 100dvh; }
/* chat-mode：隐藏顶栏，会话标题已顶到最上方 */
.shell.chat-mode .topbar { display: none !important; }
.shell.chat-mode { grid-template-rows: 1fr; }
/* 品牌菜单按钮：默认隐藏，移动端可见（chat-header 和顶栏共用） */
.topbar {
  display: none; align-items: center; gap: 16px; padding: 0 16px;
  background: var(--panel); border-bottom: 1px solid var(--border);
}
.topbar .brand { font-weight: 600; letter-spacing: .3px; white-space: nowrap; }
.brand-mark {
  display: inline-flex; align-items: center; gap: 6px; padding: 0 10px;
  height: 32px; border: 1px solid var(--border); border-radius: 10px;
  background: linear-gradient(135deg, var(--primary-a-24), var(--accent-a-18)); color: var(--text);
  flex-shrink: 0; font-weight: 600; font-size: 14px; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.brand-mark:hover { border-color: var(--primary-a-45); }
.brand-mark-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: 5px;
  background: var(--primary); color: var(--accent-fg); font-size: 11px; font-weight: 800;
  line-height: 1; flex-shrink: 0;
}
.brand-mark-icon { font-size: 16px; opacity: .6; }
.brand-mark-mobile { display: none; }
/* 抽屉顶部品牌栏 */
.drawer-brand {
  display: flex; align-items: center; gap: 10px; padding: 14px 16px 12px;
  border-bottom: 1px solid var(--border);
}
.drawer-brand-logo {
  width: 36px; height: 36px; border-radius: 10px;
  background: linear-gradient(135deg, var(--primary), var(--primary-2));
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-size: 17px; font-weight: 800; flex-shrink: 0;
  box-shadow: 0 2px 8px var(--primary-a-35);
}
.drawer-brand-text {
  display: flex; flex-direction: column; min-width: 0;
}
.drawer-brand-name {
  font-size: 18px; font-weight: 700; letter-spacing: .02em; color: var(--text);
  line-height: 1.2;
}
.drawer-brand-tagline {
  font-size: 11px; color: var(--text-2); line-height: 1.3; margin-top: 1px;
}
/* 抽屉 head 内嵌品牌（栈底显示；进入子页时由 JS 隐藏，让位给「返回 + 标题」） */
.drawer-head-brand { display: flex; align-items: center; gap: 10px; justify-content: flex-start; }
/* 名称/标语两行原来只靠基础规则的 margin-top:1px 分隔，字号缩到 16px/10px 后视觉上几乎贴在一起；
   单独加大间距 + 略微放宽行高，让两行喘口气。 */
.drawer-head-brand .drawer-brand-name { font-size: 16px; line-height: 1.3; }
.drawer-head-brand .drawer-brand-tagline { font-size: 10px; margin-top: 4px; line-height: 1.3; }
/* 主菜单品牌 logo 与 Agent 列表头像使用同一尺寸/圆角，形成垂直对齐的通讯录视觉。 */
.drawer-brand-logo.sm { width: 36px; height: 36px; border-radius: 8px; font-size: 15px; box-shadow: 0 2px 8px var(--primary-a-35); }
/* 主菜单内嵌品牌：左对齐，logo 与 Agent 头像对齐 */
.drawer-brand-inline { display: flex; align-items: center; gap: 10px; padding: 14px 4px 8px; }
.drawer-brand-inline .drawer-agent-avatar { box-shadow: 0 2px 8px var(--primary-a-35); }
.drawer-brand-inline-text { display: flex; flex-direction: column; min-width: 0; }
.drawer-brand-inline .drawer-brand-name { font-size: 18px; font-weight: 700; letter-spacing: .02em; color: var(--text); line-height: 1.2; }
.drawer-brand-inline .drawer-brand-tagline { font-size: 11px; color: var(--text-2); line-height: 1.3; margin-top: 1px; }
.topbar .spacer { flex: 1; }
.topbar-agent-switcher {
  flex: 1; max-width: 200px; height: 32px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-tint); color: var(--text); font-size: 14px; padding: 0 8px;
  appearance: none; -webkit-appearance: none; cursor: pointer;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M3 4.5L6 7.5L9 4.5' stroke='%236b7280' stroke-width='1.5' fill='none'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 8px center;
}
/* 协同：协助标签 + 弱化卡片 + 权限勾选 */
.collab-badge {
  display: inline-block; margin-left: 6px; padding: 0 6px; height: 16px; line-height: 16px;
  border-radius: 999px; font-size: 10px; font-weight: 600; vertical-align: middle;
  color: var(--accent); background: var(--accent-a-18); border: 1px solid var(--accent-a-45);
}
.collab-agent-card { border-left: 2px solid var(--accent-a-45); }
.collab-perms { display: grid; gap: 10px; margin-top: 10px; }
.collab-perm-group { display: grid; gap: 8px; padding: 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); }
.collab-perm-group.high-risk { border-color: var(--warn-a-35); background: var(--warn-a-06); }
.collab-perm-group-title { color: var(--text-2); font-size: 12px; font-weight: 650; }
.collab-perm { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text); }
.collab-member .btn.danger { flex: 0 0 auto; }
.friends-page { max-width: 1040px; }
.friends-page-card { display: grid; gap: 14px; }
.friends-card-head, .friends-hero, .friends-section-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 12px;
}
.friends-card-head h3, .friends-card-head p, .friends-hero h3, .friends-hero p, .friends-section-head h3, .friends-section-head p { margin: 0; }
.friends-overview { display: grid; gap: 10px; }
/* 概览顶栏：一句话说明 + 通知铃 + 号码卡，压成一条纤细横栏，把纵向篇幅让给好友列表 */
.friends-topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 8px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint);
}
.friends-topbar-sub { font-size: 12px; line-height: 1.5; min-width: 0; }
.friends-topbar-right { display: flex; align-items: center; gap: 10px; flex-shrink: 0; }
.friends-bell {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; border-radius: 9px; color: var(--text-2);
  border: 1px solid var(--border); background: var(--panel);
}
.friends-bell.has { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.friends-bell-dot {
  position: absolute; top: -6px; right: -6px; min-width: 16px; height: 16px; padding: 0 4px;
  display: inline-flex; align-items: center; justify-content: center;
  font: 700 10px/1 var(--mono); color: #fff; background: var(--warn); border-radius: 999px;
}
.friend-self-alias {
  display: grid; gap: 2px; justify-items: end; padding: 8px 12px;
  border: 1px solid var(--primary-a-35); border-radius: 12px; background: var(--primary-a-08);
  color: var(--text); cursor: pointer; min-width: 132px;
}
.friend-self-alias:hover { background: var(--primary-a-12); border-color: var(--primary-a-45); }
.friend-self-alias span { color: var(--text-2); font-size: 11px; line-height: 1.2; }
.friend-self-alias strong { color: var(--primary); font: 700 16px/1.2 var(--mono); letter-spacing: .02em; }
/* 顶栏内的号码卡收窄成一行胶囊，避免占两行高度 */
.friend-self-alias.compact {
  display: inline-flex; align-items: baseline; gap: 6px; justify-items: initial;
  padding: 6px 10px; border-radius: 999px; min-width: 0;
}
.friend-self-alias.compact span { font-size: 11px; }
.friend-self-alias.compact strong { font-size: 13px; }
.friends-network, .friends-card-list { display: grid; gap: 10px; }
.friends-section { display: grid; gap: 10px; padding: 14px; border: 1px solid var(--border); border-radius: 16px; background: var(--panel); }
.friend-card { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface-tint); }
.agent-friend-card { border-left: 3px solid var(--accent-a-45); }
.human-friend-card { border-left: 3px solid var(--success-a-35); }
.friend-card-main { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; align-items: flex-start; }
.friend-avatar { width: 38px; height: 38px; border-radius: 12px; display: inline-flex; align-items: center; justify-content: center; color: #fff; font-weight: 750; }
.friend-avatar.agent { background: linear-gradient(135deg, var(--primary), var(--accent)); }
.friend-avatar.human { background: var(--success); }
.friend-card-body { min-width: 0; display: grid; gap: 4px; }
.friend-card-title { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.friend-card-meta, .friend-skill, .friend-source-note { font-size: 12px; }
.friend-badge { display: inline-flex; align-items: center; padding: 1px 7px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface-tint); color: var(--text-2); font-size: 11px; line-height: 1.45; }
.friend-badge.agent, .friend-badge.stage, .friend-badge.manual { color: var(--primary); border-color: var(--primary-a-35); background: var(--primary-a-08); }
.friend-badge.human { color: var(--success); border-color: var(--success-a-35); background: var(--success-a-06); }
.friend-badge.auto { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.friend-badge.system { color: var(--accent); border-color: var(--accent-a-45); background: var(--accent-a-18); }
.friend-flow-tags { display: flex; gap: 6px; flex-wrap: wrap; }
.friend-perm-block { display: grid; grid-template-columns: 76px minmax(0, 1fr); gap: 8px; font-size: 12px; }
.friend-perm-block.risk { color: var(--warn); }
.friend-perm-label { color: var(--text-2); }
.friend-card-actions { display: flex; justify-content: flex-end; gap: 6px; flex-wrap: wrap; }
.friend-icon-btn { display: inline-flex; align-items: center; justify-content: center; min-width: 32px; padding: 6px; }
.friend-search { width: 100%; padding: 8px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); font-size: 13px; }
.friend-search:focus { outline: none; border-color: var(--primary-a-45); box-shadow: 0 0 0 3px var(--primary-a-12); }
.friends-empty { padding: 22px; border: 1px dashed var(--border); border-radius: 14px; text-align: center; background: var(--surface-tint); }
.friends-empty.compact { padding: 14px; color: var(--text-2); font-size: 13px; }
.friends-requests { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface-tint); }
.friends-requests.has-incoming { border-color: var(--warn-a-35); background: var(--warn-a-06); }
.friends-request-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.friends-request-head h3, .friends-request-head p { margin: 0; }
.friends-request-head.compact { align-items: center; }
.friends-request-head.compact strong { font-size: 13px; }
.friends-requests { padding: 10px 12px; }
.friends-request-body { display: grid; gap: 8px; }
.friends-request-title { color: var(--text-2); font-size: 12px; font-weight: 650; }
.friends-request-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center; padding: 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel); }
.friend-add-hint, .friend-resolve-card { padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); font-size: 13px; line-height: 1.55; }
.friend-add-hint.compact { padding: 8px 10px; font-size: 12px; color: var(--text-2); }
.friend-config-form { display: grid; gap: 12px; }
.friend-config-section { display: grid; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface-tint); }
.friend-config-section-head { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 8px; align-items: start; }
.friend-config-step { display: inline-flex; align-items: center; justify-content: center; width: 20px; height: 20px; border-radius: 999px; background: var(--primary-a-12); color: var(--primary); font-size: 11px; font-weight: 800; }
.friend-config-section-head strong { display: block; font-size: 13px; line-height: 1.3; }
.friend-config-section-head p { margin: 2px 0 0; color: var(--text-2); font-size: 12px; line-height: 1.45; }
.friend-config-extra { border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); padding: 0 10px; }
.friend-config-extra summary { cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 2px; color: var(--text); font-size: 13px; font-weight: 650; }
.friend-config-extra summary em { color: var(--text-2); font-size: 11px; font-style: normal; font-weight: 500; }
.friend-config-extra textarea { margin: 0 0 10px; }
.friend-config-advanced { border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); padding: 0 10px; }
.friend-config-advanced > summary { cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 2px; color: var(--text); font-size: 13px; font-weight: 650; list-style: none; }
.friend-config-advanced > summary::-webkit-details-marker { display: none; }
.friend-config-advanced > summary::before { content: '›'; display: inline-block; width: 14px; color: var(--text-2); transform: rotate(0deg); transition: transform .15s; }
.friend-config-advanced[open] > summary::before { transform: rotate(90deg); }
.friend-config-advanced > summary em { color: var(--text-2); font-size: 11px; font-style: normal; font-weight: 500; }
.friend-config-advanced .friend-config-form { padding: 0 2px 10px; }
.friend-resolve-card.agent { border-color: var(--primary-a-35); background: var(--primary-a-08); }
.friend-resolve-card.human { border-color: var(--success-a-35); background: var(--success-a-06); }
.friend-resolve-card.warn { border-color: var(--warn-a-35); background: var(--warn-a-06); color: var(--warn); }
.main { display: grid; grid-template-columns: 180px 1fr; grid-template-rows: 1fr; min-height: 0; }
.side {
  background: var(--panel); border-right: 1px solid var(--border); padding: 10px 8px;
  display: flex; flex-direction: column; gap: 8px; min-height: 0;
}
.side-user-card { display: none; }
.side-user-avatar { display: none; }
.side-user-info { display: none; }
.side-user-name { display: none; }
.side-user-meta { display: none; }
.side-agent-list { display: none; }
.side-new-agent { display: none; }
.side-agent-item { display: none; }
.side-agent-info { display: none; }
.side-agent-info-head { display: none; }
.side-agent-info-meta { display: none; }
.side-agent-info-detail { display: none; }
.side-agent-info-row { display: none; }
.side-agent-info-actions { display: none; }
.side-agent-head {
  padding: 8px 12px; font-size: 14px;
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-tint);
}
.side-agent-avatar {
  width: 36px; height: 36px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; color: #fff;
}
.side-agent-head:hover { background: var(--panel-2); border-color: var(--primary-a-45); }
/* 紧凑态：名称由会话头部居中展示，侧栏只留头像 + 切换图标，120px 窄栏内居中 */
.side-agent-head.compact { justify-content: center; gap: 8px; padding: 8px 6px; }
.side-agent-head.compact .side-agent-switch { flex-shrink: 0; display: inline-flex; color: var(--text-2); }
.side-agent-head-info {
  display: flex; flex-direction: column; gap: 2px; min-width: 0;
}
.side-agent-name {
  font-size: 15px; font-weight: 700; color: var(--text); line-height: 1.3;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-agent-type {
  display: flex; align-items: center; gap: 4px; min-width: 0;
  font-size: 11px; color: var(--text-2); line-height: 1.2;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.side-agent-id {
  display: inline-flex; align-items: center; padding: 1px 5px; border-radius: 999px;
  background: var(--primary-a-08); color: var(--primary); border: 1px solid var(--primary-a-22);
  font-family: var(--mono); font-weight: 650; line-height: 1.25;
}
.side-agent-sep { opacity: .45; }
.side-agent-kind { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-nav {
  display: flex; flex-direction: column; gap: 2px;
  background: var(--panel); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px; margin-top: 4px;
}
.side-nav-item {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 9px 10px; border: none; background: transparent;
  color: var(--text-2); border-radius: 6px; cursor: pointer;
  text-align: left; font-size: 13px;
  transition: background .15s ease, color .15s ease;
}
.side-nav-item:hover { background: var(--panel-2); color: var(--text); }
.side-nav-item.active {
  background: var(--primary-a-08); color: var(--primary); font-weight: 600;
}
.side-nav-icon { font-size: 14px; line-height: 1; }
.content { padding: 16px 20px; overflow: auto; min-width: 0; min-height: 0; contain: layout paint; scrollbar-gutter: stable; }
/* 切换栏目时新视图轻微淡入，配合双缓冲渲染消除生硬切换（聊天模式不加，避免每次进会话闪动）。 */
@keyframes viewFadeIn { from { opacity: 0; transform: translateY(3px); } to { opacity: 1; transform: none; } }
.shell:not(.chat-mode) .content > * { animation: viewFadeIn .16s ease-out; }
/* 聊天模式：.content 必须【完全不设】containment。
   注意：contain 的 layout 与 paint 两者【都】会让元素成为 absolute/fixed 后代的「包含块」
   （不是只有 paint 才会）。此前误以为「只留 layout」就安全，实际 contain:layout 仍使 .content
   成为移动端工作区浮层（position:fixed）的包含块 → 浮层以 .content（带内边距/可滚动/在网格内）为参照，
   而遮罩挂在 body 上以视口为参照，二者错位、浮层被裁剪偏移。故这里置为 none，让 fixed 面板回到视口定位。 */
.shell.chat-mode .content { contain: none; }


/* ============ 登录页（简洁扁平 + 精致细节：居中单卡片，克制纵深与入场动效） ============ */
.login-page { position: relative; min-height: 100vh; display: grid; place-items: center; padding: 24px; background: var(--bg); }
.login-card { width: 396px; max-width: 92vw; background: var(--panel); border: 1px solid var(--border); border-radius: 16px; padding: 36px 32px 26px; box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 20px 56px rgba(0,0,0,.10); animation: loginCardIn .5s cubic-bezier(.2,.8,.2,1) both; }
@keyframes loginCardIn { from { opacity: 0; transform: translateY(10px) scale(.99); } to { opacity: 1; transform: none; } }
/* 品牌区：居中、mark 在上、名称+副题在下，更精致对称 */
.login-brand { display: flex; flex-direction: column; align-items: center; gap: 12px; margin-bottom: 26px; text-align: center; }
.login-brand-mark { display: inline-grid; place-items: center; width: 46px; height: 46px; border-radius: 13px; font-size: 21px; font-weight: 800; color: var(--accent-fg); background: var(--primary); box-shadow: 0 6px 20px color-mix(in srgb, var(--primary) 34%, transparent); }
.login-brand-text { display: flex; flex-direction: column; gap: 4px; }
.login-brand-text h1 { margin: 0; font-size: 21px; font-weight: 700; color: var(--text); }
.login-brand-sub { font-size: 12.5px; color: var(--text-2); letter-spacing: .04em; }
/* 口令：字距舒展、等宽、微内阴影，突出「一串可读的码」的精致感 */
.login-code { margin: 0; padding: 18px 16px; text-align: center; font: 32px/1 var(--mono); letter-spacing: .28em; text-indent: .28em; color: var(--text); background: var(--input-bg); border: 1px solid var(--border); border-radius: 12px; box-shadow: inset 0 1px 2px rgba(0,0,0,.05); }
.login-emergency { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border); }
.wechat-bind-modal { text-align: center; }
.wechat-qr-frame { display: inline-flex; padding: 12px; margin: 8px auto 10px; border-radius: var(--r-md); background: #fff; border: 1px solid var(--border); }
.wechat-qr { display: block; width: 240px; max-width: 100%; border-radius: 8px; background: white; padding: 0; object-fit: contain; }

/* 登录方式面板：切换时轻微淡入上浮，细节更顺滑 */
.login-method-panel { animation: loginPanelFade .28s ease both; }
.login-method-panel[hidden] { display: none; }
@keyframes loginPanelFade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
/* 主路径表单：字段间 14，提交按钮上方 20 —— 让"提交"明确脱离最后一个输入组。
   原实现按钮上方只有 10px（几乎等于 label 与 input 的组内间距），读起来像密码那一组的一部分。 */
.login-field-stack { display: flex; flex-direction: column; gap: 14px; }
.login-field-stack input { width: 100%; }
/* 全卡唯一的实心色块 = 当前唯一主动作。原实现把它给了 tab 激活态，
   而真正的提交按钮是半透明描边，视觉权重完全倒挂。 */
.login-submit { width: 100%; margin-top: 20px; padding: 12px 16px; border-radius: 10px; font-size: 14.5px; font-weight: 600; }
.login-panel-lead { margin: 0 0 12px; text-align: center; font-size: 13px; color: var(--text-2); letter-spacing: .02em; }
/* 口令 + 复制并排：口令要被抄到微信里发送，复制是这个模式的主动作。 */
.login-code-row { display: flex; align-items: stretch; gap: 8px; }
.login-code-row .login-code { flex: 1 1 auto; min-width: 0; }
.login-code-copy { flex: none; padding: 0 16px; border-radius: 10px; font-size: 13px; font-weight: 600; }
.login-code-refresh { width: 100%; margin-top: 12px; border-radius: 10px; }
/* 等待态：呼吸点 + 剩余有效期，让「发完口令之后在等什么、还能等多久」可见。 */
.login-wait { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 14px; font-size: 12.5px; color: var(--text-2); }
.login-wait-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--primary); animation: loginWaitPulse 1.6s ease-in-out infinite; }
.login-wait-time { font-family: var(--mono); font-variant-numeric: tabular-nums; color: var(--text-3); }
.login-wait.is-stale .login-wait-dot { background: var(--text-3); animation: none; }
@keyframes loginWaitPulse { 0%, 100% { opacity: .25; transform: scale(.85); } 50% { opacity: 1; transform: scale(1); } }
/* 错误条：只在出错时占位（不再常驻空行），并可携带一个"下一步"动作。 */
.login-error { margin-top: 16px; padding: 10px 12px; border-radius: 10px; font-size: 12.5px; line-height: 1.6; color: var(--error); background: color-mix(in srgb, var(--error) 10%, transparent); border: 1px solid color-mix(in srgb, var(--error) 30%, transparent); }
.login-error[hidden] { display: none; }
.login-error-action { display: block; margin-top: 6px; padding: 0; border: 0; background: none; color: var(--text); font-size: 12.5px; text-align: left; text-decoration: underline; text-underline-offset: 3px; cursor: pointer; }
/* 兜底登录方式：渐进披露的唯一入口，纯文字链，权重远低于主路径。 */
.login-alt { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; margin-top: 24px; font-size: 12.5px; color: var(--text-3); }
.login-alt[hidden] { display: none; }
.login-alt-link { padding: 0; border: 0; background: none; color: var(--text-2); font-size: 12.5px; cursor: pointer; text-underline-offset: 3px; }
.login-alt-link:hover { color: var(--text); text-decoration: underline; }
.login-alt-sep { color: var(--text-3); opacity: .6; }
/* 首次部署才出现的初始化区（常态不渲染，不占高度）。 */
.login-setup { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--border); text-align: center; }
.login-setup .btn { width: 100%; margin-top: 10px; border-radius: 10px; }
/* 圆角严格外大内小：卡片 16 → 面板/口令 12 → 输入与按钮 10。 */
.login-card .btn { border-radius: 10px; }
/* 卡内输入与标签：统一精致间距 */
.login-card label { display: block; font-size: 12.5px; color: var(--text-2); letter-spacing: .02em; margin-bottom: 4px; }
.login-card input { border-radius: 10px; }
.login-qr-placeholder { display: grid; place-items: center; width: 204px; height: 204px; margin: 8px auto 6px; border-radius: 14px; border: 1px dashed var(--border); background: var(--panel-2); color: var(--text-2); font-size: 13px; }
.login-qr-img { display: block; width: 204px; height: 204px; margin: 8px auto 6px; border-radius: 14px; background: #fff; padding: 8px; object-fit: contain; box-shadow: 0 6px 22px rgba(0,0,0,.10); }
.login-qr-img[hidden], .login-qr-placeholder[hidden] { display: none; }
.login-aux-note { font-size: 12px; color: var(--text-2); text-align: center; margin: 10px 0 0; letter-spacing: .02em; line-height: 1.6; }

/* ============ 登录页星空主题：与首页同源的深空背景 + 玻璃卡（视觉连贯，不随明暗主题变浅） ============ */
.login-page.login-cosmos { background: #070b16; overflow: hidden; }
.login-cosmos::before { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: radial-gradient(760px 460px at 50% 34%, rgba(90,120,220,.16), transparent 70%); }
.login-stars { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
.login-cosmos .login-card { position: relative; z-index: 1; background: rgba(18,26,48,.55); border: 1px solid rgba(160,190,255,.16); box-shadow: inset 0 1px 0 rgba(255,255,255,.05), 0 24px 70px rgba(0,0,0,.5); -webkit-backdrop-filter: blur(16px) saturate(1.2); backdrop-filter: blur(16px) saturate(1.2); }
.is-safari .login-cosmos .login-card { -webkit-backdrop-filter: none; backdrop-filter: none; background: rgba(18,26,48,.82); }
.login-cosmos .login-brand-mark { box-shadow: 0 0 20px rgba(124,140,255,.5); }
.login-cosmos .login-brand-text h1 { color: #f2f5ff; }
.login-cosmos .login-brand-sub { color: rgba(220,226,245,.65); }
.login-cosmos .muted { color: rgba(220,226,245,.62); }
.login-cosmos .login-aux-note { color: rgba(210,218,240,.5); }
.login-cosmos .login-code { color: #eaf0ff; background: rgba(150,180,255,.06); border-color: rgba(160,190,255,.22); box-shadow: inset 0 1px 2px rgba(0,0,0,.3); }
.login-cosmos .login-panel-lead { color: rgba(220,226,245,.66); }
.login-cosmos .login-wait { color: rgba(220,226,245,.6); }
.login-cosmos .login-wait-time { color: rgba(210,218,240,.45); }
.login-cosmos .login-alt { color: rgba(210,218,240,.45); }
.login-cosmos .login-alt-link { color: rgba(220,226,245,.72); }
.login-cosmos .login-alt-link:hover { color: #eaf0ff; }
.login-cosmos .login-alt-sep { color: rgba(210,218,240,.35); }
.login-cosmos .login-error { color: #ffd9d9; background: rgba(255,95,95,.1); border-color: rgba(255,125,125,.3); }
.login-cosmos .login-error-action { color: #eaf0ff; }
.login-cosmos .login-setup { border-top-color: rgba(160,190,255,.14); }
.login-cosmos .login-card label { color: rgba(220,226,245,.7); }
.login-cosmos input { background: rgba(255,255,255,.05); border-color: rgba(160,190,255,.2); color: #eaf0ff; }
.login-cosmos input::placeholder { color: rgba(210,218,240,.4); }
.login-cosmos input:focus { border-color: rgba(150,180,255,.7); box-shadow: 0 0 0 3px rgba(120,150,255,.22); }
.login-cosmos .btn { background: rgba(150,180,255,.08); border: 1px solid rgba(160,190,255,.32); color: #eaf0ff; box-shadow: none; }
.login-cosmos .btn:hover { background: rgba(160,190,255,.14); border-color: rgba(185,208,255,.6); }
.login-cosmos .btn.primary { background: var(--primary); border-color: transparent; color: var(--accent-fg); }
.login-cosmos .btn.primary:hover { background: var(--primary); filter: brightness(1.06); }
.login-cosmos .btn.primary[disabled] { opacity: .6; filter: none; }
.login-cosmos .login-qr-placeholder { background: rgba(255,255,255,.04); border-color: rgba(160,190,255,.24); color: rgba(220,226,245,.6); }
/* 登录页动效在「减少动态效果」偏好下全部关闭（星空 canvas 已在 mountStarfield 内自行处理）。 */
@media (prefers-reduced-motion: reduce) {
  .login-card, .login-method-panel { animation: none; }
  .login-wait-dot { animation: none; opacity: .8; }
}

/* ============ 未登录首页（slogan「数字微光，群星永恒」：深空星空 + 单一实心 CTA） ============ */
/* 落地页是营销门面，独立于应用内扁平 UI：固定深空底色与固定强调色（不随主题变浅），
   让 canvas 群星与实心 CTA 在任何主题下都是同一套观感。 */
/* grid 两行（内容 / 页脚）：页脚回到正常流。原实现是 flex center + 页脚 absolute bottom:22px，
   于是 CTA 与页脚之间悬空一大片死区，页脚成了孤儿。 */
.home-landing.home-cosmos { position: relative; min-height: 100vh; min-height: 100dvh; display: grid; grid-template-rows: 1fr auto; justify-items: center; padding: 84px 24px 26px; overflow: hidden; text-align: center; background: #070b16; color: #e8ecf8; }
/* 极轻的中心微光（“数字微光”）——单一柔光斑，非炫目渐变。 */
.home-cosmos::before { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: radial-gradient(760px 460px at 50% 38%, rgba(90,120,220,.16), transparent 70%); }
.home-stars { position: fixed; inset: 0; z-index: 0; pointer-events: none; }
/* 顶栏：品牌是「定位」不是「主张」，从 hero 首行降到这里并去掉外发光（非交互装饰不该比 CTA 亮）。 */
.home-cosmos .home-topbar { position: absolute; z-index: 2; top: 0; left: 0; right: 0; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 22px 28px; }
.home-cosmos .home-brand { display: inline-flex; align-items: center; gap: 9px; }
.home-cosmos .home-brand-mark { display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 9px; font-size: 14px; font-weight: 700; color: #06222b; background: #67e8f9; }
.home-cosmos .home-brand-name { font-size: 15px; font-weight: 600; letter-spacing: .02em; color: rgba(232,236,248,.92); }
.home-cosmos .home-signin { padding: 7px 15px; border-radius: 999px; font-size: 13px; text-decoration: none; color: rgba(224,230,248,.82); border: 1px solid transparent; transition: color .2s ease, background .2s ease, border-color .2s ease; }
.home-cosmos .home-signin:hover { color: #fff; background: rgba(160,190,255,.1); border-color: rgba(160,190,255,.3); }
/* 视觉中心上移到约 44%：竖幅里人眼感知的「居中」高于几何中心。 */
.home-cosmos .home-hero { position: relative; z-index: 1; align-self: center; max-width: 640px; margin-bottom: 6vh; animation: homeHeroIn .7s cubic-bezier(.2,.8,.2,1) both; }
@keyframes homeHeroIn { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
/* CJK 显示级排版：字距归零（正字距会把「数字微光」散成四个孤立字，丢词组感）、
   字重 700（深色底叠发光时 800 的 CJK 笔画会光学膨胀并笔）。 */
.home-title { margin: 0 0 14px; font-size: 40px; line-height: 1.24; font-weight: 700; letter-spacing: 0; color: #f2f5ff; }
/* 全角逗号自带约 .5em 后置空白：词组之间要做光学压缩，而不是继续加空。 */
.home-title-comma { opacity: .5; margin: 0 -.16em 0 -.06em; }
/* 发光只在入场时收敛一次。永续动效无法指示任何东西（因为它一直在发生），
   把持续的呼吸留给星空（它才是「数字微光」真正的载体）。 */
.home-title-a, .home-title-b { text-shadow: 0 0 18px rgba(150,180,255,.34); animation: homeTitleSettle 1.5s cubic-bezier(.2,.8,.2,1) both; }
.home-title-b { animation-delay: .12s; }
@keyframes homeTitleSettle { from { text-shadow: 0 0 34px rgba(180,205,255,.75); } to { text-shadow: 0 0 18px rgba(150,180,255,.34); } }
/* 命题：替掉了原先与 slogan 同义的第二句诗——陌生访客靠这一行判断「这是什么」。 */
.home-lede { margin: 0 0 12px; font-size: 16px; line-height: 1.7; color: rgba(226,232,250,.82); letter-spacing: .01em; }
/* 能力锚点：交代「能做什么」，权重压到最低（12.5px），但仍满足 AA 对比。 */
.home-caps { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 8px; margin: 0 0 36px; padding: 0; list-style: none; font-size: 12.5px; color: rgba(206,214,240,.58); letter-spacing: .02em; }
.home-caps li { display: inline-flex; align-items: center; gap: 8px; }
.home-caps li + li::before { content: '·'; opacity: .55; }
.home-actions { display: flex; flex-direction: column; align-items: center; gap: 14px; }
/* 全页唯一实心块 = 全页唯一动作。原实现把 .primary 的每一条属性都覆盖成 5% 底 + 32% 描边，
   描边对背景仅约 2:1（不满足 WCAG 1.4.11 的 3:1），读起来像禁用态。 */
.home-cta { display: inline-flex; align-items: center; gap: .5em; padding: 13px 30px; border-radius: 999px; font-size: 15px; font-weight: 600; letter-spacing: .04em; text-decoration: none; color: #06222b; background: #67e8f9; border: 0; box-shadow: 0 10px 30px rgba(103,232,249,.18); transition: transform .25s ease, box-shadow .25s ease, filter .25s ease; }
.home-cta:hover { filter: brightness(1.06); box-shadow: 0 14px 38px rgba(103,232,249,.3); transform: translateY(-1px); }
.home-cta:active { transform: translateY(0); }
/* 箭头位移是唯一的 hover 反馈；原实现同时动 letter-spacing，会让标签在指针下重排抖动。 */
.home-cta-arrow { display: inline-block; transition: transform .25s ease; }
.home-cta:hover .home-cta-arrow { transform: translateX(4px); }
/* 诚实门槛：系统只有邀请制、没有公开注册端点，不点明会让「开始创作」直接撞上密码墙。 */
.home-gate { margin: 0; font-size: 12.5px; color: rgba(206,214,240,.58); letter-spacing: .02em; }
/* 页脚对比度提到 AA 以上（原 40% 不透明度对 #070b16 只有约 2.9:1）。 */
.home-cosmos .home-foot { position: relative; z-index: 1; padding-top: 28px; font-size: 12px; color: rgba(215,222,244,.62); letter-spacing: .04em; }
@media (max-width: 560px) {
  .home-landing.home-cosmos { padding: 72px 20px 22px; }
  .home-cosmos .home-topbar { padding: 18px; }
  .home-title { font-size: 30px; }
  .home-lede { font-size: 15px; }
  .home-cosmos .home-hero { margin-bottom: 4vh; }
  .home-cta { width: 100%; max-width: 320px; justify-content: center; }
}
@media (prefers-reduced-motion: reduce) {
  .home-cosmos .home-hero { animation: none; }
  .home-title-a, .home-title-b { animation: none; text-shadow: 0 0 18px rgba(150,180,255,.34); }
  .home-cta, .home-cta-arrow, .home-cosmos .home-signin { transition: none; }
  .home-cta:hover { transform: none; }
}

.type-picker { display: grid; gap: 10px; margin: 12px 0 18px; }
/* 类型选择：图标选项卡网格与所选类型描述。 */
.type-picker-v2 { display: grid; gap: 10px; margin: 8px 0 12px; }
.type-option-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.type-option {
  position: relative; display: flex; align-items: center; gap: 9px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--panel); color: var(--text); cursor: pointer; text-align: left;
  transition: border-color .15s, background .15s, transform .1s;
}
.type-option:hover { border-color: var(--primary-a-35); background: var(--panel-2); }
.type-option:active { transform: scale(.99); }
.type-option.active { border-color: var(--primary); background: var(--primary-a-08); box-shadow: 0 0 0 1px var(--primary-a-35) inset; }
.type-option-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; flex-shrink: 0; border-radius: 9px;
  background: var(--surface-tint); color: var(--text-2);
}
.type-option.active .type-option-icon { background: var(--primary-a-12); color: var(--primary); }
.type-option-label { flex: 1; min-width: 0; font-size: 13px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.type-option-check { display: inline-flex; flex-shrink: 0; color: var(--primary); }
.type-option-hint { margin: 0; font-size: 12px; line-height: 1.5; min-height: 18px; }
.type-search-input { width: 100%; }
.type-group-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.type-group-title { font-weight: 700; font-size: 13px; }
.type-picker-hint { font-size: 12px; text-align: right; }
.type-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
.type-empty { grid-column: 1 / -1; padding: 18px; border: 1px dashed var(--border); border-radius: 14px; text-align: center; background: var(--surface-tint); }
.type-card {
  position: relative; overflow: hidden;
  text-align: left; padding: 14px 42px 14px 14px; min-height: 104px;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: 14px;
  cursor: pointer;
  transition: background .16s var(--ease-standard), border-color .16s var(--ease-standard), box-shadow .2s var(--ease-standard), transform .2s var(--ease-spring);
}
.type-card-title {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: center; gap: 8px; min-height: 28px; margin-bottom: 6px;
}
.type-card-title-text {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.type-card-source { justify-self: end; font-style: normal; font-size: 10px; font-weight: 650; color: var(--text-2); border: 1px solid var(--border); border-radius: 999px; padding: 1px 6px; }
.type-card > span:not(.type-card-check):not(.type-card-title-text) { display: block; color: var(--text-2); font-size: 12px; line-height: 1.45; }
.type-card:hover { background: var(--panel-2); transform: translateY(-1px); }
.type-card:active { transform: scale(.985); }
.type-card.active { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary-a-35) inset, 0 10px 24px var(--primary-a-08); }
.type-card-check {
  position: absolute; top: 12px; right: 12px;
  display: flex !important; align-items: center; justify-content: center;
  width: 22px; height: 22px; border-radius: 999px;
  color: var(--accent-fg); background: var(--primary);
  font-size: 13px; font-weight: 800; line-height: 1;
  opacity: 0; transform: scale(.72);
  transition: opacity .16s var(--ease-standard), transform .24s var(--ease-spring);
}
.type-card.active .type-card-check { opacity: 1; transform: scale(1); }
.manage-tabs { display: flex; gap: 8px; margin: 4px 0 14px; }
.manage-tab-body { display: block; }
.form-section { border-top: 1px solid var(--border); padding-top: 8px; }
.works-tabs { display: flex; gap: 8px; margin-bottom: 12px; }
.git-operation-card { margin-top: 12px; overflow: hidden; }
.git-operation-card.publish-only { margin-top: 0; border: none; background: transparent; box-shadow: none; padding: 0; }
.git-operation-hero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(220px, .72fr);
  gap: 14px;
  align-items: start;
  padding: 2px 0 12px;
}
.git-operation-title { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.git-operation-title h3 { margin: 0; }
.git-operation-kicker {
  width: fit-content;
  padding: 2px 8px;
  border: 1px solid var(--primary-a-35);
  border-radius: 999px;
  color: var(--primary);
  background: var(--primary-a-06);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .04em;
}
.git-status-summary {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  flex-wrap: wrap;
  gap: 6px;
  min-width: 0;
}
.git-status-chip {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding: 2px 9px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface-tint);
  color: var(--text-2);
  font-size: 11px;
  font-weight: 650;
  white-space: nowrap;
}
.git-status-chip.ok { color: var(--success); border-color: var(--success-a-35); background: var(--success-a-06); }
.git-status-chip.warn { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.git-status-chip.bad { color: var(--error); border-color: var(--error-a-35); background: var(--error-a-06); }
.git-status-chip.running { color: var(--primary); border-color: var(--primary-a-45); background: var(--primary-a-08); }
.git-publish-flow { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin: 4px 0 12px; }
.git-publish-flow span { display: flex; align-items: center; gap: 6px; padding: 9px; border: 1px solid var(--border); border-radius: 12px; background: linear-gradient(180deg, var(--surface-tint), transparent); color: var(--text-2); font-size: 12px; }
.git-publish-flow em { display: inline-flex; align-items: center; justify-content: center; width: 18px; height: 18px; border-radius: 999px; background: var(--primary-a-12); color: var(--primary); font-style: normal; font-weight: 800; font-size: 11px; }
.git-publish-flow b { font-weight: 650; color: var(--text); }
.git-action-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; margin: 8px 0 12px; }
.git-action-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 10px;
  align-items: start;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: 14px;
  background: var(--surface-tint);
}
.git-action-card.publish { border-color: var(--primary-a-38); background: linear-gradient(135deg, var(--primary-a-12), var(--surface-tint)); }
.git-action-icon {
  width: 34px;
  height: 34px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 12px;
  border: 1px solid var(--primary-a-35);
  color: var(--primary);
  background: var(--primary-a-08);
}
.git-action-body { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.git-action-body strong { color: var(--text); }
.git-action-body span { color: var(--text-2); font-size: 12px; line-height: 1.45; }
.git-action-card .btn { grid-column: 1 / -1; justify-content: center; }
.git-status-terminal { margin-top: 8px; max-height: 260px; overflow: auto; }
/* 能力翻译卡：把抽象工具讲成"AI 现在能做什么 + 可以这样问" */
.capability-usage-hint {
  margin: 0 0 12px; padding: 12px 14px;
  border: 1px solid var(--primary-a-35); border-radius: 12px;
  background: linear-gradient(135deg, var(--primary-a-08), var(--surface-tint));
}
.cap-usage-title { font-weight: 650; color: var(--text); margin-bottom: 8px; }
.cap-usage-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; }
.cap-chip {
  display: inline-flex; align-items: center; min-height: 24px;
  padding: 2px 10px; border-radius: 999px;
  border: 1px solid var(--primary-a-35); background: var(--primary-a-08);
  color: var(--primary); font-size: 12px; font-weight: 600;
}
.cap-usage-eg { color: var(--text-2); font-size: 12px; line-height: 1.5; }
/* 工具清单"待配置/未生效"默认折叠，降低理解成本 */
.tool-section-collapsible > summary { list-style: none; cursor: pointer; }
.tool-section-collapsible > summary::-webkit-details-marker { display: none; }
.tool-fold-hint::after { content: '展开 ▾'; font-size: 12px; }
.tool-section-collapsible[open] > summary .tool-fold-hint::after { content: '收起 ▴'; }
.tool-sub-label { padding: 4px 0 2px; border-top: 1px dashed var(--border); margin-top: 10px; font-weight: 500; }
.works-empty { max-width: 760px; }
.works-empty h3 { margin-top: 0; }
.works-section-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.works-section-head h3, .works-section-head p { margin: 0; }
.works-toolbar { display: grid; grid-template-columns: minmax(180px, 1fr) auto auto; gap: 8px; align-items: center; margin: 12px 0; }
.works-recommended { margin: 10px 0 12px; padding: 10px; border: 1px solid var(--primary-a-24); border-radius: 12px; background: var(--primary-a-06); }
.works-file-list { display: flex; flex-direction: column; gap: 0; margin-top: 8px; }
.works-file-row { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.works-file-row:last-child { border-bottom: none; }
.works-file-main { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.works-file-topline { min-width: 0; display: flex; align-items: center; gap: 7px; }
.works-file-sub { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; word-break: keep-all; }
.file-kind-icon {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: linear-gradient(180deg, var(--surface-tint-2), transparent);
  color: var(--text-2);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.04);
}
.file-kind-icon svg { display: block; }
.file-kind-icon.dir,
.file-kind-icon.code,
.file-kind-icon.style,
.file-kind-icon.image,
.file-kind-icon.doc,
.file-kind-icon.data,
.file-kind-icon.shell,
.file-kind-icon.archive {
  color: var(--text-2); border-color: var(--border); background: transparent;
}
.works-file-name { min-width: 0; display: flex; align-items: center; gap: 8px; }
.works-file-path { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.works-file-meta { white-space: nowrap; text-align: right; font-size: 12px; justify-self: end; }
.works-file-actions { display: inline-flex; justify-content: flex-end; align-items: center; gap: 6px; flex-wrap: wrap; }
.artifact-ext-badge {
  flex: 0 0 auto; padding: 1px 6px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface-tint); color: var(--text-2);
  font: 10px/1.45 var(--mono);
}
.works-file-public-badge {
  flex: 0 0 auto; padding: 1px 7px; border-radius: 999px;
  border: 1px solid var(--success-a-45, var(--primary-a-38)); background: var(--success-a-08, var(--primary-a-08));
  color: var(--success, var(--primary)); font-size: 10px; line-height: 1.5; font-weight: 600;
}
.works-file-open,
.works-file-action {
  flex: 0 0 auto; min-height: 28px; padding: 4px 9px; border-radius: 999px;
  border: 1px solid var(--primary-a-38); background: var(--primary-a-08);
  color: var(--primary); font-size: 12px; line-height: 1.35; cursor: pointer;
}
.works-file-action { font-family: inherit; }
.works-file-open:hover,
.works-file-action:hover { background: var(--primary-a-16); }
.works-file-action.danger { color: var(--text-2); border-color: var(--border); background: var(--surface-tint); }
.works-file-action.danger:hover { color: var(--error); border-color: var(--error-a-45); background: var(--error-a-08); }
.model-picker-card { margin: 12px 0 18px; }
.model-policy-row { display: grid; grid-template-columns: 220px 1fr; gap: 12px; align-items: center; padding: 10px 0; border-top: 1px solid var(--border); }
.model-policy-row:first-of-type { border-top: none; }
.project-page, .settings-page, .friends-page { width: 100%; max-width: 1040px; margin: 0 auto; }
.settings-stack { display: flex; flex-direction: column; gap: 12px; }
.settings-card { display: flex; flex-direction: column; gap: 8px; }
.settings-card h3 { margin: 0; }
.settings-card p { margin: 0; }
.settings-card-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 4px; }
/* .card 本身不带 margin，部分页面把多张 .settings-card 直接堆在 .settings-page 下（未逐个手写
   marginBottom/marginTop），会导致上一张的下边框和下一张的上边框直接贴在一起。这里统一补一条
   相邻卡片间距；已经手写了 marginTop/marginBottom 的调用点不受影响——普通文档流里相邻元素的
   外边距会合并取较大值，不会变成双倍间距。 */
.settings-page > .card + .card,
/* 「工具」页（#/tools）把「我的工具库」卡与「我的技能」卡直接堆在 .account-page 下，
   同样没有逐个手写间距，会出现上一张卡的下边框与下一张卡的上边框贴在一起的同类问题。 */
.account-page > .card + .card { margin-top: 16px; }

/* 租户 BYOK：状态和操作分层，密钥输入始终只出现在站内安全模态框。 */
.tenant-credentials-card { gap: 12px; }
.tenant-credentials-note { font-size: 12px; line-height: 1.55; }
.tenant-credentials-list { display: flex; flex-direction: column; gap: 8px; }
.tenant-credential-row { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-md); background: var(--surface-tint); }
.tenant-credential-main { min-width: 0; flex: 1 1 auto; }
.tenant-credential-desc { margin-top: 6px !important; font-size: 13px; line-height: 1.5; }
.tenant-credential-detail { margin-top: 4px !important; font-size: 12px; line-height: 1.5; }
.tenant-credential-actions { flex: 0 0 auto; flex-wrap: wrap; justify-content: flex-end; }
.tenant-credentials-empty { padding: 12px; border: 1px dashed var(--border); border-radius: var(--r-md); font-size: 13px; line-height: 1.6; }
.tenant-credential-security-hint { padding: 10px 12px; border: 1px solid var(--success-a-45); border-radius: var(--r-sm); background: var(--success-a-06); color: var(--text-2); font-size: 12px; line-height: 1.55; }
@media (max-width: 640px) {
  .tenant-credential-row { flex-direction: column; }
  .tenant-credential-actions { width: 100%; justify-content: stretch; }
  .tenant-credential-actions .btn { flex: 1 1 132px; }
}
/* 版本管理弹层：Git 配置默认折叠，把空间留给高频操作（保存并发布 / Pull / 全量更新） */
.version-config-details { border: 1px solid var(--border); border-radius: var(--r-lg, 10px); background: var(--panel-2, var(--bg)); }
.version-config-details > summary { list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 12px 14px; font-size: 13px; font-weight: 650; color: var(--text); }
.version-config-details > summary::-webkit-details-marker { display: none; }
.version-config-details > summary::after { content: '⌄'; font-size: 16px; color: var(--text-2); transition: transform .15s; }
.version-config-details[open] > summary::after { transform: rotate(180deg); }
.version-config-details > .muted { padding: 0 14px; }
.version-config-details .settings-card { border-top: 1px solid var(--border); border-radius: 0; }
.version-config-details .settings-card:first-of-type { margin-top: 4px; }
.version-config-summary-title { flex: 1; }
.setting-readonly { padding: 9px 10px; border: 1px solid var(--border); border-radius: 6px; background: var(--surface-tint); color: var(--text-2); font-family: var(--mono); font-size: 12px; }
.setting-copy { width: 100%; justify-content: flex-start; cursor: pointer; }
.settings-identity-card { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 12px; align-items: center; padding: 14px; border: 1px solid var(--border); border-radius: 16px; background: linear-gradient(135deg, var(--primary-a-08), var(--surface-tint)); margin-bottom: 12px; }
.settings-agent-avatar { width: 44px; height: 44px; border-radius: 14px; display: inline-flex; align-items: center; justify-content: center; background: var(--primary); color: var(--accent-fg); font-weight: 800; font-size: 18px; }
/* 头像可点更换：按钮本身透明贴合头像形状，右下角一个小铅笔徽标提示「这里能改」，
   悬停时头像描边高亮——不靠常驻文字标签占身份卡的空间，也不会让人以为纯展示不可交互。 */
.settings-agent-avatar-btn { position: relative; padding: 0; border: 0; background: transparent; cursor: pointer; border-radius: 14px; flex: 0 0 auto; }
.settings-agent-avatar-btn:hover .settings-agent-avatar,
.settings-agent-avatar-btn:focus-visible .settings-agent-avatar { box-shadow: 0 0 0 2px var(--primary-a-45); }
.settings-agent-avatar-edit {
  position: absolute; right: -3px; bottom: -3px; width: 18px; height: 18px; border-radius: 50%;
  display: grid; place-items: center; background: var(--panel); color: var(--text-3);
  border: 1px solid var(--border); box-shadow: 0 1px 3px rgba(0,0,0,.18);
}
.settings-agent-avatar-btn:hover .settings-agent-avatar-edit { color: var(--primary); border-color: var(--primary-a-45); }
.settings-desc-input {
  width: 100%; min-height: 54px; padding: 8px 10px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); color: var(--text); font: inherit; font-size: 13px; line-height: 1.5; resize: vertical;
}
.settings-desc-input:focus { outline: none; border-color: var(--primary-a-45); box-shadow: 0 0 0 2px var(--primary-a-12); }
/* 头像选择弹窗：预设图标做成 5 列小方格网格，图标+短标签，一屏看完不用滚动；
   自定义上传 / 恢复默认降为底部一条次要按钮行，不与「选图标」这个主任务抢视线。 */
.icon-picker-body { display: grid; gap: 4px; }
.icon-preset-grid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 8px; margin-bottom: 14px; }
.icon-preset-btn {
  display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 12px 4px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface); color: var(--text-2);
  cursor: pointer; font-size: 11px; transition: border-color .12s, color .12s, background .12s;
}
.icon-preset-btn:hover { border-color: var(--primary-a-45); color: var(--primary); background: var(--primary-a-08); }
.icon-preset-btn.active { border-color: var(--primary); color: var(--primary); background: var(--primary-a-12); font-weight: 600; }
.icon-picker-actions { display: flex; gap: 8px; flex-wrap: wrap; padding-top: 10px; border-top: 1px dashed var(--border); }
.settings-identity-main { min-width: 0; display: grid; gap: 4px; }
.settings-identity-main strong { font-size: 16px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 号码收进身份卡：点击即复制，做成低调的可点胶囊 */
.settings-identity-no {
  display: inline-flex; align-items: center; gap: 5px; justify-self: start;
  padding: 2px 8px; border: 1px solid var(--primary-a-35); border-radius: 999px;
  background: var(--primary-a-08); color: var(--primary); cursor: pointer;
  font: 700 13px/1.3 var(--mono); transition: background .15s, border-color .15s;
}
.settings-identity-no:hover { background: var(--primary-a-12); border-color: var(--primary-a-45); }
.settings-identity-no-copy { opacity: .7; }
.settings-identity-tags { display: flex; flex-wrap: wrap; gap: 6px; }
/* 类型只读：图标 + 名称的胶囊，明显不是可编辑输入框 */
.setting-type-readonly { display: inline-flex; align-items: center; gap: 8px; font-family: inherit; font-size: 13px; color: var(--text); }
.setting-type-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px; background: var(--primary-a-12); color: var(--primary);
}
/* 设置页内的跳转入口行（如编程类的 Git 配置）：整行可点，右侧箭头 */
.settings-entry-row {
  display: flex; align-items: center; gap: 12px; width: 100%; margin-top: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 12px;
  background: var(--surface-tint); color: var(--text); cursor: pointer; text-align: left;
  transition: border-color .15s, background .15s;
}
.settings-entry-row:hover { border-color: var(--primary-a-35); background: var(--panel-2); }
.settings-entry-icon {
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; height: 34px; flex-shrink: 0; border-radius: 10px;
  background: var(--primary-a-12); color: var(--primary);
}
.settings-entry-main { flex: 1; min-width: 0; display: grid; gap: 2px; }
.settings-entry-main strong { font-size: 14px; }
.settings-entry-main .muted { font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.settings-entry-arrow { flex-shrink: 0; color: var(--text-2); transform: rotate(-90deg); }
.settings-danger-details { gap: 0; }
.settings-danger-details summary { cursor: pointer; display: flex; justify-content: space-between; gap: 12px; align-items: center; list-style: none; }
.settings-danger-details summary::-webkit-details-marker { display: none; }
.settings-danger-details summary em { color: var(--text-2); font-size: 12px; font-style: normal; font-weight: 500; }
.settings-danger-list { display: grid; gap: 10px; margin-top: 12px; }
.settings-danger-row { display: flex; justify-content: space-between; align-items: center; gap: 12px; padding: 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); }
.settings-danger-row.warn { border-color: var(--warn-a-35); background: var(--warn-a-06); }
.settings-danger-row.danger { border-color: var(--error-a-35); background: var(--error-a-08); }
.settings-danger-row p { margin: 2px 0 0; font-size: 12px; }
.cap-page { max-width: 1040px; }
.cap-grid { display: grid; grid-template-columns: minmax(280px,.9fr) minmax(360px,1.2fr); gap: 12px; align-items: start; }
.skill-template { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); }
.skill-template:last-child { border-bottom: none; }
.skill-enabled-row { display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; padding: 10px 0; border-bottom: 1px solid var(--border); }
.skill-enabled-row:last-child { border-bottom: none; }
.skill-enabled-row > div:first-child { min-width: 0; }
.skill-enabled-row strong { font-weight: 600; }
.skill-enabled-row .muted { margin-top: 2px; font-size: 12px; line-height: 1.5; word-break: break-word; }
.skill-enabled-row pre { grid-column: 1 / -1; margin: 6px 0 0; }

/* ── Agent 工具页：创作者视角的工具开关 + 设置 + 内置能力 ── */
.tool-guide { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin: 8px 0 12px; }
.tool-guide-card { display: grid; gap: 6px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 14px; background: linear-gradient(180deg, var(--surface-tint), transparent); transition: border-color .18s ease, transform .18s ease; }
.tool-guide-card:hover { border-color: var(--primary-a-35); transform: translateY(-1px); }
.tool-guide-top { display: flex; align-items: center; gap: 8px; }
.tool-guide-num { display: inline-grid; place-items: center; width: 20px; height: 20px; border-radius: 999px; background: var(--text); color: var(--bg); font-size: 11px; font-weight: 700; flex-shrink: 0; }
.tool-guide-card strong { font-size: 13px; font-weight: 650; }
.tool-guide-card span { color: var(--text-2); font-size: 12px; line-height: 1.55; }
.cap-card { padding-top: var(--sp-3, 10px); }
/* 筛选条：全部 / 已开启 / 需要处理 / 可开启 + 搜索 */
.cap-filterbar { position: sticky; top: 0; z-index: 3; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; padding: 8px 0; margin-bottom: 4px; background: var(--surface, var(--bg)); border-bottom: 1px solid var(--border); }
.cap-filter-sep { width: 1px; align-self: stretch; margin: 2px 4px; background: var(--border); }
/* 分组（本 Agent 的工具 / 内置能力） */
.cap-group { margin-top: 14px; }
.cap-group-head { display: flex; align-items: baseline; gap: 8px; padding: 4px 2px; }
.cap-group-head strong { font-size: 14px; font-weight: 650; }
.cap-count { font-size: 11px; color: var(--text-2); background: var(--surface-tint); border: 1px solid var(--border); border-radius: 999px; padding: 0 8px; line-height: 1.6; }
.cap-group-note { font-size: 12px; }
.cap-rows { margin-top: 4px; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
/* Ownership 小节表头（平台提供 / 预置 / 我的） */
.cap-sub { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin: 14px 2px 2px; }
.cap-sub-label { font-size: 12px; font-weight: 650; color: var(--text); }
.cap-sub-note { font-size: 11px; line-height: 1.5; }
/* 行：主体（来源·名称·状态 / 描述 / 原因）+ 操作，三区对齐 */
.cap-row { display: grid; grid-template-columns: 1fr auto; gap: 12px; align-items: center; padding: 12px 14px; border-bottom: 1px solid var(--border); transition: background .15s ease; }
.cap-row:last-child { border-bottom: none; }
.cap-row:hover { background: var(--surface-tint); }
.cap-row-readonly:hover { background: var(--surface-tint); }
.cap-row-readonly { background: var(--surface-tint); border-left: 3px solid var(--primary-a-35); }
.cap-row-main { min-width: 0; }
.cap-row-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.cap-name { font-weight: 600; font-size: 13px; }
.cap-desc { margin-top: 3px; font-size: 12px; line-height: 1.5; color: var(--text-2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cap-reason { margin-top: 4px; font-size: 12px; line-height: 1.45; color: var(--warn); background: var(--warn-a-06); border-radius: 6px; padding: 3px 8px; }
.cap-row-action { display: flex; align-items: center; justify-content: flex-end; flex-shrink: 0; }
.cap-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; justify-content: flex-end; }
/* 来源标签：中性描边，不承载状态语义 */
.cap-source { flex-shrink: 0; font-size: 11px; line-height: 1.5; padding: 0 8px; border-radius: 999px; border: 1px solid var(--border); background: var(--surface-tint); color: var(--text-2); white-space: nowrap; }
/* 状态胶囊：色块 + 形状标记（色觉障碍冗余）+ 文案。一色一义 */
.cap-status { display: inline-flex; align-items: center; gap: 4px; flex-shrink: 0; font-size: 11px; line-height: 1.6; padding: 0 8px; border-radius: 999px; border: 1px solid transparent; white-space: nowrap; }
.cap-status-mark { font-size: 9px; line-height: 1; }
/* 「需要设置」是唯一需要用户动手的状态，给状态点一个克制的呼吸提示引导注意；其余状态保持静止避免噪音。 */
.cap-status--pending .cap-status-mark { animation: capPendingPulse 1.8s ease-in-out infinite; transform-origin: center; }
@keyframes capPendingPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .cap-status--pending .cap-status-mark { animation: none; }
  .tool-guide-card, .cap-row { transition: none; }
  .tool-guide-card:hover { transform: none; }
}
.cap-empty { padding: 28px 12px; text-align: center; font-size: 13px; }
/* 默认已具备（折叠，只读，普通用户视图） */
.cap-defaults { margin-top: 14px; border: 1px dashed var(--border); border-radius: 12px; background: var(--surface-tint); }
.cap-defaults > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 12px 14px; font-size: 13px; color: var(--text-2); }
.cap-defaults > summary::-webkit-details-marker { display: none; }
.cap-defaults > summary::before { content: '▸'; color: var(--text-2); font-size: 11px; }
.cap-defaults[open] > summary::before { content: '▾'; }
.cap-defaults-title { font-weight: 600; color: var(--text); }
.cap-defaults-body { padding: 0 14px 12px; }
.cap-defaults-body .cap-rows { background: var(--surface, var(--bg)); }
/* 配置管理：按生效范围分组的工具条 */
.cfgmgr-bar { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 12px; }
.cfgmgr-scope { display: flex; flex-direction: column; gap: 5px; }
.cfgmgr-scope-label { font-size: 11px; font-weight: 600; letter-spacing: .02em; }
.cfgmgr-scope-btns { display: flex; gap: 6px; flex-wrap: wrap; }
/* 配置中心：同一类型内纵向堆叠多张卡（对话/能力模型、我的默认/本 Agent） */
.cfg-stack { display: flex; flex-direction: column; gap: 14px; }
/* 「本 Agent · 专属」层级小标题：与「我的默认」卡物理隔离 */
.cfg-scope-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; padding: 6px 2px 0; border-top: 1px dashed var(--border); margin-top: 2px; }
.cfg-scope-title { font-size: 13px; font-weight: 650; color: var(--text); }
.cfg-scope-note { font-size: 11px; line-height: 1.5; }
/* 「我的默认（跨所有 Agent）」警示头：提醒此处编辑会波及所有引用它的 Agent */
.cfg-scope-head.cfg-scope-warn { border-top-color: rgba(245,158,11,.45); background: rgba(245,158,11,.06); border-radius: 8px; padding: 6px 8px; }
.cfg-scope-head.cfg-scope-warn .cfg-scope-title { color: var(--warn); }
@media (max-width: 640px) {
  .tool-guide { grid-template-columns: 1fr; }
  .cap-row { grid-template-columns: 1fr; align-items: flex-start; }
  .cap-row-action { justify-content: flex-start; }
  .cap-desc { white-space: normal; }
}

/* 钉一下（对话内）队列记录与状态标签的通用样式（status chip / 图标按钮等仍复用） */
.todo-panel { display: grid; gap: 10px; }
.todo-panel-intro { font-size: 12px; line-height: 1.6; margin: 0; }
.todo-add-wrap { display: grid; gap: 8px; }
.todo-add-input { width: 100%; resize: vertical; font-size: 13px; line-height: 1.5; min-height: 74px; }
.todo-add-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 8px; }
.todo-panel .todo-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 6px 4px; border-bottom: 1px solid var(--border); }
.todo-summary { display: flex; flex-wrap: wrap; gap: 6px; padding: 2px 0; }
.todo-summary-chip, .todo-status-chip { display: inline-flex; align-items: center; border-radius: 999px; border: 1px solid var(--border); background: var(--surface-tint); color: var(--text-2); font-size: 11px; line-height: 1.45; padding: 1px 7px; white-space: nowrap; }
.todo-summary-chip.queued, .todo-status-chip.queued { color: var(--primary); border-color: var(--primary-a-35); background: var(--primary-a-08); }
.todo-summary-chip.running, .todo-status-chip.running { color: var(--primary); border-color: var(--primary-a-45); background: var(--primary-a-12); }
.todo-summary-chip.error, .todo-status-chip.error { color: var(--error); border-color: var(--error-a-35); background: var(--error-a-08); }
.todo-summary-chip.done, .todo-status-chip.done { color: var(--text-2); opacity: .8; }
.todo-status-chip.new { color: var(--text); }
.todo-status-chip.queued-other { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.todo-list { display: flex; flex-direction: column; gap: 4px; }
.todo-group-title { margin: 8px 2px 2px; color: var(--text-2); font-size: 11px; font-weight: 700; letter-spacing: .02em; }
.todo-row { display: grid; grid-template-columns: auto 1fr auto; align-items: flex-start; gap: 10px; padding: 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); }
.todo-row.selected { background: var(--primary-a-08); border-color: var(--primary-a-35); }
.todo-row-error { border-color: var(--error-a-35); background: var(--error-a-06); }
.todo-row-queued, .todo-row-running { border-color: var(--primary-a-24); }
.todo-row .todo-check { display: flex; align-items: center; padding-top: 3px; cursor: pointer; }
.todo-row .todo-body { min-width: 0; }
.todo-row-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 5px; }
.todo-row .todo-content { white-space: pre-wrap; word-break: break-word; line-height: 1.55; }
.todo-row .todo-content.todo-st-in_progress { color: var(--primary); }
.todo-row .todo-content.todo-st-error { color: var(--error); }
.todo-row .todo-content.todo-st-completed { color: var(--text-2); opacity: .55; text-decoration: line-through; }
.todo-error-note { margin-top: 4px; color: var(--error); font-size: 11px; line-height: 1.45; }
.todo-actions { display: inline-flex; align-items: center; justify-content: flex-end; gap: 4px; flex-wrap: wrap; max-width: 190px; }
.todo-action-text { min-height: 28px; padding: 3px 9px; border: 1px solid var(--border); border-radius: 999px; background: transparent; color: var(--text-2); font-size: 12px; cursor: pointer; }
.todo-action-text:hover { color: var(--text); background: var(--surface-tint-2); }
.todo-action-text.primary { color: var(--primary); border-color: var(--primary-a-35); background: var(--primary-a-08); }
.todo-action-text.on { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.todo-icon-btn, .todo-pin { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; border-radius: 8px; border: none; background: transparent; color: var(--text-2); cursor: pointer; opacity: .65; transition: all .15s; flex-shrink: 0; }
.todo-icon-btn:hover, .todo-pin:hover { background: var(--surface-tint); opacity: .95; }
.todo-icon-btn.danger:hover { color: var(--error); background: var(--error-a-08); }
.todo-completed-toggle { align-self: flex-start; margin-top: 6px; }
.todo-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 28px 0; color: var(--text-2); }

/* 「钉一下」面板：核心区（主）/ 队列记录（次）主次分明 */
.pin-panel { display: grid; gap: 16px; }
/* 核心区：撰写 + 单一主操作，用强调卡片突出为主区域 */
.pin-compose { display: grid; gap: 10px; padding: 14px; border: 1px solid var(--primary-a-24); border-radius: 14px; background: var(--primary-a-08); }
.pin-compose-hint { margin: 0; font-size: 12px; line-height: 1.6; color: var(--text-2); }
.pin-compose-input { width: 100%; resize: vertical; min-height: 74px; font-size: 13px; line-height: 1.55; }
.pin-compose-actions { display: flex; justify-content: flex-end; }
/* 队列记录：弱化为次级区域 */
.pin-records { display: grid; gap: 8px; }
.pin-records-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; padding: 0 2px 6px; border-bottom: 1px solid var(--border); }
.pin-records-title { font-size: 12px; font-weight: 700; letter-spacing: .02em; color: var(--text-2); }
.pin-records-counts { font-size: 11px; color: var(--text-2); white-space: nowrap; }
.pin-list { display: flex; flex-direction: column; gap: 6px; }
.pin-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: flex-start; gap: 10px; padding: 9px 11px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-tint); }
.pin-row-error { border-color: var(--error-a-35); background: var(--error-a-06); }
.pin-row-running, .pin-row-queued { border-color: var(--primary-a-24); }
.pin-row-body { min-width: 0; display: grid; gap: 5px; }
.pin-row-meta { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.pin-row-content { white-space: pre-wrap; word-break: break-word; line-height: 1.55; font-size: 13px; }
.pin-row-content.is-completed { color: var(--text-2); opacity: .55; text-decoration: line-through; }
.pin-row-actions { display: inline-flex; align-items: center; gap: 2px; }
.pin-empty { display: flex; flex-direction: column; align-items: center; justify-content: center; padding: 26px 0; color: var(--text-2); }
.disk-mount-row { display: flex; align-items: center; gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--border); }
.disk-mount-row:last-child { border-bottom: none; }
.danger-zone { margin-top: 28px; border-color: var(--error-a-45); }

/* tool page */
.tool-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-2); flex: none; }
.tool-dot.ok { background: var(--success); }
.tool-dot.off { background: var(--border); }
.tool-dot.opt { background: var(--warn); }
.tool-dot.sys { background: var(--primary); }
.tool-dashboard-body { display: grid; gap: 14px; }
.tool-dashboard-intro { padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint); color: var(--text-2); font-size: 13px; line-height: 1.55; }
.tool-metrics { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; }
.tool-metric { display: grid; gap: 2px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel); }
.tool-metric span { color: var(--text-2); font-size: 11px; }
.tool-metric strong { color: var(--text); font-size: 20px; line-height: 1.1; }
.tool-metric em { color: var(--text-2); font-size: 11px; font-style: normal; }
.tool-metric.ok strong { color: var(--success); }
.tool-metric.warn strong { color: var(--warn); }
.tool-metric.risk strong { color: var(--error); }
.tool-section { display: grid; gap: 8px; }
.tool-section-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 10px; }
.tool-section-head strong { display: block; font-size: 14px; }
.tool-section-head p { margin: 2px 0 0; color: var(--text-2); font-size: 12px; line-height: 1.45; }
.tool-card { display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--panel); }
.tool-card-strip { width: 4px; align-self: stretch; border-radius: 3px; flex-shrink: 0; }
.tool-card-main { min-width: 0; flex: 1; }
.tool-card-title { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.tool-card-name { margin-top: 2px; color: var(--text-2); font-family: var(--mono); font-size: 11px; }
.tool-card-desc { margin-top: 4px; color: var(--text-2); font-size: 12px; line-height: 1.5; }
.tool-card-actions { display: flex; align-items: center; justify-content: flex-end; gap: 6px; flex-wrap: wrap; flex-shrink: 0; }
.tool-empty { padding: 10px 12px; border: 1px dashed var(--border); border-radius: 12px; background: var(--surface-tint); font-size: 13px; }
.tool-governance-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.tool-card-wrap { flex: 1; min-width: 0; }
.tool-sub { margin: 16px 0 6px; font-size: 13px; color: var(--text); }
.tool-sub:first-of-type { margin-top: 4px; }
.tool-mem-foot { display: flex; justify-content: space-between; align-items: center;
  margin-top: 16px; padding-top: 10px; border-top: 1px solid var(--border); font-size: 12px; }
.tool-runstate { display: flex; justify-content: space-between; align-items: center;
  margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--border); }
.tool-runstate-info { display: flex; align-items: center; gap: 8px; font-size: 13px; }
.danger-zone h3 { margin-top: 0; color: var(--error); }
.danger-zone .btn { margin-top: 12px; }
.danger-actions { display: flex; flex-wrap: wrap; gap: 8px; }
.delete-files-option { display: flex; align-items: center; gap: 8px; margin: 12px 0 6px; color: var(--text); font-size: 13px; }

.page-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; margin-bottom: 16px; }
.page-head > :first-child { min-width: 0; }
.page-head > .row { flex-wrap: wrap; justify-content: flex-end; }
.page-head h2 { margin: 0 0 4px; }
.page-head p { margin: 0; }
.account-page { max-width: 1120px; margin: 0 auto; }
.account-grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 12px; align-items: start; }
.account-wide { grid-column: 1 / -1; }
.account-hero { display: flex; gap: 16px; align-items: center; }
.account-avatar-lg {
  width: 64px; height: 64px; border-radius: 18px; background: linear-gradient(135deg, var(--primary), var(--accent));
  color: white; display: flex; align-items: center; justify-content: center; font-size: 28px; font-weight: 700;
}
.account-hero-main h3,
.account-panel h3 { margin: 0 0 8px; }
.account-tags { display: flex; gap: 8px; margin-bottom: 8px; }
.account-panel { min-height: 160px; }
.panel-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; margin-bottom: 12px; }
.panel-head p { margin: 0; }
.kv { display: grid; grid-template-columns: 96px 1fr; gap: 8px 12px; }
.kv span { color: var(--text-2); }
.account-overview-grid { display: grid; grid-template-columns: 1fr minmax(260px, .9fr); gap: 12px; align-items: stretch; }
.binding-status { border: 1px dashed var(--border); border-radius: 8px; padding: 12px; background: var(--surface-tint); }
.binding-status.ok { border-style: solid; border-color: var(--success-a-45); background: var(--success-a-08); }
.invite-box { min-height: 96px; }
/* 邀请区是「偶尔用一次」的工具条，不是本页主体（主体是下面的使用者列表）。
   故意保持单层：无渐变、无内层卡、无阴影，只用一条细边框圈定范围，避免喧宾夺主。 */
.agent-invite-bar {
  display: grid; gap: 10px; margin-bottom: 14px; padding: 14px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--panel);
}
.agent-invite-bar-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.agent-invite-bar-head h3 { margin: 0; font-size: 15px; display: flex; align-items: center; gap: 8px; min-width: 0; }
/* 号码贴在标题后作为身份标识（弱化），真正可复制的号码在下面的操作行里。 */
.agent-invite-no-inline { color: var(--text-3); font: 500 12px/1 var(--mono); letter-spacing: .04em; }
.agent-invite-joinmode-select { flex: 0 0 auto; max-width: 42vw; }
.agent-invite-joinmode-hint { font-size: 12px; line-height: 1.5; margin-top: -2px; }
.agent-invite-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.agent-invite-or { color: var(--text-3); font-size: 12px; }
/* 号码本身就是可点复制的对象：做成 chip 而不是「大号码框 + 独立复制按钮」两件套。 */
.agent-invite-no-chip {
  padding: 5px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--surface-tint); color: var(--text); cursor: pointer;
  font: 650 13px/1.2 var(--mono); letter-spacing: .05em;
  transition: border-color .15s var(--ease-standard), color .15s var(--ease-standard);
}
.agent-invite-no-chip:hover:not(:disabled) { border-color: var(--primary-a-35); color: var(--primary); }
.agent-invite-no-chip:disabled { opacity: .5; cursor: not-allowed; }
.agent-invite-foot { font-size: 12px; line-height: 1.5; }
.agent-invite-status.pending { color: var(--primary); font-weight: 600; }
/* 「外部 N」直接影响计费归属，做成可 hover 查看说明的 pill，而不是纯文本，避免歧义。 */
.agent-invite-external-count {
  display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px;
  background: var(--primary-a-12); color: var(--primary); font-size: 12px; font-weight: 600; cursor: help;
}
/* 未生成邀请时不留空占位：min-height 会让这条常驻工具条凭空高出一截。 */
.agent-invite-result:not(:empty) { margin-top: 2px; }
.agent-invite-loading { display: flex; align-items: center; min-height: 40px; color: var(--text-2); font-size: 13px; }
.invite-link-card { border: 1px solid var(--success-a-45); background: var(--success-a-08); border-radius: 12px; padding: 12px; }
.invite-link-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.invite-link-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 8px; align-items: center; margin-top: 10px; }
.invite-link-input { width: 100%; min-width: 0; font-family: var(--mono); font-size: 12px; }
.invite-link-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 8px; }
.agent-invite-generated { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: center; }
.agent-invite-qr-frame {
  display: inline-flex; align-items: center; justify-content: center; width: 132px; height: 132px;
  padding: 7px; border: 1px solid var(--border); border-radius: 12px; background: #fff;
}
.agent-invite-qr { display: block; width: 116px; height: 116px; object-fit: contain; border-radius: 6px; }
.agent-invite-status { margin-top: 8px; font-size: 12px; line-height: 1.5; color: var(--text-2); }
.agent-invite-status.success { color: var(--success); font-weight: 600; }
.agent-invite-status.error { color: var(--error); }
/* 使用者/待处理申请行：主信息（用户名+ID+角色）与副信息（时间/计费）字号字重明显拉开，避免读起来像一长串平铺文本。 */
.member-row { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.member-row-primary { font-size: 14px; font-weight: 650; }
.member-row-secondary {
  display: flex; align-items: center; gap: 6px; margin-top: 4px;
  font-size: 12px; color: var(--text-2);
}
.member-payer-pill {
  display: inline-flex; align-items: center; padding: 1px 7px; border-radius: 999px;
  background: var(--surface-tint); border: 1px solid var(--border); color: var(--text-2); font-size: 11px;
}
.member-payer-pill.is-owner-pay { background: var(--primary-a-12); border-color: var(--primary-a-35); color: var(--primary); font-weight: 600; }
.join-request-card { display: flex; justify-content: space-between; align-items: center; gap: 10px; }
.success-box { border: 1px solid var(--success-a-45); background: var(--success-a-08); border-radius: 8px; padding: 12px; }
.account-actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.model-summary { display: grid; grid-template-columns: 160px repeat(3, minmax(0, 1fr)); gap: 10px; align-items: stretch; }
.model-summary > div { border: 1px solid var(--border); border-radius: 8px; padding: 10px; background: var(--surface-tint); }
.model-summary strong { display: block; }
.model-chip { min-width: 0; }
.model-chip strong,
.model-chip span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tag-picker { display: flex; flex-wrap: wrap; gap: 7px; }
.tag-picker-chip {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 30px; padding: 5px 10px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface-tint); color: var(--text-2); cursor: pointer; font-size: 12px;
  transition: background .15s var(--ease-standard), border-color .15s var(--ease-standard), color .15s var(--ease-standard), transform .16s var(--ease-spring);
}
.tag-picker-chip:hover { color: var(--text); border-color: var(--primary-a-45); background: var(--primary-a-08); transform: translateY(-1px); }
.tag-picker-chip.active { color: var(--primary); border-color: var(--primary-a-45); background: var(--primary-a-12); }
.tag-picker-chip:disabled { opacity: .58; cursor: not-allowed; transform: none; }
.tag-picker-check { font-weight: 700; }
.model-library-modal { display: flex; flex-direction: column; gap: 14px; }
.model-library-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.model-library-layout { display: grid; grid-template-columns: minmax(260px, .9fr) minmax(320px, 1.1fr); gap: 12px; align-items: start; }
.model-library-pane { border: 1px solid var(--border); border-radius: 10px; padding: 12px; background: var(--surface-tint); }
.model-library-pane h3,
.model-stats-wrap h3 { margin: 0 0 10px; }
.model-library-list { display: flex; flex-direction: column; gap: 8px; max-height: 360px; overflow: auto; }
.model-profile-row {
  width: 100%; display: grid; grid-template-columns: 1fr auto; gap: 10px; align-items: center; text-align: left;
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); padding: 10px; cursor: pointer;
}
.model-profile-row:hover,
.model-profile-row.active { background: var(--panel-2); border-color: var(--primary-a-55); }
.model-profile-main,
.model-profile-metrics { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.model-profile-main strong,
.model-profile-main span,
.model-profile-metrics span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.model-profile-metrics { text-align: right; }
.model-form-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; }
.model-form-head h3 { margin: 0; }
.model-stats-wrap { border-top: 1px solid var(--border); padding-top: 12px; }
.model-stat-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; margin-bottom: 12px; }
.model-stat-card { border: 1px solid var(--border); border-radius: 10px; padding: 10px; background: var(--surface-tint); min-width: 0; }
.model-stat-card strong,
.model-stat-card span,
.model-stat-card small { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.model-stats-section { margin-top: 12px; overflow: auto; }
.model-stats-section table { min-width: 560px; }
.model-library-item {
  width: 100%; display: flex; flex-direction: column; gap: 2px; text-align: left;
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel); color: var(--text); padding: 10px; cursor: pointer;
}
.model-library-item:hover,
.model-library-item.active { background: var(--panel-2); border-color: var(--primary-a-55); }
.model-library-item.disabled { opacity: .55; }
.category-tool-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px 12px; margin-top: 4px; }
.category-tool-check { display: flex; align-items: center; gap: 8px; font-weight: 400; }
@media (max-width: 900px) {
  .shell { grid-template-rows: 48px 1fr; }
  .shell.chat-mode { grid-template-rows: 1fr; }
  .topbar { display: flex; }
  .shell.chat-mode .topbar { display: none !important; }
  .brand-mark-mobile { display: inline-flex; border: none; background: transparent; border-radius: 8px; gap: 5px; }
  .brand-mark-mobile .brand-mark-glyph { width: 24px; height: 24px; border-radius: 6px; font-size: 13px; }
  .account-grid, .account-overview-grid, .model-summary, .cap-grid, .model-library-layout, .model-stat-grid, .tool-metrics { grid-template-columns: 1fr; }
  .tool-card { flex-direction: column; }
  .tool-card-strip { width: 100%; height: 4px; }
  .tool-card-actions { justify-content: flex-start; }
  .settings-identity-card, .settings-danger-row, .settings-field-grid { grid-template-columns: 1fr; }
  .settings-danger-row { flex-direction: column; align-items: stretch; }
  .account-wide { grid-column: auto; }
  .model-policy-row { grid-template-columns: 1fr; }
  .settings-card-head { flex-direction: column; }
  .main { grid-template-columns: 1fr; grid-template-rows: 1fr; }
  .side { display: none; }
  .content { padding: 12px; min-height: 0; overflow-y: auto; }
  .chat-shell { height: calc(100% + 24px); margin: -12px; }
  .chat-header { flex-wrap: nowrap; }
  .chat-header-actions { display: flex; flex: 1 1 0; min-width: 0; justify-content: flex-end; }
  .mobile-hide { display: none !important; }
  .msg.user .msg-content { max-width: 88%; }
}

/* lists */
.card { background: var(--panel); border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; }
.list { display: flex; flex-direction: column; gap: 8px; }

/* task page */
.task-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; height: calc(100vh - 120px); }
.timeline { overflow: auto; }
.event { background: var(--panel); border: 1px solid var(--border); border-radius: 6px;
  padding: 8px 10px; margin-bottom: 6px; }
.event .ev-h { display: flex; gap: 8px; align-items: center; font-size: 12px; color: var(--text-2); }
.event pre { margin: 6px 0 0; white-space: pre-wrap; font: 12px/1.5 var(--mono); }
.event.tool_use { border-left: 3px solid var(--primary); }
.event.tool_result.ok { border-left: 3px solid var(--success); }
.event.tool_result.bad { border-left: 3px solid var(--error); }
.event.text { border-left: 3px solid var(--text-dim); }
.event.status { background: var(--panel-2); }
.event.error { border-left: 3px solid var(--error); }
.event.pipeline.ok { border-left: 3px solid var(--success); }
.event.pipeline.bad { border-left: 3px solid var(--error); }
.event.commit { border-left: 3px solid var(--warn); }

.term { background: var(--term-bg); border: 1px solid var(--border); border-radius: 6px;
  padding: 8px; overflow: auto; font: 12px/1.5 var(--mono); white-space: pre-wrap; }

/* drawer */
.drawer-mask {
  /* 必须高于窄屏会话浮层（.chat-main z-1200）：否则窄屏点「⋯」时橱窗被会话盖住，点了看不到。 */
  position: fixed; inset: 0; z-index: 1300; display: flex;
  background: rgba(0,0,0,.46);
}
.drawer-mask.left { justify-content: flex-start; }
.drawer-mask.right { justify-content: flex-end; }
.drawer-panel {
  width: min(320px, 88vw); height: 100%; background: var(--panel); border: 1px solid var(--border);
  box-shadow: 0 18px 60px rgba(0,0,0,.42); display: flex; flex-direction: column; outline: none;
  overflow: hidden; /* 圆角裁剪内部矩形层（body/nav-page），杜绝左下圆角被直角背景"破角" */
}
.drawer-panel.left { border-left: 0; border-radius: 0; animation: drawerInLeft .16s ease-out; }
.drawer-panel.right { border-right: 0; border-radius: 0; animation: drawerInRight .16s ease-out; }
@keyframes drawerInLeft { from { transform: translateX(-18px); opacity: .7; } to { transform: translateX(0); opacity: 1; } }
@keyframes drawerInRight { from { transform: translateX(18px); opacity: .7; } to { transform: translateX(0); opacity: 1; } }
.drawer-head,
.drawer-footer { flex: 0 0 auto; display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 12px 14px; border-bottom: 1px solid var(--border); }
/* 固定 head 高度：栈底「品牌(两行)」与子页「返回+标题(一行)」内容高度不同，
   若 head 高度随内容变化，push/pop 时下方内容会整体竖向跳动。固定高度（仿 iOS 恒定导航栏）根治。 */
.drawer-head { min-height: 56px; box-sizing: border-box; }
/* 主菜单抽屉：head 左边距与列表头像左边缘对齐（body 12px + 行内 4px = 16px）。 */
.main-menu-drawer .drawer-head { padding-left: 16px; }
.drawer-footer { border-top: 1px solid var(--border); border-bottom: 0; justify-content: flex-end; flex-wrap: wrap; }
.drawer-head h3 { margin: 0; font-size: 16px; }
/* Header chrome 稳定层：品牌态 / 子页态重叠在同一固定槽位，只做 opacity/transform，
   不再切 display，避免进入「账号与设置」时 header 布局重排带来的视觉跳动。 */
.drawer-head-left { flex: 1 1 auto; min-width: 0; height: 32px; position: relative; }
.drawer-head-brand,
.drawer-subhead {
  position: absolute; left: 0; top: 50%; transform: translateY(-50%) translateZ(0);
  display: flex; align-items: center; min-width: 0;
  transition: opacity .16s var(--ease-standard), transform .22s var(--ease-spring);
}
.drawer-subhead { gap: 2px; max-width: 100%; }
.drawer-head-left.has-brand.at-root .drawer-head-brand,
.drawer-head-left:not(.has-brand) .drawer-subhead { opacity: 1; pointer-events: auto; transform: translateY(-50%) translateZ(0); }
.drawer-head-left.has-brand.at-root .drawer-subhead,
.drawer-head-left.has-brand.in-subpage .drawer-head-brand { opacity: 0; pointer-events: none; transform: translateY(-50%) translateX(-4px) translateZ(0); }
.drawer-head-left.has-brand.in-subpage .drawer-subhead { opacity: 1; pointer-events: auto; transform: translateY(-50%) translateZ(0); }
.drawer-head-title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-close {
  width: 30px; height: 30px; border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--text-2); cursor: pointer; font-size: 20px; line-height: 1;
}
.drawer-close:hover { background: var(--panel-2); color: var(--text); border-color: var(--border); }
.drawer-body { flex: 1 1 auto; min-height: 0; overflow: hidden; padding: 0; position: relative; }
/* 抽屉内 push 导航：固定视口 + 每页独立滚动 + 方向语义转场，模拟 iOS Navigation push/pop */
.drawer-nav-stack { position: relative; min-height: 100%; overflow: hidden; }
.drawer-nav-page {
  /* 根因A修复：外层只负责「位置/位移」，不带 padding/width 等参与 layout 的盒模型属性，
     确保动画起止帧几何尺寸完全一致（padding 下沉到内层 .drawer-nav-page-inner）。
     根因C修复：用 inset:0 锁定尺寸，不再叠加 width:100%，避免与 box-sizing 叠加产生亚像素差。 */
  position: absolute; inset: 0; overflow: auto;
  scrollbar-gutter: stable; /* 预留滚动条槽位：不同高度子页间切换时滚动条出现/消失不再引起横向位移跳动 */
  background: var(--panel); z-index: 1;
  overscroll-behavior: contain;
  /* 强制独立合成层并固定 3D 上下文：动画全程在 GPU 合成层完成，落帧不回流主文档。 */
  transform: translateZ(0); backface-visibility: hidden; will-change: transform, opacity;
  contain: layout paint; /* 把布局/绘制限制在本页内，子页内容变化不影响兄弟页与外层 */
}
/* padding 下沉到内层：动画作用于外层 transform，内层尺寸恒定，杜绝盒模型起止帧差异。
   底部留白加大并兼容安全区：最后一个分组不贴底/不被圆角裁剪，移动端不被手势条遮挡。 */
.drawer-nav-page-inner { padding: 4px 12px max(16px, env(safe-area-inset-bottom)); box-sizing: border-box; min-height: 100%; }
.drawer-nav-page.active { z-index: 2; }
.drawer-nav-page:not(.active) { pointer-events: none; }
/* push：新页面从右侧滑入，带轻微投影；旧页面向左退让 */
.drawer-nav-page.slide-in-from-right { z-index: 3; animation: nativePushIn .32s var(--ease-spring) forwards; }
.drawer-nav-page.slide-out-to-left { z-index: 1; animation: nativePushUnder .32s var(--ease-standard) forwards; pointer-events: none; }
/* pop：当前页面向右滑出；前一页从左侧景深恢复 */
.drawer-nav-page.slide-out-to-right { z-index: 4; animation: nativePopOut .26s var(--ease-standard) forwards; pointer-events: none; }
.drawer-nav-page.slide-in-from-left { z-index: 2; animation: nativePopUnder .26s var(--ease-standard) forwards; }
/* 所有关键帧的 transform 都显式带 translateZ(0)：保证动画全程处于同一 GPU 合成层，
   落帧（移除 class）时不发生「合成层销毁 → 主文档回流重栅格化」的亚像素微跳（根因B）。 */
@keyframes nativePushIn { from { transform: translateX(100%) translateZ(0); box-shadow: -24px 0 36px rgba(0,0,0,.18); } to { transform: translateX(0) translateZ(0); box-shadow: 0 0 0 rgba(0,0,0,0); } }
@keyframes nativePushUnder { from { transform: translateX(0) translateZ(0) scale(1); opacity: 1; } to { transform: translateX(-22%) translateZ(0) scale(.985); opacity: .62; } }
@keyframes nativePopOut { from { transform: translateX(0) translateZ(0); box-shadow: -18px 0 30px rgba(0,0,0,.14); } to { transform: translateX(100%) translateZ(0); box-shadow: -18px 0 30px rgba(0,0,0,0); } }
@keyframes nativePopUnder { from { transform: translateX(-22%) translateZ(0) scale(.985); opacity: .62; } to { transform: translateX(0) translateZ(0) scale(1); opacity: 1; } }
.drawer-back {
  display: inline-flex; align-items: center; gap: 1px;
  min-width: 52px; margin: 0 2px 0 -5px; padding: 4px 6px 4px 0;
  border: 0; border-radius: 10px; background: transparent;
  color: var(--text-2); cursor: pointer;
  opacity: 0; pointer-events: none; visibility: hidden;
  transform: translateX(-4px) translateZ(0);
  transition: opacity .16s var(--ease-standard), transform .2s var(--ease-spring), background .15s var(--ease-standard), visibility 0s linear .16s;
}
.drawer-back.visible { opacity: 1; pointer-events: auto; visibility: visible; transform: translateX(0) translateZ(0); transition-delay: 0s; }
.drawer-back-chevron { font-size: 30px; line-height: 18px; font-weight: 300; margin-top: -1px; }
.drawer-back-label { font-size: 16px; line-height: 20px; font-weight: 400; letter-spacing: -.01em; }
.drawer-back:hover { background: var(--panel-2); }
.drawer-back:active { transform: translateX(-2px) scale(.98); }
.drawer-back:focus-visible { outline: none; box-shadow: var(--focus-ring); }
.drawer-list { max-height: none; overflow: visible; }
.drawer-section { margin-top: 0; padding: 12px 0; border-bottom: 1px solid var(--border); }
.drawer-section:last-child { border-bottom: none; }
.drawer-section-title { margin: 0 0 6px; color: var(--text-2); font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; padding: 0 4px; }
.drawer-nav-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%; border: none; border-radius: 8px; background: transparent;
  color: var(--text); cursor: pointer; text-align: left;
  padding: 8px 4px; font-size: 14px;
}
.drawer-nav-item:hover { background: var(--panel-2); }
.drawer-nav-item.active {
  background: var(--primary-a-08);
  color: var(--primary);
  font-weight: 650;
}
/* 微信入口的语义态：待恢复（warn）/ 断开（danger） */
.drawer-nav-item.warn { color: var(--warn); }
.drawer-nav-item.warn:hover { background: var(--warn-a-22); }
.drawer-nav-item.danger { color: var(--text-2); }
.drawer-nav-item.danger:hover { color: var(--error); background: var(--error-a-08); }
.drawer-quick-actions { display: flex; gap: 8px; margin: 2px 0 8px; }
.drawer-stat-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin: 8px 0 2px; }
.drawer-stat-grid > div { border: 1px solid var(--border); border-radius: 8px; padding: 8px; background: var(--surface-tint); min-width: 0; }
.drawer-stat-grid strong,
.drawer-stat-grid span { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-drawer-hero { display: flex; gap: 10px; align-items: center; padding: 0 4px; }
.account-drawer-hero .account-avatar-lg { width: 40px; height: 40px; border-radius: 10px; font-size: 18px; flex-shrink: 0; }
.account-drawer-hero .account-hero-main { min-width: 0; flex: 1; }
.account-drawer-hero .account-hero-main h3 { margin: 0; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.account-drawer-hero .account-hero-main h3 + div { margin-top: 2px; }
.account-drawer-hero .account-tags { gap: 4px; flex-wrap: wrap; }
.account-drawer-hero .account-tags .tag { font-size: 10px; padding: 1px 6px; }

/* ── 账号入口 footer（钉在抽屉底部：拇指可达区，常驻可达） ──
   主菜单抽屉主任务是浏览/切换 Agent，账号设置为低频入口，钉在抽屉视口底部形成 footer：
   长 Agent 列表滚动时它始终留在拇指可达的底部热区，无需滚到列表末尾。
   根页内层改为纵向 flex，account-section 用 margin-top:auto 在短列表时也贴底；
   position:sticky 让长列表滚动时它吸附在视口底部，上方列表从其下方滚过。 */
.main-menu-drawer .drawer-nav-page-inner { display: flex; flex-direction: column; }
/* 仅根页（栈底，drawer-body 的第一个 nav-page）改为纵向 flex，让 account-section 贴底；
   子页（账号与设置等）保持 block 流，避免 flex 不折叠 margin 带来的间距差异。 */
.main-menu-drawer .drawer-nav-page ~ .drawer-nav-page .drawer-nav-page-inner { display: block; }
.main-menu-drawer .account-section {
  position: sticky; bottom: 0; z-index: 2;
  margin-top: auto;                    /* 短列表时把 footer 推到视口底部 */
  background: var(--panel);            /* 不透明底：上方列表从其下滚过时不穿帮 */
  padding: 8px 4px 4px;
  border-top: 1px solid var(--border);
  box-shadow: 0 -6px 10px -8px rgba(0,0,0,.18); /* 轻微抬起，与滚动列表分层 */
}

/* ── 账号入口行（静默行：低频入口，与 Agent 行同节奏的扁平透明行） ──
   抽屉主任务是浏览/切换 Agent，账号设置下沉到列表末尾并降级：去渐变/边框，
   头像缩到 28px 中性灰仅作识别锚点，主文案改为身份，ID 降为次要小字，
   积分右置默认 muted，仅在余额耗尽时整行 danger 高亮回收注意力。 */
.account-id-card {
  width: 100%; display: flex; align-items: center; gap: 10px;
  /* 与 .drawer-project-card 同一头像栅格：内层 page padding 12px + 行 padding 4px = 16px。 */
  padding: 8px 4px; border-radius: 8px; cursor: pointer; text-align: left;
  color: var(--text); /* button 默认不继承文字色，显式设置避免暗色下变黑 */
  background: transparent; border: none;
  transition: background .15s ease;
}
.account-id-card:hover { background: var(--panel-2); }
.account-id-card.danger { background: var(--error-a-08); }
.account-id-card.danger:hover { background: var(--error-a-16); }
.account-id-avatar {
  flex-shrink: 0; width: 28px; height: 28px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(127,127,127,.32); color: #fff;
}
.account-id-main { min-width: 0; flex: 1; }
.account-id-value { font-size: 13px; font-weight: 500; line-height: 1.3; color: var(--text); }
.account-id-sub { margin-top: 1px; font-size: 11px; color: var(--text-2); }
.account-id-credit { flex-shrink: 0; font-size: 11px; color: var(--text-2); font-variant-numeric: tabular-nums; }
.account-id-credit.danger { color: var(--error); font-weight: 600; }
.text-danger { color: var(--error) !important; }
.account-id-chevron { flex-shrink: 0; color: var(--text-2); font-size: 18px; line-height: 1; opacity: .5; }


/* 通讯录风格 Agent 行 */
.drawer-project-card,
.drawer-link-row {
  width: 100%; border: none; border-radius: 0; background: transparent;
  color: var(--text); cursor: pointer; text-align: left;
}
.drawer-project-card {
  display: flex; flex-direction: row; align-items: center; gap: 10px; padding: 10px 4px;
  border-radius: 8px;
}
.drawer-project-card:hover,
.drawer-link-row:hover { background: var(--surface-tint); }
.drawer-project-card.current { background: transparent; }
.drawer-project-card strong,
.drawer-project-card span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Agent 头像圆 */
.drawer-agent-avatar {
  width: 36px; height: 36px; border-radius: 8px; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  font-size: 15px; font-weight: 700; color: #fff;
}
.drawer-agent-info { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.drawer-agent-info strong { font-size: 14px; line-height: 1.3; }
.drawer-agent-info span { font-size: 11px; color: var(--text-2); line-height: 1.2; }
.drawer-agent-meta { display: inline-flex; align-items: center; gap: 4px; min-width: 0; max-width: 100%; }
.drawer-agent-id {
  display: inline-flex; align-items: center; padding: 1px 5px; border-radius: 999px;
  background: var(--primary-a-08); color: var(--primary) !important; border: 1px solid var(--primary-a-22);
  font-family: var(--mono); font-weight: 650; line-height: 1.25;
}
.drawer-agent-sep { opacity: .45; flex: 0 0 auto; }
.drawer-agent-kind { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.drawer-link-row { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 10px 4px; margin-top: 0; }
.drawer-link-row.active { color: var(--primary); }
.drawer-row-arrow { color: var(--text-2); font-size: 16px; flex-shrink: 0; margin-left: auto; line-height: 1; }

/* 抽屉内 push 子页面：表单与信息适配窄宽 */
.drawer-body .kv { grid-template-columns: 80px 1fr; gap: 6px 10px; font-size: 13px; }
.drawer-body .account-actions { gap: 6px; }
.drawer-body .admin-cat-item { padding: 8px 10px; gap: 8px; }
.drawer-body .admin-cat-main strong { font-size: 13px; }
.drawer-body .invite-box { min-height: 60px; }
.drawer-body .binding-status { padding: 10px; }
.drawer-body .wechat-qr { width: 200px; }

/* ===== 底部 Sheet（类 iOS Action Sheet / Bottom Sheet） ===== */
.sheet-mask {
  position: fixed; inset: 0; z-index: 1200; display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0,0,0,.5); animation: sheetFadeIn .15s ease-out;
}
@keyframes sheetFadeIn { from { opacity: 0; } to { opacity: 1; } }
.sheet-panel {
  width: 100%; max-width: 480px; max-height: 88vh; max-height: 88dvh; background: var(--panel);
  border-radius: 16px 16px 0 0; border: 1px solid var(--border); border-bottom: 0;
  display: flex; flex-direction: column; animation: sheetSlideUp .25s cubic-bezier(.32,.72,0,1);
  padding-bottom: env(safe-area-inset-bottom);
  transition: max-height .2s ease-out;
}
@keyframes sheetSlideUp { from { transform: translateY(100%); } to { transform: translateY(0); } }
.sheet-handle {
  width: 36px; height: 5px; border-radius: 3px; background: var(--border);
  margin: 8px auto 0; flex: 0 0 auto;
}
.sheet-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 12px 16px 8px; flex: 0 0 auto;
}
.sheet-head h3 { margin: 0; font-size: 16px; }
.sheet-close {
  width: 30px; height: 30px; border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--text-2); cursor: pointer; font-size: 20px; line-height: 1;
}
.sheet-close:hover { background: var(--panel-2); color: var(--text); border-color: var(--border); }
.sheet-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 0 16px 16px; }
.sheet-footer { flex: 0 0 auto; padding: 8px 16px 12px; display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; border-top: 1px solid var(--border); }

/* modal */
.modal-mask {
  position: fixed; inset: 0; background: rgba(0,0,0,.6); display: flex;
  align-items: center; justify-content: center; z-index: 1300;
}
.modal {
  background: var(--panel); border: 1px solid var(--border); border-radius: 8px;
  width: 480px; max-width: 90vw; max-height: 85vh; max-height: 85dvh; display: flex; flex-direction: column;
}
.modal.md { width: min(580px, 92vw); }
.modal.lg { width: min(1040px, 94vw); }
/* 文件编辑器：工具栏 + 编辑区（CodeMirror/textarea）+ 可选 markdown 分屏预览 */
.modal.editor-fullscreen { position: fixed; inset: 0; width: 100vw; max-width: none; height: 100vh; height: 100dvh; max-height: none; border-radius: 0; }
.modal.editor-fullscreen .body { flex: 1; }
.file-editor { display: flex; flex-direction: column; gap: 10px; min-height: 0; }
.file-editor-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.file-editor-name { font-family: var(--mono); font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.file-editor-tools { display: inline-flex; align-items: center; gap: 8px; flex-shrink: 0; }
.editor-share { display: inline-flex; align-items: center; gap: 8px; }
.editor-tool-btn { padding: 4px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--panel); color: var(--text); cursor: pointer; font-size: 12px; }
.editor-tool-btn:hover { background: var(--panel-2); }
.editor-tool-btn.active { border-color: var(--primary); color: var(--primary); background: var(--primary-a-08); }
.editor-share-toggle { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--panel); color: var(--text-2); cursor: pointer; font-size: 12px; }
.editor-share-toggle .editor-share-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--text-2); }
.editor-share-toggle.on { border-color: var(--success-a-45, var(--primary)); color: var(--success, var(--primary)); background: var(--success-a-06, var(--primary-a-08)); }
.editor-share-toggle.on .editor-share-dot { background: var(--success, var(--primary)); }
.code-editor-wrap { display: grid; grid-template-columns: 1fr; gap: 10px; min-height: 0; }
.code-editor-wrap.show-preview { grid-template-columns: 1fr 1fr; }
.code-editor-host { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; min-height: 320px; max-height: 62vh; }
.modal.editor-fullscreen .code-editor-host { max-height: none; height: 100%; }
.modal.editor-fullscreen .code-editor-wrap { flex: 1; min-height: 0; height: 100%; }
.code-editor-host .cm-editor { height: 100%; max-height: inherit; font-size: 13px; }
.code-editor-host .cm-scroller { overflow: auto; }
.code-editor-fallback { width: 100%; min-height: 320px; max-height: 62vh; resize: vertical; border: 0; padding: 10px 12px; background: var(--panel); color: var(--text); font: 13px/1.55 var(--mono); }
.modal.editor-fullscreen .code-editor-fallback { max-height: none; height: 100%; }
.md-preview { border: 1px solid var(--border); border-radius: 8px; padding: 12px 14px; overflow: auto; min-height: 320px; max-height: 62vh; background: var(--panel); font-size: 14px; line-height: 1.65; }
.modal.editor-fullscreen .md-preview { max-height: none; }
.md-preview :is(h1,h2,h3) { margin: 12px 0 8px; }
.md-preview pre { background: var(--surface-tint); padding: 10px 12px; border-radius: 8px; overflow: auto; }
.md-preview code { font-family: var(--mono); font-size: 12px; }
.md-preview img { max-width: 100%; }
@media (max-width: 640px) { .code-editor-wrap.show-preview { grid-template-columns: 1fr; } }
.modal h3 { margin: 0; padding: 0; font-size: 16px; }
.modal-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 14px 16px; border-bottom: 1px solid var(--border);
}
.modal-close {
  width: 30px; height: 30px; border: 1px solid transparent; border-radius: 8px;
  background: transparent; color: var(--text-2); cursor: pointer; font-size: 20px; line-height: 1;
}
.modal-close:hover { background: var(--panel-2); color: var(--text); border-color: var(--border); }
.modal .body { padding: 14px 16px; overflow: auto; }
.modal .footer { padding: 12px 16px; border-top: 1px solid var(--border);
  display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; }
/* 无按钮的弹层（如图片放大预览）不需要一条空白的底栏。 */
.modal .footer:empty { display: none; padding: 0; border-top: 0; }

/* 图片/视频放大预览（缩略图点击放大复用通用 modal）。 */
.media-lightbox-body { display: flex; align-items: center; justify-content: center; }
.media-lightbox-media { max-width: 100%; max-height: 76vh; display: block; margin: 0 auto; border-radius: var(--r-lg); background: #000; }

/* toast */
#toast-root { position: fixed; right: 16px; top: 16px; z-index: 2000; display: flex; flex-direction: column; gap: 8px; }
.toast { padding: 8px 14px; background: var(--panel); border: 1px solid var(--border);
  border-left: 3px solid var(--primary); border-radius: 6px; min-width: 240px; }
.toast.success { border-left-color: var(--success); }
.toast.error { border-left-color: var(--error); }
.toast.warn { border-left-color: var(--warn); }

/* tabs */
.tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--border); margin-bottom: 12px; }
.tab { padding: 8px 14px; cursor: pointer; color: var(--text-2); border-bottom: 2px solid transparent; }
.tab.active { color: var(--text); border-bottom-color: var(--primary); }

/* table */
table { width: 100%; border-collapse: collapse; }
th, td { padding: 8px 10px; border-bottom: 1px solid var(--border); text-align: left; }
th { color: var(--text-2); font-weight: 500; font-size: 12px; }
tr:hover td { background: var(--panel-2); }

/* ============================================================
 * Codex 风格对话页
 * ============================================================ */

/* 整个 chat shell：单列布局，撑满 .content 高度 */
.chat-shell {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  height: calc(100% + 32px);            /* content padding 上下各 16px，负 margin 抵消 */
  margin: -16px -20px;                  /* 抵消 .content 的 padding 撑满 */
}
/* 三栏：中栏(工作区/社区) + 右栏(会话)。最终列宽由末尾覆写层统一定义。*/
.chat-shell.ws-collapsed,
.chat-shell.ws-open { grid-template-columns: minmax(0, 1fr) var(--chat-w, 480px); }
.workspace-panel {
  position: relative; min-width: 0; min-height: 0;
  /* 注意：--surface 变量在主题里【未定义】（只有 --surface-tint/-raised），裸 var(--surface) 会解析为透明，
     导致移动端浮层主体透明、透出遮罩（“下面透明一块”）。用 --bg 兜底保证不透明。 */
  border-left: 1px solid var(--border); background: var(--surface, var(--bg));
  display: flex; flex-direction: column; overflow: hidden;
}
.workspace-panel-head {
  display: flex; align-items: center; gap: 8px; padding: 10px 12px;
  border-bottom: 1px solid var(--border); background: var(--panel); min-height: 44px;
}
.workspace-panel-head .ws-name { display: flex; align-items: center; gap: 5px; min-width: 0; flex: 1; font-weight: 600; font-size: 13px; }
.ws-name .ws-name-icon { flex: 0 0 auto; }
.ws-name .ws-name-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 下拉小箭头 ⌄：暗示「点这里可切换/管理文件夹」，与收起面板的横向 ❯ 从形状上区分 */
.ws-name .ws-name-caret { flex: 0 0 auto; font-size: 11px; line-height: 1; color: var(--text-2); transform: translateY(-1px); }
/* 文件夹名可点击 = 进入文件夹管理（切换 / 新建 / 重命名 / 删除），做成明确的可点标签 */
.ws-name-btn { cursor: pointer; border-radius: 7px; padding: 3px 7px; margin: 0 -4px; border: 1px solid transparent; transition: background .15s, border-color .15s; }
.ws-name-btn:hover { background: var(--surface-tint); border-color: var(--border); }
.ws-name-btn:hover .ws-name-caret { color: var(--text); }
/* 头部层级切换：「工作区 / 社区」两个并列内容空间。类型 chips 从属于选中的空间，
   因此层级切换本身做成头部 tabs（与类型 chips 的视觉权重拉开）。 */
.ws-scope-tabs { gap: 2px; }
.ws-scope-tab {
  appearance: none; cursor: pointer; border: 1px solid transparent; border-radius: 7px;
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto;
  padding: 3px 8px; background: transparent; color: var(--text-2);
  font: inherit; line-height: 1.3; white-space: nowrap;
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
.ws-scope-tab:hover { background: var(--surface-tint); color: var(--text); }
.ws-scope-tab.is-active { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); border-color: color-mix(in srgb, var(--accent) 35%, transparent); }
.ws-scope-tab-count {
  padding: 0 5px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-3); background: color-mix(in srgb, var(--text) 6%, transparent);
}
.ws-scope-tab.is-active .ws-scope-tab-count { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
/* 「发现」角标表示"我没看过的新内容"（不是总数）。它只需要完成一件事：让人知道值得去看一眼。
   所以形态是一个小红点，不是带数字的实心徽标——数字徽标的视觉重量与"未读消息待处理"同级，
   在一个逛内容的入口上会被读成待办压力（用户原话：提示太强烈了）。具体条数由 aria-label /
   title 承载（读屏与悬浮仍可得），版面上不占位。进入发现视图后 JS 会清零并隐藏它。
   注意：此处必须覆盖 .ws-scope-tab-count 的 padding/min-width，否则空文本会撑成一个小胶囊。 */
.ws-scope-tab.has-unseen .ws-scope-tab-count {
  padding: 0; min-width: 0;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--error); color: transparent;
  /* 与「发现」二字留一点呼吸位，并略微上提贴近文字顶部，读起来是"标记"而不是"另一个字符"。 */
  margin-left: 1px; align-self: flex-start; margin-top: 2px;
  /* 深色/暖纸底上都要能与 tab 自身背景分离，但只用一圈极窄的纸色描边，不做外发光。 */
  box-shadow: 0 0 0 1.5px var(--panel);
}
/* 暖阅读档下，选中态原样借用全局强调色（深青绿）——即便已按色温校准，仍是暖纸面上
 * 唯一一块冷色，用户反馈"暖底里有一块蓝"。选中态改用纸面抬升+ 边框来表达高亮，
 * 不依赖强调色本身；其余主题（含链接、按钮等强调色用法）不受影响，仍保留冷色跳出效果。 */
html.sepia .ws-scope-tab.is-active {
  color: var(--text); background: var(--panel); border-color: var(--border);
  font-weight: 600; box-shadow: var(--shadow-1);
}
/* 计数胶囊在暖纸档改用纸面色阶，避免借用冷强调色。
   :not(.has-unseen) 是必需的：未读小红点也复用 .ws-scope-tab-count，若被这条规则命中，
   红点会在暖纸主题下被刷成灰底（同权重但位置在后），未读提示直接消失。 */
html.sepia .ws-scope-tab.is-active:not(.has-unseen) .ws-scope-tab-count { color: var(--text); background: var(--surface-tint-2); }
/* 卡内脚注：卡片自己的最后一行（社区条目的分享者/时间/版本 + 删除）。
   这里不再有"卡 + 卡下独立 meta 行"两块DOM——那种拼法即使把间隙调到 0、底色描边全对齐，
   两块之间仍有一条实体接缝，读者要判断这行字属于上面还是下面那张卡，列表被逐条切断。
   现在它是卡片内容的一部分：只用一条内嵌虚线把它与正文分层（弱于卡片自身描边一档），
   底色/描边/圆角全部由卡片本体负责，脚注不再声明任何独立的容器外观。 */
.ws-card-footnote {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-top: 10px; padding-top: 7px;
  border-top: 1px dashed color-mix(in srgb, var(--card-border) 75%, transparent);
  font-size: 11.5px; line-height: 1.5;
}
/* ws-pack-text-btn 默认隐藏、仅卡片 hover 时显形（为标题行的悬浮动作设计）；脚注里的删除
   是常驻信息行的一部分，且触屏没有 hover——必须一直可见，否则按钮在 DOM 里用户永远看不到。 */
.ws-card-footnote .ws-pack-text-btn { visibility: visible; opacity: 1; }
/* 等高网格里脚注贴卡底（同 .ws-pack-actions 的既有做法）：同一行的卡内容多少不同，
   脚注若跟随正文浮在中间，一行里几张卡的分享信息会各在一个高度，扫读时无法横向对齐。
   margin-top:auto 会吃掉基础的 10px 间距，所以内容饱满时靠 padding-top 保证最小分隔。 */
.prompt-delivery-card.is-list .ws-card-footnote { margin-top: auto; padding-top: 9px; }
/* 单一类型发现视图：上方没有吸顶筛选条，首张卡自己补回那段呼吸位（见 renderCommunitySection 的 flush）。 */
.ws-community.is-flush { margin-top: 12px; }
.ws-community-empty { padding: 4px 2px; }

/* ══ 信息流版式（「发现」列表，.prompt-delivery-card.is-feed）══
   与工作区列表卡的分工：工作区是"找我自己已知的东西"，紧凑行更快；
   发现是"逛别人的东西"，用户靠画面决定点不点，所以封面必须有足够尺寸。 */
.prompt-delivery-card.is-feed { padding: 0; overflow: hidden; gap: 0; }
/* 封面：4:5 竖版。这类内容以竖屏 9:16 / 2:3 为主，16:9 会把竖图上下裁掉大半；
   4:5 对横竖素材都只做轻微裁切，且在多栏网格里高度可控（不会出现一张长条卡）。 */
.ws-feed-cover {
  position: relative; width: 100%; aspect-ratio: 4 / 5; overflow: hidden;
  background: var(--panel-2); flex: none;
}
.ws-feed-cover-media { display: block; width: 100%; height: 100%; object-fit: cover; }
/* 图片加载重试后仍失败：降级为占位标记，不留原生裂图（同 prompt-shot-thumb.is-placeholder 语汇）。 */
.ws-feed-cover.is-broken { display: flex; align-items: center; justify-content: center; }
.ws-feed-cover-mark { font-size: 22px; line-height: 1; color: var(--text-3); opacity: .55; }
/* 视频角标：静止首帧与静态图在流里看起来完全一样，不标记用户无从判断这条是视频。 */
.ws-feed-cover-badge {
  position: absolute; left: 8px; bottom: 8px; display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 7px; border-radius: 999px; font-size: 10.5px; font-weight: 600;
  color: #fff; background: rgba(0, 0, 0, .55); backdrop-filter: blur(4px);
}
/* 封面之外的文字区自己承担内边距（卡片 padding 已归零，否则封面无法出血铺满）。 */
.prompt-delivery-card.is-feed > .prompt-delivery-head { padding: 10px 12px 0; }
.prompt-delivery-card.is-feed > .ws-pack-summary { padding: 0 12px; margin-top: 5px; }
.prompt-delivery-card.is-feed > .prompt-pack-meta { padding: 0 12px; margin-top: 7px; }
/* margin-top 用 auto（而非固定值）：与 .is-list 的贴底逻辑保持一致（见上条注释）——
   信息流卡等高但每张卡摘要行数、有无封面各不相同，脚注若不贴底，同一行几张卡的
   「照这个做」按钮/作者信息会停在不同高度，扫读时对不齐。 */
.prompt-delivery-card.is-feed > .ws-card-footnote { margin: auto 12px 10px; }
/* 无封面（文章/文档等纯文本内容）：不塞灰色占位图——占位图不提供信息，还让整列卡看起来"图挂了"。
   改为把文字规格提上来：标题更大、摘要给到 4 行，让文字本身成为这张卡的画面。 */
.prompt-delivery-card.is-feed:not(:has(.ws-feed-cover)) > .prompt-delivery-head { padding-top: 12px; }
.prompt-delivery-card.is-feed:not(:has(.ws-feed-cover)) .prompt-delivery-title h3 { font-size: 15px; line-height: 1.4; }
.prompt-delivery-card.is-feed:not(:has(.ws-feed-cover)) > .ws-pack-summary {
  -webkit-line-clamp: 4; line-clamp: 4; font-size: 12.5px;
}

/* ── 作者身份行 ── */
.ws-feed-meta { display: flex; align-items: center; gap: 7px; min-width: 0; }
.ws-feed-author {
  display: inline-flex; align-items: center; gap: 5px; min-width: 0;
  padding: 0; border: 0; background: none; cursor: pointer; color: var(--text-2);
  font-size: 11.5px; font-weight: 600;
}
.ws-feed-author:hover { color: var(--text-1); }
.ws-feed-author-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 10ch; }
/* 头像色块由 JS 按 userId 派生（同一个人恒定同色，用户靠颜色记住作者）。 */
.ws-feed-avatar {
  flex: none; width: 18px; height: 18px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; font-size: 9px; font-weight: 700; letter-spacing: -.02em;
}
.ws-feed-time { font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-feed-acts { display: flex; align-items: center; gap: 6px; flex: none; }
.ws-feed-uses { font-size: 11px; }
/* 「照这个做」是卡面主动作（发现页唯一的价值出口），所以保留文字、常驻可见（触屏没有 hover）；
   但视觉权重必须压到最低一档：填充色块在单张卡上叫"强调"，在信息流里重复二十次就只剩噪音
   ——用户的原话是"满屏按钮，感觉太重了"。所以静息态无底色、无描边，只有墨色文字 + 一个
   识别用的图标；抬高权重的事交给 hover/键盘焦点，此时它是唯一被指向的对象，强调才成立。

   颜色为什么不是--accent：本仓库有"去蓝收敛"规范（见文件末尾小节）——浅色/暖纸主题下
   交互强调统一走墨色 --ink 或中性灰，只有语义色（success/warn/error）保留。--accent 是冷蓝，
   打在暖纸底上就是一块跳出来的冷斑，用户能直接看出"这块颜色和别处不是一套"。 */
.ws-feed-use-btn {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 6px; font-size: 11.5px; font-weight: 600; border-radius: 7px;
  color: var(--ink); background: none; border: 1px solid transparent;
}
.ws-feed-use-btn:hover, .ws-feed-use-btn:focus-visible {
  background: color-mix(in srgb, var(--ink) 8%, transparent);
  border-color: color-mix(in srgb, var(--ink) 22%, transparent);
}
/* 图标只做识别锚点，不参与语义（纯图标按钮用户猜不出是"拿去用"）：
   尺寸压到与文字同高，避免它比文字更抢眼。 */
.ws-feed-use-btn svg { flex: none; opacity: .85; }
.ws-feed-del-btn { padding: 3px 6px; color: var(--text-3); }
.ws-feed-del-btn:hover { color: var(--error); }
/* 「只看 TA 分享的」筛选提示：隐式筛选必须给一条可撤销的说明，
   否则用户会以为其他内容消失了。同「去蓝收敛」规范走中性灰，不用冷蓝。 */
.ws-feed-author-filter {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  margin-bottom: 8px; padding: 6px 10px; border-radius: 8px;
  background: color-mix(in srgb, var(--ink) 6%, var(--elev-2));
  border: 1px solid var(--line-2);
  font-size: 11.5px;
}
.ws-feed-author-filter .btn { padding: 2px 8px; font-size: 11px; }
/* 「原始文件」视图的管理员平台文件开关：小字号弱化按钮，常驻可见（不是卡片 hover 动作）。 */
.ws-files-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.ws-platform-files-toggle { font-size: 11px; padding: 2px 8px; color: var(--text-3); }
.ws-platform-files-toggle.is-on { color: var(--accent); }

/* ═══ 沉浸式阅读层 ═══
   内容详情平铺工作区面板（替代圆角弹窗）：列表层保持挂载被覆盖，
   返回时滚动位置/筛选/搜索原样保留。滑入滑出 200ms 内完成，不抢戏。
   阅读面用 elev-2（与会话主轨同级）：与工作区 elev-1 拉开明度差，
   阅读区一眼是"翻开的一页"，而不是与背景融为一体的同温层。 */
.ws-read-layer {
  position: absolute; inset: 0; z-index: 30;
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
  background: var(--elev-2);
  transform: translateX(18px); opacity: 0; pointer-events: none;
  transition: transform var(--dur-base) var(--ease-standard), opacity var(--dur-base) var(--ease-standard);
}
.ws-read-layer.is-open { transform: none; opacity: 1; pointer-events: auto; }
.ws-read-head {
  flex: 0 0 auto; display: flex; align-items: center; gap: 8px;
  height: 42px; min-height: 42px; padding: 0 8px 0 6px;
  border-bottom: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
}
/* 返回按钮带上一层标题（见 renderReadingPane）：给宽度上限并截断，
   否则一个长内容名会把中间的标题位挤到没有，头部变成"两个标题打架"。 */
.ws-read-back {
  flex: 0 0 auto; font-size: 12px; padding: 4px 8px;
  max-width: 34%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ws-read-title {
  flex: 1 1 auto; min-width: 0; font-size: 13px; font-weight: 600;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  transition: opacity var(--dur-fast, .15s) var(--ease-standard, ease);
}
/* 折叠态：内容里已经有同名大标题时，头部这份让位（见 syncReadingPaneTitleMode）。
   只降透明度、不退出布局——它占着flex 中间的伸缩位，抽出 DOM 流会让右侧动作区横向跳动。 */
.ws-read-title.is-collapsed { opacity: 0; }
.ws-read-actions { flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px; }
/* 阅读层头部动作：紧凑 ghost（图标+文字）。实心 primary 大按钮在窄头部里太突兀。 */
.ws-read-action {
  font-size: 11.5px; font-weight: 500; padding: 3px 8px; min-height: 0;
  border-radius: 7px; color: var(--text-2);
}
.ws-read-action:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.ws-read-action .icon { margin-right: 2px; }
.ws-read-close { flex: 0 0 auto; font-size: 15px; padding: 2px 9px; }
/* 「复制」这类正向动作与「×」这类退出动作之间加一道分隔：8px 的等距会让它们读作
   同一组按钮，鼠标从复制滑过去很容易顺手点掉 ×（代价是丢掉整条浏览路径）。 */
.ws-read-actions:not(:empty) + .ws-read-close {
  margin-left: 4px; padding-left: 13px;
  border-left: 1px solid color-mix(in srgb, var(--border) 60%, transparent);
  border-radius: 0 8px 8px 0;
}
.ws-read-body { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 12px 14px 24px; }
/* 打开阅读层时正文拿焦点（为了空格/方向键能直接翻页），但它不是可交互控件，
   不该画出焦点环——只在键盘 Tab 主动走到它时才提示。 */
.ws-read-body:focus { outline: none; }
/* 阅读规格：长文本最大行长约束，等宽提示词块行高放宽。 */
.ws-read-body .ws-detail-sheet { max-width: 72ch; margin-inline: auto; }
.ws-read-body .ws-prompt-editor-ta { line-height: 1.7; }
/* 阅读内容像"纸张"从阅读面微微浮起：长文本有明确承载面，不贴背景。 */
.ws-read-body .ws-detail-sheet,
.ws-read-body .ws-prompt-editor {
  background: var(--elev-3);
  border: 1px solid var(--card-border);
  border-radius: 12px;
  padding: 16px 18px;
  box-shadow: var(--card-shadow), var(--elev-edge);
}
/* 头部统计：产品数 / 未提交数，弱化呈现不抢名称主体 */
.ws-picker-section { font-size: 11px; color: var(--text-2); letter-spacing: .04em; margin: 4px 2px 6px; }
.workspace-panel-body { flex: 1; overflow-y: auto; min-height: 0; padding: 8px 10px; container-type: inline-size; container-name: wsbody; }
/* 类型切换器：从占58px 高的卡片网格降级为一行 chips。
   它的职责只是「切换看哪类内容」，不是内容本身——做成卡片会与下方真正的内容卡争夺视觉权重，
   且副标题（"不分类型，全部列出"/"最近 xxx"）属于可推断信息，删掉后首屏能多露出一行内容。*/
.ws-type-chips {
  display: flex; flex-wrap: wrap; gap: 6px;
  margin: 0 0 10px;
}
.ws-type-chip {
  appearance: none; cursor: pointer;
  display: inline-flex; align-items: center; gap: 6px; min-width: 0;
  padding: 5px 10px; border: 1px solid transparent; border-radius: 999px;
  font-size: 12px; line-height: 1.3; color: var(--text-2);
  background: var(--surface-tint);
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
.ws-type-chip:hover { color: var(--text); background: var(--btn-hover); }
.ws-type-chip-icon { display: inline-flex; align-items: center; flex: 0 0 auto; opacity: .75; }
.ws-type-chip-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; font-weight: 600; }
.ws-type-chip-count {
  flex: 0 0 auto; padding: 0 5px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-3); background: color-mix(in srgb, var(--text) 6%, transparent);
}
.ws-type-chip.is-active {
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 42%, transparent);
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.ws-type-chip.is-active .ws-type-chip-icon { opacity: 1; }
.ws-type-chip.is-active .ws-type-chip-count { color: var(--accent); background: color-mix(in srgb, var(--accent) 16%, transparent); }
/* 原始文件是排查用的技术视图，弱化到最低权重：不参与日常扫读，但仍可点达。
   不用 margin-left:auto顶到行尾——chips 换行时会被推出可视区甚至被裁切。 */
.ws-type-chip.is-technical { color: var(--text-3); background: transparent; }
.ws-type-chip.is-technical:hover { color: var(--text-2); background: var(--surface-tint); }

/* 筛选条单行化：类型 chips 是可横滚的 rail（类型再多也不换行——换行才是吸顶高度跳动的根源），
   搜索默认紧凑、聚焦展开，rail 自动收缩让位；排序图标钉在行尾。
   行高【固定】28px（不是 min-height）：搜索/排序按内容量显隐时整行高度不变，消除跳跃感——
   不能让任何一个子元素（如 .btn 基类默认 padding 推出的 34px）把条撑高。
   左侧 4px 内缩：首个 chip 不与面板内容区左缘贴齐，与下方卡片左边距形成对齐节奏。
   边框画在外层 wrap 上、图标与输入框都是 flex 项：绝对定位的图标在容器宽度被压缩时会脱离输入框，
   这里用纯 flex 结构从根上排除错位。 */
.ws-filter-bar { display: flex; align-items: center; gap: 6px; margin: 0 0 10px; min-width: 0; height: 28px; padding-left: 4px; }
.ws-filter-bar .ws-type-chips {
  flex: 1 1 auto; min-width: 0; margin: 0; height: 28px;
  flex-wrap: nowrap; overflow-x: auto; overflow-y: hidden; scrollbar-width: none;
}
.ws-filter-bar .ws-type-chips::-webkit-scrollbar { display: none; }
.ws-filter-bar .ws-type-chip { flex: 0 0 auto; height: 28px; padding-top: 0; padding-bottom: 0; }
.ws-list-search-wrap {
  display: flex; align-items: center; gap: 6px;
  flex: 0 0 auto; width: 112px; min-width: 0; height: 28px;
  padding: 0 9px;
  border: 1px solid var(--border); border-radius: 8px;
  background: var(--input-bg);
  transition: width var(--dur-base) var(--ease-standard), border-color var(--dur-fast) var(--ease-standard);
}
.ws-list-search-wrap:focus-within { width: 176px; border-color: var(--accent); }
.ws-list-search-icon { flex: 0 0 auto; display: inline-flex; align-items: center; color: var(--text-3); }
.ws-list-search {
  flex: 1 1 auto; min-width: 0; width: auto;
  padding: 0; border: 0; outline: none;
  /* search 类型控件自带浏览器外观与聚焦环，不重置会在我们的边框外再叠一圈，形成双层描边。 */
  appearance: none; -webkit-appearance: none; box-shadow: none;
  font-size: 12px; color: var(--text); background: transparent;
}
.ws-list-search:focus, .ws-list-search:focus-visible { outline: none; box-shadow: none; }
.ws-list-search::-webkit-search-cancel-button { cursor: pointer; }
/* 命中计数后缀：替代原「清除（N/M）」按钮，不占独立控件位。 */
.ws-list-count { flex: 0 0 auto; font-size: 10.5px; color: var(--text-3); font-variant-numeric: tabular-nums; }

/* 排序：低频操作收敛成图标菜单，不再占用一个常驻下拉框与搜索框争宽度。
   高度必须钉死 28px（.btn 基类 padding 6px + 14px 字体会推出 ~34px，曾把吸顶条撑高 6px）。 */
.ws-sort { position: relative; flex: 0 0 auto; }
.ws-sort-btn { height: 28px; padding: 0 7px; display: inline-flex; align-items: center; font-size: 12px; color: var(--text-3); }
.ws-sort-btn:hover, .ws-sort.is-open .ws-sort-btn { color: var(--text); }
.ws-sort-menu {
  display: none; position: absolute; right: 0; top: calc(100% + 4px); z-index: 30;
  min-width: 128px; padding: 4px;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel); box-shadow: 0 8px 24px color-mix(in srgb, var(--bg) 70%, transparent);
}
.ws-sort.is-open .ws-sort-menu { display: block; }
.ws-sort-item {
  appearance: none; cursor: pointer; width: 100%;
  display: flex; align-items: center; gap: 6px;
  padding: 6px 8px; border: 0; border-radius: 7px;
  font-size: 12px; text-align: left; color: var(--text-2); background: transparent;
}
.ws-sort-item:hover { color: var(--text); background: var(--surface-tint); }
.ws-sort-item.is-on { color: var(--accent); font-weight: 600; }
.ws-sort-item-check { display: inline-flex; align-items: center; width: 13px; flex: 0 0 13px; }

/* 筛选 + 检索吸顶：滚动几十项内容时切类型/搜索始终可达。
   背景必须与工作区面板同色（elev-1）：用 --bg 会深一档，滚动时卡片从条底透出形成"遮挡第一行"的错觉；
   不允许负边距——负边距会让首行卡片滑进条底。
   padding-top 承接面板 body 的顶距：吸附位（top:0）与自然位完全一致，滚动归零时零跳变。 */
.ws-sticky-bar {
  position: sticky; top: 0; z-index: 20;
  padding: 8px 0 8px;
  background: var(--elev-1);
}

/* 系列分组：同产品线批量产出的内容折叠成一组，长列表收敛为几行标题。
   上边距不可省：系列标题紧贴上一张卡片时会读成那张卡的一部分。*/
.ws-series { margin: 14px 0 10px; }
.ws-series:first-child { margin-top: 0; }
.ws-series-head {
  appearance: none; cursor: pointer; width: 100%;
  display: flex; align-items: center; gap: 7px;
  padding: 7px 9px; margin: 0 0 8px;
  border: 1px solid transparent; border-radius: 10px;
  text-align: left; color: var(--text-2); background: var(--surface-tint);
  transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.ws-series-head:hover { color: var(--text); background: var(--btn-hover); }
.ws-series-head.is-open { color: var(--text); background: transparent; border-color: var(--border); }
.ws-series-caret { flex: 0 0 auto; font-size: 10px; opacity: .7; }
.ws-series-name {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12px; font-weight: 700; font-family: var(--mono);
}
/* 事实型分组名（类型 · 日期，见 seriesLabelOf）：走正文字体。等宽字体是"这是标识符/代码"
   的既有语汇，套在人话上会让用户重新把它读成一串机器串——恰恰是要消除的观感。 */
.ws-series-name.is-fact { font-family: inherit; font-weight: 600; letter-spacing: normal; }
.ws-series-count {
  flex: 0 0 auto; margin-left: auto; padding: 0 6px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; font-variant-numeric: tabular-nums;
  color: var(--text-3); background: color-mix(in srgb, var(--text) 6%, transparent);
}

/* 内容卡列表：容器足够宽时双栏，充分利用横向空间，消除单列右侧大片空白。
   用容器查询：侧栏被拖宽即自动两栏，拖窄自动回落单栏，与视口尺寸无关。 */
.ws-object-list { display: grid; gap: 10px;margin-top: 8px; }
@container wsbody (min-width: 640px) {
  .ws-object-list { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@container wsbody (min-width: 920px) {
  .ws-object-list { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* 双/三栏下让卡片等高对齐，避免一卡撑开整行。 */
.ws-object-list > .prompt-delivery-card.workspace { margin-bottom: 0; height: 100%; }
/* ── 列表态内容卡 ──
   等高、单层边框、无内嵌子卡：网格里只回答「这是哪个包」，明细走详情抽屉。 */
.prompt-delivery-card.is-list {
  gap: 9px; height: 100%;
  /* 内容自上而下：头部、chips、动作条永远贴底，卡片高度一致，消除网格锯齿留白。 */
  justify-content: flex-start;
}
.prompt-delivery-card.is-list .prompt-pack-meta { margin-top: -2px; }
.prompt-delivery-card.is-list .ws-pack-actions { margin-top: auto; }
/* 画幅缩略块：提示词包没有图，但"竖屏/横屏"是扫读时第一判断，用比例色块替代同质文件图标。 */
.ws-pack-thumb {
  flex: 0 0 auto; position: relative; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  width: 34px; border-radius: 7px;
  background: linear-gradient(150deg, color-mix(in srgb, var(--accent) 22%, transparent), color-mix(in srgb, var(--accent) 7%, transparent));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 20%, transparent);
}
.ws-pack-thumb.is-landscape { width: 42px; }
.ws-pack-thumb-label {
  font-size: 9px; font-weight: 700; letter-spacing: -.02em; line-height: 1;
  color: color-mix(in srgb, var(--accent) 82%, var(--text));
  font-variant-numeric: tabular-nums;
}
/* 主动作条：复制是提示词的终点，但列表里 39 张卡同时出现，"主"只能靠淡强调色表达，
   不能用铺满卡片的实底按钮——那会让整屏只剩按钮，内容反而看不见。右对齐 + 收缩宽度。*/
.ws-pack-actions { display: flex; align-items: center; justify-content: flex-end; gap: 4px; padding-top: 2px; }
.ws-pack-copy {
  flex: 0 1 auto; min-width: 0; padding: 5px 10px; font-size: 12px; font-weight: 600;
  color: var(--accent); border-color: transparent;
  background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.ws-pack-copy:hover { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.ws-pack-detail { flex: 0 0 auto; padding: 5px 8px; font-size: 11.5px; color: var(--text-3); }
.ws-pack-detail:hover { color: var(--text-2); }
/* 详情抽屉里的卡片本身已在弹层内，去掉重复的外框与内边距，避免"框中框"。 */
.ws-detail-sheet > .prompt-delivery-card { border: 0; padding: 0; background: transparent; }
.workspace-panel .ws-collapse-btn, .workspace-panel .ws-expand-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; border-radius: 8px; border: 1px solid var(--border);
  background: transparent; color: var(--text-2); cursor: pointer; flex-shrink: 0;
}
.workspace-panel .ws-collapse-btn:hover, .workspace-panel .ws-expand-btn:hover { color: var(--text); background: var(--surface-tint); }
/* 收起态：竖排窄轨，只显示展开把手 + 变更角标 */
.workspace-panel.collapsed { align-items: center; }
.workspace-panel.collapsed .workspace-panel-head { flex-direction: column; padding: 8px 6px; border-bottom: none; background: transparent; gap: 6px; }
.workspace-panel.collapsed .ws-name, .workspace-panel.collapsed .workspace-panel-body { display: none; }
.ws-change-badge {
  min-width: 16px; height: 16px; padding: 0 4px; border-radius: 999px;
  background: var(--primary); color: var(--accent-fg); font-size: 10px; line-height: 16px; text-align: center;
}
.ws-file-row { display: flex; align-items: center; gap: 6px; padding: 4px 6px; border-radius: 6px; font-size: 12px; cursor: default; }
.ws-file-row:hover { background: var(--surface-tint); }
.ws-file-row .ws-file-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
.ws-file-kind { width: 16px; flex-shrink: 0; text-align: center; }
.ws-row-actions { display: none; align-items: center; gap: 3px; flex-shrink: 0; }
.ws-file-row:hover .ws-row-actions { display: inline-flex; }
.ws-row-actions button {
  height: 24px; border: 0; background: transparent; color: var(--text-2);
  font-size: 11px; padding: 0 7px; border-radius: 7px; cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
}
.ws-row-actions button:hover { color: var(--text); background: color-mix(in srgb, var(--text) 7%, transparent); }
.ws-row-actions button.danger:hover { color: var(--error); }
.ws-row-actions .ws-row-more { width: 24px; padding: 0; }
.ws-entry-menu {
  position: fixed; z-index: 1600; min-width: 132px; padding: 5px;
  display: grid; gap: 2px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel); box-shadow: 0 12px 32px rgba(0,0,0,.18);
}
.ws-entry-menu button {
  border: 0; background: transparent; color: var(--text); border-radius: 7px;
  padding: 7px 9px; cursor: pointer; display: flex; align-items: center; gap: 8px;
  font-size: 12px; text-align: left;
}
.ws-entry-menu button:hover { background: var(--panel-2); }
.ws-entry-menu button.danger { color: var(--error); }
.ws-preview-wrap { height: min(68vh, 720px); min-height: 420px; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; background: var(--panel); box-shadow: inset 0 0 0 1px var(--surface-tint); }
.ws-preview-frame { width: 100%; height: 100%; border: 0; display: block; background: var(--panel); }
.ws-preview-image { display: block; width: 100%; height: 100%; object-fit: contain; background: var(--panel-2); }
/* 暖阅读档下把媒体留白衬底拉回中性：contain 会在图片四周露出衬底，暖色衬底会让用户
 * 误判图片本身色偏（印刷品给图片留白边同理）。只此一处需要——其余缩略图都是 object-fit:
 * cover，铺满不留白，看不到衬底色。 */
html.sepia .ws-preview-image { background: #eeedeb; }
/* 语义对象卡：绑定业务语义模型时，对象作为一等视图置顶；文件树降为其下的存储载体。
   按对象协议（objectSchema）渲染——标题 + 有值的协议字段，模型无关，未来 AI 造的新模型自动生效。 */
.ws-object-card {
  display: flex; flex-direction: column; gap: 6px; padding: 9px 11px; margin-bottom: 6px;
  border: 1px solid var(--border); border-radius: 10px; background: var(--panel-2);
  cursor: pointer; transition: background .15s, border-color .15s;
}
.ws-object-card:hover { border-color: var(--border); background: var(--surface-tint); }
.ws-object-head { display: flex; align-items: center; gap: 7px; min-width: 0; }
.ws-object-icon { color: var(--primary); flex-shrink: 0; display: inline-flex; }
.ws-object-title { font-size: 13px; font-weight: 600; color: var(--text); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ws-object-badge { flex-shrink: 0; font-size: 10px; line-height: 1; padding: 3px 7px; border-radius: 999px; color: var(--primary); background: color-mix(in srgb, var(--primary) 12%, transparent); }
.ws-object-fields { display: grid; gap: 3px; }
.ws-object-field { display: flex; gap: 8px; font-size: 11.5px; line-height: 1.5; }
.ws-object-field-k { flex-shrink: 0; width: 52px; color: var(--text-2); }
.ws-object-field-v { flex: 1; min-width: 0; color: var(--text); overflow: hidden; text-overflow: ellipsis; display: -webkit-box; line-clamp: 2; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.ws-object-sub { font-size: 11px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 提示词清单（视频提示词包对象卡）：每条提示词一行，点击弹出可编辑复制面板 */
.ws-prompt-list { display: grid; grid-template-columns: minmax(0, 1fr); gap: 5px; margin-top: 2px; }
.ws-prompt-item { display: flex; align-items: center; gap: 8px; min-width: 0; width: 100%; padding: 7px 10px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-tint); color: var(--text); cursor: pointer; text-align: left; font: inherit; }
.ws-prompt-item:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); background: color-mix(in srgb, var(--primary) 7%, var(--surface-tint)); }
.ws-prompt-item-icon { flex-shrink: 0; display: inline-flex; color: var(--text-2); }
.ws-prompt-item-title { flex: 1 1 auto; min-width: 0; font-size: 12px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-family: var(--mono, monospace); }
.ws-prompt-item-arrow { flex-shrink: 0; font-size: 15px; line-height: 1; }
.ws-prompt-empty { display: block; width: 100%; margin-top: 2px; padding: 8px 10px; border: 1px dashed var(--border); border-radius: 8px; background: transparent; color: var(--text-2); font-size: 11.5px; text-align: left; cursor: pointer; }
.ws-prompt-empty:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); color: var(--text); }

/* 提示词包交付卡：面向使用者组织为「镜头 → 用途 → 复制」，而不是技术文件树。 */
.prompt-delivery-card { min-width: 0; display: flex; flex-direction: column; gap: 11px; padding: 13px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel); }
.prompt-delivery-head { display: flex; align-items: center; gap: 10px; min-width: 0; }
.prompt-delivery-icon { display: grid; place-items: center; width: 34px; height: 34px; flex: 0 0 auto; border-radius: 10px; color: var(--primary); background: var(--primary-a-08); }
.prompt-delivery-title { min-width: 0; display: grid; gap: 2px; }
.prompt-delivery-title h3 { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.prompt-delivery-title span { color: var(--text-3); font-size: 10px; }
/* 详情态标题：这一页唯一的大标题（头部导航条的同名标题改为滚动后才接管，见 .ws-read-title.is-collapsed）。
   1) 字号升到 17px：它现在要独自承担"这是什么"，还按列表卡的 14px 写就压不住下面 12px 的正文；
   2) 允许换行、不截断：详情只有一个标题、宽度整条可用，用省略号换来的整齐毫无价值——
      用户恰恰是点进来看全名的（列表卡才需要截断保持行高一致）；
   3) 类型标签升到11px：14px 标题下的 10px 字会掉进"装饰性灰字"层级，没人读。*/
.prompt-delivery-card.detail .prompt-delivery-head { align-items: flex-start; }
/* 标题占满除主动作外的剩余宽度：标题多行时，主动作钉在第一行右侧不随之换行。 */
.prompt-delivery-card.detail .prompt-delivery-title { flex: 1 1 auto; }
.prompt-delivery-card.detail .prompt-delivery-title h3 {
  font-size: 17px; line-height: 1.35; letter-spacing: -.01em;
  white-space: normal; overflow: visible; text-overflow: clip; overflow-wrap: anywhere;
}
.prompt-delivery-card.detail .prompt-delivery-title span { font-size: 11px; }
.prompt-pack-meta { display: flex; flex-wrap: wrap; gap: 6px; }
.prompt-pack-chip { padding: 4px 8px; border: 1px solid var(--border); border-radius: 999px; color: var(--text-2); background: var(--surface-tint); font-size: 11px; line-height: 1.3; }
.prompt-pack-guide { min-width: 0; margin: 0; padding: 7px 9px; border-left: 2px solid var(--primary-a-24); border-radius: 0 8px 8px 0; color: var(--text-2); background: var(--surface-tint); font-size: 12px; line-height: 1.6; overflow-wrap: anywhere; }
/* Safari 详情页整卡溢出屏幕：flex/grid 子项默认 min-width:auto（=内容的 min-content），
   Safari 对内部 -webkit-line-clamp 元素的 min-content 计算会取"整段未换行"的宽度，
   若链路上任一层级没有显式 min-width:0覆盖这个默认值，这个超宽值会一路撑大到最外层
   卡片，导致详情页整卡宽度超出屏幕（Chrome/Firefox 对此更宽容，不易复现）。
   这里把 .prompt-shot-list→.prompt-shot→…→.prompt-artifact-file 整条链路都补上
   min-width:0，从根上掐断"内容撑破容器"。 */
.prompt-shot-list { min-width: 0; display: grid; gap: 10px; }
.prompt-shot { min-width: 0; display: grid; gap: 7px; }
.prompt-shot.has-thumb { display: flex; align-items: flex-start; gap: 10px; }
.prompt-shot.has-thumb .prompt-shot-body { flex: 1 1 auto; min-width: 0; display: grid; gap: 7px; }
.prompt-shot-thumb {
  position: relative; flex: 0 0 auto; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  width: 56px; height: 56px; border-radius: 10px;
  background: var(--surface-tint);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-3) 28%, transparent);
  cursor: zoom-in;
}
.prompt-shot-thumb:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 45%, transparent); }
.prompt-shot-thumb-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; background: var(--surface-tint);
}
/* 未关联成图时的占位：同尺寸、虚线描边，关联后原地替换成缩略图，布局不跳动。
   不是可点击元素，所以去掉 zoom-in 光标与 hover 高亮。 */
.prompt-shot-thumb.is-placeholder {
  flex-direction: column; gap: 1px; cursor: default;
  background: repeating-linear-gradient(135deg, color-mix(in srgb, var(--border) 30%, transparent) 0 1px, transparent 1px 7px), var(--surface-tint);
  box-shadow: none; border: 1px dashed color-mix(in srgb, var(--text-3) 34%, transparent);
}
.prompt-shot-thumb.is-placeholder:hover { box-shadow: none; }
.prompt-shot-thumb-mark { font-size: 15px; line-height: 1; color: var(--text-3); opacity: .55; }
.prompt-shot-thumb-text { color: var(--text-3); font-size: 9.5px; line-height: 1.3; text-align: center; padding: 0 2px; }
.prompt-shot-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: 6px 9px; color: var(--text); }
.prompt-shot-head strong { font-size: 12.5px; }
.prompt-shot-duration { color: var(--text-2); font-size: 11px; }
.prompt-shot-beat { min-width: 0; color: var(--text-2); font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.prompt-artifact-list { min-width: 0; display: grid; gap: 6px; }
/* 标题行（图标+标题+生成/复制）与正文预览拆成两条独立的行：正文必须拿到卡片的全部
   宽度，不能像此前那样和「生成」「复制」按钮挤在同一条flex 行里——按钮只出现在第一行，
   却会把整段（含第2、3行）的可用宽度都压窄，正文因此在按钮早已结束的地方仍被挤在左边，
   右侧那片空白其实是按钮占位留下的死区，不是正文真的显示不下。 */
.prompt-artifact-row { display: grid; gap: 5px; min-width: 0; padding: 8px 9px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-tint); }
.prompt-artifact-head { display: flex; align-items: center; gap: 8px; min-width: 0; }
.prompt-artifact-icon { flex: 0 0 auto; display: inline-flex; color: var(--text-2); }
.prompt-artifact-head-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 6px; }
.prompt-artifact-main { min-width: 0; display: grid; gap: 2px; width: 100%; padding: 0; border: 0; background: transparent; color: var(--text); text-align: left; font: inherit; cursor: pointer; }
.prompt-artifact-main:hover .prompt-artifact-file { color: var(--primary); }
button.prompt-artifact-label {
  flex: 1 1 auto; min-width: 0; padding: 0; border: 0; background: transparent;
  color: var(--text); text-align: left; font: inherit; cursor: pointer;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; font-weight: 600;
}
button.prompt-artifact-label:hover { color: var(--primary); }
button.prompt-artifact-label:disabled { cursor: default; }
.prompt-artifact-file { min-width: 0; color: var(--text-3); font-size: 11px; line-height: 1.5; overflow-wrap: anywhere; }
/* 常驻的"可展开"提示：与 .has-preview 的两行截断成对出现，明确告知截断是可点开看全文的
   功能，而不是内容显示不全的缺陷。 */
.prompt-artifact-more { min-width: 0; color: var(--text-3); font-size: 10.5px; line-height: 1.4; }
.prompt-artifact-main:hover .prompt-artifact-more { color: var(--primary); }
/* 正文预览最多两行：先让人一眼判断能否使用，点击名称查看完整，右侧复制始终复制全文。 */
.prompt-artifact-row.has-preview .prompt-artifact-file {
  display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  color: var(--text-2); white-space: normal;
}
/* 详情态放宽到 6 行 + 行高 1.75：两行是列表态的"能否使用"判断量，而用户点进详情就是来读的，
   在阅读页里继续按列表的尺度裁剪，等于让人为了看内容再点一次。提示词是长句密排的文本块，
   行高 1.5 在 11px 字号下会糊成一片，读两行就要重新找行首。 */
.ws-detail-sheet .prompt-artifact-row.has-preview .prompt-artifact-file { -webkit-line-clamp: 6; line-clamp: 6; }
.ws-detail-sheet .prompt-artifact-file { font-size: 11.5px; line-height: 1.75; }

/* ── 详情页层级压平 ──
   原本是三层都有"底色 + 描边"的盒子：纸张 → 分组卡 → 提示词行。框中框让读者每读一段
   都要先解析一次"我现在在第几层"，而最内层那层盒子并不承担任何新信息——它要表达的只是
   "这段提示词属于上面那个镜头"，一条左侧细线就够。层级信息一点没丢，盒子少了一层。
   hover 时线变accent：从"整块变色"改成"线变色"，反馈仍然明确但不再整片闪。 */
.ws-detail-sheet .prompt-artifact-row {
  padding: 2px 0 3px 10px; border: 0; border-radius: 0;
  border-left: 2px solid color-mix(in srgb, var(--text-3) 24%, transparent);
  background: none;
}
.ws-detail-sheet .prompt-artifact-row:hover {
  background: none; border-left-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
/* 少了盒子内边距后，同一镜头下的两条提示词需要靠间距自己分开。 */
.ws-detail-sheet .prompt-artifact-list { gap: 11px; }

/* ── 详情页主视觉 ──
   刻意不在顶部另加一张封面图：列表卡的封面用的就是第一个分组的图，顶部再放一次的话，
   多镜内容会出现"同一张图在一屏里出现两遍"，单镜内容更是纯重复。正确做法是让"分组自己的
   那张图"在详情态足够大，而不是补一个副本——用户点进来要看的是画面，不是画面的缩略图。
   56px 是列表态尺度（只够确认"有图"），详情态给到 104px 并改成按原图宽高比不裁切，
   竖屏 9:16 素材也能看清内容；图文仍并排，保持"这段词对应这个画面"的对应关系。
   gallery 版式（图片提示词包）已经是大图上、词在下，不参与这里的覆盖。
   占位框（is-placeholder，还没生成首帧）必须跟已生成的缩略图同一套尺寸规则——
   之前占位框被:not(.is-placeholder) 排除在外，停留在列表态的 56px 小方块，
   跟旁边 104px 的真图挤在一起，宽度对不齐、行高也不一致，看起来像排版错了；
   占位框没有真实图片可依据宽高比，给一个固定的比例（16:9）撑高度，宽度对齐即可。 */
.ws-detail-sheet .prompt-shot.has-thumb:not(.is-gallery) .prompt-shot-thumb {
  width: 104px; height: auto; aspect-ratio: auto; align-self: start;
}
.ws-detail-sheet .prompt-shot.has-thumb:not(.is-gallery) .prompt-shot-thumb:not(.is-placeholder) .prompt-shot-thumb-img {
  position: static; inset: auto; width: 100%; height: auto; object-fit: initial;
}
.ws-detail-sheet .prompt-shot.has-thumb:not(.is-gallery) .prompt-shot-thumb.is-placeholder {
  aspect-ratio: 16 / 9;
}
/* 单镜内容：没有"多镜横向对比"的需求，那张图就是这份内容的主视觉——
   升为上图下词、铺满内容列宽（等价于 gallery 单栏的观感，但不改类型声明的 layout 语义）。
   占位框同理铺满整宽，避免"这条有图铺满、那条没生成图就缩成小方块"的错觉。 */
.ws-detail-sheet .prompt-shot-list > .prompt-shot.has-thumb:only-child:not(.is-gallery) { display: block; }
.ws-detail-sheet .prompt-shot-list > .prompt-shot.has-thumb:only-child:not(.is-gallery) .prompt-shot-thumb {
  width: 100%; margin-bottom: 10px; border-radius: 12px;
}
.ws-detail-sheet .prompt-shot-list > .prompt-shot.has-thumb:only-child:not(.is-gallery) .prompt-shot-thumb.is-placeholder {
  aspect-ratio: 16 / 9;
}
/* 详情态的"还有更多"提示要说清点它会发生什么：阅读页里的「展开全文」容易被理解成
   就地展开，实际是打开一个新的阅读层（子页）。 */
.ws-detail-sheet .prompt-artifact-more::after { content: ' （打开完整提示词）'; }

/* 署名行：紧贴详情标题下方，是阅读这份内容的前置语境（谁做的 / 多新 / 第几版）。 */
.ws-detail-byline {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  margin: 7px 0 0; font-size: 11.5px; color: var(--text-2);
}
.ws-detail-byline-name { font-weight: 600; }
.ws-detail-byline-dot { color: var(--text-3); }
/* 详情页主动作：紧跟大标题右侧一起随内容滚动（见 .prompt-delivery-head）。
   这页的首要任务是"读"，"用"是读完之后才产生的次要动作，且它现在挨着 17px 的大标题，
   实底药丸按钮在这个位置视觉分量太重、会跟标题抢注意力——弱化成文字+图标的线框态，
   常态几乎不出声，hover/focus 才给出可点反馈，读的时候不打扰，要用的时候能找到。 */
.ws-detail-use-btn {
  flex: none; margin-top: 3px;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 9px; font-size: 12px; font-weight: 600; border-radius: 7px;
  color: var(--text-2); background: none; border: 1px solid var(--border);
}
.ws-detail-use-btn:hover, .ws-detail-use-btn:focus-visible {
  color: var(--ink); border-color: color-mix(in srgb, var(--ink) 32%, var(--border));
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.ws-detail-use-btn svg { opacity: .8; }
/* 详情页动作组（「照这个做」+「分享」）：两者是同一时刻的两种去向——"我自己要用"与
   "让别人也看到"，所以并列而不是把其中一个收进「更多」。整组用 flex 而非让两颗按钮
   各自 margin-top：标题行是 align-items 未对齐的多行容器，逐颗设外边距会让两颗钮在
   标题折行时错开半行高。 */
.ws-detail-actions { flex: none; display: inline-flex; align-items: center; gap: 6px; margin-top: 3px; }
.ws-detail-actions .ws-detail-use-btn { margin-top: 0; }
/* 分享与「照这个做」同一档线框样式，但静息态更弱一档（文字色 --text-3 而非 --text-2）：
   两颗视觉完全相同的按钮并排会变成"一对开关"，用户得逐个读文字才知道哪个是主路径。
   主次靠色阶拉开半档即可，不用实底/描边这种跨档差异——那会把分享压成"次要功能"，
   而它其实是这页的第二个真实出口。 */
.ws-detail-share-btn {
  flex: none;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 4px 9px; font-size: 12px; font-weight: 600; border-radius: 7px;
  color: var(--text-3); background: none; border: 1px solid var(--border);
  cursor: pointer;
}
.ws-detail-share-btn:hover, .ws-detail-share-btn:focus-visible {
  color: var(--ink); border-color: color-mix(in srgb, var(--ink) 32%, var(--border));
  background: color-mix(in srgb, var(--ink) 6%, transparent);
}
.ws-detail-share-btn svg { opacity: .8; }
/* 生成中禁用态：必须保留可读文字对比度（disabled 默认的浏览器灰会把"生成中…"压到看不清），
   只降不透明度并挡住指针，不改色值。 */
.ws-detail-share-btn:disabled { opacity: .6; cursor: default; }
/* ── 添加文件面板：工作区素材 / 本地上传 ──
 * 默认停在「工作区素材」：真实高频诉求是"引用刚生成的那张图"，此前完全无路可走。
 * 缩略图网格而不是文件名列表——图片靠看，不靠读文件名。 */
.attach-picker-tabs { display: flex; gap: 6px; margin: 0 0 12px; }
.attach-picker-tab {
  flex: 0 0 auto; padding: 6px 12px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: transparent; color: var(--text-3); font-size: 12.5px;
}
.attach-picker-tab.is-active { color: var(--text); border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.attach-picker { min-height: 180px; }
.attach-picker-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(96px, 1fr)); gap: 10px; max-height: 48vh; overflow-y: auto; }
.attach-picker-cell {
  display: grid; gap: 5px; padding: 6px; cursor: pointer; text-align: left;
  border: 1px solid var(--border); border-radius: 12px; background: transparent;
}
.attach-picker-cell.is-selected { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.attach-picker-thumb { width: 100%; aspect-ratio: 1/ 1; object-fit: cover; border-radius: 8px; display: block; }
.attach-picker-thumb.is-video { display: grid; place-items: center; color: var(--text-3); background: var(--elev-2); }
.attach-picker-name { font-size: 11px; color: var(--text-3); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.attach-picker-foot { display: flex; justify-content: flex-end; margin-top: 12px; }
.attach-picker-local { display: grid; gap: 12px; justify-items: start; padding: 8px 0; }

.prompt-artifact-copy { flex: 0 0 auto; min-height: 28px; padding: 4px 9px; font-size: 11px; }
/* 「生成」按钮：与复制同尺寸同列，视觉上略强一档（它是花钱的主动作，复制是免费的辅助动作），
 * 但仍留在 ghost 家族里，不做实心主按钮——一行里出现实心按钮会把整个列表的焦点全吸走。 */
.prompt-artifact-generate {
  flex: 0 0 auto; min-height: 28px; padding: 4px 9px; font-size: 11px;
  display: inline-flex; align-items: center; gap: 4px;
  color: var(--accent); border-color: color-mix(in srgb, var(--accent) 38%, transparent);
}
.prompt-artifact-generate:hover:not(:disabled) {
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  border-color: color-mix(in srgb, var(--accent) 55%, transparent);
}
/* 缺参考图时禁用而不隐藏：用户需要看到"下一步是先生成首帧"，藏起来等于没有引导。 */
.prompt-artifact-generate.is-blocked { color: var(--text-3); border-color: var(--border); opacity: .6; cursor: not-allowed; }
.prompt-pack-manifest { align-self: flex-start; }
/* 图片提示词包详情：瀑布式图片浏览（by block.layout==='gallery'，声明驱动，非kind 特判）。
 *用 CSS 多列布局排布卡片——高度随图片原比例自适应，天然产生错落的瀑布效果，无需 JS 计算。
 * 每卡结构不变：大图铺满在上，提示词块（图标+文案+复制按钮）维持原有形式，只是挪到图片下方。 */
.prompt-shot-list.is-gallery { display: block; column-count: 2; column-gap: 12px; }
/* 只有 1 个镜头时不需要（也不能有）两栏，否则唯一卡片被固定分配进第一栏，
   右侧留出与卡片等宽的空白，视觉上像"图片没有跟随容器宽度自适应"。 */
.prompt-shot-list.is-gallery.is-single { column-count: 1; }
.prompt-shot.is-gallery.has-thumb { display: block; }
/* 卡片化：图 + 标题 + 提示词必须被同一个边框/背景圈起来，否则纵向瀑布流里镜头一多，
   无法判断中间的提示词块到底属于上面那张图还是下面那张图——此前只靠"卡间 margin
   比卡内 gap 大一点"这种弱对比来暗示分组，没有边框时肉眼分不出来。现在把图片全出血
   贴在卡片顶部（overflow:hidden 裁出圆角），文字区带内边距，整卡才是一个可见的、
   不会有歧义的从属单元。 */
.prompt-shot.is-gallery {
  break-inside: avoid; margin: 0 0 14px;
  border: 1px solid var(--border); border-radius: 14px;
  background: var(--panel-2); overflow: hidden;
}
.prompt-shot.is-gallery .prompt-shot-body { display: grid; gap: 7px; margin: 0; padding: 10px 11px 11px; }
/* 详情页大图不再按固定 3:4 裁切——那会让展示比例既不等于类型声明的画幅（如 4:5），
   也不等于点开放大后看到的原图真实比例，三处比例互相打脸。这里改成让图片按自身
   原始宽高比自适应铺满卡片宽度（去掉绝对定位 + object-fit:cover 的裁切链路），
   缩略图、文案里的画幅 chip、放大图三处就统一成同一个"原画幅比例"。 */
.prompt-shot-thumb.is-gallery {
  width: 100%; height: auto; aspect-ratio: auto; border-radius: 0; display: block;
}
.prompt-shot-thumb.is-gallery .prompt-shot-thumb-img {
  position: static; inset: auto; width: 100%; height: auto; object-fit: initial;
}
/* is-gallery 的 display:block 覆盖了 is-placeholder 依赖的 inline-flex 居中，
   导致"待生图"图标+文字堆在占位块左上角，而不是像非gallery 布局那样居中显示。
   两个类同时命中时用更具体的选择器把居中拿回来。 */
.prompt-shot-thumb.is-gallery.is-placeholder {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
}
@media (max-width: 560px) {
  .prompt-shot-list.is-gallery { column-count: 1; }
}
/* ============ 图文文章正文（content_stream 的阅读态） ============
   这一块的唯一目标是「能读完」。它不是资产验收视图，所以排版规格按长文阅读定，
   而不是沿用提示词包那套 11–14px 的清单尺度：
   · 正文 16px / 行高 1.9：阅读层已把行宽压到 72ch（≈36 个汉字），配 1.9 行高才不串行；
     此前 14px/1.75 是从"清单里的说明文字"继承来的，一篇 2000 字的文章按清单尺度排，
     读者读三屏就要放弃。
   · 首段（导语）稍大：它承担"要不要读下去"的判断，是全文最贵的一段。
   · `## / ###` 起头的文字段渲染成小标题：sections 只有 text/image 两种段型，层级只能由
     正文自己的记号表达；没有层级的长文只能从头读到尾，扫读、回看、分享某一节全都做不到。
   · 配图整段独占一行、按原比例铺满阅读列宽，图下跟图注——它是"插进正文里的一张图"，
     不是"一条带缩略图的清单行"。 */
.article-content-stream { display: grid; gap: 22px; margin: 6px 0 2px; }
.article-paragraph {
  margin: 0; color: var(--text);
  font-size: 16px; line-height: 1.9; letter-spacing: .01em;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.article-content-stream > .article-paragraph:first-child { font-size: 17px; }
/* 小标题与下一段之间不要再留 22px：标题与它统辖的正文必须比段间距更近，
   否则标题会在视觉上飘在两段之间，读者判断不出它属于上面还是下面。 */
.article-subhead {
  margin: 8px 0 -8px; color: var(--text);
  font-size: 15.5px; font-weight: 650; line-height: 1.55; letter-spacing: .01em;
}
h4.article-subhead { font-size: 14.5px; font-weight: 600; color: var(--text-2); }
/* figure 的浏览器默认 margin 是 1em 40px：不清零会让每张配图凭空左右缩进 40px，
   与正文左缘对不齐（看起来像"图没对齐"，其实是默认样式）。 */
.prompt-shot.article-inline-shot { margin: 0; }
/* 图片按 gallery 取原图（is-gallery 缩略图规则），但外层容器不要 artifact_groups 那套
   "缩略图+正文并排一行"的 flex 布局（那是给 56px 小方块设计的）——文章配图要整段独占
   一行、图在上文在下，才像一张真正插进正文里的配图，而不是一条带缩略图的清单行。 */
.prompt-shot.article-inline-shot.has-thumb { display: grid; gap: 8px; }
.article-inline-shot .prompt-shot-thumb.is-gallery { border-radius: 12px; }
/* 关键修复：阅读层里 `.ws-detail-sheet .prompt-shot.has-thumb:not(.is-gallery) .prompt-shot-thumb`
   （宽 104px，为多镜提示词包的并排小图设计）特异性高于 `.prompt-shot-thumb.is-gallery`
   的 width:100%，导致文章配图在详情页被压成 104px 的小缩略图——一篇图文文章的配图退化成
   了列表缩略图。这里用同等以上特异性把"铺满阅读列宽 + 原比例不裁切"拿回来。 */
.ws-detail-sheet .prompt-shot.article-inline-shot.has-thumb .prompt-shot-thumb.is-gallery {
  width: 100%; height: auto; aspect-ratio: auto; align-self: stretch; border-radius: 12px;
}
/* 还没生成的配图用 4:5 占位：文章配图以竖版为主，用 16:9 会在正文里压出一条扁横条，
   生成后图片撑开真实比例，版面又跳一次。 */
.ws-detail-sheet .prompt-shot.article-inline-shot.has-thumb .prompt-shot-thumb.is-gallery.is-placeholder {
  aspect-ratio: 4 / 5; max-height: 420px;
}
/* 图注：图片的说明，不是正文——比正文小一档、弱一档，但仍在可读区间（不是 10px 装饰字）。 */
.article-figcaption {
  margin: 0; padding: 0 2px;
  color: var(--text-2); font-size: 12.5px; line-height: 1.65;
}
.article-inline-shot .prompt-shot-body { margin: 0; padding: 0 2px; }
.article-inline-shot .prompt-shot-head strong { display: none; } /* 条目编号是内部标识，读文章的人不需要看到*/
/* 阅读层里配图提示词原文默认收起：它是生产资料。此前它以正文同级的段落形态跟在每张图后面，
   读者会把"a young woman standing by the window, soft morning light…"当成文章内容读，
   一篇 3 图的文章因此凭空多出 3 段跑题外文。保留标题行（点它仍可看全文）与复制/重新生成
   按钮，所以创作动作一个都没少；工作区面板（创作者视角）不受影响，仍显示预览。 */
.ws-detail-sheet .article-inline-shot .prompt-artifact-main { display: none; }
.ws-detail-sheet .article-inline-shot .prompt-artifact-row { border-left: 0; padding-left: 0; }
.ws-detail-sheet .article-inline-shot button.prompt-artifact-label {
  flex: 0 0 auto; font-size: 11.5px; font-weight: 500; color: var(--text-3);
}
.ws-detail-sheet .article-inline-shot .prompt-artifact-head { gap: 6px; }

/* 工作区内容卡：面向普通用户，必须一眼看出「这是几件独立的东西」。
   此前这里把卡片压成border:0 + 发丝下划线的紧凑列表，纵向铺开后区分度不足、
   密密麻麻像一整块文本。现在恢复独立卡片：实边框 + 圆角 + 卡间距+ 悬停反馈。 */
.prompt-delivery-card.workspace {
  padding: 12px 13px;
  margin-bottom: 10px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: var(--panel-2);
  transition: border-color .15s, background .15s, transform .15s;
}
.prompt-delivery-card.workspace:hover {
  border-color: color-mix(in srgb, var(--primary) 32%, var(--border));
  background: var(--panel);
}
.prompt-delivery-card.workspace .prompt-delivery-head { gap: 9px; }
.prompt-delivery-card.workspace .prompt-delivery-icon { width: 30px; height: 30px; color: var(--primary); background: var(--primary-a-08); }

/* 媒体预览：图片/视频类内容的可视化首块。用户预期是「看到这张图」而不是读元数据字段。 */
.ws-media-preview {
  display: block; width: 100%; padding: 0; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-tint); overflow: hidden; line-height: 0;
}
.ws-media-preview.is-clickable { cursor: zoom-in; }
.ws-media-preview.is-clickable:hover { border-color: color-mix(in srgb, var(--primary) 45%, var(--border)); }
.ws-media-image, .ws-media-video {
  display: block; width: 100%; max-height: 220px; object-fit: contain; background: var(--panel-2);
}
.ws-media-preview.is-audio, .ws-media-preview.is-missing {
  display: flex; align-items: center; gap: 8px; padding: 10px 11px; line-height: 1.5; font-size: 12px;
}
/* 详情态图片/视频不复用列表缩略图的 220px 高度上限：那是给卡片列表设计的紧凑尺寸，
 * 套在"点进去"的详情大图上等于把正常尺寸的照片/视频压进一条矮横条，两侧留出大片
 * 空白——看起来像"没有跟随容器宽度自适应"。is-detail 只在详情态套用，改成按素材
 * 自身宽高比在阅读层可用宽高内尽量放大：宽图基本铺满容器宽度，竖图也能用到远高于
 * 220px 的高度，而不是被死板地夹在一条固定矮横条里。 */
.ws-media-preview.is-detail {
  width: 100%; max-height: none; padding: 0;
  display: flex; align-items: center; justify-content: center;
}
.ws-media-image.is-detail, .ws-media-video.is-detail {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: min(78vh, 860px);
  object-fit: contain;
}
/* 详情态本身也不该被72ch 的文字阅读列宽压窄——那是给长文本可读性设的行长上限，
 * 套在图片/视频上只会让画面两侧空出大片留白。用 :has() 探测正文里是否含媒体预览块，
 * 命中就解除列宽上限，让上面 is-detail 的自适应尺寸有整个阅读层宽度可用。 */
.ws-read-body .ws-detail-sheet:has(.ws-media-preview) { max-width: none; }
.ws-media-audio { width: 100%; }
.ws-media-missing-icon { flex: 0 0 auto; display: inline-flex; color: var(--text-3); }

/* 「原始文件」类型卡：与内容类型同排但视觉降级，暗示这是技术细节而非日常入口。 */
/* 「原始文件」的弱化样式已随类型切换器改版迁移到 .ws-type-chip.is-technical。 */
.ws-files-note { margin: 0 4px 8px; font-size: 11.5px; line-height: 1.6; }

/* ── 内容选中 → 修改目标绑定 ── */
/* 可选中卡外壳：相对定位承载右上角选择钮；选中时高亮描边。 */
.ws-selectable { position: relative; display: block; height: 100%; }
.ws-select-btn {
  position: absolute; top: 10px; right: 8px; z-index: 2;
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; border-radius: 8px; cursor: pointer;
  /* 常驻边框+白底会在白卡右上角形成"框中框"，是卡片顶部最扎眼的一块。
     未交互时只留图标，边框与底色留到hover/选中态再出现。 */
  border: 1px solid transparent; background: transparent;
  color: var(--text-3); opacity: 0; transition: opacity .15s, color .15s, border-color .15s, background .15s;
}
/* 桌面靠 hover 显现，触屏（无 hover）常驻可见，避免「找不到怎么选中」。 */
.ws-selectable:hover .ws-select-btn, .ws-select-btn:focus-visible { opacity: 1; }
@media (hover: none), (pointer: coarse) { .ws-select-btn { opacity: .9; } }
.ws-select-btn:hover { color: var(--text); border-color: var(--accent); background: var(--panel); }
.ws-select-btn.is-on {
  opacity: 1; color: var(--accent-fg); border-color: var(--accent);
  background: var(--accent);
}
/* ── 选中态：唯一定义（列表内/列表外同一套）──
   收敛前有两处独立实现：这条（通用，底色基准 --panel-2）与 6042 那条
   （仅 .ws-object-list 直接子代，底色基准 --elev-3 且多一条左侧色条）。
   同一个"选中"语义在不同容器里长得不一样，是比"信号过量"更根本的一致性缺陷——
   所以两处必须同时改，只改一处会让另一处继续沿用旧样式。

   信号从 4 重压到 3 重，删掉的是**外圈光晕**：
   border-color: accent 与 box-shadow: 0 0 0 1px accent45% 是同一位置的两层描边
   （1px 边框紧贴 1px 外圈），本质是"2px 描边但带色差"，纯冗余；而且在多栏网格里
   外圈会与相邻卡的边框粘连成一片。
   保留左侧 2px 色条而不是删它：多栏网格中视线沿左边缘垂直扫描，左条是最易命中的锚点；
   而且"正在被修改"的瞬时信号早已有自己的专属通道（虚线描边，见 6049 注释），
   不需要左条为它腾位。 */
.ws-selectable.is-selected > .prompt-delivery-card.workspace,
.ws-selectable.is-selected > .ws-object-card {
  border-color: var(--accent);
  box-shadow: inset 2px 0 0 var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, var(--elev-3));
}

/* 会话输入框上方的目标条：告诉用户「本轮要对它做什么」。 */
.ws-target-bar {
  display: flex; align-items: center; gap: 9px;
  margin: 0 0 8px; padding: 8px 11px;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, var(--border));
  border-radius: 11px; background: color-mix(in srgb, var(--accent) 7%, var(--panel));
}
.ws-target-icon { flex: 0 0 auto; display: inline-flex; color: var(--accent); }
.ws-target-main { flex: 1 1 auto; min-width: 0; display: grid; gap: 2px; }
.ws-target-title { display: flex; align-items: baseline; gap: 4px; min-width: 0; font-size: 12.5px; }
.ws-target-verb { flex: 0 0 auto; font-weight: 700; }
/* 四个意图动词的色彩按「强度梯度」排布，而不是各挑一个好看的颜色。
   原先reference/use 硬编码 #0891b2 / #b45309（Tailwind 600 档），与 token 层不同源，
   主题切换时不跟随，暖色档下尤其显脏；而且 #0891b2 与 accent 青色相近却语义无关，
   用户会徒劳地去找两者的关联。改为一条可读出高低的序列，全部落在 token 内：
     修改(accent 青) > 使用(warn 琥珀) > 参考(text-2) > 自动/围绕(text-3 最弱)
   依据是对目标对象的"侵入性"：修改会动它、使用会消费它、参考只是看它、
   自动/围绕则根本不是用户选的（平台推断），理应最弱。 */
.ws-target-verb.is-modify { color: var(--accent); }
.ws-target-verb.is-use { color: var(--warn); }
.ws-target-verb.is-reference { color: var(--text-2); }
/* auto = 平台按消息语义判断用法的中性色，不与显式「修改」的强色混淆。 */
.ws-target-verb.is-auto { color: var(--text-3); }
.ws-target-verb.is-focus { color: var(--text-3); }
/* 回落为「话题围绕」时的弱化态：它不是你选的目标，是平台推断的上下文锚点。 */
.ws-target-bar.is-focus { border-style: dashed; background: var(--panel); }
.ws-target-bar.is-focus .ws-target-icon { color: var(--text-3); }

/* 复制按钮成功/失败瞬时反馈：文案变为「已复制/复制失败」并切换色彩，短暂停留后还原。
   两条都改走语义 token：成功档原先硬编码 #16a34a（能显示但不跟随主题），
   失败档原先用未定义的 var(--danger)（**整条声明失效**，失败反馈根本不出现），
   于是成功有色、失败无色——最需要被看见的那一半反而是隐形的。 */
.is-copy-ok {
  color: var(--success) !important;
  border-color: color-mix(in srgb, var(--success) 45%, var(--border)) !important;
  background: color-mix(in srgb, var(--success) 8%, var(--panel)) !important;
}
.is-copy-fail {
  color: var(--error) !important;
  border-color: color-mix(in srgb, var(--error) 45%, var(--border)) !important;
  background: color-mix(in srgb, var(--error) 7%, var(--panel)) !important;
}
.btn.is-copy-ok, .btn.is-copy-fail,
.ai-code-copy.is-copy-ok, .ai-code-copy.is-copy-fail,
.prompt-artifact-copy.is-copy-ok, .prompt-artifact-copy.is-copy-fail { transition: color .15s, background .15s, border-color .15s; }

/* ── 执行可视化：操作徽章 ──
 * 顶部活动条已退役：执行反馈只出现在被操作的内容卡上，不占用面板顶部视觉焦点。
 * 不用整卡变色或无限呼吸（装饰性动效，无信息量且抢主会话焦点）。
 * 操作徽章只在卡片左上角标记「增/删/改」，执行中轻微呼吸、结束定格、短暂停留后淡出。
 * 色彩对齐 Codex 语义：改=琥珀、建=绿、删=红。动效克制——只有徽章在动，卡片主体不变。 */
.ws-selectable { position: relative; }
.ws-op-badge {
  /* 放在卡片右上角框内，而不是悬在卡片外沿；右移避开右上角选定按钮。 */
  position: absolute; top: 10px; right: 40px; z-index: 3;
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 8px; border-radius: 999px;
  font-size: 10.5px; font-weight: 700; line-height: 1.5; white-space: nowrap;
  border: 1px solid; box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12);
  animation: ws-badge-in .22s ease-out;
  pointer-events: none;
}
@keyframes ws-badge-in {
  from { opacity: 0; transform: translateY(-4px) scale(0.92); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}
/* 执行中：徽章轻微呼吸（仅透明度，不变尺寸不扩张阴影，克制）。 */
@keyframes ws-badge-breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.62; }
}
.ws-op-badge.is-active { animation: ws-badge-in .22s ease-out, ws-badge-breathe 1.5s ease-in-out 0.22s infinite; }
.ws-op-badge.is-done { animation: ws-badge-in .22s ease-out; }
.ws-op-badge.is-fading { opacity: 0; transform: translateY(-3px); transition: opacity .3s, transform .3s; }
/* 语义色彩：全部走 token，不再硬编码 Tailwind 600 档。
   底色混合比从 12%/10% 统一降到 8%：浅色主题下"彩字 + 同色淡底"会同时抬高底色亮度，
   12% 时 light档的绿字只剩 4.33:1（10.5px 徽章不适用大字3:1 豁免），8% 回到 4.57:1。
   read 档原先用 #0891b2，与 accent 青色相近却是另一个色值——直接归到 accent。 */
.ws-op-badge.is-write { color: var(--warn); background: color-mix(in srgb, var(--warn) 8%, var(--panel)); border-color: color-mix(in srgb, var(--warn) 40%, var(--border)); }
.ws-op-badge.is-create { color: var(--success); background: color-mix(in srgb, var(--success) 8%, var(--panel)); border-color: color-mix(in srgb, var(--success) 40%, var(--border)); }
.ws-op-badge.is-delete { color: var(--error); background: color-mix(in srgb, var(--error) 8%, var(--panel)); border-color: color-mix(in srgb, var(--error) 40%, var(--border)); }
.ws-op-badge.is-read { color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel)); border-color: color-mix(in srgb, var(--accent) 35%, var(--border)); }
.ws-op-badge.is-done.is-write { color: var(--warn); }
.ws-op-badge.is-done.is-create { color: var(--success); }
.ws-op-badge.is-done.is-delete { color: var(--error); }
/* 新对象尚未进入服务端投影时的乐观空卡：占据它最终会出现的位置，只让内部骨架轻扫，
   避免把“新建中”错误贴到任意存量卡片上。真实对象出现后原位接替。 */
.ws-ghost-create { min-height: 168px; }
.ws-ghost-card {
  min-height: 168px; height: 100%;
  border-style: dashed; border-color: color-mix(in srgb, var(--success) 38%, var(--border));
  background: color-mix(in srgb, var(--success) 3%, var(--panel));
  pointer-events: none; overflow: hidden;
}
.ws-ghost-card .prompt-delivery-title { color: var(--text-2); }
.ws-ghost-icon { color: var(--success) !important; background: color-mix(in srgb, var(--success) 10%, var(--panel)) !important; }
.ws-ghost-lines { display: grid; gap: 10px; margin-top: 10px; }
.ws-ghost-lines i {
  display: block; height: 10px; border-radius: 999px;
  background: linear-gradient(90deg, var(--panel-2) 20%, color-mix(in srgb, var(--success) 12%, var(--panel)) 45%, var(--panel-2) 70%);
  background-size: 220% 100%; animation: ws-ghost-sweep 1.8s ease-in-out infinite;
}
.ws-ghost-lines i:nth-child(1) { width: 72%; }
.ws-ghost-lines i:nth-child(2) { width: 92%; animation-delay: .12s; }
.ws-ghost-lines i:nth-child(3) { width: 55%; animation-delay: .24s; }
@keyframes ws-ghost-sweep { 0% { background-position: 100% 0; } 100% { background-position: -100% 0; } }
.ws-target-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 600; }
.ws-target-hint { font-size: 11px; line-height: 1.4; }
.ws-target-intent-toggle {
  flex: 0 0 auto; border: 1px solid var(--border); background: var(--panel);
  color: var(--text-2); font-size: 11px; border-radius: 8px; padding: 4px 8px; cursor: pointer;
}
.ws-target-intent-toggle:hover { color: var(--text); border-color: var(--accent); }
.ws-target-clear { flex: 0 0 auto; width: 26px; height: 26px; padding: 0; font-size: 16px; line-height: 1; border-radius: 8px; }

/* 消息气泡上的目标标注：一眼看出这条「改成20秒」指的是哪个内容，轻量不进上下文。 */
.msg-target-chip {
  display: inline-flex; align-items: center; gap: 4px;
  margin: 0 0 6px; padding: 3px 8px; max-width: 100%;
  border-radius: 7px; font-size: 11px; line-height: 1.3;
  background: color-mix(in srgb, var(--accent) 10%, var(--panel));
  border: 1px solid color-mix(in srgb, var(--accent) 26%, var(--border));
  color: var(--accent);
}
.msg-target-chip svg { flex: 0 0 auto; }
.msg-target-chip-verb { flex: 0 0 auto; font-weight: 700; }
.msg-target-chip-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 500; }
.msg.user .msg-content { min-width: 0; }
/* 提示词编辑/复制面板 */
.ws-prompt-editor { display: grid; gap: 8px; }
.ws-prompt-editor-hint { font-size: 11.5px; }
/* 已进入沉浸式阅读层（三级页），页面本身就能滚——文本框没必要再套一层自己的滚动条，
   那是"滚动套滚动"，读者手指划到内容底再往下划，会先撞上textarea 内部滚动到底才换页面滚动，
   体感是"卡住了"。改为随内容自适应高度（由 JS 按 scrollHeight 撑高），这里只关掉内部滚动/
   手动拖拽（overflow: hidden +去掉 resize），高度完全交给内容撑开，页面级滚动统一体验。*/
.ws-prompt-editor-ta { width: 100%; min-height: 120px; overflow: hidden; resize: none; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--bg); color: var(--text); white-space: pre-wrap; word-break: break-word; font: 13px/1.6 var(--mono); box-sizing: border-box; }
.ws-prompt-editor-ta:focus { outline: none; border-color: color-mix(in srgb, var(--primary) 55%, var(--border)); }
.ws-prompt-editor-actions { justify-content: flex-end; }
.ws-change-mark { font-family: var(--mono, monospace); font-size: 11px; width: 12px; text-align: center; flex-shrink: 0; }
.ws-change-mark.add { color: var(--success); } .ws-change-mark.mod { color: var(--warn); } .ws-change-mark.del { color: var(--error); }
.ws-section-title { font-size: 11px; color: var(--text-2); text-transform: uppercase; letter-spacing: .04em; margin: 10px 4px 4px; }
/* 底部工具排：钉一下 / 微信 / 发布 —— 同款「图标+文字」小胶囊，尺寸/内距/间距一处统一，
   保证并排三颗完全等大。（.btn 基类已含 inline-flex 与 gap，故这里只收紧内距与字号。） */
.chat-input-left .chat-tool-btn { position: relative; padding: 3px 10px; font-size: 12px; gap: 5px; line-height: 1.4; }
/* 视觉保持紧凑胶囊，触控热区用伪元素撑到 44px 高（不改布局高度，底部不多占一寸空间）。
   「+ 添加文件」是移动端引用工作区素材的唯一入口，实测可点高度原本只有约 23px，
   不到 HIG 标准的一半——而设置页的保存按钮早已按 44px 执行，这里属于标准漏网。 */
.chat-input-left .chat-tool-btn::before {
  content: ''; position: absolute; left: 0; right: 0; top: 50%;
  height: 44px; transform: translateY(-50%);
}
/* 微信按钮：状态仅用「颜色 + 文字」表达，不加实边框——与旁边两颗 ghost 保持同款外观，一眼可读。
   未连=默认灰；已连=绿；待恢复=橙。图标随 currentColor 一起变色。 */
.wechat-btn.on { color: var(--wechat); }
.wechat-btn.on:hover { background: var(--wechat-a-38); }
.wechat-btn.stale { color: var(--warn); }
.wechat-btn.stale:hover { background: rgba(245,158,11,.12); }

 /* ── 会话区右上角「版本」按钮（替代原呼吸灯，与「作品」入口同列）── */
 .chat-header-actions .ws-version-btn { display: inline-flex; align-items: center; gap: 5px; padding: 4px 10px; font-size: 12px; line-height: 1.4; border-radius: 8px; flex-shrink: 0; }
.ws-version-btn:hover { background: var(--surface-tint); color: var(--text); }
/* ② 动作级：内容卡操作徽章（.ws-op-badge，见上），跟随最新工具事件 */
/* ③ 产物级：本轮活动文件（进行中，尚未固化到 git） */
/* 置顶固定坞：封顶高度 + 内部滚动，行数增减只在坞内滚，绝不推动下方文件树（消除上下跳动） */
.ws-live {
  flex-shrink: 0; max-height: 168px; overflow-y: auto;
  padding: 2px 10px 6px; border-bottom: 1px dashed var(--border);
  background: color-mix(in srgb, var(--primary) 4%, transparent);
}
.ws-live .ws-section-title { margin-top: 6px; }
.workspace-panel.collapsed .ws-live { display: none !important; } /* 收起态不显示 */
.ws-live-row.write .ws-file-name { color: var(--warn); font-weight: 500; }
.ws-live-row.read .ws-file-name, .ws-live-row.search .ws-file-name { color: var(--text-2); }
.ws-live-row.exec .ws-file-name { color: var(--text-2); font-style: italic; }
/* 直接反馈到文件树：本轮触碰且已在快照中的文件行即时点亮 + 图标轻脉冲 */
.file-tree-row.ws-live-hit { background: var(--surface-tint-2); }
.file-tree-row.ws-live-hit.live-write > .file-tree-name { color: var(--warn); font-weight: 600; }
.file-tree-row.ws-live-hit > .file-tree-kind { animation: ws-live-pulse 1.4s ease-in-out infinite; }
@keyframes ws-live-pulse { 0%, 100% { transform: scale(1); opacity: .85; } 50% { transform: scale(1.18); opacity: 1; } }
/* 变更角标：数字变化时 pop 放大吸引注意 */
.ws-change-badge.pop { animation: ws-badge-pop .4s ease; }
@keyframes ws-badge-pop { 0% { transform: scale(1); } 40% { transform: scale(1.5); } 100% { transform: scale(1); } }
/* turn 结束固化：本轮写过的文件在 git 变更列表里闪一下（新旧衔接的收敛感） */
.ws-file-row.ws-flash { animation: ws-flash 1.6s ease; }
@keyframes ws-flash { 0% { background: rgba(16,185,129,.28); } 100% { background: transparent; } }
.file-tree {
  display: flex; flex-direction: column; gap: 1px; margin-top: 8px;
  /* 层级视觉基准：缩进步进 + 导引线颜色，供子行统一引用 */
  --tree-indent: 16px; --tree-gutter: 6px;
  --tree-guide: color-mix(in srgb, var(--text) 16%, transparent);
  --tree-guide-active: color-mix(in srgb, var(--text) 32%, transparent);
}
.file-tree-row {
  --depth: 0; position: relative;
  display: flex; align-items: center; gap: 6px; min-width: 0;
  padding: 5px 6px 5px calc(var(--tree-gutter) + var(--depth) * var(--tree-indent));
  border-radius: 8px; font-size: 12px; cursor: default;
}
/* 层级导引线：为每个祖先层画一条竖直细线，即使缩进很浅也能一眼看清父子归属（VS Code 式 indent guides）。 */
.file-tree-row::before {
  content: ''; position: absolute; top: 0; bottom: 0;
  left: calc(var(--tree-gutter) + 9px);
  width: calc(var(--depth) * var(--tree-indent)); pointer-events: none;
  background-image: repeating-linear-gradient(to right, var(--tree-guide) 0 1px, transparent 1px var(--tree-indent));
}
.file-tree-row:hover { background: var(--surface-tint); }
.ws-file-tree .file-tree-row { padding-right: 82px; }
.file-tree-row.dir { cursor: pointer; }
/* 目录行 = “容器”：中等字重 + 主文本色；文件行弱化为次文本色，靠字重/明度差拉开层级，而非只靠缩进。 */
.file-tree-row.dir > .file-tree-name { font-weight: 600; color: var(--text); }
.file-tree-row.file > .file-tree-name { color: var(--text-2); }
/* 已展开目录：极淡底纹 + 左侧主色竖条，明确标记“这是一个已打开、其下内容归属于它”的父节点。 */
.file-tree-row.dir.is-open { background: color-mix(in srgb, var(--primary) 7%, transparent); }
.file-tree-row.dir.is-open::after {
  content: ''; position: absolute; top: 3px; bottom: 3px;
  left: calc(var(--tree-gutter) + var(--depth) * var(--tree-indent) - 2px);
  width: 2px; border-radius: 2px; background: var(--tree-guide-active); pointer-events: none;
}
.file-tree-toggle { width: 12px; flex: 0 0 12px; color: var(--text-2); font-size: 11px; text-align: center; transition: color .15s; }
.file-tree-row.dir.is-open .file-tree-toggle { color: var(--primary); }
.file-tree-kind { width: 16px; flex: 0 0 16px; text-align: center; }
.file-tree-name { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-tree-count { flex-shrink: 0; font-size: 11px; }
/* 文件树行操作：只露出一个主操作 + 更多，不再整排「编辑/改名/删除」铺开。
   行右侧预留宽度，按钮绝对定位，不挤压文件名，也不需要夸张的白色渐变遮罩。 */
.file-tree-row .ws-row-actions {
  position: absolute; right: 6px; top: 50%; transform: translateY(-50%);
  margin-left: 0; z-index: 1; padding: 1px;
  background: color-mix(in srgb, var(--panel) 78%, transparent);
  border: 1px solid color-mix(in srgb, var(--border) 55%, transparent);
  border-radius: 9px; backdrop-filter: blur(6px);
  box-shadow: 0 4px 14px rgba(0,0,0,.08);
}
.is-safari .file-tree-row .ws-row-actions { backdrop-filter: none; -webkit-backdrop-filter: none; }
.works-file-tree { border-top: 1px solid var(--border); padding-top: 4px; }
.works-file-tree .file-tree-row { font-size: 13px; padding-top: 8px; padding-bottom: 8px; border-bottom: 1px solid var(--border); border-radius: 0; }
.works-file-tree .file-tree-row:last-child { border-bottom: none; }
.ws-file-tree .file-tree-row:hover .ws-row-actions,
.ws-file-tree .file-tree-row:focus-within .ws-row-actions { display: inline-flex; }
@media (prefers-reduced-motion: reduce) {
   .ws-change-badge.pop, .ws-file-row.ws-flash, .file-tree-row.ws-live-hit > .file-tree-kind,
   .ws-object-list > .ws-selectable.ws-has-op-badge > .prompt-delivery-card,
   .ws-object-list > .ws-selectable.ws-has-op-badge > .ws-object-card { animation: none; }
}
/* 窄屏：中栏工作区/社区继续作为主画面；会话改为从右侧滑出的抽屉，不再反过来把工作区浮层化。 */
@media (max-width: 1199px) {
  .chat-shell.ws-collapsed, .chat-shell.ws-open, .chat-shell.chat-collapsed { grid-template-columns: 1fr; }
  .workspace-panel { position: relative; inset: auto; width: auto; z-index: auto; box-shadow: none; }
  .workspace-panel.collapsed { display: flex; }
  .chat-main {
    position: fixed; top: 0; right: 0; bottom: 0; width: min(92vw, 565px); z-index: 1200;
    border-left: 1px solid var(--line-2); box-shadow: -10px 0 28px color-mix(in srgb, var(--text) 16%, transparent);
    transform: translateX(calc(100% + 12px)); transition: transform .22s var(--ease-standard, ease);
  }
  .chat-shell.mobile-chat-open .chat-main { transform: translateX(0); }
  .mobile-chat-open-btn {
    display: inline-flex; position: fixed; right: 0; top: 50%; z-index: 1190;
    align-items: center; gap: 5px; padding: 9px 8px 9px 10px;
    border: 1px solid var(--line-2); border-right: 0; border-radius: 9px 0 0 9px;
    background: var(--panel); color: var(--text-2); font-size: 12px; cursor: pointer;
    transform: translateY(-50%); box-shadow: -4px 4px 12px color-mix(in srgb, var(--text) 8%, transparent);
  }
  .chat-shell.mobile-chat-open .mobile-chat-open-btn { display: none; }
}
.chat-main {
  position: relative;
  display: flex; flex-direction: column;
  min-width: 0;     /* 防 overflow */
  min-height: 0;    /* 允许中间消息区滚动，而不是把输入框顶出屏幕 */
  background: var(--bg);
  /* 隔离聊天内部层叠：消息流里大量 .stream-appear（will-change）会创建堆叠上下文，
     若不隔离，浮层（回到底部按钮 / 执行记录面板）的低 z-index 会与它们在同一祖先
     上下文里直接竞争，导致偶发被遮挡。isolate 把聊天整体收进独立堆叠上下文，
     外层（抽屉/弹窗 1100+）仍在其上，内部浮层只需高于消息流即可稳定置顶。 */
  isolation: isolate;
}
.chat-main.empty { align-items: center; justify-content: center; }
.chat-empty { text-align: center; color: var(--text-2); }
.chat-empty h2 { color: var(--text); margin-bottom: 8px; }

/* 微信连接按钮（在 chat-header 中） */
.conv-wechat-btn {
  padding: 3px 8px; font-size: 12px; line-height: 1.35;
  border-radius: 999px; background: transparent; color: var(--wechat); border-color: var(--wechat-a-38);
}
.conv-wechat-btn:hover { background: var(--wechat-a-08); }
.conv-wechat-btn.disconnect { color: var(--text-2); border-color: var(--border); background: var(--surface-tint); }
.conv-wechat-btn.disconnect:hover { color: var(--error); border-color: var(--error-a-45); background: var(--error-a-08); }

/* 右栏：header / 消息流 / 输入 */
.chat-header {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 16px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
/* 三栏顶栏：左右两侧等比 flex，让居中标题视觉居中；左品牌入口、右 ⋯ 工具栏入口 */
.chat-header-left { display: flex; align-items: center; gap: 6px; flex: 1 1 0; min-width: 0; justify-content: flex-start; }
.chat-header-actions { display: flex; align-items: center; gap: 6px; flex: 1 1 0; min-width: 0; justify-content: flex-end; }
/* 居中标题：Agent 名（主）+ 当前会话名（副，作上下文锚点） */
.chat-header-title {
  flex: 0 1 auto; min-width: 0;
  display: flex; flex-direction: column; align-items: center; text-align: center;
  line-height: 1.25; gap: 0;
}
.chat-header-title-main {
  font-weight: 600; font-size: 14px; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%;
}
.chat-header-title-sub {
  display: inline-flex; align-items: center; gap: 4px; max-width: 100%;
  font-size: 12px; color: var(--text-2); white-space: nowrap;
}
.chat-header-title-sub-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.theme-toggle-btn { font-size: 16px; padding: 4px 8px !important; line-height: 1; }
.agent-toolbar-btn { font-size: 18px; padding: 4px 10px !important; line-height: 1; }
/* Agent 工具栏抽屉：单层结构无子页，隐藏「返回」按钮占位，让顶部 Agent 名左对齐到栏目名 */
.agent-toolbar-drawer .drawer-back { display: none; }
.agent-toolbar-drawer .drawer-head { padding-left: 16px; }
.agent-toolbar-drawer .drawer-head-title { font-weight: 600; }
.conv-dropdown {
  position: absolute; top: calc(100% + 4px); left: 0;
  min-width: 220px; max-height: 360px; overflow: auto;
  background: var(--panel); border: 1px solid var(--border); border-radius: 10px;
  box-shadow: 0 12px 36px rgba(0,0,0,.35); padding: 8px; z-index: 500;
}
.conv-dropdown-item {
  width: 100%; padding: 6px 10px; border: none; border-radius: 6px;
  background: transparent; color: var(--text); cursor: pointer; text-align: left;
  font-size: 13px; display: flex; align-items: center; justify-content: space-between; gap: 4px;
}
.conv-dropdown-item:hover { background: var(--panel-2); }
.conv-dropdown-item.current { color: var(--primary); background: var(--primary-a-08); }
.conv-dropdown-item-badges { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }
.conv-dropdown-item-text { display: flex; align-items: center; gap: 7px; overflow: hidden; min-width: 0; flex: 1; }
.conv-dropdown-item-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }

/* ── 会话运行态状态点（会话清单名称前）：闲着/执行中/等待交互/出错 ── */
.conv-state-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; display: inline-block; }
.conv-state-dot.idle { background: var(--text-2); opacity: .45; }
.conv-state-dot.running { position: relative; background: var(--primary); }
.conv-state-dot.waiting { background: var(--warn); box-shadow: 0 0 5px var(--warn-a-45); }
.conv-state-dot.error { background: var(--error); box-shadow: 0 0 5px rgba(248,81,73,.6); }
/* 雷达波纹改用 ::after + transform:scale + opacity（纯合成器属性），
   替代原来逐帧动 box-shadow spread（0→6px，每帧重画）。会话列表多条同时 running 时收益更明显。 */
.conv-state-dot.running::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
  background: var(--primary-a-45);
  animation: conv-pulse-ring 1.4s ease-out infinite; will-change: transform, opacity;
}
@keyframes conv-pulse-ring {
  0% { transform: scale(1); opacity: .55; }
  100% { transform: scale(3.2); opacity: 0; }
}
.conv-wechat-badge {
  display: inline-flex; align-items: center; gap: 2px;
  margin-left: 4px; padding: 1px 6px; border-radius: 999px;
  font-size: 10px; line-height: 1.35; font-weight: 600;
  background: var(--wechat-a-18); color: var(--wechat); border: 1px solid var(--wechat-a-45);
  box-shadow: 0 0 4px var(--wechat-a-15);
  white-space: nowrap; flex-shrink: 0;
}
.conv-dropdown-wechat-action {
  width: 100%; padding: 4px 10px; border-radius: 6px;
  font-size: 12px; cursor: pointer; text-align: left;
  border: 1px dashed var(--border); background: transparent; color: var(--text-2);
}
.conv-dropdown-wechat-action:hover { background: var(--panel-2); }
.conv-dropdown-wechat-action.connected {
  border-color: var(--wechat-a-35); color: var(--wechat); background: var(--wechat-a-06);
}
.conv-dropdown-wechat-action.connected:hover { background: var(--error-a-08); color: var(--error); border-color: var(--error-a-35); }
.conv-dropdown-archive {
  flex-shrink: 0; padding: 2px 6px;
  font-size: 11px; line-height: 1.3; color: var(--text-2); cursor: pointer;
  border-radius: 4px; border: 1px solid var(--border); background: transparent;
  white-space: nowrap;
}
.conv-dropdown-archive:hover { color: var(--error); border-color: var(--error-a-35); background: var(--error-a-08); }

/* ── 会话列表（在「⋯」Agent 工具栏抽屉的「会话」分组内）：每行 = 状态点 + 完整会话名 + 微信徽章 + 重命名/删除 ── */
.conv-list { display: flex; flex-direction: column; gap: 4px; }
.conv-new-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  width: 100%; margin-bottom: 8px; padding: 7px 12px;
  background: transparent; color: var(--text-2);
  border: 1px dashed var(--border); border-radius: 8px;
  font-size: 13px; cursor: pointer;
  transition: background .15s var(--ease-standard), color .15s var(--ease-standard), border-color .15s var(--ease-standard);
}
.conv-new-btn:hover { color: var(--text); background: var(--panel-2); border-color: var(--text-2); }
.conv-list-row {
  display: flex; align-items: center; gap: 4px;
  border-radius: 8px; padding: 2px 4px 2px 2px;
}
.conv-list-row:hover { background: var(--panel-2); }
.conv-list-row.current { background: var(--primary-a-08); }
.conv-list-row-main {
  flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px;
  padding: 7px 8px; border: none; background: transparent; color: var(--text);
  cursor: pointer; text-align: left; font-size: 14px; border-radius: 6px;
}
.conv-list-row.current .conv-list-row-main { color: var(--primary); font-weight: 600; }
.conv-list-row-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; flex: 1; }
.conv-list-row-actions { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
.conv-list-action {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px; padding: 0; border-radius: 6px;
  border: 1px solid transparent; background: transparent; color: var(--text-2); cursor: pointer;
}
.conv-list-action:hover { background: var(--panel); color: var(--text); }
.conv-list-action.delete:hover { color: var(--error); background: var(--error-a-08); }

/* 消息流 */
.chat-messages {
  flex: 1; min-height: 0; overflow: auto;
  padding: 20px 16px;
  display: flex; flex-direction: column; gap: 16px;
  scroll-behavior: auto;
  /* 关掉浏览器滚动锚定：它会在上方内容尺寸变化时主动改写 scrollTop 以"保持视觉位置"，
   * 与会话区的吸底跟随直接冲突，且改写会派发 scroll 事件、污染"用户是否想离开底部"的
   * 判定，导致自动跟随偶发失效。IM 会话区一律以"跟随最新"为准，不需要视觉位置保持。 */
  overflow-anchor: none;
}
.chat-bottom-sentinel { flex: 0 0 1px; height: 1px; pointer-events: none; }
.scroll-bottom-btn {
  position: absolute; right: 24px; bottom: calc(var(--composer-h, 108px) + 12px); z-index: 20;
  display: inline-flex; align-items: center; gap: 6px;
  height: 34px; padding: 0 12px; border-radius: 999px;
  border: 1px solid var(--primary-a-45); background: var(--surface-raised); color: var(--text);
  box-shadow: 0 10px 30px rgba(0,0,0,.32); cursor: pointer;
  opacity: 0; transform: translateY(8px); pointer-events: none;
  transition: opacity .16s ease, transform .16s ease, background .16s ease;
}
.scroll-bottom-btn.show { opacity: 1; transform: translateY(0); pointer-events: auto; }
.scroll-bottom-btn:hover { background: var(--panel-2); }
.scroll-bottom-btn.has-new { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary-a-22), 0 10px 30px rgba(0,0,0,.32); }
/* 「查看本轮结果」态：用户在上方阅读时，结构化结果出现后用主色浮标引导直达，而不是只能回到底部。 */
.scroll-bottom-btn.has-result { border-color: var(--primary); background: var(--primary-a-08); box-shadow: 0 0 0 1px var(--primary-a-22), 0 10px 30px rgba(0,0,0,.32); }
.scroll-bottom-btn.has-result .scroll-bottom-text { color: var(--primary); font-weight: 600; }
.scroll-bottom-icon { font-size: 16px; line-height: 1; color: var(--primary); }
.scroll-bottom-text { font-size: 12px; }

/* 一组 turn = 用户气泡 + AI 气泡 */
/* 已回退 content-visibility:auto（曾用于长会话性能优化，见下方说明）：
   .turn 高度差异极大（一句话 vs 含图片/工具块/交付卡的长内容），auto 260px 只是一个粗略估算。
   用户往上翻历史时，原本被跳过渲染的 turn 进入视口会从"占位高度"跳变为"真实高度"，
   这个尺寸变化同时被两套机制感知并各自尝试补偿滚动位置：浏览器自身的 scroll anchoring，
   以及本文件 app.js 里专门 observe(.turn) 的 ResizeObserver（用于「回到底部」浮标与吸底判定）——
   两者叠加导致翻阅历史时持续跳动、无法正常阅读。这正是加规则时预留的回退条件命中，
   故直接移除，不再连带排查 ResizeObserver/scroll anchoring 逻辑本身。 */
.turn { display: flex; flex-direction: column; gap: 12px; }
.turn.optimistic { opacity: .78; }

.msg { display: flex; gap: 10px; max-width: 100%; }
.msg.user { flex-direction: column; align-items: flex-end; }
.msg.user .msg-content {
  background: var(--primary); color: var(--accent-fg);
  padding: 10px 14px; border-radius: 14px 14px 4px 14px;
  max-width: 75%;
  white-space: pre-wrap; word-break: break-word;
}
/* 自己发出内容的复制入口：常态完全不可见（不占视觉注意力），只在鼠标悬停这条消息时才
   淡入显示；空间提前预留（margin-top 常驻），避免 hover 时把下方内容顶出去造成跳动。 */
.msg-user-actions { display: flex; justify-content: flex-end; margin-top: 4px; opacity: 0; transition: opacity .15s ease; }
.msg.user:hover .msg-user-actions,
.msg.user:focus-within .msg-user-actions { opacity: 1; }
.msg-user-copy {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; padding: 0; border: 0; border-radius: 6px;
  background: transparent; color: var(--text-2); cursor: pointer;
  transition: color .15s, background .15s;
}
.msg-user-copy:hover { color: var(--text); background: var(--panel); }
.msg-user-copy:focus-visible { outline: 2px solid color-mix(in srgb, var(--primary) 55%, transparent); outline-offset: 1px; }
.msg.ai { align-items: flex-start; }
.msg.ai .msg-avatar {
  flex: 0 0 28px; width: 28px; height: 28px;
  border-radius: 50%; background: var(--panel-2);
  display: flex; align-items: center; justify-content: center;
  font-size: 14px; color: var(--primary);
  border: 1px solid var(--border);
}
.msg.ai .msg-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 8px; position: relative; }
.msg.ai .msg-content {
  background: var(--panel); border: 1px solid var(--border);
  padding: 12px 14px; border-radius: 4px 14px 14px 14px;
  white-space: pre-wrap; word-break: break-word;
}
/* 活动指示器已就近 in-flow（不再覆盖正文），无需为其预留顶部空白 */
.ai-text {
  margin: 0 -6px; padding: 4px 6px; border-radius: 8px;
  line-height: 1.65;
  transition: background .9s ease-out, box-shadow .9s ease-out;
}
.ai-text.is-growing {
  background: linear-gradient(90deg, var(--primary-a-08), transparent 92%);
  box-shadow: inset 2px 0 0 var(--primary-a-24);
}
/* 已定稿的完整 assistant 消息段：保留段落边界，避免多段正文紧贴成一坨。 */
.ai-text.ai-text-settled + .ai-text { margin-top: 10px; }
.ai-process {
  margin: 6px 0 8px;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: color-mix(in srgb, var(--surface, var(--panel)) 88%, transparent);
  overflow: hidden;
}
.ai-process > summary {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 7px 10px;
  cursor: pointer;
  user-select: none;
  color: var(--text-2);
  font-size: 12.5px;
  list-style: none;
}
.ai-process > summary::-webkit-details-marker { display: none; }
.ai-process > summary::before {
  content: '›';
  color: var(--primary);
  font-weight: 700;
  transition: transform .16s ease;
}
.ai-process[open] > summary::before { transform: rotate(90deg); }
.ai-process > summary:hover { color: var(--text); background: var(--surface-tint); }
.ai-process .ai-process-content {
  margin: 0;
  padding: 10px 12px;
  border-top: 1px solid var(--border);
  background: var(--surface, var(--panel));
}
/* 结果优先层：终态先呈现交付、验证与下一步，过程叙事和阶段证据保留在其后。 */
.turn-delivery {
  margin: 0 0 12px; padding: 11px 12px 10px;
  border: 1px solid var(--border); border-left: 3px solid var(--primary);
  border-radius: 11px; background: var(--surface-tint);
}
.turn-delivery-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.turn-delivery-head strong { font-size: 14px; line-height: 1.45; }
.turn-delivery-head.status-done { color: var(--success); }
.turn-delivery-head.status-paused,
.turn-delivery-head.status-blocked,
.turn-delivery-head.status-incomplete { color: var(--warn); }
.turn-delivery-head.status-failed { color: var(--error); }
.turn-delivery-head.claim-rejected { color: var(--warn); }
.turn-delivery-count { flex: 0 0 auto; padding: 2px 7px; border-radius: 999px; color: var(--text-2); background: var(--panel); font-size: 11px; }
.turn-delivery-summary { margin: 5px 0 0; color: var(--text); line-height: 1.6; white-space: pre-wrap; word-break: break-word; }
.turn-delivery-actions { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 9px; }
.turn-delivery-continue { min-height: 28px; padding: 4px 9px; font-size: 12px; }
.turn-delivery-details:not(:empty) { margin-top: 10px; }
.turn-delivery-details .turn-summary { margin: 0; padding-top: 9px; }

/* ============ 运维提示条（turn-notice）============
   与「业务失败原因」严格分层的第二类信息：它描述的是平台观测状态
   （连接静默、状态查询失败），不是本轮任务的结论。
   视觉上刻意做得比交付区弱一档——无标题、无卡片、只有一行细字加一枚图标，
   让它可被读到但不与结论争夺注意力；任务拿到终态后由JS 主动撤下。 */
.turn-notice { display: flex; flex-direction: column; gap: 5px; margin: 7px 0 0; }
.turn-notice-row {
  display: flex; align-items: flex-start; gap: 7px;
  padding: 6px 9px; border-radius: 8px;
  border: 1px solid transparent;
  font-size: 12px; line-height: 1.6;
}
.turn-notice-row.tone-warn {
  color: var(--warn); background: var(--warn-a-06);
  border-color: var(--warn-a-35);
}
.turn-notice-row.tone-info { color: var(--text-2); background: var(--surface-tint); border-color: var(--border); }
.turn-notice-icon { flex: 0 0 auto; margin-top: 1px; }
.turn-notice-text { min-width: 0; word-break: break-word; }
/* ============================================================
 * 会话正文排版（Markdown-lite → 语义 DOM）
 *
 * 目标是「长文可读」而不是「元素好看」：
 *  ·竖向节奏统一为4 档间距（4/ 8 / 14 / 20），块间留白大于块内留白，
 *    读者靠留白就能分组，不需要靠边框/底色区分；
 *  · 强调只用字重与颜色，不用色块——一段话里出现两种底色就失去了强调意义；
 *  · 列表交回浏览器 marker +缩进（真正的 ul/ol 嵌套），不再用底色卡片和虚线分隔，
 *    那种画法把「要点」读成了「表格」，噪音压过内容。
 * ============================================================ */
.ai-plain-text {
  /* pre-wrap 仅用于兜底纯文本分支；结构化分支里的软换行已由 <br> 承载。 */
  white-space: pre-wrap; word-break: break-word;
  font-size: 14px; line-height: 1.78; color: var(--text);
}
/* 结构化渲染成功后交由各块自己控制留白：容器不再整体 pre-wrap，
   否则源文本换行会与块级间距叠加，长回答被撑成一堆空行。
   标记由 fillPlainTextNode 显式添加（不用 :has()，避开旧 WebView 支持缺口）。 */
.ai-plain-text.is-rich { white-space: normal; }

/* —— 段落 —— */
.ai-plain-para { margin: 8px 0; line-height: 1.78; }
.ai-plain-para:first-child { margin-top: 0; }
.ai-plain-para:last-child { margin-bottom: 0; }

/* —— 标题：按层级分级，靠字号/字重/上间距建立节奏，不再一律700 加粗 —— */
.ai-plain-head { margin: 20px 0 8px; color: var(--text); line-height: 1.45; font-weight: 650; }
.ai-plain-head:first-child { margin-top: 2px; }
.ai-plain-head-h1 { font-size: 16.5px; font-weight: 700; letter-spacing: -.01em; }
.ai-plain-head-h2 { font-size: 15px; font-weight: 700; }
.ai-plain-head-h3 { font-size: 14px; font-weight: 650; }
.ai-plain-head-h4, .ai-plain-head-h5, .ai-plain-head-h6 {
  font-size: 13px; font-weight: 650; color: var(--text-2);
  letter-spacing: .02em;
}
/* h1/h2 带一条极淡的分组线：长回答里章节感靠它建立，比加大字号更克制 */
.ai-plain-head-h1, .ai-plain-head-h2 { padding-bottom: 5px; border-bottom: 1px solid var(--line, var(--border)); }

/* —— 列表：真正的 ul/ol 嵌套；marker 用主色但只上色不加粗，避免与加粗正文抢焦点 —— */
.ai-plain-list-group { margin: 8px 0; }
.ai-plain-list-group:first-child { margin-top: 0; }
.ai-plain-list-group:last-child { margin-bottom: 0; }
.ai-plain-list {
  margin: 0; padding-left: 1.5em;
  font-size: inherit; line-height: 1.75; color: inherit;
}
.ai-plain-list + .ai-plain-list { margin-top: 6px; }
.ai-plain-list.is-bullet { list-style: disc; }
.ai-plain-list.is-ordered { list-style: decimal; }
/* 嵌套层级换marker 形状：视觉上一眼分层，且不依赖缩进像素 */
.ai-plain-list-l1.is-bullet { list-style: circle; }
.ai-plain-list-l2.is-bullet { list-style: square; }
.ai-plain-list-l3.is-bullet { list-style: disc; }
.ai-plain-list-l1.is-ordered { list-style: lower-alpha; }
.ai-plain-list-l2.is-ordered { list-style: lower-roman; }
.ai-plain-list-l3.is-ordered { list-style: decimal; }
.ai-plain-list-item {
  margin: 5px 0; padding-left: 2px;
  word-break: break-word;
}
.ai-plain-list-item::marker { color: var(--text-3); }
.ai-plain-list.is-ordered > .ai-plain-list-item::marker { color: var(--primary); font-variant-numeric: tabular-nums; }
/* 子列表贴紧父项：留白只在同层之间，父子之间收紧，层级关系才读得出来 */
.ai-plain-list-item > .ai-plain-list { margin-top: 4px; }
.ai-plain-list-body { display: inline; }

/* —— 任务清单：只读呈现（AI 输出的状态，不是可交互控件），勾选框对齐首行基线 —— */
.ai-plain-list-item.is-task { list-style: none; margin-left: -1.25em; display: flex; align-items: flex-start; gap: 7px; }
.ai-task-box {
  flex: 0 0 auto; width: 14px; height: 14px; margin-top: 4px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 4px;
  font-size: 10px; line-height: 1; color: transparent;
}
.ai-plain-list-item.is-checked > .ai-task-box { border-color: var(--primary); background: var(--primary-a-08); color: var(--primary); }
.ai-plain-list-item.is-checked > .ai-plain-list-body { color: var(--text-2); }

/* —— 引用块：左侧竖条+ 轻微内缩，不加底色（底色会让引用比正文更抢眼，本末倒置）—— */
.ai-plain-quote {
  margin: 10px 0; padding: 2px 0 2px 12px;
  border-left: 3px solid var(--primary-a-35);
  color: var(--text-2);
}
.ai-plain-quote .ai-plain-para { margin: 4px 0; }
.ai-plain-quote .ai-plain-quote { margin: 6px 0; border-left-color: var(--border); }

/* —— 表格：只保留横线（竖线会把表格画成网格，密度过高），表头浅底 —— */
.ai-plain-table-wrap { margin: 10px 0; overflow-x: auto; border: 1px solid var(--border); border-radius: 10px; }
.ai-plain-table-wrap:focus-visible { outline: 2px solid var(--primary-a-45); outline-offset: 1px; }
.ai-plain-table { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 1.6; }
.ai-plain-table th,
.ai-plain-table td {
  padding: 7px 11px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border); word-break: break-word;
}
.ai-plain-table thead th {
  background: var(--surface-tint); color: var(--text);
  font-weight: 650; white-space: nowrap;
}
.ai-plain-table tbody tr:last-child td { border-bottom: 0; }
.ai-plain-table tbody tr:hover td { background: var(--surface-tint); }

/* —— 分隔线：比正文边框更淡，只做「话题切换」提示 —— */
.ai-plain-divider { height: 0; border-top: 1px solid var(--border); margin: 16px 0; opacity: .7; }

/* —— 行内语义：强调只动字重与颜色；链接可点可辨；行内代码与代码块同族但更轻 —— */
.ai-inline-strong { font-weight: 650; color: var(--text); }
.ai-inline-em { font-style: italic; color: inherit; }
.ai-inline-del { color: var(--text-3); text-decoration-thickness: 1px; }
.ai-inline-code {
  padding: 1px 5px; margin: 0 1px;
  border: 1px solid var(--border); border-radius: 5px;
  background: var(--surface-tint); color: var(--text);
  font-family: var(--mono); font-size: .92em; word-break: break-all;
}
.ai-inline-link {
  color: var(--primary);
  text-decoration: underline; text-decoration-color: var(--primary-a-35);
  text-underline-offset: 2px; text-decoration-thickness: 1px;
  word-break: break-all;
}
.ai-inline-link:hover { text-decoration-color: var(--primary); }
.ai-inline-link:focus-visible { outline: 2px solid var(--primary-a-45); outline-offset: 2px; border-radius: 3px; }
/* 外链标记：告诉用户会跳走，避免误以为是站内锚点 */
.ai-inline-link::after {
  content: '↗'; display: inline-block; margin-left: 2px;
  font-size: .82em; opacity: .6; text-decoration: none;
}
.ai-code-block { margin: 10px 0; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-tint); overflow: hidden; }
.ai-code-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-height: 31px; padding: 0 7px 0 10px; border-bottom: 1px solid var(--border); }
.ai-code-lang { min-width: 0; font-size: 11px; color: var(--text-2); }
.ai-code-copy { appearance: none; border: 0; border-radius: 6px; padding: 3px 7px; color: var(--text-2); background: transparent; font: inherit; font-size: 11px; cursor: pointer; }
.ai-code-copy:hover { color: var(--text); background: var(--panel); }
.ai-code-copy:focus-visible { outline: 2px solid color-mix(in srgb, var(--primary) 55%, transparent); outline-offset: 1px; }
.ai-code-pre { margin: 0; padding: 10px 12px; overflow-x: auto; font-size: 12.5px; line-height: 1.6; }

/* 取消正文内联光标：Agent 输出已是文本 + 组件 + 工具的混合形态，进度统一由消息级 turn-status 呼吸态表达。 */
.stream-appear {
  animation: streamAppear .42s ease-out both, streamGlow .9s ease-out;
}
@keyframes streamAppear {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}
@keyframes streamGlow {
  0% { filter: drop-shadow(0 0 0 var(--primary-a-24)); }
  18% { filter: drop-shadow(0 0 14px var(--primary-a-22)); }
  100% { filter: drop-shadow(0 0 0 transparent); }
}
.structured-output {
  margin: 12px 0 2px; padding: 10px 0 0;
  border-top: 1px solid var(--border); background: transparent;
  white-space: normal;
}
.structured-output-head { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; margin-bottom: 8px; }
.structured-output-head strong { font-size: 13px; letter-spacing: .01em; }
.structured-output-list { display: grid; gap: 8px; }
.structured-card {
  border: 1px solid var(--border); border-left: 3px solid var(--primary);
  border-radius: 10px; padding: 9px 11px; background: var(--surface-tint);
  box-shadow: none;
}
.structured-card.decision { border-left-color: var(--primary); }
.structured-card.implementation { border-left-color: var(--success); }
.structured-card.todo { border-left-color: var(--warn); }
.structured-card.issue,
.structured-card.warning { border-left-color: var(--error); }
.structured-card.constraint,
.structured-card.preference { border-left-color: var(--border); }
.structured-card-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 6px; }
.structured-badge {
  display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 999px;
  font-size: 11px; font-weight: 700; color: var(--primary); background: var(--primary-a-08);
}
.structured-badge.implementation { color: var(--success); background: var(--success-a-08); }
.structured-badge.todo { color: var(--warn); background: var(--warn-a-06); }
.structured-badge.issue,
.structured-badge.warning { color: var(--error); background: var(--error-a-08); }
.structured-badge.constraint,
.structured-badge.preference { color: #7c3aed; background: rgba(139, 92, 246, .10); }
.structured-meta { color: var(--text-2); font-size: 11px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.structured-card h4 { margin: 0 0 6px; font-size: 14px; line-height: 1.45; }
.structured-card p { margin: 0; color: var(--text); line-height: 1.65; white-space: pre-wrap; word-break: break-word; }

/* ============ 通用渲染组件（in-flow） ============
 * 视觉融入原则：与散文同宽、左对齐；用「左侧 3px 语义色条 + 极浅底」表达层次，
 * 不用粗描边/大投影，避免把卡片做成「浮于文字之上的弹窗」而割裂阅读流。
 * 间距与段落节奏一致（margin 12px 0），让组件像「抬升一段的段落」自然嵌进正文。
 */
.render-component {
  margin: 12px 0; padding: 10px 12px; border-radius: 10px;
  border: 1px solid var(--border); border-left: 3px solid var(--primary);
  background: var(--surface-tint); white-space: normal;
  font-size: 13.5px; line-height: 1.6;
}
.render-component .rc-head { font-size: 12.5px; font-weight: 700; letter-spacing: .02em; color: var(--text); margin-bottom: 8px; }
.render-component .rc-text { margin: 0; color: var(--text); white-space: pre-wrap; word-break: break-word; }
.render-component + .render-component { margin-top: 8px; }
/* 卡片紧贴前一段散文时收紧顶部，避免出现「段落空行 + 卡片」的断层 */
.ai-plain-text + .render-component { margin-top: 10px; }
.render-component + .ai-plain-text { margin-top: 2px; }
/* 首类内容组件流：容器不增加卡片层，组件自身保持统一视觉；阶段内按 sequence 排序。 */
.content-component-stream { display: contents; }
.content-component[data-stage-id] { scroll-margin-block: 80px; }

/* —— callout 提示框：覆盖风险/结论/注意等单点关键信息 —— */
.render-component.rc-callout { padding: 0; border: none; background: transparent; }
.render-component.rc-callout .rc-callout-body { padding: 9px 12px; border-radius: 10px; border: 1px solid var(--border); border-left: 3px solid var(--primary); background: var(--primary-a-08); }
.render-component.rc-callout-info .rc-callout-body { border-left-color: var(--primary); background: var(--primary-a-08); }
.render-component.rc-callout-success .rc-callout-body { border-left-color: var(--success); background: var(--success-a-08); }
.render-component.rc-callout-warning .rc-callout-body { border-left-color: var(--warn); background: var(--warn-a-06); }
.render-component.rc-callout-danger .rc-callout-body { border-left-color: var(--error); background: var(--error-a-08); }
.render-component.rc-callout-neutral .rc-callout-body { border-left-color: var(--text-2); background: var(--surface-tint); }
.render-component .rc-callout-title { font-weight: 700; font-size: 13px; margin-bottom: 3px; color: var(--text); }
.render-component.rc-callout-success .rc-callout-title { color: var(--success); }
.render-component.rc-callout-warning .rc-callout-title { color: var(--warn); }
.render-component.rc-callout-danger .rc-callout-title { color: var(--error); }
.render-component.rc-callout .rc-callout-body > p.rc-text:last-child { margin-bottom: 0; }

/* —— steps 步骤：替代「一长串 1. 2. 3. 散文」—— */
.render-component.rc-steps { border-left-color: var(--primary); }
.render-component.rc-steps .rc-steps { margin: 0; padding: 0; list-style: none; counter-reset: rcstep; display: grid; gap: 8px; }
.render-component.rc-steps .rc-step { position: relative; padding-left: 30px; }
.render-component.rc-steps .rc-step::before {
  counter-increment: rcstep; content: counter(rcstep);
  position: absolute; left: 0; top: 0; width: 20px; height: 20px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 700; color: var(--primary);
  background: var(--primary-a-08); border: 1px solid var(--primary-a-22);
}
.render-component.rc-steps .rc-step-title { font-weight: 600; color: var(--text); margin-bottom: 1px; }
.render-component.rc-steps .rc-step-body { color: var(--text-2); font-size: 13px; }

/* —— kv 键值清单：配置/参数/属性 ——
 * 网格必须落在 <dl> 自身。此前选择器写成 .render-component.rc-kv，而外层容器同时带
 * render-component + rc-kv 两个类：网格生效在【容器】上，于是标题被塞进第一列（窄）、
 * 整份 dl 被塞进第二列，而 dl 自己反倒不是网格——表现就是「标题孤零零留在左边，
 * 键值全挤到右侧窄栏里，且标签与值上下堆叠、长句逐字换行」。
 * 标签列用 fit-content(30%) 封顶：既随内容自适应，也不会被一个长标签吃掉整行宽度。 */
dl.rc-kv { margin: 0; display: grid; grid-template-columns: fit-content(30%) minmax(0, 1fr); gap: 4px 14px; }
dl.rc-kv dt { color: var(--text-2); font-size: 12.5px; word-break: break-word; }
dl.rc-kv dd { margin: 0; color: var(--text); white-space: pre-wrap; word-break: break-word; }

/* —— stat 指标：验证结果/性能数据 —— */
.render-component.rc-stat { border-left-color: var(--success); }
.render-component.rc-stat .rc-stat-row { display: flex; flex-wrap: wrap; gap: 10px; }
.render-component.rc-stat .rc-stat { min-width: 84px; padding: 8px 12px; border-radius: 8px; background: var(--surface-tint); border: 1px solid var(--border); }
.render-component.rc-stat .rc-stat-value { font-size: 18px; font-weight: 700; color: var(--text); line-height: 1.2; }
.render-component.rc-stat .rc-stat-label { font-size: 12px; color: var(--text-2); margin-top: 2px; }
.render-component.rc-stat .rc-stat-hint { font-size: 11px; color: var(--text-2); margin-top: 1px; }

/* —— compare 对比表：方案/选型 —— */
.render-component.rc-compare { border-left-color: var(--cat-1); padding-right: 8px; }
.render-component.rc-compare .rc-compare-wrap { overflow-x: auto; }
.render-component.rc-compare table.rc-compare { width: 100%; border-collapse: collapse; font-size: 13px; }
.render-component.rc-compare .rc-compare th, .render-component.rc-compare .rc-compare td { padding: 6px 10px; text-align: left; border-bottom: 1px solid var(--border); white-space: pre-wrap; word-break: break-word; vertical-align: top; }
.render-component.rc-compare .rc-compare thead th { font-size: 12px; color: var(--text-2); font-weight: 700; border-bottom-color: var(--primary-a-22); }
.render-component.rc-compare .rc-compare-corner { width: auto; }
.render-component.rc-compare .rc-compare-label { color: var(--text-2); font-weight: 600; white-space: nowrap; }
.render-component.rc-compare .rc-compare tbody tr:last-child td, .render-component.rc-compare .rc-compare tbody tr:last-child th { border-bottom: none; }

/* summary 复用既有 .structured-output，无需重复样式；rc-summary 仅占位 */
.render-component.rc-summary { border: none; background: transparent; padding: 0; margin: 0; }

/* —— copy_block 可复制内容块：代码 / 提示词 / 命令 / 配置 —— */
.render-component.rc-copy-block { padding: 0; overflow: hidden; border-left-color: var(--primary); background: var(--surface, var(--panel)); }
.render-component.rc-copy-block .rc-copy-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 8px 10px; border-bottom: 1px solid var(--border); background: var(--surface-tint); }
.render-component.rc-copy-block .rc-copy-title { display: flex; align-items: center; gap: 8px; min-width: 0; font-weight: 700; color: var(--text); font-size: 12.5px; }
.render-component.rc-copy-block .rc-copy-lang { font: 11px/1.4 var(--mono); color: var(--text-2); border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px; background: var(--surface, var(--panel)); }
.render-component.rc-copy-block .rc-copy-btn { padding: 2px 10px; font-size: 12px; white-space: nowrap; }
.render-component.rc-copy-block .rc-copy-code { margin: 0; padding: 12px; max-height: 420px; overflow: auto; background: var(--bg); color: var(--text); font: 12px/1.55 var(--mono); white-space: pre; tab-size: 2; }
.render-component.rc-copy-block .rc-copy-code code { font: inherit; color: inherit; }

/* —— 通用布局渲染器：tree / timeline / stat-checks / log-highlights / gallery —— */
.render-component.rc-tree-wrap { border-left-color: var(--primary); }
.render-component .rc-tree, .render-component .rc-tree ul { list-style: none; margin: 0; padding: 0; }
.render-component .rc-tree { display: grid; gap: 4px; }
.render-component .rc-tree-node { position: relative; padding-left: 16px; }
.render-component .rc-tree-node::before { content: ''; position: absolute; left: 4px; top: 0; bottom: 0; border-left: 1px solid var(--border); }
.render-component .rc-tree-node > .rc-tree { margin-top: 4px; }
.render-component .rc-tree-label { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--text); }
.render-component .rc-badge { display: inline-flex; align-items: center; font-size: 11px; padding: 1px 6px; border-radius: 999px; border: 1px solid var(--border); color: var(--text-2); background: var(--surface-tint); }
.render-component .rc-badge-ok { color: var(--success); border-color: var(--success); background: var(--success-a-08); }
.render-component .rc-badge-err { color: var(--error); border-color: var(--error); background: var(--error-a-08); }
.render-component .rc-badge-warn { color: var(--warn); border-color: var(--warn); background: var(--warn-a-06); }
.render-component .rc-badge-muted { color: var(--text-2); }

.render-component.rc-timeline { border-left-color: var(--primary); }
.render-component .rc-timeline { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.render-component .rc-tl-item { display: grid; grid-template-columns: max-content 1fr; gap: 10px; }
.render-component .rc-tl-dot { display: flex; align-items: flex-start; padding-top: 2px; }
.render-component .rc-tl-body { border-left: 2px solid var(--border); padding-left: 10px; }
.render-component .rc-tl-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.render-component .rc-tl-time { font-size: 11px; font-weight: 700; color: var(--primary); font-family: var(--mono); }
.render-component .rc-tl-title { font-size: 13px; font-weight: 600; color: var(--text); }
.render-component .rc-tl-text { font-size: 13px; margin-top: 2px; }
.render-component .rc-tl-decision { font-size: 12px; margin-top: 2px; }

.render-component .rc-stat-checks { display: grid; gap: 4px; margin-top: 8px; }
.render-component .rc-stat-check { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--text-2); }
.render-component .rc-log-highlights { list-style: none; margin: 8px 0 0; padding: 0; display: grid; gap: 2px; max-height: 180px; overflow: auto; }
.render-component .rc-log-line { font: 12px/1.5 var(--mono); color: var(--text-2); white-space: pre-wrap; word-break: break-word; }
.render-component .rc-log-warn { color: var(--warn); }
.render-component .rc-log-error { color: var(--error); }
.render-component .rc-mono { font-family: var(--mono); }

.render-component.rc-gallery .rc-gallery-row { display: flex; flex-wrap: wrap; gap: 10px; }
.render-component.rc-gallery .rc-gallery-item { margin: 0; min-width: 120px; }
.render-component.rc-gallery .rc-gallery-item img { max-width: 200px; max-height: 160px; border-radius: 8px; border: 1px solid var(--border); }
.render-component.rc-gallery .rc-gallery-item figcaption { font-size: 12px; font-weight: 600; color: var(--text); margin-top: 4px; }

/* ============================================================
 * promptshot：图片提示词卡 / 详情（上图下词）
 *
 * 图占主要面积——它是"这条提示词值不值得用"的唯一证据；提示词正文在下方，
 * 等宽字+ 复制按钮，是复现它的唯一手段。未关联成图时占位块保持同样的
 * aspect-ratio，关联后版式不跳动。
 * ============================================================ */
.render-component.rc-promptshot {
  margin: 12px 0; padding: 0; overflow: hidden;
  border: 1px solid var(--border); border-radius: var(--r-lg, 12px);
  background: var(--panel);
}
.rc-promptshot .rc-ps-head {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 9px 12px; border-bottom: 1px solid var(--line, var(--border));
}
.rc-promptshot .rc-ps-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; color: var(--text); }
.rc-promptshot .rc-ps-state { flex-shrink: 0; padding: 1px 7px; border-radius: 999px; font-size: 10.5px; font-weight: 600; letter-spacing: .02em; }
.rc-promptshot .rc-ps-state.is-done { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.rc-promptshot .rc-ps-state.is-pending { color: var(--text-3); background: var(--surface-tint); }

/* 图区：整卡宽，最大高度收敛以免竖版图把会话撑得过长 */
.rc-promptshot .rc-ps-stage {
  position: relative; width: 100%; max-height: min(62vh, 560px);
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-tint); overflow: hidden;
}
.rc-promptshot .rc-ps-stage img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rc-promptshot .rc-ps-empty {
  flex-direction: column; gap: 5px; padding: 18px;
  background:
    repeating-linear-gradient(135deg, color-mix(in srgb, var(--border) 26%, transparent) 0 1px, transparent 1px 9px),
    var(--surface-tint);
  border-bottom: 1px dashed var(--border);
}
.rc-promptshot .rc-ps-empty-mark { font-size: 26px; line-height: 1; color: var(--text-3); opacity: .5; }
.rc-promptshot .rc-ps-empty-title { color: var(--text-2); font-size: 13px; font-weight: 650; }
.rc-promptshot .rc-ps-empty-hint { max-width: 30em; color: var(--text-3); font-size: 11.5px; line-height: 1.6; text-align: center; }
.rc-promptshot .rc-ps-empty-aspect {
  position: absolute; right: 8px; bottom: 8px;
  padding: 1px 6px; border-radius: 5px;
  color: var(--text-3); background: color-mix(in srgb, var(--panel) 82%, transparent);
  font: 10px/1.6 var(--mono);
}

/* 词区 */
.rc-promptshot .rc-ps-body { display: grid; gap: 8px; padding: 10px 12px 12px; }
.rc-promptshot .rc-ps-prompt-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.rc-promptshot .rc-ps-label { color: var(--text-3); font-size: 10.5px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
.rc-promptshot .rc-ps-copy { flex-shrink: 0; padding: 2px 9px; font-size: 11.5px; }
.rc-promptshot .rc-ps-prompt {
  margin: 0; max-height: 240px; overflow: auto;
  padding: 9px 10px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--input-bg, var(--surface-tint));
  color: var(--text); font: 12px/1.7 var(--mono);
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.rc-promptshot .rc-ps-negative { display: flex; align-items: baseline; gap: 8px; color: var(--text-2); font-size: 11.5px; line-height: 1.6; }
.rc-promptshot .rc-ps-negative span:last-child { min-width: 0; overflow-wrap: anywhere; }
.rc-promptshot .rc-ps-meta { display: flex; flex-wrap: wrap; gap: 5px; }
.rc-promptshot .rc-ps-chip {
  display: inline-flex; align-items: baseline; gap: 4px;
  padding: 2px 8px; border: 1px solid var(--border); border-radius: 999px;
  background: transparent; font-size: 11px;
}
.rc-promptshot .rc-ps-chip em { color: var(--text-3); font-style: normal; }
.rc-promptshot .rc-ps-chip b { color: var(--text); font-weight: 600; }
.rc-promptshot .rc-ps-dims {
  display: grid; grid-template-columns: minmax(72px, auto) minmax(0, 1fr); gap: 3px 10px;
  margin: 2px 0 0; padding-top: 8px; border-top: 1px solid var(--line, var(--border));
}
.rc-promptshot .rc-ps-dims dt { color: var(--text-3); font-size: 11.5px; line-height: 1.6; }
.rc-promptshot .rc-ps-dims dd { margin: 0; min-width: 0; color: var(--text); font-size: 11.5px; line-height: 1.6; overflow-wrap: anywhere; }
.rc-promptshot .rc-ps-dim-note { display: block; color: var(--text-3); font-size: 11px; line-height: 1.55; }

@media (max-width: 640px) {
  .rc-promptshot .rc-ps-stage { max-height: 68vh; }
  .rc-promptshot .rc-ps-prompt { max-height: 200px; font-size: 11.5px; }
  .rc-promptshot .rc-ps-dims { grid-template-columns: minmax(0, 1fr); gap: 0 0; }
  .rc-promptshot .rc-ps-dims dt { margin-top: 6px; font-weight: 600; }
}

html.light .render-component.rc-callout-neutral .rc-callout-body { border-left-color: var(--text-2); }
.ai-error {
  background: var(--error-a-08);
  border: 1px solid var(--error);
  color: var(--error);
  padding: 8px 12px; border-radius: 6px;
  font: 12px/1.5 var(--mono);
  white-space: pre-wrap; word-break: break-word;
}
.ai-pipeline {
  margin: 6px 0 0; padding: 8px 12px; border-radius: 6px;
  font: 12px/1.5 var(--mono); white-space: pre-wrap; word-break: break-word;
  border: 1px solid var(--success-a-42); color: var(--text); background: var(--success-a-08);
}
.ai-pipeline.bad { border-color: var(--error); color: var(--error); background: var(--error-a-08); }
/* 阶段节点只负责把流式正文归位；过程标题、来源、状态和更新不进入普通用户界面。
   当前进展统一由下方不可展开的胶囊表达，避免与正文争夺注意力或泄露内部细节。 */
.work-stages { display: flex; flex-direction: column; gap: 0; width: 100%; max-width: 760px; }
.work-stage { display: contents; }
.work-stage-head,
.work-stage-updates { display: none !important; }
.work-stage-body { padding: 0; }
.work-stage-model-output:not(:empty) { margin: 0; padding: 0; border: 0; }
.work-stage-model-output .ai-text { margin: 0; }

.turn-summary {
  margin: 10px 0 4px; padding: 0;
  border: 0; border-radius: 0;
  background: transparent; white-space: normal; word-break: normal; overflow-wrap: normal;
}
/* 本轮结果出现时的一次性高亮描边，告诉用户“这是这一轮的结果”，动画结束后由 JS 移除该类。 */
.turn-summary.result-focus { animation: resultFocus 1.4s ease-out; }
@keyframes resultFocus {
  0% { box-shadow: 0 0 0 0 var(--primary-a-38); border-color: var(--primary); }
  35% { box-shadow: 0 0 0 4px var(--primary-a-22); border-color: var(--primary); }
  100% { box-shadow: 0 0 0 0 rgba(0,0,0,0); }
}
.turn-summary-head { display: flex; justify-content: space-between; align-items: baseline; gap: 10px; margin-bottom: 8px; }
.turn-summary-head strong { font-size: 13px; }
.turn-summary-list { display: flex; flex-direction: column; gap: 4px; }
.turn-summary-row { display: grid; grid-template-columns: 18px minmax(0, 1fr) auto auto min-content; gap: 8px; align-items: center; font: 12px/1.45 var(--mono); }
.turn-summary-symbol { font-weight: 700; text-align: center; }
.turn-summary-row.added .turn-summary-symbol { color: var(--success); }
.turn-summary-row.modified .turn-summary-symbol { color: var(--warn); }
.turn-summary-row.deleted .turn-summary-symbol { color: var(--error); }
.turn-summary-path { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.turn-summary-actions { display: inline-flex; align-items: center; justify-content: flex-end; gap: 6px; }
.turn-summary-open {
  min-height: 28px; padding: 4px 9px; border-radius: 999px; border: 1px solid var(--primary-a-38);
  background: var(--primary-a-08); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", sans-serif;
  font-size: 12px; line-height: 1.35; display: inline-flex; align-items: center;
}
.turn-summary-open:hover { background: var(--primary-a-16); }
.turn-summary-label { color: var(--text-2); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", sans-serif; font-size: 11px; white-space: nowrap; word-break: keep-all; min-width: 28px; }
.turn-summary-all { display: inline-flex; align-self: flex-start; margin-top: 4px; font-size: 12px; }

/* 推荐下一步（豆包风格推荐气泡） */
.next-actions { margin: 4px 0 8px; padding: 10px 12px; border: 1px solid var(--border); border-radius: 10px; background: var(--panel-2); }
.next-actions-hint { font-size: 12px; color: var(--text-2); margin-bottom: 8px; }
.next-actions-list { display: flex; flex-wrap: wrap; gap: 6px; }
.next-action-btn {
  padding: 6px 14px; border: 1px solid var(--border); border-radius: 8px;
  background: var(--panel); color: var(--text); font-size: 13px;
  cursor: pointer; transition: background .12s, border-color .12s;
}
.next-action-btn:hover { background: var(--panel-2); border-color: var(--text-2); }
.next-action-btn.primary { background: var(--primary-a-08); border-color: var(--primary-a-38); color: var(--primary); }
.next-action-btn.primary:hover { background: var(--primary-a-16); }

/* ── 交互组件：AI 在对话流中向用户提问的内联卡片 ── */
.interaction-card {
  margin: 4px 0 8px;
  border: 1px solid var(--primary-a-24);
  border-radius: 12px;
  background: var(--primary-a-06);
  overflow: hidden;
  transition: border-color .2s var(--ease-standard), opacity .25s var(--ease-standard);
}
.interaction-card.answered {
  border-color: var(--primary-a-35);
  background: var(--primary-a-06);
}
/* 能力配置卡：作为「对话内嵌问询块」融入消息流，而非醒目告警弹层。
   弱化边框与底色，仅用细分隔线与轻量小标签；高风险再由 .capability-pill.risk-high 点缀。 */
.interaction-card.capability-action-card {
  border-color: var(--border);
  background: var(--surface-tint);
}
.interaction-capability-head {
  padding: 12px 14px 8px;
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.interaction-capability-kicker {
  color: var(--text-2);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .04em;
}
.interaction-capability-title {
  font-size: 15px;
  font-weight: 700;
  color: var(--text);
}
.interaction-capability-desc {
  color: var(--text-2);
  font-size: 13px;
  line-height: 1.55;
}
.interaction-capability-meta,
.interaction-missing-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.capability-pill,
.interaction-missing-list span {
  display: inline-flex;
  align-items: center;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 11px;
  border: 1px solid var(--border);
  color: var(--text-2);
  background: var(--surface-tint);
}
.capability-pill.risk-low { color: var(--success); border-color: var(--success-a-35); background: var(--success-a-06); }
.capability-pill.risk-medium { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.capability-pill.risk-high { color: var(--error); border-color: var(--error-a-35); background: var(--error-a-06); }

/* ---- 对象插件写回确认卡（混排进会话流的 inline diff 卡，非弹层） ---- */
.interaction-card.writeback-card { border-color: var(--border); background: var(--surface-tint); }
.writeback-head .writeback-path {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; padding: 1px 6px; border-radius: 6px;
  background: var(--primary-a-06); border: 1px solid var(--border); color: var(--text-2);
}
.writeback-warning {
  padding: 7px 10px; border-radius: 8px; font-size: 12px; line-height: 1.5;
  color: var(--error); background: var(--error-a-06); border: 1px solid var(--error-a-35);
}
.writeback-body { padding: 10px 14px 4px; display: flex; flex-direction: column; gap: 8px; }
.writeback-evidence {
  border: 1px solid var(--border); border-radius: 8px; background: var(--primary-a-06);
  font-size: 12px;
}
.writeback-evidence > summary {
  padding: 7px 10px; cursor: pointer; color: var(--text-2); font-weight: 600; user-select: none;
}
.writeback-evidence-text {
  padding: 0 10px 9px; color: var(--text); line-height: 1.6; white-space: pre-wrap; word-break: break-word;
}
.writeback-diff-collapse > summary {
  padding: 4px 2px; cursor: pointer; color: var(--text-2); font-size: 12px; user-select: none;
}
.wb-diff {
  border: 1px solid var(--border); border-radius: 8px; overflow: auto; max-height: 360px;
  background: var(--surface);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 12px; line-height: 1.55;
}
.wb-diff-line { padding: 0 10px; white-space: pre; min-height: 18px; color: var(--text-2); }
.wb-diff-file { color: var(--text-3, var(--text-2)); font-weight: 700; background: var(--surface-tint); }
.wb-diff-hunk { color: var(--primary); background: var(--primary-a-06); }
.wb-diff-add { color: var(--success); background: var(--success-a-06); }
.wb-diff-del { color: var(--error); background: var(--error-a-06); text-decoration: none; }
.wb-diff-fold { color: var(--text-3, var(--text-2)); text-align: center; background: var(--surface-tint); }
.writeback-truncated { font-size: 11px; color: var(--warn); }

/* ================= 对象插件工作台（抽屉 + 聚光灯 + delta 卡） ================= */
.obj-wb { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px 20px; }
.obj-wb-tabs { display: flex; flex-wrap: wrap; gap: 6px; }
.obj-wb-tab {
  padding: 4px 10px; border-radius: 999px; font-size: 12px; cursor: pointer;
  border: 1px solid var(--border); background: transparent; color: var(--text-2);
}
.obj-wb-tab.on { color: var(--text); border-color: var(--primary-a-35); background: var(--primary-a-06); }
.obj-wb-head { display: flex; align-items: baseline; gap: 8px; }
.obj-wb-name { font-size: 16px; font-weight: 700; color: var(--text); }
.obj-wb-ver {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 11px; color: var(--text-2); padding: 1px 8px; border-radius: 999px;
  border: 1px solid var(--border); background: var(--surface-tint);
}
.obj-wb-status {
  padding: 8px 10px; border-radius: 8px; font-size: 12px; color: var(--primary);
  background: var(--primary-a-06); border: 1px solid var(--primary-a-24);
  animation: obj-wb-pulse 1.6s ease-in-out infinite;
}
@keyframes obj-wb-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.obj-wb-panels { display: flex; flex-direction: column; gap: 12px; }
.obj-wb-panel {
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
  padding: 10px 12px 12px; transition: border-color .3s, box-shadow .3s;
}
.obj-wb-panel-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 6px; }
.obj-wb-panel-title { font-size: 12px; font-weight: 700; color: var(--text-2); letter-spacing: .03em; }
/* 聚光灯：AI 正在读写该面板绑定字段（active）/ 刚被更新（changed） */
/* 同上思路：静态基础光环常驻 + ::after 叠层动 opacity，替代逐帧重画 box-shadow spread。 */
.obj-wb-panel.wb-active {
  position: relative; border-color: var(--primary-a-35);
  box-shadow: 0 0 0 3px var(--primary-a-06);
}
.obj-wb-panel.wb-active::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 0 6px var(--primary-a-06);
  opacity: 0; animation: obj-wb-spot-glow 1.2s ease-in-out infinite; will-change: opacity;
}
@keyframes obj-wb-spot-glow { 0%, 100% { opacity: 0; } 50% { opacity: 1; } }
.obj-wb-panel.wb-changed {
  position: relative; border-color: var(--success);
  box-shadow: 0 0 0 3px var(--success-a-06);
}
.obj-wb-panel.wb-changed::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: 0 0 0 6px var(--success-a-06);
  opacity: 1; animation: obj-wb-flash-glow .8s ease-out 3; will-change: opacity;
}
@keyframes obj-wb-flash-glow { 0% { opacity: 1; } 100% { opacity: 0; } }
.obj-wb-empty { padding: 14px 10px; font-size: 12px; color: var(--text-2); line-height: 1.6; text-align: center; }
.obj-wb-metric { font-size: 26px; font-weight: 700; color: var(--text); line-height: 1.2; word-break: break-all; }
.obj-wb-kv { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 8px 14px; }
.obj-wb-kv-label { font-size: 11px; color: var(--text-2); }
.obj-wb-kv-value { font-size: 13px; color: var(--text); word-break: break-word; white-space: pre-wrap; }
.obj-wb-list { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 4px; font-size: 13px; color: var(--text); }
.obj-wb-links a { color: var(--primary); text-decoration: none; }
.obj-wb-links a:hover { text-decoration: underline; }
.obj-wb-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.obj-wb-table th, .obj-wb-table td { padding: 5px 8px; border-bottom: 1px solid var(--border); text-align: left; color: var(--text); }
.obj-wb-table th { color: var(--text-2); font-weight: 600; }
.obj-wb-progress { position: relative; height: 18px; border-radius: 999px; background: var(--surface-tint); border: 1px solid var(--border); overflow: hidden; }
.obj-wb-progress-bar { height: 100%; background: var(--primary-a-24); transition: width .5s ease; }
.obj-wb-progress-num { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--text); }
.obj-wb-badge { display: inline-flex; margin: 2px 6px 2px 0; padding: 2px 10px; border-radius: 999px; font-size: 12px; border: 1px solid var(--border); background: var(--surface-tint); color: var(--text); }
.obj-wb-text { font-size: 13px; color: var(--text); line-height: 1.65; white-space: pre-wrap; word-break: break-word; }
/* 时间线（操作记录 = 轻量回放） */
.obj-wb-timeline { display: flex; flex-direction: column; gap: 2px; }
.obj-wb-tl-item { border-radius: 8px; }
.obj-wb-tl-item[open] { background: var(--surface-tint); }
.obj-wb-tl-head { display: flex; align-items: center; gap: 8px; padding: 6px 8px; cursor: pointer; font-size: 12px; user-select: none; }
.obj-wb-tl-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.obj-wb-tl-dot.ok { background: var(--success); }
.obj-wb-tl-dot.bad { background: var(--error); }
.obj-wb-tl-op { color: var(--text); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.obj-wb-tl-time { margin-left: auto; color: var(--text-2); font-size: 11px; }
.obj-wb-tl-effects { padding: 0 10px 8px 25px; display: flex; flex-direction: column; gap: 4px; font-size: 12px; color: var(--text-2); }
.obj-wb-tl-effect { display: flex; align-items: center; gap: 8px; }
.obj-wb-tl-key { font-size: 11px; padding: 0 6px; border-radius: 5px; background: var(--primary-a-06); border: 1px solid var(--border); color: var(--text-2); }
/* 进化记录 */
.obj-wb-evolution { display: flex; flex-direction: column; gap: 8px; }
.obj-wb-evo-item { border: 1px solid var(--border); border-radius: 10px; padding: 8px 10px; background: var(--surface-tint); }
.obj-wb-evo-head { display: flex; align-items: center; gap: 8px; }
.obj-wb-evo-hash { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; padding: 1px 7px; border-radius: 999px; background: var(--success-a-06); color: var(--success); border: 1px solid var(--success-a-35); }
.obj-wb-evo-commit { font-size: 11px; color: var(--text-2); }
.obj-wb-evo-time { margin-left: auto; font-size: 11px; color: var(--text-2); }
.obj-wb-evo-file { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; font-size: 11px; color: var(--text-2); margin-top: 4px; }
.obj-wb-evo-evidence { font-size: 12px; color: var(--text); line-height: 1.55; margin-top: 4px; }
/* 会话流 delta 卡 */
.obj-delta-card { border: 1px solid var(--primary-a-24); border-radius: 12px; background: var(--primary-a-06); padding: 10px 12px; margin: 4px 0 8px; display: flex; flex-direction: column; gap: 8px; }
.obj-delta-head { display: flex; align-items: center; gap: 8px; }
.obj-delta-icon { color: var(--primary); }
.obj-delta-title { font-size: 13px; font-weight: 700; color: var(--text); }
.obj-delta-list { display: flex; flex-direction: column; gap: 4px; }
.obj-delta-item { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.obj-delta-summary { color: var(--text); }
.obj-delta-key { font-size: 11px; padding: 0 6px; border-radius: 5px; background: var(--surface); border: 1px solid var(--border); color: var(--text-2); }
.obj-delta-open { align-self: flex-start; font-size: 12px; }
.capability-return-banner {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  padding: 12px 30px 12px 14px;
  margin-bottom: 12px;
  border: 1px solid var(--warn-a-35);
  border-radius: 14px;
  background: linear-gradient(135deg, var(--warn-a-06), var(--primary-a-06));
  position: relative;
  transition: opacity .3s, transform .3s;
}
.capability-return-banner.dismissing {
  opacity: 0;
  transform: translateY(-8px);
  pointer-events: none;
}
.capability-return-dismiss {
  position: absolute;
  top: 6px;
  right: 8px;
  background: none;
  border: none;
  color: var(--text-2);
  font-size: 14px;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  line-height: 1;
  opacity: .85;
}
.capability-return-dismiss:hover { opacity: 1; color: var(--text); background: var(--panel-2); }
.capability-return-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.capability-return-main strong { color: var(--warn); }
.capability-return-main span { color: var(--text-2); font-size: 12px; line-height: 1.45; }
.capability-return-stale {
  border-color: var(--border);
  background: var(--panel-2);
}
.capability-return-stale .capability-return-main strong { color: var(--text-2); }
.interaction-option.action-only {
  border-style: dashed;
}
.interaction-card.cancelled {
  border-color: var(--border);
  opacity: .55;
}
.interaction-card.timed-out {
  border-color: var(--warn-a-35);
  background: var(--warn-a-06);
  opacity: .75;
}
.interaction-card.timed-out .interaction-option {
  opacity: .5;
  cursor: not-allowed;
}
.interaction-card.timed-out .interaction-status {
  border-top-color: var(--warn-a-22);
  color: var(--warn);
}
/* turn 终态（done/failed/canceled）时的交互卡样式：
   未完成交互卡 → 灰色禁用；已确认交互卡下游失败 → 红色警示 */
.interaction-card.turn-ended {
  border-color: var(--border);
  background: var(--surface-tint);
  opacity: .65;
}
.interaction-card.turn-ended .interaction-option {
  opacity: .5;
  cursor: not-allowed;
}
.interaction-card.turn-ended .interaction-custom textarea,
.interaction-card.turn-ended .interaction-custom .btn {
  opacity: .5;
  cursor: not-allowed;
}
.interaction-card.turn-ended .interaction-status {
  border-top-color: var(--border);
  color: var(--text-3);
}
/* 已回答卡片按后续任务真实终态着色；成功不再被统一误画成红色。 */
.interaction-card.turn-ended.answered.downstream-done {
  opacity: 1;
}
.interaction-card.turn-ended.answered.downstream-done .interaction-status {
  border-top-color: var(--success-a-22);
  color: var(--success);
}
.interaction-card.turn-ended.answered.downstream-canceled .interaction-status {
  border-top-color: var(--warn-a-22);
  color: var(--warn);
}
.interaction-card.turn-ended.answered.downstream-failed .interaction-status {
  border-top-color: var(--error-a-22);
  color: var(--error);
}
.interaction-question {
  padding: 12px 14px 8px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.55;
  color: var(--text);
  /* 后端问题文案大量使用多行（额度追加卡、验收补齐卡、澄清卡都是多行叙述），
     不保留换行会被折成一整段，读起来是一团。 */
  white-space: pre-wrap;
  /* 卡片是 overflow:hidden，超长无空格串（路径、id、URL）不换行就会被直接裁掉看不见。 */
  overflow-wrap: anywhere;
}
.interaction-answer-summary {
  margin: 0 14px 10px;
  padding: 8px 10px;
  display: flex;
  align-items: baseline;
  gap: 10px;
  border: 1px solid var(--primary-a-18);
  border-radius: 8px;
  background: var(--surface-tint);
}
.interaction-answer-label {
  flex-shrink: 0;
  color: var(--text-3);
  font-size: 11px;
  font-weight: 600;
}
.interaction-answer-value {
  min-width: 0;
  color: var(--text);
  font-size: 13px;
  line-height: 1.45;
  overflow-wrap: anywhere;
}
.interaction-options {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 4px 14px 12px;
}
.interaction-option {
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel);
  color: var(--text);
  font-size: 13px;
  font-weight: 500;
  cursor: pointer;
  transition: all .15s var(--ease-standard);
  text-align: left;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 72px;
}
.interaction-option:hover {
  border-color: var(--primary-a-45);
  background: var(--panel-2);
  transform: translateY(-1px);
  box-shadow: 0 2px 8px rgba(0,0,0,.08);
}
.interaction-option:active {
  transform: scale(.97);
}
.interaction-option.primary {
  border-color: var(--primary);
  background: var(--primary);
  color: #fff;
}
.interaction-option.primary:hover {
  background: var(--primary-2);
  border-color: var(--primary-2);
}
.interaction-option.danger {
  border-color: var(--error);
  color: var(--error);
  background: var(--error-a-06);
}
.interaction-option.danger:hover {
  background: var(--error-a-12);
}
.interaction-option .opt-label {
  font-weight: 600;
  /* 选项文案可能含长路径/长标题；卡片是overflow:hidden，不换行就会被裁掉。 */
  overflow-wrap: anywhere;
}
.interaction-option .opt-desc {
  font-size: 11px;
  color: var(--text-2);
  font-weight: 400;
}
.interaction-option.primary .opt-desc {
  color: rgba(255,255,255,.7);
}
.interaction-option:disabled {
  opacity: .62;
  cursor: not-allowed;
  transform: none !important;
}
.interaction-option.selected {
  opacity: 1;
  border-color: var(--primary);
  background: var(--primary-a-12);
  color: var(--text);
  outline: 2px solid var(--primary);
  outline-offset: 1px;
}
/* 自定义输入区域 */
.interaction-custom {
  padding: 0 14px 12px;
  display: flex;
  gap: 8px;
  align-items: flex-start;
}
.interaction-custom textarea {
  flex: 1;
  min-height: 36px;
  max-height: 80px;
  font-size: 13px;
  padding: 6px 10px;
  border-radius: 8px;
}
.interaction-custom .btn {
  flex-shrink: 0;
  margin-top: 0;
}
.interaction-status {
  padding: 8px 14px;
  font-size: 12px;
  color: var(--text-2);
  border-top: 1px solid var(--primary-a-12);
  display: flex;
  align-items: center;
  gap: 6px;
}
.interaction-card.answered .interaction-status {
  border-top-color: var(--primary-a-22);
  color: var(--primary);
}
.interaction-status-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--primary);
  animation: pulse 1.2s infinite;
}
.interaction-card.answered .interaction-status-dot {
  background: var(--primary);
  animation: none;
}

/* ===== 交互卡内嵌表单字段 ===== */
.interaction-fields {
  padding: 4px 14px 8px;
}
.interaction-fields .field label {
  font-size: 12px;
}
.interaction-fields .field input,
.interaction-fields .field select,
.interaction-fields .field textarea {
  font-size: 13px;
  padding: 7px 10px;
}
.interaction-fields .field-error input,
.interaction-fields .field-error select,
.interaction-fields .field-error textarea,
.interaction-fields .field-invalid input,
.interaction-fields .field-invalid select,
.interaction-fields .field-invalid textarea {
  border-color: var(--error);
}
.interaction-fields .field-error::after {
  content: '此项必填';
  color: var(--error);
  font-size: 11px;
}
/* 必填为空与格式不合规是两种错误，提示必须分开：格式错时说“此项必填”会让用户
   反复确认自己明明填了、却不知道是格式问题。 */
.interaction-fields .field-invalid::after {
  content: '填写格式不正确';
  color: var(--error);
  font-size: 11px;
}
.interaction-radio-group,
.interaction-checkbox-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* 交互卡选项：整行可点的选项卡片——圆钮/勾选框在左上，标题与说明在右侧竖排。
 * 原先是 [钮 标题 说明] 三者平铺同一 flex 行，标题与说明互抢宽度，窄容器下逐字换行。 */
.interaction-opt {
  display: flex; align-items: flex-start; gap: 9px; margin: 0;
  padding: 9px 11px; cursor: pointer;
  border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-tint);
  transition: border-color .15s ease, background .15s ease;
}
.interaction-opt:hover { border-color: var(--primary-a-45); }
.interaction-opt > input { flex: 0 0 auto; margin: 2px 0 0; }
.interaction-opt .opt-main { min-width: 0; display: grid; gap: 2px; }
.interaction-opt .opt-label { font-size: 13px; line-height: 1.5; color: var(--text); }
.interaction-opt .opt-desc { font-size: 11.5px; line-height: 1.55; color: var(--text-2); }
.interaction-opt:has(> input:checked) { border-color: var(--primary); background: var(--primary-a-08); }
.interaction-opt:has(> input:checked) .opt-label { font-weight: 600; }
.interaction-opt:has(> input:disabled) { cursor: default; opacity: .72; }
.interaction-opt:has(> input:focus-visible) { outline: 2px solid var(--accent-a-45); outline-offset: 1px; }
/* 每个问题之间要有呼吸：多问卡里一连四五个问题挤在一起会读成一团。 */
.interaction-fields.form-stack { gap: 14px; }
.interaction-card.answered .interaction-fields input,
.interaction-card.answered .interaction-fields select,
.interaction-card.answered .interaction-fields textarea {
  opacity: .7;
}
.interaction-card.timed-out .interaction-fields input,
.interaction-card.timed-out .interaction-fields select,
.interaction-card.timed-out .interaction-fields textarea {
  opacity: .5;
  pointer-events: none;
}

/* 活动指示器：合并「AI 正在思考」状态 + 「执行记录」进度，单枚胶囊原地刷新。
   借鉴旧版「思考中」放在 AI 气泡左下角（in-flow，避免纯思考无正文时塌陷）；面板向上浮层展开，默认折叠、仅点击展开。 */
.execution-record-dock {
  align-self: flex-start; position: relative; z-index: 6;
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
}
/* 展开面板时抬升整颗 dock 的层叠级，使其上的浮层面板覆盖相邻 turn 的 dock（同为 z-index:6）
   与回到底部按钮（z-index:20）；否则同 z-index 下后继 turn 的 dock 因 DOM 顺序在后会压住面板。 */
.execution-record-dock.open { z-index: 30; }
.execution-record-toggle {
  display: inline-flex; align-items: center; justify-content: flex-start; gap: 5px;
  height: 26px; padding: 0 10px;
  border-radius: 999px; border: 1px solid var(--primary-a-24);
  background: var(--surface-raised); color: var(--text-2);
  font-size: 12px; cursor: pointer;
  box-sizing: border-box;
  /* 固定最小宽度消除动词切换时的横向晃动；步数单独放徽章区
     168px 兜底最长状态文案「AI 正在执行操作…」「AI 正在整理结果…」+ 圆点 + 间距 + 内边距 */
  min-width: 168px; max-width: 70vw;
  box-shadow: none; transition: background .15s ease, border-color .15s ease, box-shadow .15s ease;
}
.execution-record-toggle:hover { color: var(--text); border-color: var(--primary-a-45); background: var(--panel-2); }
/* 仅「可点击」的胶囊在 hover 时给极轻微抬升，作为可交互暗示（resting flat, hover lift）。 */
.execution-record-dock:not(.no-detail) .execution-record-toggle:hover { box-shadow: 0 2px 8px rgba(0,0,0,.10); }
/* 纯状态（无可展开的执行步骤）：是标签不是按钮，去掉点击态与悬停反馈 */
.execution-record-dock.no-detail .execution-record-toggle { cursor: default; }
.execution-record-dock.no-detail .execution-record-toggle:hover { color: var(--text-2); border-color: var(--primary-a-24); background: var(--surface-raised); }
.execution-record-text { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.execution-record-steps { flex: 0 0 auto; font-size: 11px; color: var(--text-3); white-space: nowrap; margin-left: 2px; }
.execution-record-dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .75; flex: 0 0 auto; }
.execution-record-dock.is-running .execution-record-dot { animation: pulse 1.25s ease-in-out infinite; color: var(--primary); }
.execution-record-dock.is-running .execution-record-toggle { color: var(--primary); border-color: var(--primary-a-22); background: var(--primary-a-08); }
.execution-record-dock.is-waiting .execution-record-toggle { color: var(--accent); border-color: var(--accent); background: var(--accent-a-18); }
.execution-record-dock.is-waiting .execution-record-dot { color: var(--accent); }
/* 交互卡自身已带一枚“等待你的选择/确认…”呼吸灯；同屏再叠加活动指示器的等待态呼吸灯，
   两处文案还不一致（一个说“选择”一个说“确认”），会让用户误以为有两套独立等待逻辑。存在
   未回答的真实交互卡时，隐藏活动指示器的等待态，只保留交互卡内的那一枚，避免重复。 */
.msg-body:has(.interaction-card:not(.answered):not(.timed-out):not(.turn-ended)) .execution-record-dock.is-waiting {
  display: none !important;
}
.execution-record-dock.is-stale .execution-record-toggle { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn) 6%, transparent); }
.execution-record-dock.is-done .execution-record-dot { color: var(--success); opacity: .9; }
.execution-record-dock.is-done .execution-record-toggle { color: var(--success); border-color: var(--success-a-35); background: var(--success-a-06); }
.execution-record-dock.has-error .execution-record-toggle { color: var(--error); border-color: color-mix(in srgb, var(--error) 42%, transparent); background: color-mix(in srgb, var(--error) 7%, transparent); }
.execution-record-dock.has-error .execution-record-dot { color: var(--error); }
.execution-record-dock.has-warning .execution-record-toggle { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.execution-record-dock.has-warning .execution-record-dot { color: var(--warn); }
.exec-fail-count { color: var(--error); }
.exec-recovered-count { color: var(--warn); }
/* done 终态胶囊保持绿色，「过程波折已恢复 N」作为黄色子徽章叠加而非染整颗胶囊 */
.exec-recovered-badge {
  display: inline-block; margin-left: 2px; padding: 0 6px; border-radius: 999px;
  font-size: 11px; line-height: 1.5; color: var(--warn);
  background: var(--warn-a-12, var(--warn-a-06));
  border: 1px solid var(--warn-a-35);
}
.platform-wrap:empty,
.tools-wrap:empty { display: none; }
.platform-wrap, .tools-wrap { display: flex; flex-direction: column; gap: 6px; }
.platform-wrap:not(:empty) + .tools-wrap:not(:empty) { margin-top: 8px; }
.tool-group {
  border: 1px solid var(--border);
  border-radius: 8px; overflow: hidden;
  background: var(--surface-tint);
}
.tool-group-head {
  padding: 7px 10px; cursor: pointer;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text-2);
}
.tool-group-head:hover { background: var(--surface-tint-2); color: var(--text); }
.tool-group-body { display: flex; flex-direction: column; gap: 6px; padding: 6px; border-top: 1px solid var(--border); }
.tool {
  border: 1px solid var(--border);
  border-radius: 6px; overflow: hidden;
  background: var(--panel-2);
}
.tool.tool-use { border-left: 3px solid var(--primary); }
.tool.tool-ok { border-left: 3px solid var(--success); }
.tool.tool-bad { border-left: 3px solid var(--error); }
.tool-head {
  padding: 6px 10px; cursor: pointer;
  display: flex; align-items: center; gap: 8px;
  font-size: 12px; color: var(--text);
}
.tool-head:hover { background: var(--surface-tint-2); }
.tool-head-icon { color: var(--primary); }
.tool-ok .tool-head-icon { color: var(--success); }
.tool-bad .tool-head-icon { color: var(--error); }
.tool-toggle { color: var(--text-2); font-size: 10px; }
.tool-body {
  margin: 0; padding: 8px 12px;
  background: var(--term-bg); border-top: 1px solid var(--border);
  font: 11px/1.5 var(--mono);
  white-space: pre-wrap; word-break: break-word;
  max-height: 360px; overflow: auto;
}
/* P1 工具 body 超长截断：容器复用 .tool-body 视觉，内部 pre 只放头部、尾部折叠为展开按钮 */
.tool-body-pre {
  margin: 0; font: inherit;
  white-space: pre-wrap; word-break: break-word;
}
.tool-body-more {
  display: block; margin-top: 8px; padding: 4px 10px;
  background: transparent; border: 1px dashed var(--border); border-radius: 6px;
  color: var(--text-2); font-size: 11px; cursor: pointer; text-align: left;
}
.tool-body-more:hover { color: var(--text-1); border-color: var(--text-2); }
.recovery-actions {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 8px 10px; border-top: 1px solid var(--error-a-28);
  background: var(--error-a-06);
}
.recovery-actions .muted { flex: 1 1 100%; font-size: 12px; }
.recovery-actions .btn { font-size: 12px; padding: 4px 9px; }
/* grounding 整轮重来后，上一轮（已作废）的工具/系统动作记录：灰显 + 右侧「已作废」徽章，保留审计。 */
.tool.tool-stale { opacity: .5; }
.tool.tool-stale .tool-head { text-decoration: line-through; text-decoration-color: var(--border); }
.tool.tool-stale .tool-head::after {
  content: '已作废'; margin-left: auto;
  font-size: 10px; line-height: 1; padding: 2px 7px; border-radius: 999px;
  border: 1px solid var(--border); color: var(--text-2); background: var(--surface-tint);
  text-decoration: none; flex: none;
}
/* turn 状态已合并进右上角「活动指示器」(.execution-record-dock)，底部状态行不再单独展示；
   .turn-status 仍保留为状态机内部驱动元素（dataset/className 供终态判定与看门狗使用），仅视觉隐藏。 */
.turn-status { display: none !important; }
.turn-status {
  align-self: flex-start; display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; border-radius: 999px; padding: 3px 8px;
  border: 1px solid var(--border); background: var(--surface-tint); color: var(--text-2);
}
.turn-status.queued, .turn-status.running, .turn-status.committing, .turn-status.starting, .turn-status.interacting {
  color: var(--primary); background: var(--primary-a-08); border-color: var(--primary-a-22);
}
.turn-status.running::before, .turn-status.queued::before, .turn-status.interacting::before, .turn-status.phase-writing::before, .turn-status.phase-tooling::before, .turn-status.phase-finalizing::before, .turn-status.phase-processing::before, .turn-status.phase-reconnecting::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.turn-status.queued::before, .turn-status.interacting::before, .turn-status.phase-thinking::before, .turn-status.phase-writing::before, .turn-status.phase-tooling::before, .turn-status.phase-finalizing::before, .turn-status.phase-processing::before, .turn-status.phase-reconnecting::before { animation: pulse 1.25s ease-in-out infinite; box-shadow: 0 0 0 3px color-mix(in srgb, currentColor 14%, transparent); }
.turn-status.phase-tooling { color: var(--accent); border-color: var(--accent); background: var(--accent-a-18); }
.turn-status.phase-finalizing { color: var(--primary); border-color: var(--primary-a-38); background: var(--primary-a-08); }
.turn-status.phase-processing { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 30%, transparent); background: color-mix(in srgb, var(--warn) 5%, transparent); }
.turn-status.phase-reconnecting { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn) 6%, transparent); }
.turn-status.running::before { opacity: .72; }
@keyframes pulse { 0%,100% { opacity: .35; transform: scale(.92); } 50% { opacity: 1; transform: scale(1.08); } }
.turn-status.running, .turn-status.committing, .turn-status.starting { color: var(--primary); }
.turn-status.interacting { color: var(--accent); border-color: var(--accent); background: var(--accent-a-18); }
.turn-status.done { color: var(--success); border-color: var(--success-a-35); background: var(--success-a-06); }
.turn-status.failed { color: var(--error); border-color: var(--error-a-35); background: var(--error-a-06); }
.turn-status.blocked, .turn-status.paused, .turn-status.incomplete { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.turn-status.canceled { color: var(--text-3); border-color: var(--border); background: var(--surface-tint); }
/* 未知/异常状态：琥珀色警告样式（替代灰色默认），避免"灰色点"让用户困惑 */
.turn-status.undefined, .turn-status.null, .turn-status.unknown { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn) 6%, transparent); }
.turn-status.undefined::before, .turn-status.null::before, .turn-status.unknown::before { content: '?'; display: inline-flex; align-items: center; justify-content: center; width: 6px; height: 6px; border-radius: 50%; background: currentColor; font-size: 5px; line-height: 1; font-weight: 700; }
/* 运行超时警告：SSE 仍有活动但 turn 已运行过久（turn.end 丢失） */
.turn-status.stale-warning { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 35%, transparent); background: color-mix(in srgb, var(--warn) 6%, transparent); }
.turn-status.stale-warning::before { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: currentColor; animation: pulse 1s infinite; }

/* 终止按钮软超时提示：运行超过 SOFT_TIMEOUT 时变为琥珀色警告 */
.action-btn.action-slow { color: var(--warn); border-color: var(--warn); background: color-mix(in srgb, var(--warn) 8%, transparent); }

/* 运行进度统一使用 turn-status 消息级呼吸态；正文不再显示内联光标，避免文本/组件混排时焦点错位。 */

/* 上下文压缩提示 */
.context-compressed-hint {
  border-style: solid; border-color: var(--primary-a-22);
  background: var(--primary-a-08);
}

/* 加载更早消息 */
.load-earlier-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 10px 16px; border-radius: 10px;
  background: var(--panel-2); border: 1px solid var(--border);
  font-size: 13px; color: var(--text-2); cursor: pointer;
  transition: background .15s ease, border-color .15s ease;
}
.load-earlier-btn:hover { background: var(--panel-2); border-color: var(--primary-a-45); color: var(--text); }

/* ============ 断档提示条============
   分页窗口与实时新消息共存时，已渲染的两段 turn 之间必然可能出现缺口。
   与其静默拼接（用户会看到「第 90 条」后面直接接上「第 121 条」，像凭空丢了30 条），
   不如把缺口做成一条可读、可操作的分隔提示：左右细线 + 中间胶囊按钮，
   视觉上明确「这里是断点」，点击就地补齐。 */
.turn-gap { display: flex; align-items: center; gap: 10px; margin: 14px 0; }
.turn-gap-line { flex: 1 1 auto; height: 1px; background: var(--border); }
.turn-gap-btn {
  flex: 0 0 auto; display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 11px; border-radius: 999px;
  border: 1px dashed var(--border); background: var(--panel);
  color: var(--text-2); font: inherit; font-size: 12px; cursor: pointer;
  transition: color .15s ease, border-color .15s ease, background .15s ease;
}
.turn-gap-btn:hover { color: var(--primary); border-color: var(--primary-a-45); border-style: solid; background: var(--primary-a-08); }
.turn-gap-btn:focus-visible { outline: 2px solid var(--primary-a-45); outline-offset: 2px; }

/* 输入区 */
.chat-input {
  flex: 0 0 auto;
  border-top: 1px solid var(--border);
  background: var(--panel);
  padding: 12px 16px;
  /* 全面屏底部手势条会直接压在下方工具排上。此前全站只有 drawer / sheet / toast 处理了安全区，
     而这里是使用频率最高的操作区，反倒漏了。max() 保证非全面屏设备仍是12px 常规内距。 */
  padding-bottom: max(12px, env(safe-area-inset-bottom));
}
.prompt-chips {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  margin-bottom: 8px;
}
.prompt-chips-label { color: var(--text-2); font-size: 12px; margin-right: 2px; }
.prompt-chip {
  max-width: 220px; padding: 4px 9px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface-tint); color: var(--text-2); cursor: pointer;
  font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.prompt-chip:hover { color: var(--text); border-color: var(--primary-a-45); background: var(--primary-a-08); }
/* 高度由 JS 按内容自适应（autosizeComposer），min/max 只作兜底：
   空态 56px（此前 48px 与 40px 发送按钮几乎顶满，上下各只剩 4px 空隙，视觉上
   "按钮比框还大"；56px 让按钮四周留出对称的 8px 呼吸空间，见下方 .composer-actions），
   写到 200px 后才交还给内部滚动。 */
.chat-input textarea {
  resize: none;
  min-height: 56px;
  max-height: 200px;
  font-size: 16px; /* ≥16px 防止 iOS Safari 自动放大输入框 */
}
.pending-interaction-bar {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center;
  margin-bottom: 10px; padding: 10px 12px; border-radius: 14px;
  border: 1px solid var(--warn-a-35); background: var(--warn-a-06);
}
.pending-interaction-main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.pending-interaction-main strong { color: var(--warn); font-size: 12px; }
.pending-interaction-main span { color: var(--text); font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chat-input-hint { font-size: 12px; }
/* 会话产品焦点：清楚显示当前选中对象与使用模式，避免“选中即默认修改”。 */
.product-focus-bar {
  display: flex; align-items: center; gap: 8px; margin: 0 0 8px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint);
}
.product-focus-icon { color: var(--text-2); display: inline-flex; flex: 0 0 auto; }
.product-focus-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; flex: 1 1 auto; }
.product-focus-main strong { font-size: 12px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.product-focus-main .muted { font-size: 11px; }
.product-focus-clear { flex: 0 0 auto; }
/* Codex 风格附件条：以紧凑、可移除的上下文胶囊呈现，不打断编辑流。 */
.composer-attachments { display: flex; flex-wrap: wrap; gap: 6px; margin: 0 0 8px; }
.composer-attachment, .message-attachment {
  display: inline-flex; align-items: center; gap: 6px; min-width: 0;
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface-tint);
  color: var(--text-2); font-size: 12px; line-height: 1; text-decoration: none;
}
.composer-attachment { max-width: min(100%, 360px); padding: 7px 7px 7px 9px; }
.composer-attachment.is-image { padding: 4px 7px 4px 4px; }
.composer-attachment-thumb-wrap, .message-attachment-thumb-wrap { position: relative; display: block; flex: 0 0 auto; }
.composer-attachment-thumb-wrap { width: 42px; height: 42px; }
.composer-attachment-thumb { width: 42px; height: 42px; display: block; border-radius: 7px; object-fit: cover; background: var(--panel-2); }
.composer-attachment-thumb-wrap video.composer-attachment-thumb { object-fit: cover; }
.attachment-reference-badge {
  position: absolute; top: 4px; left: 4px; z-index: 1;
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  color: #fff; background: rgba(8, 11, 20, .82); border: 1px solid rgba(255, 255, 255, .55);
  box-shadow: 0 1px 5px rgba(0, 0, 0, .28); font-size: 10px; font-weight: 700; line-height: 1;
}
.composer-attachment-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.composer-attachment-state { color: var(--text-3); font-size: 11px; white-space: nowrap; }
.composer-attachment-remove { display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; padding: 0; border: 0; border-radius: 6px; color: var(--text-3); background: transparent; cursor: pointer; }
.composer-attachment-remove:hover:not(:disabled) { background: var(--panel-2); color: var(--text); }
.composer-attachment-remove:disabled { cursor: wait; opacity: .45; }
.composer-attachment.failed { border-color: var(--error-a-45); color: var(--error); }
.composer-attachment.clickable { cursor: pointer; }
.composer-attachment.clickable:hover { background: var(--panel-2); }
.composer-attachment.clickable:focus-visible { outline: 2px solid var(--accent-a-45); outline-offset: 1px; }
.composer-attachment.failed .composer-attachment-state { text-decoration: underline; }
.message-attachments { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.message-attachment { padding: 7px 9px; color: inherit; background: color-mix(in srgb, #fff 14%, transparent); border-color: color-mix(in srgb, #fff 28%, transparent); }
.message-attachment.is-image { width: 168px; padding: 5px; flex-direction: column; align-items: stretch; gap: 5px; cursor: zoom-in; font: inherit; text-align: left; }
.message-attachment-thumb-wrap { width: 100%; height: 112px; }
.message-attachment-thumb { width: 100%; height: 112px; display: block; border-radius: 7px; object-fit: cover; background: color-mix(in srgb, #fff 10%, transparent); }
.message-attachment-video-thumb { position: relative; display: block; width: 100%; height: 112px; border-radius: 7px; overflow: hidden; background: #000; }
.message-attachment-video-thumb video { width: 100%; height: 100%; object-fit: cover; display: block; }
.message-attachment-play-overlay { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #fff; background: rgba(0,0,0,.18); pointer-events: none; }
.message-attachment-info { display: flex; align-items: center; justify-content: space-between; gap: 8px; min-width: 0; padding: 1px 3px; }
.message-attachment-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.message-attachment:hover { background: color-mix(in srgb, #fff 22%, transparent); }
.message-attachment small { opacity: .72; font-size: 10px; white-space: nowrap; }
/* 输入框 + 悬浮发送/终止按钮：按钮固定在输入框内右下角（现代对话输入范式） */
.composer { position: relative; display: block; }
/* 52px = 右侧留白 12 + 按钮 32 + 文字与按钮之间 8，保证最后一个字不会钻到按钮底下。 */
.composer textarea { width: 100%; padding-right: 52px; box-sizing: border-box; }

/* ── 下一步建议（ghost suggestion）──
   视觉重量刻意等于 placeholder：同字号、同起点、最弱一档文字色，无边框、无背景、无图标。
   它是"输入框的一种空态"，不是第五个需要处理的控件——上一代那排常驻推荐 chips 之所以
   被完全无视，恰恰因为它长得像控件却又不重要，于是每轮都在争夺注意力、每轮都被跳过。
   接受后文字出现在完全相同的位置与字号上，因此没有任何视觉跳动。 */
.composer-ghost {
  position: absolute; left: 0; top: 0; right: 52px;
  display: flex; align-items: center; gap: 8px;
  min-height: 56px; padding: 0 12px; box-sizing: border-box;
  font-size: 16px; line-height: 1.5; color: var(--text-3);
  border-radius: var(--r-lg); cursor: pointer;
  animation: composer-ghost-in .12s ease-out;
  /* 未聚焦时不吃点击：用户第一次点输入框的意图可能是"我要自己打字"，
     必须让点击穿透到 textarea 完成聚焦。聚焦之后（下面的 :focus-within）ghost 才可点——
     此时用户已经同时看见了这句建议和光标，再点它就是明确的"接受"。
     这样移动端不需要 Tab 键也能接受，且不会误吞想自己输入的那一次点击。 */
  pointer-events: none;
  user-select: none;
}
.composer:focus-within .composer-ghost { pointer-events: auto; }
@keyframes composer-ghost-in { from { opacity: 0; } to { opacity: 1; } }
.composer-ghost-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
/* Tab 键帽：只对有物理键盘的用户有意义，窄屏隐藏（移动端靠轻点接受）。
   放在文本右侧而不是左侧，避免它成为这一行的视觉入口——那会让提示看起来像快捷键说明。 */
.composer-ghost-key {
  flex: 0 0 auto; font-size: 10px; line-height: 1; padding: 3px 5px;
  border: 1px solid var(--border); border-radius: 4px; color: var(--text-3); opacity: .65;
}
.composer:focus-within .composer-ghost-key { opacity: .9; }
@media (max-width: 640px) { .composer-ghost-key { display: none; } }
@media (prefers-reduced-motion: reduce) { .composer-ghost { animation: none; } }
/* 四周等距 12px：空态输入框高 56px、按钮 32px，(56-32)/2 = 12，于是上/下/右三边留白
   完全相同。此前是 right:10 / bottom:8 / 按钮 40px——下方仅剩 8px、右侧 10px，且带底色描边的
   终止态是个 42px 的实心圆盘，占满输入框 75% 的高度，读起来就是"圆盘贴在框的右下角边上"。 */
.composer-actions {
  position: absolute; right: 12px; bottom: 12px;
  display: flex; align-items: center; gap: 8px;
}
/* 右侧只剩一个 chat-input-left，原来的 space-between 是给早已不再渲染的 .chat-run-actions
   守位（那条规则同期删除），留着只会让人以为右侧还有一组操作，并在底部撑出一片无意义留白。 */
.chat-input-bar {
  display: flex; justify-content: flex-start; align-items: center;
  margin-top: 8px; gap: 12px;
}
.chat-input-left { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
/* 底部三颗工具按钮的内距/字号统一由 .chat-tool-btn（见上方定义）负责，
   此处不再单独给 .btn 设内距，避免两条同特异性规则互相覆盖导致大小不一。 */

/* 发送/终止 icon 按钮*/
/* 32px 而非 40px：这颗按钮是回车发送的兜底入口，和它同处一框的输入区才是主角。
   40px 的圆在 56px 高的输入框里只能各留 8px 边距，终止态（有底色+描边的实心圆盘）尤其显得
   "顶满并贴住右下角"。缩到 32px 后四周各留 12px，圆盘不再与框边、圆角相互挤压。
   触控热区不受影响——仍由下面 44×44 的伪元素承载。 */
.action-btn {
  position: relative;
  width: 32px; height: 32px; border-radius: 50%; border: none;
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; transition: background .15s ease, color .15s ease, opacity .15s ease, transform .1s ease;
  flex-shrink: 0;
}
/* 触控热区补足到 Apple HIG 的 44×44，但用绝对定位的伪元素承载，不占布局尺寸——
   否则 56px 高的输入框里塞不下，底部还得整体加高。必须 absolute：.action-btn 是 flex 容器，
   静态伪元素会变成 flex item 把图标挤偏。 */
.action-btn::before {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: 44px; height: 44px; transform: translate(-50%, -50%);
}
.action-btn:active { transform: scale(.92); }
.action-btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }
.action-btn svg { display: block; position: relative; }
/* 发送态：只留纸飞机图标，不做实心圆按钮。
   回车才是发送的主路径（title 已提示"回车发送"），这颗按钮只是装饰性的兜底入口——
   一个和输入框同权重的醒目实心圆反而抢戏，让人误以为"必须点它才能发"。
   去掉背景/边框，图标本身的颜色变化（is-idle 更淡、hover 更深）就是唯一反馈。 */
.action-send { background: transparent; color: var(--text-2); }
.action-send:hover:not(:disabled) { background: var(--surface-tint); color: var(--text); }
/* 空态（没有文字 / 没有附件 / 没有待发生成请求）再淡一档。
   刻意不使用 disabled：会丢掉键盘可达性与 title 提示，且附件仍在上传等场景需要那条 toast
   解释"为什么现在不能发"，按钮必须保持可点。 */
.action-send.is-idle { background: transparent; color: var(--text-3); }
.action-send.is-idle:hover:not(:disabled) { background: var(--surface-tint); color: var(--text-2); }
/* 终止态：浅底 + 红色 icon */
.action-stop {
  background: var(--error-a-08); color: var(--error); border: 1px solid var(--error-a-35);
}
.action-stop:hover:not(:disabled) { background: var(--error-a-16); }
/* 强制取消：超时后仍不可正常终止时的琥珀色警告按钮 */
.action-force-cancel {
  background: var(--warn-a-06); color: var(--warn); border-color: var(--warn-a-35);
}
.action-force-cancel:hover:not(:disabled) { background: color-mix(in srgb, var(--warn) 16%, transparent); }
/* 等待态 */
.action-pending {
  background: var(--panel-2); color: var(--text-2);
}
.action-pending svg { animation: spin 1.2s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

@media (max-width: 900px) {
  .main { grid-template-columns: 1fr; grid-template-rows: 1fr; }
  .side { display: none; }
  .content { padding: 12px; min-height: 0; overflow-y: auto; }
  .chat-shell { height: calc(100% + 24px); margin: -12px; }
  .chat-header { flex-wrap: nowrap; }
  .chat-header-actions { justify-content: flex-end; }
  .mobile-hide { display: none !important; }
  .msg.user .msg-content { max-width: 88%; }
}
@media (max-width: 640px) {
  html, body { overscroll-behavior: none; }
  .shell { grid-template-rows: 48px 1fr; }
  .shell.chat-mode { grid-template-rows: 1fr; }
  .topbar { display: flex; gap: 4px; padding: 0 6px; }
  .shell.chat-mode .topbar { display: none !important; }
  .brand-mark-mobile { display: inline-flex; border: none; background: transparent; border-radius: 8px; gap: 5px; padding: 0 4px; font-size: 13px; }
  .brand-mark-mobile:hover { background: var(--panel-2); }
  .brand-mark-mobile .brand-mark-glyph { width: 22px; height: 22px; border-radius: 6px; font-size: 12px; }
  .chat-header .brand-mark-mobile > span:not(.brand-mark-glyph) { display: none; }
  /* 移动端 tab：只显示图标，去掉文字节省空间 */
  .main { grid-template-columns: 1fr; grid-template-rows: 1fr; }
  .side { display: none; }
  .content { padding: 12px; min-height: 0; overflow-y: auto; }
  .chat-header { flex-wrap: nowrap; padding: 6px 10px; gap: 6px; }
  .chat-header-left { flex: 1 1 0; min-width: 0; }
  .chat-header-actions { display: flex; flex: 1 1 0; min-width: 0; justify-content: flex-end; }
  /* 移动端仍保留右上角 ⋯ 工具栏入口 */
  .chat-header-actions .agent-toolbar-btn { display: inline-flex !important; }
  .chat-header-actions .muted { font-size: 11px; }
  /* 头部工作区按钮：紧凑图标+文字胶囊，与底部工具按钮风格一致 */
  .chat-header-actions .ws-mobile-btn { padding: 3px 8px; font-size: 12px; gap: 4px; line-height: 1.4; }
  .chat-header-actions .ws-mobile-btn .ws-change-badge { font-size: 10px; min-width: 14px; height: 14px; padding: 0 3px; }
  .mobile-hide { display: none !important; }
  .conv-wechat-btn { max-width: 58px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding-left: 7px; padding-right: 7px; }
  .chat-shell { grid-template-columns: 1fr; height: calc(100% + 24px); max-height: calc(100vh - 48px); max-height: calc(100dvh - 48px); margin: -12px; overflow: hidden; }
  .chat-messages { padding: 16px 10px; }
  .execution-record-toggle { min-width: 140px; max-width: 70vw; }
  /* 原 8px 10px 内距太紧：输入框几乎贴着屏幕两侧，右侧发送按钮又贴着输入框边缘，
     两层"贴边"叠加显得局促。放宽到 10px 14px，与更高的输入框（见 min-height:56px）
     一起给整块输入区多留呼吸空间。 */
  .chat-input { padding: 10px 14px; }
  .chat-input-left .muted { display: none; }
  .pending-interaction-bar { grid-template-columns: 1fr; }
  /* 交互卡此前完全没有窄屏规则，只靠通用 flex 兜底：选项按钮在窄屏被挤成两三字一行，
     并排字段（IP + 端口那种 group）也只会压缩不换行。交互卡是本轮唯一的操作入口，
     不能在手机上退化成难点中的一团。 */
  .interaction-question { padding: 10px 12px 6px; }
  .interaction-capability-head { padding: 10px 12px 6px; }
  .interaction-options { padding: 4px 12px 10px; gap: 6px; }
  /* 窄屏一行一个选项：选项文案常带描述，横向并排必然逐字换行。 */
  .interaction-option { width: 100%; text-align: left; padding: 9px 12px; }
  .interaction-fields { padding-left: 12px; padding-right: 12px; }
  /* 并排字段在窄屏改为纵向堆叠（.field-row 是 flex 布局）。 */
  .field-row { flex-direction: column; }
  .field-row > .field-shrink { flex: 1 1 auto; }
  .interaction-custom { padding-left: 12px; padding-right: 12px; }
  /* 移动端输入交互：发送/终止按钮统一浮于输入框内右下角（.composer 内定位，尺寸与间距
     已在基础规则里统一放宽，此处不再重复一份旧值，避免两处数字将来对不上）；
     键盘换行键即发送（enterkeyhint=send + beforeinput 兜底） */
  .chat-input-bar { margin-top: 6px; min-height: 0; }
  /* 回到底部按钮改为相对输入区实测高度定位（--composer-h 由 ResizeObserver 写入）：
     输入框现在会随内容自适应增高，附件条/目标条也会动态出现，原先写死的 116px 必然
     在某个状态下把按钮顶到输入区里面或悬空。 */
  .scroll-bottom-btn { right: 14px; bottom: calc(var(--composer-h, 108px) + 12px); }
  .todo-row { grid-template-columns: auto minmax(0, 1fr); }
  .todo-actions { grid-column: 2; justify-content: flex-start; max-width: none; }
  .todo-add-actions { justify-content: stretch; }
  .todo-add-actions .btn { flex: 1; }
  .pin-compose-actions { justify-content: stretch; }
  .pin-compose-actions .btn { flex: 1; justify-content: center; }
  .git-operation-hero { grid-template-columns: 1fr; }
  .git-status-summary { justify-content: flex-start; }
  .git-publish-flow { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .type-grid { grid-template-columns: 1fr; }
  .type-option-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .type-group-head { flex-direction: column; align-items: flex-start; }
  .type-picker-hint { text-align: left; }
  .agent-invite-bar { padding: 12px; border-radius: 12px; }
  /* 窄屏标题与加入权限下拉换行堆叠，避免下拉被标题挤成一个只剩箭头的窄条。 */
  .agent-invite-bar-head { flex-direction: column; align-items: stretch; gap: 8px; }
  .agent-invite-joinmode-select { max-width: none; width: 100%; min-height: 40px; }
  .agent-invite-actions > .btn { width: 100%; min-height: 44px; }
  .agent-invite-no-chip { min-height: 40px; }
  .agent-invite-generated { grid-template-columns: 1fr; }
  .agent-invite-qr-frame { width: 100%; height: auto; min-height: 180px; }
  .agent-invite-qr { width: min(180px, 64vw); height: min(180px, 64vw); }
  .invite-link-row { grid-template-columns: 1fr; }
  .friends-card-head, .friends-section-head { flex-direction: column; }
  .friends-topbar { flex-direction: column; align-items: stretch; }
  .friends-topbar-right { justify-content: space-between; }
  .friend-self-alias:not(.compact) { justify-items: start; width: 100%; }
  .friends-request-head { flex-direction: column; }
  .friends-request-row { grid-template-columns: 1fr; }
  .invite-link-row .btn { width: 100%; }
  .works-tabs { flex-wrap: wrap; }
  .works-toolbar { grid-template-columns: 1fr; }
  .works-section-head { flex-direction: column; }
  .works-file-row { grid-template-columns: auto minmax(0, 1fr); align-items: flex-start; }
  .works-file-actions { grid-column: 2; justify-content: flex-start; margin-top: 4px; }
  /* 移动端：优先保证「文件名 + 操作按钮」同一行。窄屏空间不足时，类型徽标/状态下沉到第 2 行，
     避免把“预览”挤到下一行。 */
  .turn-summary-row { grid-template-columns: 18px minmax(0, 1fr) auto; align-items: center; column-gap: 6px; row-gap: 6px; }
  .turn-summary-symbol { grid-column: 1; grid-row: 1; }
  .turn-summary-path { grid-column: 2; grid-row: 1; min-width: 0; }
  .turn-summary-actions { grid-column: 3; grid-row: 1; justify-content: flex-end; white-space: nowrap; }
  .turn-summary-actions:empty { display: none; }
  .turn-summary-row .artifact-ext-badge { grid-column: 2; grid-row: 2; justify-self: start; }
  .turn-summary-label { grid-column: 3; grid-row: 2; justify-self: end; }
  .turn-summary-open { padding: 3px 8px; min-height: 26px; white-space: nowrap; flex: 0 0 auto; }
  /* 移动端：大模态框改为全屏推入（height 用 100dvh 跟随虚拟键盘动态缩放） */
  .modal { width: 100% !important; max-width: 100% !important; max-height: 100vh !important; max-height: 100dvh !important; border-radius: 0 !important; height: 100vh; height: 100dvh; }
  .modal .body { flex: 1; min-height: 0; }
  .model-library-layout { grid-template-columns: 1fr; }
  .model-library-pane { max-height: none; }
  .model-library-list { max-height: 200px; }
  .model-stat-grid { grid-template-columns: repeat(2, 1fr); }
  .load-earlier-btn { font-size: 12px; padding: 8px 12px; }
  /* ── Apple HIG: 移动端保存按钮 ── */
  .btn-save { width: 100%; min-height: 44px; font-size: 16px; font-weight: 600; border-radius: 10px; padding: 10px 16px; }
  .settings-card-head .row { flex-wrap: wrap; }
  .settings-card-head .row .btn:not(.btn-save) { flex: 1; min-height: 44px; }
  .settings-card-head .row .btn-save { flex: 1; }
  .settings-card > .row:has(> .btn-save) { width: 100%; }
  .settings-page { padding-bottom: 16px; }

  /* —— 渲染组件移动端可读性 ——
   * 桌面端样式不动；此处只收紧密度、抬字号下限、消除嵌套滚动与横向滚动孤岛。 */
  .render-component { margin: 10px 0; padding: 9px 11px; font-size: 13px; border-radius: 9px; }
  .render-component .rc-head { font-size: 12.5px; margin-bottom: 6px; }
  .render-component + .render-component { margin-top: 7px; }
  .render-component.rc-callout .rc-callout-body { padding: 8px 11px; }
  .render-component .rc-callout-title { font-size: 12.5px; }
  .render-component.rc-steps .rc-steps { gap: 7px; }
  .render-component.rc-steps .rc-step { padding-left: 24px; }
  .render-component.rc-steps .rc-step::before { width: 18px; height: 18px; font-size: 10.5px; }
  .render-component.rc-steps .rc-step-body { font-size: 12.5px; }
  /* kv：标签/值上下堆叠，避免长标签挤压值列 */
  dl.rc-kv { grid-template-columns: minmax(0, 1fr); gap: 2px 0; }
  dl.rc-kv dt { font-size: 12px; }
  dl.rc-kv dd { font-size: 12.5px; }
  .render-component.rc-stat .rc-stat-row { gap: 8px; }
  .render-component.rc-stat .rc-stat { min-width: 76px; padding: 7px 10px; }
  .render-component.rc-stat .rc-stat-value { font-size: 16px; }
  .render-component.rc-stat .rc-stat-label { font-size: 11.5px; }
  .render-component.rc-stat .rc-stat-hint { font-size: 11.5px; }
  /* compare / code_change / command_plan：表格转堆叠卡片，消除横向滚动孤岛；
     td 借 data-label 在 ::before 内联列名，保留列归属上下文。 */
  .render-component.rc-compare { padding-right: 9px; }
  .render-component.rc-compare .rc-compare-wrap { overflow: visible; }
  .render-component.rc-compare table.rc-compare,
  .render-component.rc-compare .rc-compare thead,
  .render-component.rc-compare .rc-compare tbody,
  .render-component.rc-compare .rc-compare tr { display: block; }
  .render-component.rc-compare .rc-compare thead { display: none; }
  .render-component.rc-compare .rc-compare tbody tr { padding: 7px 0; border-bottom: 1px solid var(--border); }
  .render-component.rc-compare .rc-compare tbody tr:last-child { border-bottom: none; }
  .render-component.rc-compare .rc-compare th,
  .render-component.rc-compare .rc-compare td { display: block; padding: 2px 0; border-bottom: 0; text-align: left; }
  .render-component.rc-compare .rc-compare-label { font-weight: 700; color: var(--text); white-space: normal; margin-bottom: 3px; font-size: 12.5px; }
  .render-component.rc-compare .rc-compare td { font-size: 12.5px; }
  .render-component.rc-compare .rc-compare td::before { content: attr(data-label) "："; color: var(--text-2); font-size: 11.5px; margin-right: 6px; }
  .render-component .rc-tree-node { padding-left: 12px; }
  .render-component .rc-tree-label { font-size: 12.5px; }
  .render-component .rc-timeline { gap: 8px; }
  .render-component .rc-tl-body { padding-left: 8px; }
  .render-component .rc-tl-title { font-size: 12.5px; }
  .render-component .rc-tl-text { font-size: 12.5px; }
  .render-component .rc-tl-time { font-size: 11.5px; }
  /* log-highlights：取消嵌套滚动，避免与外层聊天竖滑打架 */
  .render-component .rc-log-highlights { max-height: none; overflow: visible; }
  .render-component .rc-log-line { font-size: 11.5px; }
  .render-component .rc-badge { font-size: 11px; }
  .render-component .rc-stat-check { font-size: 12px; }
}

/* ===== admin console ===== */
.form-grid { display: grid; grid-template-columns: 96px 1fr; gap: 10px 12px; align-items: center; }
.form-grid label { color: var(--text-2); }
.form-grid > div[class~="muted"] { grid-column: 1 / -1; }

.admin-layout { display: grid; grid-template-columns: 188px minmax(0, 1fr); gap: 18px; align-items: start; }
.admin-nav {
  display: flex; flex-direction: column; gap: 4px; position: sticky; top: 0;
  padding: 6px; border: 1px solid var(--border); border-radius: 14px; background: var(--surface-tint);
}
.admin-nav-item {
  text-align: left; padding: 9px 12px; border-radius: 10px; border: 1px solid transparent;
  background: transparent; color: var(--text-2); cursor: pointer; font-size: 14px;
  transition: background .15s var(--ease-standard), color .15s var(--ease-standard), border-color .15s var(--ease-standard), transform .08s var(--ease-standard);
}
.admin-nav-item:hover { background: var(--panel-2); color: var(--text); }
.admin-nav-item:active { transform: scale(.985); }
.admin-nav-item.active { background: var(--primary-a-12); color: var(--text); border-color: var(--primary-a-55); }
.admin-panel-host { min-height: min(680px, calc(100vh - 160px)); max-width: 1120px; min-width: 0; }
.admin-composite-page { display: flex; flex-direction: column; gap: 12px; }
.admin-subtabs {
  display: flex; flex-wrap: wrap; gap: 8px; padding: 8px;
  border: 1px solid var(--border); border-radius: 14px; background: var(--surface-tint);
}
.admin-subtab-host { min-width: 0; }
.admin-loading { padding: 28px 4px; }
.admin-page .kv { grid-template-columns: 120px 1fr; }
.admin-section-hero {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: 16px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: 16px;
  background: linear-gradient(135deg, var(--primary-a-08), var(--surface-tint));
}
.admin-section-hero h3 { margin: 0 0 4px; font-size: 18px; }
.admin-section-hero p { margin: 0; line-height: 1.5; }
.admin-empty-state {
  border: 1px dashed var(--border); border-radius: 14px; padding: 22px 16px;
  background: var(--surface-tint); text-align: center;
}
.admin-empty-state.compact { padding: 18px 12px; }
.admin-empty-state.error { border-color: var(--error-a-45); background: var(--error-a-06); }
.admin-empty-title { margin-bottom: 4px; color: var(--text); font-weight: 650; }
.admin-search-card {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 12px; align-items: end;
  padding: 14px; margin-bottom: 12px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel);
}
.admin-search-main { min-width: 0; }

/* 列表条目：此前无样式，导致系统工具 / 系统设置等页是无边框无间距的裸 div 堆叠（排版散乱）。
   统一为带卡片边框、分隔与内距的清爽列表，桌面宽页与抽屉窄页通用。 */
.list-item {
  padding: 12px 14px;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel);
}
.list-item + .list-item { margin-top: 8px; }
/* 在管理台/抽屉里成组出现时，drawer-section-title 与其下条目形成清晰分组节奏 */
.drawer-page .drawer-section-title,
.admin-panel-host .drawer-section-title { margin: 14px 2px 8px; }
.drawer-page .drawer-section-title:first-child,
.admin-panel-host .drawer-section-title:first-child { margin-top: 0; }

.admin-table { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.admin-table-head, .admin-table-row { display: flex; align-items: center; gap: 12px; padding: 10px 12px; }
.admin-table-head { background: var(--panel-2); color: var(--text-2); font-size: 12px; }
.admin-table-row { border-top: 1px solid var(--border); }
.admin-cell { flex: 0 0 140px; }
/* 账号列：给一个下限宽度，避免在固定列已顶满 min-width:920px 时被 flex 压成 0 宽——
   否则长账号（含长 token 的邮箱）在 0 宽列里逐字竖排换行，把整行撑到几百 px 高，
   其余单元格因 align-items:center 居中，表现为表头与数据行之间出现超大空白行距。 */
.admin-cell.grow { flex: 1 1 220px; min-width: 180px; overflow: hidden; }
.admin-cell.grow strong { display: block; overflow-wrap: anywhere; word-break: break-word; }
.admin-cell select { width: auto; max-width: 100%; }
/* 用户管理列较多，窄面板内允许横向滚动，避免长账号把「角色/状态」列顶歪或覆盖。 */
.admin-users-table { overflow-x: auto; overflow-y: hidden; }
.admin-users-table .admin-table-head,
.admin-users-table .admin-table-row { min-width: 920px; }
.admin-switch { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--text-2); cursor: pointer; user-select: none; }
.admin-switch input { width: auto; margin: 0; cursor: pointer; }

.admin-cat-list { display: flex; flex-direction: column; gap: 8px; }
.admin-cat-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 12px; border: 1px solid var(--border); border-radius: 8px;
}
.admin-cat-item.disabled { opacity: .6; }
.admin-cat-main { min-width: 0; }
.admin-cat-actions { display: flex; gap: 6px; flex-shrink: 0; }

.usage-page { display: flex; flex-direction: column; gap: 12px; }
.usage-metric-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 10px; }
.usage-metric {
  min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 14px;
  background: var(--panel); box-shadow: inset 0 1px 0 rgba(255,255,255,.025);
}
.usage-metric.primary { background: linear-gradient(135deg, var(--primary-a-16), var(--panel)); border-color: var(--primary-a-45); }
.usage-metric.risk { background: linear-gradient(135deg, var(--error-a-08), var(--panel)); border-color: var(--error-a-35); }
.usage-metric.warn { background: linear-gradient(135deg, var(--warn-a-06), var(--panel)); border-color: var(--warn-a-35); }
.usage-metric-label { color: var(--text-2); font-size: 12px; }
.usage-metric-value { margin-top: 4px; color: var(--text); font-size: 24px; font-weight: 720; letter-spacing: -.02em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage-metric-hint { margin-top: 4px; color: var(--text-2); font-size: 11px; line-height: 1.45; }
.usage-insight {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; align-items: start;
  padding: 12px 14px; border: 1px solid var(--warn-a-35); border-radius: 14px;
  background: var(--warn-a-06); color: var(--text); font-size: 13px; line-height: 1.6;
}
.usage-insight strong { color: var(--warn); white-space: nowrap; }
.usage-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
.usage-panel {
  min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 16px;
  background: var(--panel); display: flex; flex-direction: column; gap: 10px;
}
.usage-panel-wide { grid-column: 1 / -1; }
.usage-panel-head { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
.usage-panel-head h4 { margin: 0 0 4px; font-size: 15px; }
.usage-panel-head p { margin: 0; font-size: 12px; line-height: 1.5; }
.usage-row { padding: 10px 0; border-top: 1px solid var(--border); }
.usage-row:first-of-type { border-top: none; }
.usage-row-top { display: flex; justify-content: space-between; gap: 12px; align-items: baseline; }
.usage-row-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 620; }
.usage-row-value { flex-shrink: 0; font-family: var(--mono); font-size: 12px; color: var(--text); }
.usage-row-meta { margin-top: 3px; font-size: 11px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.usage-bar { height: 6px; margin-top: 8px; border-radius: 999px; background: var(--surface-tint); overflow: hidden; }
.usage-bar span { display: block; height: 100%; border-radius: inherit; background: linear-gradient(90deg, var(--primary), var(--accent)); }
.usage-trend { height: 150px; display: grid; grid-template-columns: repeat(14, minmax(18px, 1fr)); gap: 8px; align-items: end; padding-top: 6px; }
.usage-trend-day { min-width: 0; height: 100%; display: grid; grid-template-rows: 1fr auto; gap: 6px; align-items: end; }
.usage-trend-bar { height: 118px; display: flex; align-items: end; justify-content: center; border-radius: 999px; background: var(--surface-tint); overflow: hidden; }
.usage-trend-bar span { width: 100%; min-height: 6px; border-radius: inherit inherit 0 0; background: linear-gradient(180deg, var(--primary), var(--primary-a-35)); }
.usage-trend-label { text-align: center; font-size: 10px; white-space: nowrap; }

.identity-result { margin-top: 12px; }
.identity-card {
  overflow: hidden; border: 1px solid var(--border); border-radius: 16px; background: var(--panel);
}
.identity-card-head {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 12px; align-items: center;
  padding: 16px; background: linear-gradient(135deg, var(--surface-tint-2), transparent);
}
.identity-avatar {
  width: 44px; height: 44px; border-radius: 14px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary-a-16); color: var(--primary); font-weight: 750;
}
.identity-avatar.user { background: var(--success-a-12); color: var(--success); }
.identity-main { min-width: 0; }
.identity-number { font-family: var(--mono); font-size: 24px; font-weight: 760; letter-spacing: -.02em; }
.identity-meta { margin-top: 2px; font-size: 12px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.identity-reassign { padding: 14px 16px 16px; border-top: 1px solid var(--border); }
.identity-reassign p { margin: 0 0 10px; font-size: 12px; line-height: 1.5; }
.identity-reassign-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center; }

.sandbox-page { display: flex; flex-direction: column; gap: 12px; }
.sandbox-hero {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: 16px; border: 1px solid var(--border); border-radius: 16px; background: var(--panel);
}
.sandbox-hero.ok { border-color: var(--success-a-42); background: linear-gradient(135deg, var(--success-a-08), var(--panel)); }
.sandbox-hero.warn { border-color: var(--warn-a-35); background: linear-gradient(135deg, var(--warn-a-06), var(--panel)); }
.sandbox-hero.neutral { background: linear-gradient(135deg, var(--surface-tint-2), var(--panel)); }
.sandbox-hero h3 { margin: 0 0 4px; font-size: 18px; }
.sandbox-hero p { margin: 0; line-height: 1.5; }
.sandbox-hero-badge {
  flex-shrink: 0; padding: 5px 10px; border-radius: 999px; border: 1px solid var(--border);
  font-size: 12px; font-weight: 650; white-space: nowrap;
}
.sandbox-hero-badge.ok { color: var(--success); border-color: var(--success-a-45); background: var(--success-a-08); }
.sandbox-hero-badge.warn { color: var(--warn); border-color: var(--warn-a-35); background: var(--warn-a-06); }
.sandbox-hero-badge.neutral { color: var(--text-2); background: var(--surface-tint); }
.sandbox-status-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.sandbox-status-card {
  min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 14px; background: var(--panel);
}
.sandbox-status-card.ok { border-color: var(--success-a-35); background: var(--success-a-06); }
.sandbox-status-card.warn { border-color: var(--warn-a-35); background: var(--warn-a-06); }
.sandbox-status-label { color: var(--text-2); font-size: 12px; }
.sandbox-status-value { margin-top: 4px; color: var(--text); font-size: 18px; font-weight: 720; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sandbox-status-hint { margin-top: 4px; color: var(--text-2); font-size: 11px; line-height: 1.45; }
.sandbox-callout {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 10px; align-items: start;
  padding: 12px 14px; border-radius: 14px; font-size: 13px; line-height: 1.6; border: 1px solid var(--border); background: var(--surface-tint);
}
.sandbox-callout.ok { border-color: var(--success-a-35); background: var(--success-a-06); }
.sandbox-callout.ok strong { color: var(--success); }
.sandbox-callout.warn { border-color: var(--warn-a-35); background: var(--warn-a-06); }
.sandbox-callout.warn strong { color: var(--warn); }
.sandbox-callout.neutral strong { color: var(--text); }
.sandbox-panel {
  min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 16px; background: var(--panel);
}
.sandbox-detail-list { margin-top: 10px; border: 1px solid var(--border); border-radius: 12px; overflow: hidden; }
.sandbox-detail-row {
  display: grid; grid-template-columns: 130px minmax(0, 1fr); gap: 12px; align-items: center;
  padding: 11px 12px; border-top: 1px solid var(--border);
}
.sandbox-detail-row:first-child { border-top: none; }
.sandbox-detail-row span { color: var(--text-2); font-size: 12px; }
.sandbox-detail-row strong { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-weight: 520; font-family: var(--mono); font-size: 12px; }
.sandbox-note { margin-top: 10px; color: var(--text-2); font-size: 13px; line-height: 1.65; }

.system-agent-factory-page { display: flex; flex-direction: column; gap: 12px; }
.system-agent-compose {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(180px, 240px) auto;
  gap: 12px; align-items: end; padding: 14px; border: 1px solid var(--border);
  border-radius: 16px; background: var(--panel);
}
.system-agent-workbench { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: 12px; align-items: start; }
.system-agent-governance-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; align-items: start; }
/* 质量事件通常最长，独占左列并跨两行；右列上下叠放「代码诊断」与「AI 日报」，避免右列留白与视觉遮挡。 */
.system-agent-governance-grid > .governance-primary { grid-column: 1; grid-row: 1 / span 2; }
.system-agent-panel {
  min-width: 0; padding: 14px; border: 1px solid var(--border); border-radius: 16px;
  background: var(--panel); display: grid; gap: 10px;
}
.system-agent-panel.grow { min-height: 520px; }
.system-agent-panel h4 { margin: 0; }
.system-agent-list { display: grid; gap: 8px; }
.system-agent-blueprint-item {
  width: 100%; text-align: left; padding: 10px 12px; border: 1px solid var(--border);
  border-radius: 12px; background: var(--surface-tint); color: var(--text); cursor: pointer;
}
.system-agent-blueprint-item:hover { background: var(--surface-tint-2); }
.system-agent-blueprint-item.active { border-color: var(--primary-a-45); background: var(--primary-a-08); }
.system-agent-blueprint-title { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.system-agent-asset-row {
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 12px; align-items: flex-start;
  padding: 11px 12px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint);
}
.system-agent-asset-row.compact { padding: 9px 10px; }
/* 主内容占满一行的基准宽度；窄栏（如治理网格左半栏）放不下操作按钮时，
   按钮组整体换到下一行，避免溢出被右侧面板遮挡导致点不到。 */
.system-agent-asset-main { min-width: 0; flex: 1 1 220px; }
/* 操作按钮组：允许自身换行兜底，并靠右对齐，配合外层换行不再横向溢出。 */
.system-agent-asset-row > .row:last-child { flex-wrap: wrap; justify-content: flex-end; }
.system-agent-ref-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.system-agent-preview-card { display: grid; gap: 14px; }
.system-agent-preview-head { display: flex; justify-content: space-between; gap: 12px; align-items: flex-start; }
.system-agent-preview-head h3 { margin: 0 0 4px; }
.system-agent-preview-head p { margin: 0; }
.system-agent-form-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.system-agent-form-grid .field:nth-child(3),
.system-agent-form-grid .field:nth-child(4) { grid-column: 1 / -1; }
.system-agent-check-grid {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px;
  padding: 10px; border: 1px solid var(--border); border-radius: 12px; background: var(--surface-tint);
}
.system-agent-eval-box {
  display: grid; gap: 8px; padding: 12px; border: 1px solid var(--border);
  border-radius: 14px; background: var(--surface-tint);
}
.system-agent-eval-row {
  display: grid; grid-template-columns: minmax(120px, .35fr) minmax(0, 1fr); gap: 10px;
  padding-top: 8px; border-top: 1px solid var(--border); font-size: 12px;
}
.system-agent-eval-row span { font-weight: 650; }
.system-agent-eval-row em { color: var(--text-2); font-style: normal; }

@media (max-width: 900px) {
  .usage-metric-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .usage-grid { grid-template-columns: 1fr; }
  .sandbox-status-grid { grid-template-columns: 1fr; }
  .system-agent-compose, .system-agent-workbench, .system-agent-governance-grid, .system-agent-form-grid { grid-template-columns: 1fr; }
  .system-agent-governance-grid > .governance-primary { grid-column: auto; grid-row: auto; }
  .system-agent-check-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 720px) {
  .admin-layout { grid-template-columns: 1fr; }
  .admin-nav { flex-direction: row; flex-wrap: nowrap; overflow-x: auto; position: static; }
  .admin-nav-item { white-space: nowrap; flex: 0 0 auto; }
  .admin-search-card, .identity-reassign-row { grid-template-columns: 1fr; }
  .usage-metric-grid { grid-template-columns: 1fr; }
  .usage-insight, .sandbox-callout { grid-template-columns: 1fr; }
  .sandbox-hero { flex-direction: column; }
  .system-agent-check-grid, .system-agent-eval-row { grid-template-columns: 1fr; }
  .capability-return-banner { flex-direction: column; align-items: stretch; }
  .capability-return-dismiss { top: 4px; right: 4px; }
  .sandbox-detail-row { grid-template-columns: 1fr; gap: 4px; }
  .panel-head { flex-wrap: wrap; }
  .admin-table-head { display: none; }
  .admin-users-table .admin-table-head, .admin-users-table .admin-table-row { min-width: 0; }
  .admin-table-row { flex-direction: column; gap: 8px; padding: 14px 12px; }
  .admin-cell { flex: unset; min-width: 0; display: flex; align-items: center; flex-wrap: wrap; gap: 4px; }
  .admin-cell.grow { margin-bottom: 0; }
  .admin-cell::before { content: attr(data-label) '：'; display: inline-block; flex: 0 0 auto; font-size: 12px; color: var(--text-2); margin-right: 2px; white-space: nowrap; }
  .admin-cell select { max-width: 100%; }
}

/* ============================================================
 * 浅色主题专属覆写
 * —— 基础样式已通过 CSS 变量自动适配，此处仅保留仍需选择器级覆写的样式
 * ============================================================ */

/* 结构线 & 边框增强 */
html.light .side { border-right-color: var(--border); }
html.light .side-agent-head:hover { background: var(--surface-tint); border-color: var(--border); }
html.light .topbar { border-bottom-color: var(--border); }

/* 输入框浅色需重设 focus 态 */
html.light input:focus, html.light textarea:focus, html.light select:focus {
  border-color: var(--primary);
}

/* 按钮浅色特定态 */
html.light .btn.primary { color: #fff; }

/* 标签 —— 半透明背景由变量驱动，此处仅补结构 */
html.light .tag { border-color: var(--border); color: var(--text-2); }
html.light .tag.queued { background: var(--surface-tint); }

/* 卡片 —— 浅色加阴影提层级 */
html.light .card { background: var(--panel); border-color: var(--border); }

/* 对话页 */
html.light .chat-header { background: var(--panel); border-bottom-color: var(--border); }
html.light .chat-input { background: var(--panel); border-top-color: var(--border); }
html.light .chat-main { background: var(--bg); }
html.light .msg.ai .msg-avatar { background: var(--panel-2); border-color: var(--border); }
html.light .msg.ai .msg-content { background: var(--panel); border-color: var(--border); }
html.light .msg.user .msg-content { background: var(--primary); color: var(--accent-fg); }

/* 工具输出 & 终端 —— 背景已由 --term-bg 变量驱动 */
html.light .tool { background: var(--panel-2); border-color: var(--border); }
html.light .tool.tool-use { border-left-color: var(--primary); }
html.light .tool.tool-ok { border-left-color: var(--success); }
html.light .tool.tool-bad { border-left-color: var(--error); }

/* 品牌 */
html.light .brand-mark {
  background: linear-gradient(135deg, var(--primary-a-12), var(--accent-a-18));
  border-color: var(--border); color: var(--text);
}
html.light .drawer-brand-logo {
  box-shadow: 0 2px 8px var(--primary-a-18);
}

/* 会话下拉 */
html.light .conv-dropdown { background: var(--panel); border-color: var(--border); box-shadow: 0 8px 24px rgba(0,0,0,.1); }

/* 浮层 —— 浅色下降透明度、加阴影 */
html.light .drawer-panel { background: var(--panel); border-color: var(--border); box-shadow: -8px 0 30px rgba(0,0,0,.08); }
html.light .drawer-head, html.light .drawer-footer { border-color: var(--border); }
html.light .modal { background: var(--panel); border-color: var(--border); }
html.light .modal-mask { background: rgba(0,0,0,.32); }
html.light .modal-head, html.light .modal .footer { border-color: var(--border); }
html.light .sheet-panel { background: var(--panel); border-color: var(--border); }

/* Toast & 登录 */
html.light .toast { background: var(--panel); border-color: var(--border); }
/* 登录页亮色适配已由 html.light .login-shell 统一接管（split 玻璃外壳）；login-card 自身保持透明。 */
html.light .binding-status { border-color: var(--border); }
html.light .binding-status.ok { border-color: var(--success-a-35); background: var(--success-a-06); }
html.light .success-box { border-color: var(--success-a-35); background: var(--success-a-06); }

/* 工具组 */
html.light .tool-group { border-color: var(--border); }

/* 微信指示器 —— 浅色下需深绿确保可读 */
html.light .conv-wechat-badge { color: var(--success); }
html.light .conv-wechat-btn { color: var(--success); }
html.light .conv-wechat-btn.disconnect { color: var(--text-2); border-color: var(--border); }
html.light .conv-wechat-btn.disconnect:hover { color: var(--error); }

/* 摘要 & 状态 */
html.light .turn-status.queued, html.light .turn-status.running, html.light .turn-status.committing, html.light .turn-status.starting, html.light .turn-status.interacting {
  color: var(--text-2); background: transparent; border-color: var(--border);
}
html.light .turn-status.interacting { color: var(--text); border-color: var(--border); }
html.light .turn-status.unknown, html.light .turn-status.stale-warning { color: var(--warn); background: var(--warn-a-06); border-color: var(--warn-a-35); }
html.light .action-force-cancel { background: var(--warn-a-06); color: var(--warn); border-color: var(--warn-a-35); }
html.light .action-force-cancel:hover:not(:disabled) { background: var(--warn-a-22); }

/* 表格 & 管理 */
html.light .admin-table { border-color: var(--border); }
html.light .admin-table-head { background: var(--panel-2); }
html.light .wechat-qr,
html.light .wechat-qr-frame { background: #fff; }
html.light .wechat-qr-frame { border-color: var(--border); box-shadow: 0 12px 34px rgba(15,23,42,.10); }
/*冷蓝黑（slate）阴影在暖底上会明显发青，且这里扩散达 34px 最容易看出色偏，换棕调。
 * 二维码衬底刻意保持纯白：扫码识别率依赖高反差，媒体类内容不参与主题暖化。 */
html.sepia .wechat-qr-frame { box-shadow: 0 12px 34px rgba(74,54,38,.12); }
html.light .context-compressed-hint { background: var(--primary-a-08); border-color: var(--primary-a-35); }
html.light .load-earlier-btn { background: var(--panel-2); border-color: var(--border); }
html.light .load-earlier-btn:hover { background: var(--surface-tint); }

/* 事件 */
html.light .event { background: var(--panel); border-color: var(--border); }
html.light .event.status { background: var(--panel-2); }

/* 浅色 hover 态 —— 变量驱动的 surface-tint 在浅色下即为 rgba(0,0,0,...)，
   但 hover 需稍深，此处统一补一层 */
html.light .side-nav-item:hover { background: rgba(0,0,0,.04); }
html.light .side-nav-item.active { background: var(--primary-a-08); }
html.light .drawer-project-card:hover, html.light .drawer-link-row:hover { background: rgba(0,0,0,.04); }
html.light .drawer-project-card.current { background: var(--primary-a-08); }
html.light .type-card { background: var(--panel); }
html.light .type-card:hover { background: var(--panel-2); }

/* 恢复 & 管线 */
html.light .recovery-actions { border-top-color: var(--error-a-28); }
html.light .ai-pipeline { border-color: var(--success-a-35); }
html.light .ai-pipeline.bad { border-color: var(--error); color: var(--error); }
html.light .ai-error { border-color: var(--error); color: var(--error); }

/* ── 浅色主题阴影增强 ──
 * 深色主题靠边框和微妙表面差异做层级；浅色主题用阴影提供深度感，
 * 遵循 Material Design 3 "Elevation" 原则 */
html.light .card { box-shadow: none; }
html.light .modal { box-shadow: 0 20px 60px rgba(0,0,0,.12); }
html.light .conv-dropdown { box-shadow: 0 8px 24px rgba(0,0,0,.1); }
html.light .scroll-bottom-btn { box-shadow: 0 4px 16px rgba(0,0,0,.08); }
html.light .toast { box-shadow: 0 4px 12px rgba(0,0,0,.08); }
html.light .chat-header { box-shadow: 0 1px 0 rgba(0,0,0,.06); }
html.light .chat-input { box-shadow: 0 -1px 0 rgba(0,0,0,.06); }
html.light .action-stop { background: var(--error-a-06); }
html.light .side { box-shadow: 1px 0 0 rgba(0,0,0,.06); }
html.light .topbar { box-shadow: 0 1px 0 rgba(0,0,0,.06); }

/* ===== 主题切换分段控件 ===== */
.theme-switch-row { display: flex; align-items: center; justify-content: center; gap: 8px; padding: 6px 0; }
.theme-switch {
  position: relative; display: flex; gap: 0;
  background: var(--panel-2); border: 1px solid var(--border); border-radius: 8px;
  padding: 2px; min-width: 216px;
}
.theme-switch-option {
  position: relative; z-index: 1;
  flex: 1; display: flex; align-items: center; justify-content: center; gap: 4px;
  padding: 5px 8px; border: none; background: transparent;
  color: var(--text-2); font-size: 12px; cursor: pointer;
  border-radius: 6px; transition: color .15s ease;
  white-space: nowrap;
}
.theme-switch-option[aria-pressed="true"] { color: var(--text); }
.theme-switch-icon { font-size: 13px; line-height: 1; }
/* 三档滑块：指示器宽度按档数均分，位移按档位序号推进。
 * 用 calc((100% - 2px) / 3) 而不是 33.333%，是为了扣掉容器 2px 内边距造成的累积误差，
 * 否则第三档会溢出右边缘约 1–2px。 */
.theme-switch-indicator {
  position: absolute; top: 2px; bottom: 2px; left: 2px;
  width: calc((100% - 4px) / 3); background: var(--panel);
  border-radius: 6px; box-shadow: 0 1px 3px rgba(0,0,0,.12);
  transition: transform .2s cubic-bezier(.4,0,.2,1);
}
.theme-switch[data-active="sepia"] .theme-switch-indicator {
  transform: translateX(100%);
}
.theme-switch[data-active="dark"] .theme-switch-indicator {
  transform: translateX(200%);
}

/* ===== 详情页 iOS 设置风格 ===== */
.detail-page { padding: 0; }
.detail-section { margin-bottom: 20px; }
.detail-section-title {
  margin: 0 0 6px; padding: 0 4px;
  color: var(--text-2); font-size: 11px; font-weight: 600;
  letter-spacing: .04em; text-transform: uppercase;
}
.detail-card {
  background: var(--panel-2); border-radius: 12px;
  padding: 0; overflow: hidden;
  border: 1px solid var(--border);
}
.detail-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 12px 14px;
  border-bottom: 1px solid var(--border);
}
.detail-row:last-child { border-bottom: none; }
.detail-row-label { color: var(--text-2); font-size: 13px; flex-shrink: 0; min-width: 64px; }
.detail-row-value { color: var(--text); font-size: 13px; text-align: right; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.detail-row-btn {
  width: 100%; border: none; background: transparent; cursor: pointer;
  color: var(--text); text-align: left;
}
.detail-row-btn:hover { background: rgba(128,128,128,.06); }

/* 头像大卡 */
.profile-hero {
  display: flex; align-items: center; gap: 14px;
  padding: 16px 4px; margin-bottom: 4px;
}
.profile-avatar-xl {
  width: 56px; height: 56px; border-radius: 14px;
  background: linear-gradient(135deg, var(--primary), var(--accent));
  color: white; display: flex; align-items: center; justify-content: center;
  font-size: 24px; font-weight: 700; flex-shrink: 0;
}
.profile-hero-info h3 { margin: 0 0 4px; font-size: 15px; }
.profile-hero-tags { display: flex; gap: 4px; }

/* 表单字段 */
.detail-field {
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
}
.detail-field:last-child { border-bottom: none; }
.detail-field-label {
  display: block; margin-bottom: 4px;
  color: var(--text-2); font-size: 11px; font-weight: 600;
  letter-spacing: .02em;
}
.detail-input {
  width: 100%; padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--border); background: var(--panel);
  color: var(--text); font-size: 13px;
  transition: border-color .15s;
}
.detail-input:focus { outline: none; border-color: var(--primary); }

/* 提示、空态、提示框 */
.detail-hint {
  padding: 2px 4px; color: var(--text-2); font-size: 12px; line-height: 1.5;
}
.detail-empty {
  padding: 24px 14px; text-align: center; color: var(--text-2); font-size: 13px;
}
.detail-error {
  padding: 6px 14px 10px; color: var(--error); font-size: 12px; min-height: 20px;
}
.detail-callout {
  border-radius: 10px; padding: 12px 14px; margin-top: 8px;
  font-size: 13px; line-height: 1.5;
}
.detail-callout.ok {
  background: var(--success-a-08); border: 1px solid var(--success-a-45);
}
.detail-callout.warn {
  background: rgba(245,158,11,.08); border: 1px solid rgba(245,158,11,.4);
}
.detail-callout.error {
  background: var(--error-a-08); border: 1px solid var(--error-a-45);
}
.detail-action-btn {
  width: 100%; margin-top: 12px;
}
.detail-link {
  color: var(--primary); text-decoration: none; font-size: 13px;
}
.detail-link:hover { text-decoration: underline; }

/* 状态小圆点 */
.status-dot {
  display: inline-flex; align-items: center; gap: 5px;
}
.status-dot::before {
  content: ''; display: inline-block; width: 7px; height: 7px;
  border-radius: 50%; background: var(--success);
}

/* 标签 */
.tag-green { background: var(--success-a-08); color: var(--success); border: 1px solid var(--success-a-45); }

/* 浅色模式适配 */
html.light .detail-card { background: var(--surface-tint); }
html.light .detail-row-btn:hover { background: var(--surface-tint-2); }
html.light .detail-input { background: var(--input-bg); }

/* 外观设置：品牌色固定，只保留深浅主题。 */
.appearance-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 6px 0; }
.appearance-row + .appearance-row { border-top: 1px solid var(--border); }
.appearance-label { font-size: 13px; }
.theme-switch[data-active="dark"] .theme-switch-indicator { transform: translateX(calc(100% + 2px)); }

/* —— 会话 token 超 24H 失效（无法主动推送，需用户在微信再发消息）—— */
/* 头部按钮：警示色 */
.conv-wechat-btn.stale { color: var(--warn); border-color: var(--warn); background: var(--warn-a-06); }
.conv-wechat-btn.stale:hover { background: var(--warn-a-22); }
/* 下拉徽章：待恢复态 */
.conv-wechat-badge.stale { background: var(--warn-a-22); color: var(--warn); border-color: var(--warn-a-35); box-shadow: none; }
.wechat-recover p { margin: 0 0 10px; line-height: 1.6; }
.wechat-recover-steps {
  display: grid; gap: 8px; margin: 10px 0 12px; padding: 10px 12px;
  border: 1px solid var(--warn-a-35); border-radius: 10px;
  background: var(--warn-a-06); color: var(--text);
  font-size: 13px;
}

/* ============================================================
 * Native Refinement Layer —— 让整体观感更接近优秀的苹果软件
 * 设计原则（Apple HIG）：Clarity 清晰 · Deference 克制 · Depth 纵深
 *  · 8pt 间距节奏、克制的层级、spring 动效与即时按压反馈
 * 本层为「叠加覆写」，放在文件末尾依靠层叠顺序生效，
 * 仅触碰安全属性，不改动既有结构，便于回退。
 * ============================================================ */
:root {
  /* 间距阶（8pt 基准） */
  --sp-1: 4px; --sp-2: 8px; --sp-3: 12px; --sp-4: 16px; --sp-5: 20px; --sp-6: 24px;
  /* 圆角阶 */
  --r-sm: 8px; --r-md: 10px; --r-lg: 14px; --r-xl: 18px;
  /* 动效曲线：standard 标准 / spring 带回弹 */
  --ease-standard: cubic-bezier(.4, 0, .2, 1);
  --ease-spring: cubic-bezier(.32, .72, 0, 1);
  /* 聚焦光环：定义已收敛到文件头 :root 唯一一处（见那里的说明），此处不再重复声明。 */
}

/* —— 字体渲染：开启抗锯齿 + 微收紧字距，靠近 macOS / SF 文本观感 —— */
html, body {
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  letter-spacing: -0.01em;
}
h1, h2, h3, h4 { letter-spacing: -0.02em; }
/* 等宽内容不参与字距收紧，避免代码错位 */
pre, code, .term, textarea, .login-code, [class*="mono"] { letter-spacing: normal; }

/* —— 选区 & 细滚动条：苹果式克制视觉 —— */
::selection { background: var(--primary-a-24); }
* { scrollbar-width: thin; scrollbar-color: var(--border) transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-track { background: transparent; }
*::-webkit-scrollbar-thumb {
  background: var(--border); border-radius: 999px;
  border: 2px solid transparent; background-clip: padding-box;
}
*::-webkit-scrollbar-thumb:hover { background: var(--text-2); background-clip: padding-box; }

/* —— 控件：更大的触控区 + 聚焦光环（替代生硬的描边变色）—— */
input, select, textarea {
  padding: 9px 12px; border-radius: var(--r-sm);
  transition: border-color .15s var(--ease-standard), box-shadow .15s var(--ease-standard), background .15s var(--ease-standard);
}
input:not([type="checkbox"]):not([type="radio"]) { min-height: 38px; }
input:focus, textarea:focus, select:focus { border-color: var(--primary); box-shadow: var(--focus-ring); }

/* —— 按钮：即时按压反馈 + 平滑过渡（不动既有圆角/内距，避免回归）—— */
.btn { transition: background .15s var(--ease-standard), border-color .15s var(--ease-standard), color .15s var(--ease-standard), transform .08s var(--ease-standard), box-shadow .15s var(--ease-standard); }
.btn:active:not(:disabled) { transform: scale(.97); }
.btn.primary { box-shadow: 0 1px 2px var(--primary-a-35); }
.btn.primary:active:not(:disabled) { box-shadow: 0 1px 1px var(--primary-a-22); }

/* —— 设置卡：Apple「分组」观感——更柔的圆角、更舒展的内距与组间节奏 —— */
.settings-card { gap: var(--sp-4); padding: var(--sp-5); border-radius: var(--r-lg); }
.settings-card > h3, .settings-card-head h3 { font-size: 16px; font-weight: 650; }
.settings-card-head { align-items: center; margin-bottom: 0; }
.settings-card-head > :first-child, .panel-head > :first-child { min-width: 0; flex: 1 1 auto; }
.settings-card-head > .row, .panel-head > .row { flex: 0 0 auto; flex-wrap: wrap; justify-content: flex-end; max-width: 100%; }
.settings-card-head p { margin-top: 4px; line-height: 1.5; }
.settings-field-group { display: flex; flex-direction: column; gap: 10px; padding: 12px; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--surface-tint); }
.settings-field-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 14px; }
.settings-field { min-width: 0; }
.settings-field-label { display: block; color: var(--text-2); font-size: 11px; margin-bottom: 2px; }
.settings-field-value { display: block; color: var(--text); font-size: 12.5px; overflow-wrap: anywhere; }
/* Agent 管理页「会话引导样例」：多行可增删的文本列表。*/
.settings-examples-list { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
.settings-example-row { display: flex; align-items: center; gap: 8px; }
.settings-example-row input { flex: 1 1 auto; min-width: 0; }
.settings-example-row .btn { flex: 0 0 auto; padding: 0 10px; line-height: 1; }

/* —— 字段标签：紧贴控件、字重略增，形成清晰的「标签—控件」组 —— */
.field > label { font-size: 12px; font-weight: 600; color: var(--text-2); }
.field-hint { line-height: 1.5; }

/* —— 侧栏导航：active 药丸高亮 + 轻按压反馈 —— */
.side-nav-item { transition: background .15s var(--ease-standard), color .15s var(--ease-standard), transform .08s var(--ease-standard); }
.side-nav-item:active { transform: scale(.98); }

/* —— 浮层：磨砂背景 + spring 入场，强化纵深层级 —— */
.modal-mask, .drawer-mask, .sheet-mask {
  backdrop-filter: saturate(160%) blur(8px);
  -webkit-backdrop-filter: saturate(160%) blur(8px);
  /* iOS/WebKit 已知坑：内容卡里的 <video> 缩率图（首帧封面）会被提升到独立的硬件视频
     合成层，个别机型上这层会无视普通 z-index 大小顺序，穿透浮层盖在遮罩/面板之上——
     表现就是移动端分享/删除时弹出的二次确认面板，确认按钮被卡片自己的视频缩率图挡住点不到。
     backdrop-filter 本身会促使浏览器把遮罩提升为独立合成层从而正确排到视频层之上，
     但 Safari 在下面一条规则里把 backdrop-filter 降级掉了，所以这里显式补一个
     translateZ(0) 强制遮罩自身单独成层，不依赖 backdrop-filter 是否生效都能压住视频层。 */
  transform: translateZ(0);
  -webkit-transform: translateZ(0);
}
/* Safari/WebKit 对 backdrop-filter 合成开销大，频繁开关浮层时明显卡顿；
   降级为纯色遮罩（背景色本身已足够深，不做模糊也不影响可读性）。 */
.is-safari .modal-mask, .is-safari .drawer-mask, .is-safari .sheet-mask {
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
.modal { animation: nativeModalPop .32s var(--ease-spring); transform-origin: center; }
@keyframes nativeModalPop {
  from { opacity: 0; transform: scale(.94) translateY(10px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}

/* —— Toast：spring 滑入 + 更柔的阴影与圆角 —— */
.toast {
  border-radius: var(--r-md);
  box-shadow: 0 8px 30px rgba(0,0,0,.18);
  animation: nativeToastIn .3s var(--ease-spring);
}
@keyframes nativeToastIn {
  from { opacity: 0; transform: translateX(16px) scale(.98); }
  to   { opacity: 1; transform: translateX(0) scale(1); }
}

/* —— Grouped Inset List：iOS 设置页最标志性的分组列表范式 ——
 * 整组一张大圆角卡片，组内多项靠「不到左边的发丝分隔线」区隔，
 * 而非每项都画边框；行有按压/悬停反馈。 */
.grouped-list {
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  overflow: hidden;
}
.grouped-list .glist-row {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  position: relative;
  transition: background .15s var(--ease-standard);
}
.grouped-list .glist-row:hover { background: var(--primary-a-08); }
/* 发丝分隔线：左侧内缩，对齐标题文本，最后一行不画 */
.grouped-list .glist-row::after {
  content: '';
  position: absolute;
  left: var(--sp-4); right: 0; bottom: 0;
  height: 1px;
  background: var(--border);
  transform: scaleY(.5);
  transform-origin: bottom;
}
.grouped-list .glist-row:last-child::after { display: none; }
.glist-main { flex: 1; min-width: 0; }
.glist-title { display: flex; align-items: center; gap: var(--sp-2); font-weight: 600; }
.glist-title > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.glist-sub { margin-top: 2px; font-size: 12px; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.glist-actions { display: flex; align-items: center; justify-content: flex-end; gap: var(--sp-2); flex-shrink: 0; flex-wrap: wrap; }
.glist-danger { color: var(--error); }
/* 读写徽章：胶囊状、克制 */
.glist-badge { font-size: 11px; font-weight: 600; padding: 1px 7px; border-radius: 999px; line-height: 1.6; }
.glist-badge.ro { color: var(--text-2); background: rgba(127,127,127,.14); }
.glist-badge.rw { color: var(--warn); background: var(--warn-a-22); }

/* —— iOS 风格分段控件（Segmented Control）：替代短选项下拉框 —— */
.segmented-control {
  display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
  gap: 2px; padding: 3px;
  border: 1px solid var(--border);
  border-radius: 12px;
  background: rgba(120,120,128,.16);
}
.segmented-option {
  border: 0; border-radius: 9px; padding: 7px 10px;
  background: transparent; color: var(--text-2);
  cursor: pointer; text-align: center;
  transition: background .18s var(--ease-standard), color .18s var(--ease-standard), box-shadow .18s var(--ease-standard), transform .2s var(--ease-spring);
}
.segmented-option:hover { color: var(--text); }
.segmented-option:active { transform: scale(.98); }
.segmented-option.active { background: var(--panel); color: var(--text); box-shadow: 0 1px 3px rgba(0,0,0,.16); }
.segmented-option .seg-title { display: block; font-size: 13px; font-weight: 650; }
.segmented-option .seg-hint { display: block; margin-top: 2px; font-size: 11px; color: var(--text-2); }
.segmented-option:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* Agent 好友协作方式：用解释型卡片替代三个专业下拉（stage/trigger/workMode），
   让用户选择“它怎么帮你”，而不是理解底层执行参数。 */
.friend-mode-grid { display: grid; grid-template-columns: 1fr; gap: 8px; }
.friend-mode-card {
  position: relative; width: 100%; text-align: left; cursor: pointer;
  border: 1px solid var(--border); border-radius: 12px; background: var(--panel);
  color: var(--text); padding: 11px 38px 11px 12px;
  transition: background .16s var(--ease-standard), border-color .16s var(--ease-standard), box-shadow .18s var(--ease-standard), transform .18s var(--ease-spring);
}
.friend-mode-card:hover { background: var(--panel-2); transform: translateY(-1px); }
.friend-mode-card.active { border-color: var(--primary); box-shadow: 0 0 0 1px var(--primary-a-35) inset, 0 8px 20px var(--primary-a-08); }
.friend-mode-card strong { display: flex; align-items: center; gap: 6px; font-size: 13px; line-height: 1.35; }
.friend-mode-card > span:not(.friend-mode-check) { display: block; color: var(--text-2); font-size: 12px; line-height: 1.45; margin-top: 4px; }
.friend-mode-check {
  position: absolute; top: 11px; right: 12px; width: 18px; height: 18px; border-radius: 999px;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 11px; font-weight: 800; background: var(--primary); color: var(--accent-fg);
  opacity: 0; transform: scale(.72); transition: opacity .16s var(--ease-standard), transform .2s var(--ease-spring);
}
.friend-mode-card.active .friend-mode-check { opacity: 1; transform: scale(1); }
.friend-mode-badge { font-size: 10px; font-weight: 700; color: var(--primary); background: var(--primary-a-08); border: 1px solid var(--primary-a-35); border-radius: 999px; padding: 0 6px; }
.friend-trust-segment { grid-auto-flow: column; }

/* —— iOS 风格拨动开关（toggle switch）：替代默认复选框 ——
 * 开关行：左侧标签/说明，右侧轨道；开态用主色，关态中性灰，
 * 旋钮带柔性投影与 spring 位移。 */
.switch-field { display: flex; align-items: center; gap: var(--sp-4); }
.switch-field-main { flex: 1; min-width: 0; }
.switch-field-label { font-weight: 500; color: var(--text); }
.switch {
  position: relative; flex-shrink: 0;
  display: inline-flex; align-items: center;
  width: 44px; height: 26px; cursor: pointer;
}
.switch input { position: absolute; opacity: 0; width: 0; height: 0; margin: 0; }
.switch-slider {
  position: absolute; inset: 0;
  border-radius: 999px;
  background: rgba(120,120,128,.32);
  transition: background .25s var(--ease-standard);
}
.switch-slider::before {
  content: '';
  position: absolute; top: 2px; left: 2px;
  width: 22px; height: 22px;
  border-radius: 999px; background: #fff;
  box-shadow: 0 1px 3px rgba(0,0,0,.3), 0 0 1px rgba(0,0,0,.2);
  transition: transform .25s var(--ease-spring);
}
.switch input:checked + .switch-slider { background: var(--primary); }
.switch input:checked + .switch-slider::before { transform: translateX(18px); }
.switch input:focus-visible + .switch-slider { box-shadow: var(--focus-ring); }
.switch input:disabled + .switch-slider { opacity: .5; cursor: not-allowed; }

/* —— 尊重「减少动态效果」无障碍偏好 —— */
@media (prefers-reduced-motion: reduce) {
  .modal, .toast, .drawer-panel, .sheet-panel, .drawer-nav-page, .stream-appear, .turn-summary.result-focus { animation: none !important; }
  .btn:active, .side-nav-item:active, .type-card:active, .segmented-option:active, .tag-picker-chip:active { transform: none; }
  .type-card, .type-card-check, .segmented-option, .tag-picker-chip, .switch-slider, .switch-slider::before, .ai-text { transition: none !important; }
  .turn-status.queued::before, .turn-status.interacting::before, .turn-status.phase-thinking::before, .turn-status.phase-writing::before, .turn-status.phase-tooling::before, .turn-status.phase-finalizing::before, .turn-status.phase-processing::before, .turn-status.phase-reconnecting::before, .execution-record-dock.is-running .execution-record-dot, .work-stage.status-analyzing .work-stage-marker, .work-stage.status-in_progress .work-stage-marker { animation: none !important; opacity: .65; transform: none !important; }
}

/* 移动端工作区入口按钮：仅移动端可见，桌面端有右栏窄轨把手无需此按钮 */
.ws-mobile-btn { display: none !important; }
/* 工作区在 1199px 以下已改为浮层，入口断点必须一致，避免 981–1199px 没有打开入口。 */
@media (max-width: 1199px) {
  .ws-mobile-btn { display: inline-flex !important; align-items: center; }
}
/* 移动端工作区浮层展开时，点击面板外区域可关闭（遮罩层） */
.ws-mobile-overlay {
  position: fixed; inset: 0; background: rgba(0,0,0,.3); z-index: 1150;
  display: none;
}
.ws-mobile-overlay.show { display: block; }

/* ============================================================
 * Cosmic Studio —— 统一的 AI 创作平台视觉系统
 * 安静画布承载内容；微光只强调品牌、AI 状态与关键创作行动。
 * ============================================================ */
.tabnum, .metric, .usage, .credits, .token-usage,
[class*="count"], [class*="usage"], [class*="credit"] { font-variant-numeric: tabular-nums; }

:where(button, a, input, select, textarea, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 2px;
}
.drawer-panel:focus-visible,
.modal:focus-visible,
.sheet-panel:focus-visible { outline: none; }
.btn { min-height: 34px; border-radius: var(--r-sm); transition: background var(--dur-fast), border-color var(--dur-fast), color var(--dur-fast), transform var(--dur-fast); }
.btn.primary { background: var(--text); border-color: var(--text); color: var(--bg); box-shadow: none; }
.btn.primary:hover { background: var(--text-2); border-color: var(--text-2); transform: none; box-shadow: none; }
.btn.primary:active:not(:disabled) { transform: scale(.98); filter: brightness(.97); }
.card, .settings-card { border-color: var(--border); border-radius: var(--r-lg); box-shadow: none; }

/* 品牌 logo 圆形的实际生效样式在文件后半段（.brand-mark-glyph 等，用固定的
   --brand-mark-bg/--brand-mark-fg），此处渐变蓝底覆写已废弃删除，避免混淆。 */
.drawer-nav-item.active, .side-nav-item.active { background: transparent; box-shadow: none; }
.drawer-project-card.current { background: transparent; box-shadow: none; }
.segmented-option.active, .segmented-option[aria-selected="true"] { color: var(--accent-fg); background: var(--primary); box-shadow: none; }

.content { background-image: radial-gradient(720px 420px at 54% -160px, var(--primary-a-08), transparent 72%); }
.side-section-label { padding: 0 8px 6px; color: var(--text-3); font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; }

.chat-header { min-height: 50px; background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(14px); }
.is-safari .chat-header { backdrop-filter: none; -webkit-backdrop-filter: none; }
.chat-header-title-sub { margin-top: 2px; color: var(--text-3); font-size: 10px; letter-spacing: .06em; text-transform: uppercase; }
/* 输入区与顶栏用同一套材质语言：顶栏已是半透明 + 毛玻璃，输入区此前是实色，
   上下不对称、底部像贴上去的一块面板。Safari 下 backdrop-filter 同样降级（见上方 .chat-header）。
   注：刻意不给.chat-messages 加底部渐隐遮罩——滚动容器上的 mask 会让最后一行正文半透明，
   在吸底追新的会话里会被当成"内容没加载完"的 bug，风险大于观感收益。 */
.chat-input { background: color-mix(in srgb, var(--panel) 92%, transparent); backdrop-filter: blur(14px); }
.is-safari .chat-input { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--panel); }
.composer textarea { border-color: color-mix(in srgb, var(--border) 82%, transparent); background: var(--input-bg); border-radius: var(--r-lg); }
.msg.ai .msg-content { border-color: color-mix(in srgb, var(--border) 75%, transparent); background: color-mix(in srgb, var(--panel) 96%, var(--primary-a-06)); }
.msg.user .msg-content { background: linear-gradient(135deg, var(--primary), color-mix(in srgb, var(--primary) 72%, var(--accent))); }

.modal-mask, .sheet-mask, .drawer-mask { background: var(--overlay); }
.modal { border-radius: var(--r-xl); box-shadow: var(--shadow-3); }
.sheet-panel { box-shadow: 0 -18px 60px rgba(0,0,0,.28); }
.drawer-panel { box-shadow: var(--shadow-3); }

#toast-root { width: min(380px, calc(100vw - 24px)); right: 12px; top: 12px; }
.toast {
  display: grid; grid-template-columns: auto minmax(0,1fr); align-items: start; gap: 10px;
  min-width: 0; width: 100%; padding: 11px 13px; border-left-width: 1px;
  border-radius: var(--r-md); background: var(--surface-raised); box-shadow: var(--shadow-2);
}
.toast-dot { width: 8px; height: 8px; margin-top: 6px; border-radius: 50%; background: var(--primary); }
.toast.success .toast-dot { background: var(--success); }
.toast.warn .toast-dot { background: var(--warn); }
.toast.error .toast-dot { background: var(--error); }
.toast-message { min-width: 0; line-height: 1.5; overflow-wrap: anywhere; }
.toast.leaving { opacity: 0; transform: translateX(10px); transition: opacity .18s, transform .18s; }

.page-state {
  display: grid; grid-template-columns: auto minmax(0,1fr) auto; align-items: center; gap: 12px;
  width: min(640px, 100%); margin: 24px auto; padding: 18px; border: 1px dashed var(--border);
  border-radius: var(--r-lg); background: var(--surface-tint);
}
.page-state-icon { display: grid; place-items: center; width: 38px; height: 38px; border-radius: 12px; color: var(--primary); background: var(--primary-a-08); }
.page-state-copy { display: grid; gap: 3px; min-width: 0; }
.page-state-copy strong { font-size: 14px; }
.page-state-copy span { font-size: 12px; }
.page-state.error { border-color: var(--error-a-35); background: var(--error-a-06); }
.page-state.error .page-state-icon { color: var(--error); background: var(--error-a-08); }
.page-state.loading .page-state-icon { animation: studioBreathe 1.8s ease-in-out infinite; }
@keyframes studioBreathe { 50% { opacity: .55; transform: scale(.96); } }

.studio-home, .agents-page { width: min(1180px, 100%); margin: 0 auto; padding: 18px 8px 48px; }
.studio-hero {
  position: relative; overflow: hidden; padding: clamp(28px, 5vw, 64px); border: 1px solid var(--border);
  border-radius: 24px; background: radial-gradient(620px 280px at 50% 0, var(--primary-a-16), transparent 72%), var(--panel);
  text-align: center;
}
.studio-hero::before { content: ''; position: absolute; width: 220px; height: 220px; top: -150px; right: 8%; border-radius: 50%; background: var(--accent-a-18); filter: blur(60px); pointer-events: none; }
.studio-eyebrow { display: inline-flex; align-items: center; gap: 6px; color: var(--primary); font-size: 10px; font-weight: 750; letter-spacing: .14em; }
.studio-hero h1, .page-title-row h1 { margin: 10px 0 8px; font-size: clamp(28px, 4.5vw, 48px); line-height: 1.12; letter-spacing: -.035em; }
.studio-hero-sub { width: min(620px, 100%); margin: 0 auto 24px; color: var(--text-2); font-size: 15px; line-height: 1.7; }
.creation-composer { position: relative; width: min(760px, 100%); margin: 0 auto; padding: 8px; border: 1px solid var(--primary-a-35); border-radius: 20px; background: color-mix(in srgb, var(--input-bg) 88%, transparent); box-shadow: 0 18px 50px rgba(0,0,0,.16), 0 0 0 1px var(--primary-a-06) inset; text-align: left; }
.creation-prompt { min-height: 94px; max-height: 220px; padding: 14px 16px; border: 0; background: transparent; box-shadow: none !important; resize: vertical; font: 15px/1.65 inherit; }
.creation-composer-bar { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 4px 4px 4px 10px; border-top: 1px solid var(--border); }
.creation-agent { display: flex; align-items: center; gap: 7px; min-width: 0; color: var(--text-2); font-size: 12px; }
.creation-agent-select { width: auto; max-width: 220px; min-height: 32px; padding: 4px 28px 4px 8px; border: 0; background-color: transparent; color: var(--text); box-shadow: none !important; }
.creation-submit { min-height: 38px; padding: 8px 15px; border-radius: 12px; }
.creation-starters { display: flex; justify-content: center; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.creation-starter { display: inline-flex; align-items: center; gap: 7px; padding: 7px 11px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface-tint); color: var(--text-2); cursor: pointer; font: inherit; }
.creation-starter:hover { color: var(--text); border-color: var(--primary-a-45); background: var(--primary-a-08); }
.studio-section { margin-top: 34px; }
.studio-section-head, .page-title-row { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; margin-bottom: 14px; }
.studio-section-head h2, .page-title-row h1 { margin: 0; font-size: 22px; }
.studio-section-head p, .page-title-row p { margin: 3px 0 0; }
.studio-agent-grid, .agents-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 12px; }
.studio-agent-card, .agent-overview-card { border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--panel); transition: border-color .18s, background .18s, transform .18s; }
.studio-agent-card:hover, .agent-overview-card:hover { border-color: var(--primary-a-45); background: color-mix(in srgb, var(--panel) 96%, var(--primary)); transform: translateY(-1px); }
.studio-agent-main { display: grid; grid-template-columns: auto minmax(0,1fr) auto; gap: 12px; align-items: center; width: 100%; padding: 16px; border: 0; background: transparent; color: var(--text); text-align: left; cursor: pointer; }
.studio-agent-icon { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 13px; color: var(--primary); background: var(--primary-a-08); }
/* 自定义头像图片：铺满容器裁切、去掉 tint 底色（图片本身已经是身份视觉，不再需要色块衬底）。
   用双 class 选择器把优先级提到 (0,2,0)，稳定压过 .drawer-agent-avatar 等处已有的 !important 底色规则，
   不依赖源码书写顺序。三处头像容器（侧栏/抽屉/概览卡）共用同一套自定义图片表现。 */
.side-agent-dot.has-agent-image,
.drawer-agent-avatar.has-agent-image,
.studio-agent-icon.has-agent-image {
  background: transparent !important; padding: 0; overflow: hidden;
}
.agent-avatar-img { width: 100%; height: 100%; object-fit: cover; display: block; border-radius: inherit; }
.studio-agent-copy { display: grid; gap: 3px; min-width: 0; }
.studio-agent-copy strong { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.studio-agent-copy small { display: -webkit-box; overflow: hidden; color: var(--text-2); font-size: 11px; line-height: 1.45; -webkit-box-orient: vertical; line-clamp: 2; -webkit-line-clamp: 2; }
.studio-agent-arrow { color: var(--text-3); }
.studio-agent-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; border-top: 1px solid var(--border); }
.studio-agent-type, .agent-overview-meta { color: var(--text-3); font-size: 11px; }
/* 网格末尾的「新增」占位位：与实卡同宽同圆角，但用虚线 + 透明底表达「这是空位、不是内容」。
   height:100% 是必须的——实卡是「主体 + 底部操作行」两段结构，占位卡若不撑满会比同行实卡矮一截，
   在 3 列网格里露出一条参差的下边缘。静止态刻意保持安静（text-3 + 虚线），只在 hover/focus 升为
   primary：新增是低频动作，不该在每次浏览列表时都与真实 Agent 争夺注意力。 */
.studio-agent-add-tile {
  width: 100%; height: 100%; min-height: 108px;
  border-style: dashed; background: transparent;
}
.studio-agent-add-tile:hover, .studio-agent-add-tile:focus-within {
  border-style: dashed; border-color: var(--primary-a-45); background: var(--primary-a-08);
}
/* 普通用户：整卡只有一个动作（按号码添加），保持原来的整卡居中横向布局。 */
button.studio-agent-add-tile {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 16px; color: var(--text-3); cursor: pointer; text-align: left;
}
button.studio-agent-add-tile:hover, button.studio-agent-add-tile:focus-visible { color: var(--primary); }
/* 创作者：主（新建，占满剩余空间）+ 次（按号码加入他人的 Agent，降级为底部一条细行）两段。
   否则创作者账号完全没有「加入别人 Agent」的路径——普通用户反倒有，因为那是他们唯一能做的事。 */
article.studio-agent-add-tile { display: flex; flex-direction: column; }
.studio-agent-add-main {
  flex: 1; display: flex; align-items: center; gap: 10px; width: 100%; min-height: 0;
  padding: 16px; border: 0; background: transparent; color: var(--text-3); text-align: left; cursor: pointer;
}
.studio-agent-add-main:hover, .studio-agent-add-main:focus-visible { color: var(--primary); }
.studio-agent-add-secondary {
  flex: 0 0 auto; padding: 8px 16px; border: 0; border-top: 1px dashed var(--border);
  background: transparent; color: var(--text-3); font-size: 12px; text-align: left; cursor: pointer;
  transition: color .15s var(--ease-standard);
}
.studio-agent-add-secondary:hover, .studio-agent-add-secondary:focus-visible { color: var(--primary); }
.studio-agent-add-plus {
  display: grid; place-items: center; flex: 0 0 auto; width: 34px; height: 34px;
  border: 1px dashed currentColor; border-radius: 11px;
}
.studio-agent-add-copy { display: grid; gap: 2px; min-width: 0; }
.studio-agent-add-copy strong { font-size: 14px; font-weight: 600; }
.studio-agent-add-copy small { color: var(--text-3); font-size: 11px; line-height: 1.45; }
/* 「全部 Agent」入口卡：只在首页装不下全部 Agent 时才出现（见 pageCreativeHome）。实线边框 + 与
   真实卡片同款「图标 + 文案 + 箭头」布局，读作"列表还有更多，点开看完整的"，而不是像虚线新增位
   那样是个"空位"。整卡可点、不设底部操作行——它本身只承载一个动作，不需要再拆一层次要操作。 */
.studio-agent-viewall-tile {
  display: flex; align-items: center; gap: 12px; width: 100%; height: 100%; min-height: 108px;
  padding: 16px; border: 1px solid var(--border); border-radius: var(--r-lg); background: var(--panel);
  color: var(--text); text-align: left; cursor: pointer; transition: border-color .18s, background .18s, transform .18s;
}
.studio-agent-viewall-tile:hover, .studio-agent-viewall-tile:focus-visible {
  border-color: var(--primary-a-45); background: color-mix(in srgb, var(--panel) 96%, var(--primary)); transform: translateY(-1px);
}
.studio-agent-viewall-icon { display: grid; place-items: center; flex: 0 0 auto; width: 40px; height: 40px; border-radius: 13px; color: var(--primary); background: var(--primary-a-08); }
.studio-agent-viewall-copy { display: grid; gap: 3px; min-width: 0; flex: 1; }
.studio-agent-viewall-copy strong { font-size: 14px; }
.studio-agent-viewall-copy small { color: var(--text-2); font-size: 11px; }
/* 卡片本身只是外框，内容分两截：可点击主体（进创作）+ 一条轻量底部操作行（工作区）。
   之前是「工作区」「开始创作」两个同等视觉权重的实心按钮并排，3卡×2键铺开显得眼花缭乱；
   改为整卡可点直达创作（同首页 studio-agent-card 的单大按钮惯例），次要动作降级为底部小字按钮。 */
.agent-overview-card { display: flex; flex-direction: column; }
.agent-overview-main-btn { display: grid; grid-template-columns: auto minmax(0,1fr) auto; gap: 12px; align-items: center; width: 100%; padding: 16px; border: 0; background: transparent; color: var(--text); text-align: left; cursor: pointer; }
.agent-overview-main { min-width: 0; }
.agent-overview-title { display: flex; align-items: center; gap: 6px; }
.agent-overview-title h3 { margin: 0; font-size: 15px; }
.agent-overview-main p { margin: 5px 0 0; display: -webkit-box; overflow: hidden; line-clamp: 2; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.agent-overview-meta { display: flex; gap: 8px; }
.agent-overview-actions { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 12px; border-top: 1px solid var(--border); }

.ws-technical-files { margin-top: 12px; border-top: 1px solid var(--border); }
.ws-technical-files > summary { display: flex; align-items: center; justify-content: space-between; padding: 10px 4px; cursor: pointer; list-style: none; }
.ws-technical-files > summary::-webkit-details-marker { display: none; }
.ws-technical-files > summary::after { content: '›'; font-size: 16px; transition: transform .16s; }
.ws-technical-files[open] > summary::after { transform: rotate(90deg); }
.ws-technical-files-body { padding-bottom: 8px; }
.ws-empty-note { padding: 10px 6px; font-size: 12px; }
/* 工作区"从未产出过任何内容"首次使用引导：比一行小字更醒目，降低"是不是坏了"的疑虑。 */
.ws-empty-hero {
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 32px 20px 26px; margin: 4px 0 8px;
  border: 1px dashed var(--border); border-radius: 14px;
  background: var(--surface-tint); text-align: center;
}
.ws-empty-hero-icon { color: var(--text-2); opacity: .75; }
.ws-empty-hero-title { font-weight: 650; color: var(--text); font-size: 14px; }
.ws-empty-hero-desc { font-size: 12.5px; line-height: 1.6; max-width: 320px; }
/* 引导样例列表：左对齐行+ 右侧箭头，长文案不会被居中排版揉成"气泡"，
   悬停整行抬起并高亮描边，明确表达"这是可点的"。 */
.ws-empty-hero-examples {
  display: flex; flex-direction: column; gap: 6px;
  width: 100%; max-width: 440px; margin-top: 14px;
}
.ws-empty-hero-examples-label {
  display: flex; align-items: center; gap: 8px;
  margin-bottom: 2px; color: var(--text-3); font-size: 11.5px; letter-spacing: .02em;
}
.ws-empty-hero-examples-label::before,
.ws-empty-hero-examples-label::after {
  content: ''; flex: 1 1 auto; height: 1px; background: var(--border);
}
.ws-empty-hero-example {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 10px 12px; text-align: left; cursor: pointer;
  font: inherit; font-size: 12.5px; line-height: 1.55; color: var(--text);
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  transition: border-color .15s, background .15s, box-shadow .15s, transform .15s;
  /* 触屏上不设 touch-action 会触发系统"双击缩放"手势判定，第一次点击会被吃掉当
     手势探测，必须再点一次才生效；manipulation 关掉缩放/滚动手势，单击立即生效。
     tap-highlight 去掉移动端默认的点击灰色遮罩，避免和下面的 hover/active 反馈打架。 */
  touch-action: manipulation; -webkit-tap-highlight-color: transparent;
}
.ws-empty-hero-example-text { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }
.ws-empty-hero-example-arrow {
  flex: 0 0 auto; color: var(--text-3); opacity: .55;
  transition: transform .15s, opacity .15s, color .15s;
}
/* hover 反馈只在真正有鼠标的设备上生效：触屏上 :hover 会在首次点击时被系统当成
   "先悬停试探"而消耗掉，导致要点两下才能真正触发 onclick。用 (hover: hover) 把
   触屏设备排除在外，改由下面的 :active 规则提供即时的按压反馈。 */
@media (hover: hover) {
  .ws-empty-hero-example:hover {
    background: var(--accent-a-18); border-color: var(--accent-a-45);
    box-shadow: var(--shadow-1); transform: translateY(-1px);
  }
  .ws-empty-hero-example:hover .ws-empty-hero-example-arrow { color: var(--accent); opacity: 1; transform: translateX(2px); }
}
.ws-empty-hero-example:active {
  background: var(--accent-a-18); border-color: var(--accent-a-45);
  transform: translateY(0); box-shadow: none;
}
.ws-empty-hero-example:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.works-page { max-width: 1160px; }

@media (hover: none), (pointer: coarse) {
  .ws-row-actions { display: inline-flex !important; }
  .ws-file-tree .file-tree-row { padding-right: 42px; }
  .ws-row-primary { display: none !important; }
  .ws-row-actions button { min-width: 36px; min-height: 36px; }
}

@media (max-width: 900px) {
  .studio-home, .agents-page { padding: 8px 0 32px; }
  .studio-agent-grid, .agents-grid { grid-template-columns: repeat(2, minmax(0,1fr)); }
}
@media (max-width: 640px) {
  .login-page { padding: 14px; }
  .login-card { width: 100%; max-width: 100%; padding: 28px 20px 22px; }
  /* 窄屏下口令与「复制」同行：字号降一档，保证 6 位口令 + 按钮不换行、不压缩字距。 */
  .login-code { font-size: 28px; padding: 16px 12px; letter-spacing: .2em; text-indent: .2em; }
  .login-code-copy { padding: 0 12px; }
  .studio-hero { padding: 28px 14px 22px; border-radius: 18px; }
  .studio-hero h1 { font-size: 30px; }
  .studio-hero-sub { font-size: 13px; }
  .creation-composer { padding: 6px; border-radius: 16px; }
  .creation-composer-bar { align-items: stretch; flex-direction: column; padding: 8px 4px 4px; }
  .creation-agent { justify-content: space-between; padding: 0 5px; }
  .creation-agent-select { flex: 1; max-width: 72%; }
  .creation-submit { width: 100%; }
  .creation-starters { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); }
  .creation-starter { justify-content: center; border-radius: 10px; }
  .studio-section-head, .page-title-row { align-items: stretch; flex-direction: column; }
  .studio-agent-grid, .agents-grid { grid-template-columns: 1fr; }
  .page-state { grid-template-columns: auto minmax(0,1fr); margin: 12px auto; }
  .page-state > .btn { grid-column: 1 / -1; width: 100%; }
  #toast-root { left: 12px; right: 12px; width: auto; top: max(12px, env(safe-area-inset-top)); }
}

/* ============================================================
 * Agent Workspace —— 明确的左 / 中 / 右三栏
 * 左：当前 Agent 功能；中：会话；右：工作区。
 * ============================================================ */
.main { grid-template-columns: 180px minmax(0, 1fr); }
.side {
  gap: 0; padding: 0 7px; overflow-y: auto;
  /* 比应用底再暗半档的锚定色：让窗口有 native app 的框体感，与内容区拉开层级。 */
  background: var(--side-bg);
  border-right-color: color-mix(in srgb, var(--border) 82%, transparent);
}
/* 左栏 Agent 入口：紧凑态把身份圆标与下拉一起收进一个轻量胶囊，
   使下拉明确属于 Agent 切换，而不是悬在旁边的孤立图标。 */
.side-agent-head {
  box-sizing: border-box; width: 100%; height: 48px; min-height: 48px;
  gap: 7px; padding: 6px 4px; margin: 0 0 10px;
  border: 0; border-radius: 0;
  background: transparent; color: var(--text); text-align: left; cursor: pointer;
  transition: background .15s, border-color .15s;
}
.side-agent-head.compact {
  width: fit-content; min-width: 64px; height: 38px; min-height: 38px;
  gap: 5px; padding: 3px 8px 3px 3px; margin: 5px auto 15px;
  border: 0; border-radius: 999px; background: var(--surface-tint-2);
}
/* 胶囊已承担背景与圆角，内部“视”只保留文字身份，不再形成第二层圆底。 */
.side-agent-head.compact .side-agent-avatar {
  width: 32px; height: 32px; flex-basis: 32px;
  border-radius: 0; background: transparent !important; box-shadow: none !important;
}
.side-agent-head.compact .side-agent-switch { color: var(--text-2); }
.side-agent-head:hover { background: var(--surface-tint); border-color: var(--primary-a-22); }
.side-agent-head:active { background: var(--primary-a-08); }
.side-agent-avatar, .side-agent-placeholder {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; flex: 0 0 32px; border-radius: 10px;
}
.side-agent-placeholder { color: var(--primary); background: var(--primary-a-08); border: 1px dashed var(--primary-a-35); }
.side-agent-head-info { flex: 1; gap: 3px; }
.side-agent-name { font-size: 13px; font-weight: 680; }
.side-agent-type { font-size: 10px; color: var(--text-3); }
.side-agent-switch { display: none; }
.side-section-label { display: none; }
.side-nav {
  gap: 3px; margin: 0; padding: 0; border: 0; border-radius: 0;
  background: transparent;
}
.side-nav-item {
  min-height: 38px; gap: 7px; padding: 8px 7px; border-radius: 9px;
  color: var(--text-2); font-size: 13px; font-weight: 520;
}
.side-nav-item:hover { color: var(--text); background: var(--surface-tint-2); }
.side-nav-item.active {
  color: var(--primary); background: var(--primary-a-08); font-weight: 650;
  box-shadow: inset 2px 0 0 var(--primary);
}
.side-nav-icon { width: 17px; color: currentColor; }

.main-menu-drawer { width: min(350px, 92vw); }
.main-menu-drawer .drawer-section { padding: 14px 0; }
.main-menu-drawer .drawer-section-title { margin-bottom: 8px; }
.main-menu-drawer .drawer-project-card { padding: 9px 6px; border-radius: 10px; }
.main-menu-drawer .drawer-project-card.current { background: transparent; box-shadow: none; }
.main-menu-drawer .drawer-project-card.current::after { content: '当前'; margin-left: auto; color: var(--primary); font-size: 10px; font-weight: 700; }
.main-menu-drawer .drawer-nav-item { min-height: 38px; padding: 8px 6px; }

/* 会话是阅读轨：桌面默认约 565px，工作区承接余宽；保留拖拽微调，但不再让右栏反向挤压会话。 */
/* 栏位顺序 = DOM 顺序：中栏（工作区/社区，吃余宽） + 右栏（会话，固定阅读轨）。
   桌面端工作区不再可收起，ws-collapsed 与 ws-open 同构（仅窄屏浮层态才有区别）。 */
.chat-shell.ws-open,
.chat-shell.ws-collapsed { grid-template-columns: minmax(0, 1fr) var(--chat-w, clamp(420px, 34vw, 480px)); }
/* 会话收起：中栏占满，会话保留 44px 窄轨承载展开把手（否则按钮随会话消失就展不开）。 */
.chat-shell.chat-collapsed { grid-template-columns: minmax(0, 1fr) 44px; }
.chat-main { background: var(--bg); }
.chat-header { box-sizing: border-box; height: 48px; min-height: 48px; padding: 6px 14px; }
.chat-header-title-main { font-size: 13px; }
.workspace-panel-head { box-sizing: border-box; height: 48px; min-height: 48px; padding: 8px 11px; }
.chat-messages { padding: 22px clamp(16px, 3vw, 36px); }
.chat-messages > .turn, .chat-messages > .load-earlier-btn, .chat-messages > .turn-gap, .chat-messages > .chat-bottom-sentinel { width: min(820px, 100%); margin-inline: auto; }
.chat-input { padding-inline: clamp(12px, 3vw, 32px); }
.chat-input > * { width: min(840px, 100%); margin-inline: auto; }
.workspace-panel { background: color-mix(in srgb, var(--panel) 97%, var(--bg)); }
.workspace-panel-head { min-height: 42px; height: 42px; padding: 5px 11px; background: transparent; }
.workspace-panel-body {
  flex: 1; overflow-y: auto; min-height: 0; padding: 0 11px 18px; container-type: inline-size; container-name: wsbody;
  /* 跳动治理：① padding-top 交给吸顶条自带（见 .ws-sticky-bar），吸附位与自然位完全一致；
     ② scrollbar-gutter 恒定预留滚动槽——内容多→少切换时滚动条消失不再引起内容宽度 reflow。 */
  scrollbar-gutter: stable;
}
.workspace-panel .ws-name { font-size: 12px; }
.ws-object-card { padding: 11px 12px; border-radius: 12px; background: var(--surface-tint); }
.ws-technical-files { margin-top: 14px; }

.semantic-works { display: grid; gap: 16px; }
.semantic-works-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 16px; }
.semantic-works-head h3 { margin: 0; font-size: 20px; }
.semantic-works-head p { margin: 4px 0 0; font-size: 13px; }
.semantic-work-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 12px; }
.semantic-work-card {
  min-width: 0; overflow: hidden; border: 1px solid var(--border); border-radius: 15px;
  background: var(--panel); transition: border-color .16s, transform .16s, background .16s;
}
.semantic-work-card:hover { border-color: var(--primary-a-35); background: color-mix(in srgb, var(--panel) 97%, var(--primary)); transform: translateY(-1px); }
.semantic-work-head { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 10px; padding: 14px; border-bottom: 1px solid var(--border); }
.semantic-work-icon { display: grid; place-items: center; width: 36px; height: 36px; border-radius: 11px; color: var(--primary); background: var(--primary-a-08); }
.semantic-work-title { min-width: 0; display: grid; gap: 2px; }
.semantic-work-title h3 { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; }
.semantic-work-title span { color: var(--text-3); font-size: 10px; }
.semantic-work-open { padding: 5px 9px; border: 1px solid var(--primary-a-35); border-radius: 8px; color: var(--primary); font-size: 11px; }
.semantic-work-fields { display: grid; gap: 7px; margin: 0; padding: 13px 14px; }
.semantic-work-field { display: grid; grid-template-columns: 64px minmax(0, 1fr); gap: 9px; font-size: 12px; line-height: 1.5; }
.semantic-work-field dt { color: var(--text-3); }
.semantic-work-field dd { margin: 0; color: var(--text); overflow-wrap: anywhere; }
.semantic-work-empty { margin: 0; padding: 14px; font-size: 12px; }
.semantic-work-assets { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 14px 13px; border-top: 1px solid var(--border); }
.semantic-work-assets-label { width: 100%; margin-bottom: 2px; color: var(--text-3); font-size: 10px; }
.semantic-work-assets a { display: inline-flex; align-items: center; gap: 5px; max-width: 100%; padding: 4px 7px; border-radius: 7px; background: var(--surface-tint-2); color: var(--text-2); font-size: 11px; }
.semantic-work-assets a span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.semantic-work-assets a:hover { color: var(--primary); background: var(--primary-a-08); }

@media (max-width: 1199px) and (min-width: 901px) {
  .main { grid-template-columns: 180px minmax(0, 1fr); }
  .semantic-work-grid { grid-template-columns: 1fr; }
}
@media (max-width: 900px) {
  .semantic-work-grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .semantic-works-head { align-items: flex-start; flex-direction: column; }
}

/* ============================================================
 * Codex-inspired quiet UI —— 单一强调色、文字层级、低对比分隔线
 * 仅错误/警告保留语义色；普通信息不使用彩色边条、胶囊或渐变卡片。
 * ============================================================ */
.side-nav-item.active {
  color: var(--text); background: transparent; box-shadow: none; font-weight: 650;
}
.side-nav-item.active::before { content: '›'; width: 10px; margin-left: -2px; color: var(--primary); font-size: 17px; line-height: 1; }
.side-nav-item:not(.active)::before { content: ''; width: 10px; margin-left: -2px; }
.side-nav-item:hover { background: var(--surface-tint); }

.stream-appear { animation: none; filter: none; }
.msg.user .msg-content {
  color: var(--text); background: var(--surface-tint-2); border: 1px solid var(--border);
}
.msg.ai .msg-content { background: transparent; border-color: transparent; }
.turn-summary.result-focus { animation: none; }

/* 终态交付：外层会话已有边界，不再叠加上边线；用轻量状态徽章替代分割线。 */
.turn-delivery {
  margin: 0 0 14px; padding: 8px 0 10px; border: 0;
  border-radius: 0; background: transparent;
}
.turn-delivery-head strong {
  display: inline-flex; align-items: center; min-height: 24px;
  padding: 3px 9px; border-radius: 999px; font-size: 12px; line-height: 1.45;
}
.turn-delivery-head.status-done strong { color: var(--success); background: var(--success-a-08); }
.turn-delivery-head.status-paused strong,
.turn-delivery-head.status-blocked strong,
.turn-delivery-head.status-incomplete strong { color: var(--warn); background: var(--warn-a-06); }
.turn-delivery-head.status-failed strong { color: var(--error); background: var(--error-a-08); }
.turn-delivery-count { padding: 0; border-radius: 0; color: var(--text-2); background: transparent; }
.turn-delivery-summary { margin-top: 6px; color: var(--text-2); }
.turn-delivery-actions { margin-top: 8px; }
.turn-delivery-details:not(:empty) { margin-top: 10px; }

.structured-output { margin: 14px 0 4px; padding-top: 10px; }
.structured-output-head { margin-bottom: 2px; }
.structured-output-list { gap: 0; }
.structured-card {
  padding: 11px 0; border: 0; border-bottom: 1px solid var(--border); border-radius: 0;
  background: transparent; box-shadow: none;
}
.structured-card:last-child { border-bottom: 0; }
.structured-card-top { justify-content: flex-start; margin-bottom: 5px; }
.structured-badge,
.structured-badge.implementation,
.structured-badge.todo,
.structured-badge.issue,
.structured-badge.warning,
.structured-badge.constraint,
.structured-badge.preference {
  padding: 0; border-radius: 0; color: var(--text-2); background: transparent; font-weight: 650;
}
.structured-card.issue .structured-badge,
.structured-card.warning .structured-badge { color: var(--error); }
.structured-meta { margin-left: auto; }
.structured-card h4 { font-size: 14px; margin-bottom: 4px; }
.structured-card p { color: var(--text-2); }

.render-component {
  margin: 14px 0; padding: 10px 0; border: 0; border-top: 1px solid var(--border);
  border-radius: 0; background: transparent; font-size: 13px; line-height: 1.6;
}
.render-component .rc-head { margin-bottom: 7px; font-size: 12px; color: var(--text-2); }
.render-component.rc-callout { padding: 0; border-top: 0; }
.render-component.rc-callout .rc-callout-body,
.render-component.rc-callout-info .rc-callout-body,
.render-component.rc-callout-success .rc-callout-body,
.render-component.rc-callout-warning .rc-callout-body,
.render-component.rc-callout-danger .rc-callout-body,
.render-component.rc-callout-neutral .rc-callout-body {
  padding: 10px 12px; border: 1px solid var(--border); border-left-width: 1px;
  border-radius: 8px; background: var(--surface-tint);
}
.render-component .rc-callout-title,
.render-component.rc-callout-success .rc-callout-title,
.render-component.rc-callout-warning .rc-callout-title { color: var(--text); }
.render-component.rc-callout-danger .rc-callout-title { color: var(--error); }
.render-component.rc-steps .rc-steps { gap: 10px; }
.render-component.rc-steps .rc-step { padding-left: 24px; }
.render-component.rc-steps .rc-step::before {
  width: 17px; height: 17px; border: 0; border-radius: 0; color: var(--text-2); background: transparent;
}
.render-component.rc-steps .rc-step-body { color: var(--text-2); }
.render-component.rc-usage-guide .rc-head { color: var(--text); font-size: 13px; font-weight: 650; }
.render-component.rc-usage-guide .rc-guide-intro { margin: 0 0 10px; color: var(--text-2); }
.render-component.rc-usage-guide .rc-guide-section { margin: 10px 0; }
.render-component.rc-usage-guide .rc-guide-label { margin-bottom: 4px; color: var(--text-2); font-size: 12px; font-weight: 650; }
.render-component.rc-usage-guide .rc-guide-list { margin: 0; padding-left: 17px; color: var(--text-2); }
.render-component.rc-usage-guide .rc-guide-list li + li { margin-top: 3px; }
.render-component.rc-usage-guide .rc-steps { gap: 10px; }
.render-component.rc-usage-guide .rc-step { padding-left: 24px; }
.render-component.rc-usage-guide .rc-step::before {
  width: 17px; height: 17px; border: 0; border-radius: 0; color: var(--text-2); background: transparent;
}
dl.rc-kv { grid-template-columns: fit-content(30%) minmax(0, 1fr); gap: 6px 16px; }
.render-component.rc-stat .rc-stat-row { gap: 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.render-component.rc-stat .rc-stat {
  min-width: 100px; padding: 10px 14px; border: 0; border-right: 1px solid var(--border);
  border-radius: 0; background: transparent;
}
.render-component.rc-stat .rc-stat:last-child { border-right: 0; }
.render-component.rc-stat .rc-stat-value { font-size: 17px; }
.render-component.rc-compare { padding-right: 0; }
.render-component.rc-compare .rc-compare thead th { border-bottom-color: var(--border); color: var(--text-2); }
.render-component.rc-copy-block { border: 1px solid var(--border); border-radius: 8px; }
.render-component.rc-copy-block .rc-copy-head { background: transparent; }
.render-component.rc-copy-block .rc-copy-lang { padding: 0; border: 0; background: transparent; }
.render-component.rc-copy-block .rc-copy-code { background: color-mix(in srgb, var(--bg) 94%, var(--panel)); }
.render-component .rc-badge,
.render-component .rc-badge-ok,
.render-component .rc-badge-err,
.render-component .rc-badge-warn,
.render-component .rc-badge-muted {
  padding: 0; border: 0; border-radius: 0; color: var(--text-2); background: transparent;
}
.render-component .rc-badge-err { color: var(--error); }
.render-component .rc-badge-warn { color: var(--warn); }
.render-component .rc-tl-time { color: var(--text-2); }
.render-component .rc-gallery-item img { border-radius: 6px; }

/* ============================================================
 * 正文排版原语组件（section / bullets / table / quote）
 *
 * 这四个组件替代模型手写Markdown：排版尺度与会话正文（.ai-plain-*）
 * 严格对齐，让「组件渲染」与「兜底渲染」处在同一个设计系统里，
 * 用户看不出两条通道的差别，但组件通道的层级与间距是平台完全可控的。
 * ============================================================ */
.render-component.rc-section { margin: 12px 0; padding: 0; border: 0; }
.render-component.rc-section .rc-section-title {
  margin: 0 0 6px; color: var(--text);
  font-size: 14px; font-weight: 650; line-height: 1.45;
}
.render-component.rc-section .rc-section-para {
  margin: 8px 0; color: var(--text); font-size: 14px; line-height: 1.78; word-break: break-word;
}
.render-component.rc-section .rc-section-para:first-of-type { margin-top: 0; }
.render-component.rc-section .rc-section-para:last-child { margin-bottom: 0; }

.render-component.rc-bullets { margin: 12px 0; padding: 0; border: 0; }
.render-component.rc-bullets .rc-bullets-list {
  margin: 0; padding-left: 1.5em; font-size: 14px; line-height: 1.75; color: var(--text);
}
.render-component.rc-bullets .rc-bullets-list.is-bullet { list-style: disc; }
.render-component.rc-bullets .rc-bullets-list.is-ordered { list-style: decimal; }
.render-component.rc-bullets .rc-bullets-list.is-sub { list-style: circle; margin-top: 4px; font-size: 13.5px; }
.render-component.rc-bullets .rc-bullet-item { margin: 5px 0; padding-left: 2px; word-break: break-word; }
.render-component.rc-bullets .rc-bullets-list.is-bullet > .rc-bullet-item::marker { color: var(--text-3); }
.render-component.rc-bullets .rc-bullets-list.is-ordered > .rc-bullet-item::marker { color: var(--primary); font-variant-numeric: tabular-nums; }

.render-component.rc-table-block { margin: 12px 0; padding: 0; border: 0; }
.render-component.rc-table-block .rc-table-wrap {
  overflow-x: auto; border: 1px solid var(--border); border-radius: 10px;
}
.render-component.rc-table-block .rc-table-wrap:focus-visible { outline: 2px solid var(--primary-a-45); outline-offset: 1px; }
.render-component.rc-table-block .rc-table { width: 100%; border-collapse: collapse; font-size: 13px; line-height: 1.6; }
.render-component.rc-table-block .rc-table th,
.render-component.rc-table-block .rc-table td {
  padding: 7px 11px; text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--border); word-break: break-word;
}
.render-component.rc-table-block .rc-table thead th {
  background: var(--surface-tint); color: var(--text); font-weight: 650; white-space: nowrap;
}
.render-component.rc-table-block .rc-table tbody tr:last-child td { border-bottom: 0; }
.render-component.rc-table-block .rc-table tbody tr:hover td { background: var(--surface-tint); }

.render-component.rc-quote {
  margin: 12px 0; padding: 2px 0 2px 12px;
  border: 0; border-left: 3px solid var(--primary-a-35);
  color: var(--text-2);
}
.render-component.rc-quote .rc-quote-body {
  margin: 0; font-size: 14px; line-height: 1.75; word-break: break-word;
}
.render-component.rc-quote .rc-quote-source {
  margin-top: 5px; color: var(--text-3); font-size: 12px;
}
.render-component.rc-quote .rc-quote-source::before { content: '—— '; }

.interaction-card { border-color: var(--border); background: transparent; }
.interaction-card.answered { border-color: var(--border); background: var(--surface-tint); }
.capability-pill,
.interaction-missing-list span { color: var(--text-2); border-color: var(--border); background: transparent; }
.capability-pill.risk-low { color: var(--text-2); border-color: var(--border); background: transparent; }
.capability-pill.risk-medium { color: var(--warn); border-color: var(--border); background: transparent; }
.capability-pill.risk-high { color: var(--error); border-color: var(--border); background: transparent; }
.next-actions { padding: 8px 0; border: 0; border-top: 1px solid var(--border); border-radius: 0; background: transparent; }
.next-action-btn,
.next-action-btn.primary { color: var(--text-2); background: transparent; border-color: var(--border); }
.next-action-btn:hover,
.next-action-btn.primary:hover { color: var(--text); background: var(--surface-tint); border-color: var(--text-3); }

.module-page { max-width: 1040px; }
.module-page > .page-head { margin-bottom: 18px; padding-bottom: 13px; border-bottom: 1px solid var(--border); }
.module-page > .page-head h2 { margin: 0; font-size: 21px; }
.module-page > .page-head p { margin: 4px 0 0; font-size: 13px; }
.module-tabs { gap: 18px; margin: -7px 0 18px; border-bottom: 1px solid var(--border); }
.module-tabs .btn {
  min-height: 36px; padding: 7px 1px; border: 0; border-bottom: 2px solid transparent;
  border-radius: 0; color: var(--text-2); background: transparent; box-shadow: none;
}
.module-tabs .btn.primary { color: var(--text); background: transparent; border-bottom-color: var(--text); }
.module-tabs .btn:hover { color: var(--text); background: transparent; }
.module-page .card,
.module-page .settings-card,
.module-page .friends-section,
.module-page .friend-card,
.module-page .tool-card,
.module-page .semantic-work-card,
.module-page .settings-identity-card {
  border-color: var(--border); background: transparent; box-shadow: none;
}
.module-page .tool-card-strip { display: none; }
.module-page .tool-card { border-radius: 8px; }
.module-page .tool-guide { display: flex; gap: 0; margin: 4px 0 16px; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.module-page .tool-guide-card { display: flex; align-items: baseline; gap: 7px; flex: 1; padding: 9px 12px; border: 0; border-right: 1px solid var(--border); border-radius: 0; background: transparent; }
.module-page .tool-guide-card:last-child { border-right: 0; }
.module-page .tool-guide-card:hover { border-color: var(--border); transform: none; }
.module-page .tool-guide-top { gap: 5px; }
.module-page .tool-guide-num { display: inline; width: auto; height: auto; border-radius: 0; color: var(--text-2); background: transparent; }
.module-page .friend-card { border-left-width: 1px; border-radius: 8px; }
.module-page .friend-avatar.agent,
.module-page .friend-avatar.human { color: var(--text); background: var(--surface-tint-2); }
.module-page .friend-badge,
.module-page .friend-badge.agent,
.module-page .friend-badge.human,
.module-page .friend-badge.stage,
.module-page .friend-badge.manual,
.module-page .friend-badge.auto,
.module-page .friend-badge.system { color: var(--text-2); border-color: var(--border); background: transparent; }
.module-page .friends-topbar,
.module-page .friends-requests,
.module-page .friend-add-hint,
.module-page .friend-config-section { background: transparent; border-color: var(--border); }
.module-page .friends-bell.has { color: var(--text); border-color: var(--border); background: transparent; }
.module-page .friends-bell-dot { background: var(--text); }
.module-page .semantic-work-icon,
.module-page .settings-agent-avatar { color: var(--text); background: var(--surface-tint-2); }
.module-page .semantic-work-card:hover { border-color: var(--text-3); background: var(--surface-tint); transform: none; }
.module-page .semantic-work-open { color: var(--text); border-color: var(--border); }
.module-page .tag { color: var(--text-2); border-color: var(--border); background: transparent; }
.module-page .admin-section-hero,
.module-page .usage-metric,
.module-page .usage-metric.primary,
.module-page .usage-metric.warn,
.module-page .usage-metric.risk { background: transparent; border-color: var(--border); }

/* Agent 选择与按钮：沿用 Codex 的单色前景层级，不使用彩色头像或选中边框。 */
.main-menu-drawer .drawer-project-card.current,
.drawer-project-card.current {
  background: transparent; box-shadow: none; border: 0;
}
.main-menu-drawer .drawer-project-card.current:hover { background: var(--surface-tint); }
.drawer-agent-avatar,
.side-agent-avatar {
  color: var(--text) !important; background: var(--surface-tint-2) !important;
  box-shadow: none !important; border: 0;
}
.drawer-project-card.current .drawer-agent-avatar,
.side-agent-head:hover .side-agent-avatar { color: var(--primary) !important; }
.main-menu-drawer .drawer-project-card.current::after {
  content: '当前'; margin-left: auto; color: var(--text-3); font-size: 10px; font-weight: 600;
}
.side-agent-head { border-color: var(--border); }
.side-agent-head:hover { background: var(--surface-tint); border-color: var(--border); }

.btn.primary {
  color: var(--bg); background: var(--text); border-color: var(--text); box-shadow: none;
}
.btn.primary:hover {
  color: var(--bg); background: color-mix(in srgb, var(--text) 86%, var(--bg));
  border-color: color-mix(in srgb, var(--text) 86%, var(--bg)); box-shadow: none;
}
.btn.primary:active:not(:disabled) { background: var(--text-2); border-color: var(--text-2); }
/* 与上方基础规则保持同一套"只留图标、不做实心圆"设计，这里只需跟着换成本主题的文字色，
   不再重复背景/边框——否则这份后加载的主题覆盖会把发送按钮打回沉重的实心圆。 */
.action-send { color: var(--text-2); background: transparent; border: none; }
.action-send:hover:not(:disabled) { background: var(--surface-tint); color: var(--text); }
.action-send.is-idle { color: var(--text-3); background: transparent; }
.action-send.is-idle:hover:not(:disabled) { background: var(--surface-tint); color: var(--text-2); }
.segmented-option.active,
.segmented-option[aria-selected="true"] { color: var(--bg); background: var(--text); box-shadow: none; }
.switch input:checked + .switch-slider { background: var(--text-2); }

/* 工作区：内容优先、弱边界，并支持桌面拖动调宽。
   手柄贴在面板右缘（= 会话左边界），因为会话已移到右栏。 */
.workspace-resize-handle {
  position: absolute; z-index: 4; top: 0; bottom: 0; right: -3px; width: 7px;
  cursor: col-resize; touch-action: none;
}
.workspace-resize-handle::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 3px; width: 1px;
  background: transparent; transition: background .12s;
}
.workspace-resize-handle:hover::after,
.workspace-resize-handle:focus-visible::after,
.workspace-resizing .workspace-resize-handle::after { background: var(--text-3); }
body.workspace-resizing { cursor: col-resize; user-select: none; }
.workspace-panel .ws-collapse-btn,
.workspace-panel .ws-expand-btn { border-color: transparent; border-radius: 6px; }
.workspace-panel .ws-collapse-btn:hover,
.workspace-panel .ws-expand-btn:hover { background: var(--surface-tint); }
.workspace-panel .ws-object-card {
  margin-bottom: 0; padding: 11px 2px; border: 0; border-bottom: 1px solid var(--border);
  border-radius: 0; background: transparent;
}
.workspace-panel .ws-object-card:hover { border-color: var(--border); background: transparent; }
.workspace-panel .ws-object-icon { color: var(--text-2); }
.workspace-panel .ws-object-badge { color: var(--text-3); background: transparent; }
.workspace-panel .ws-prompt-item {
  padding: 7px 2px; border: 0; border-top: 1px solid var(--border); border-radius: 0;
  background: transparent;
}
.workspace-panel .ws-prompt-item:hover { border-color: var(--border); background: var(--surface-tint); }
.workspace-panel .ws-change-badge { color: var(--bg); background: var(--text-2); }
.workspace-panel .ws-section-title { color: var(--text-3); }
.workspace-panel .file-tree-row:hover { background: var(--surface-tint); }
@media (max-width: 1199px) {
  .workspace-resize-handle { display: none; }
  /* 末尾的桌面工作区规则不能覆盖移动端：面板改为 fixed 浮层后，聊天区始终只占一列。 */
  .chat-shell.ws-collapsed, .chat-shell.ws-open, .chat-shell.chat-collapsed { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  /* Agent Workspace 的桌面双栏定义位于早期移动端规则之后，这里做最终断点保护。 */
  .main { width: 100%; min-width: 0; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); }
  .content { grid-column: 1; width: 100%; max-width: 100%; min-width: 0; }
}

/* 状态依靠符号 + 文案；仅“需处理/错误”使用语义色。 */
.cap-status {
  color: var(--text-2); background: transparent; border-color: var(--border);
}
.cap-status--active,
.cap-status--inactive,
.cap-status--waiting { color: var(--text-2); }
.cap-status--pending { color: var(--warn); }
.cap-status--disabled { color: var(--error); }
.module-page .tag,
.module-page .tool-pill {
  color: var(--text-2) !important; background: transparent !important; border-color: var(--border) !important;
}

/* 浅色最终保护层：避免高特异性历史规则把透明激活项重新变成白字。 */
html.light .module-tabs .btn.primary {
  color: var(--text); background: transparent; border-bottom-color: var(--text);
}
html.light .btn.primary {
  color: var(--bg); background: var(--text); border-color: var(--text);
}
html.light .segmented-option.active,
html.light .segmented-option[aria-selected="true"] {
  color: var(--bg); background: var(--text);
}
html.light .side-nav-item.active,
html.light .drawer-project-card.current { background: transparent; box-shadow: none; }

@media (max-width: 640px) {
  .prompt-shot-beat { flex-basis: 100%; white-space: normal; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { scroll-behavior: auto !important; }
  .page-state.loading .page-state-icon, .studio-agent-card, .agent-overview-card, .semantic-work-card { animation: none !important; transition: none !important; transform: none !important; }
}

/* ═══ 视觉层级重整 ═══
   问题：三栏原本都是同权重白底+ 同款卡片，加上卡内嵌套三四层描边，整屏没有主次，
   眼睛不知道该落在哪里（表现为"零散"）。
   原则：用背景明度差表达层级，用留白替代边框，同一屏里只保留一层描边。
   2026-08 海拔化：层级令牌统一为 --elev-0..4——深色靠明度台阶 + 顶部受光边，
   浅色靠白面 + 环境阴影；不再各面各写死颜色。 */

/* 会话是主轨（右栏），用 elev-2 抬半档；内容管理（中栏）退到 elev-1 凹陷半档，
   卡片（elev-3）在两栏之上浮起。层级：elev-0 底 < elev-1 中栏 < elev-2 会话 < elev-3 卡。 */
.chat-main { background: var(--elev-2); }
.workspace-panel { background: var(--elev-1); border-left: 1px solid var(--border); }
.workspace-panel-head { background: transparent; border-bottom-color: color-mix(in srgb, var(--border) 60%, transparent); }

/* 悬浮会话框（桌面端）：四周留白、细边 + 轻阴影 + 圆角，框外与工作区同底（elev-1），
   读起来是"浮在工作区右侧的会话组件"，而不是顶天立地的贴边栏。
   窄屏不启用：移动端会话是全屏抽屉，悬浮留白只会浪费宽度。 */
@media (min-width: 1200px) {
  .chat-shell { background: var(--elev-1); }
  .chat-shell > .chat-main {
    margin: 10px;
    border: 1px solid var(--card-border);
    border-radius: 14px;
    box-shadow: var(--shadow-2);
    overflow: hidden;
  }
  /* 会话收起成 44px 窄轨时不保留悬浮卡样式：圆角竖条悬浮在右侧既无内容也不美观，
     退回贴右缘的平直细轨，只承载展开把手。 */
  .chat-shell.chat-collapsed > .chat-main {
    margin: 0; border: 0; border-radius: 0; box-shadow: none;
  }
}

/* 卡片：elev-3 底色 + 弱化边框（--card-border）浮起；深色再补顶部受光边，浅色用环境阴影。
   社区卡与工作区卡是同一形态（社区的分享信息已并入卡内脚注 .ws-card-footnote），
   都直接挂在 .ws-selectable 下，因此下面所有卡片状态样式只需一套选择器。 */
.ws-object-list > .ws-selectable > .prompt-delivery-card,
.ws-object-list > .ws-selectable > .ws-object-card,
.ws-object-list > .prompt-delivery-card {
  background: var(--elev-3);
  border-color: var(--card-border);
  box-shadow: var(--card-shadow), var(--elev-edge);
}
.ws-object-list > .ws-selectable > .prompt-delivery-card:hover,
.ws-object-list > .ws-selectable > .ws-object-card:hover {
  background: var(--elev-4);
  border-color: color-mix(in srgb, var(--accent) 30%, var(--border));
  box-shadow: var(--card-shadow-hover), var(--elev-edge);
}
/* 选中态：在浮起之上再加一道 accent 侧缘，选中身份一眼可读。
   与通用那处（见 .ws-selectable.is-selected 唯一定义）保持同一套信号：
   边框 + 左侧 2px 色条 + 6% 底色，**不含**外圈光晕（与 border 同位重复、且会粘连邻卡）。
   这里额外带 --card-shadow / --elev-edge 是卡片自身的海拔表达，与选中信号无关，必须保留，
   否则选中的卡会"塌回"平面、看起来比周围的卡矮一档。 */
.ws-object-list > .ws-selectable.is-selected > .prompt-delivery-card,
.ws-object-list > .ws-selectable.is-selected > .ws-object-card {
  border-color: var(--accent);
  box-shadow: var(--card-shadow), var(--elev-edge), inset 2px 0 0 var(--accent);
  background: color-mix(in srgb, var(--accent) 6%, var(--elev-3));
}

/* ── 修改态：与选中态视觉通道分开，允许同屏叠加 ──
   .is-selected 是用户主动、静态持续的强信号，占实线描边+外发光这条通道；「正在被修改」是系统
   触发、瞬时的信号，改走虚线描边这条弱一档、专属的通道——不抢选中的描边，两者可以同时出现在
   同一张卡上且都能被读出来（选中未必是被改的那张，被改的也未必是选中的那张）。
   颜色跟随ensureOpBadge 写入的 --op-badge-color（与卡右上角 .ws-op-badge 同色：写=琥珀/
   建=绿/删=红/读=青），用户只需学一套「颜色=操作类型」的映射。 */
.ws-object-list > .ws-selectable.ws-has-op-badge:not(.is-selected) > .prompt-delivery-card,
.ws-object-list > .ws-selectable.ws-has-op-badge:not(.is-selected) > .ws-object-card {
  border-style: dashed;
  border-color: color-mix(in srgb, var(--op-badge-color, var(--warn)) 48%, var(--card-border));
  background: color-mix(in srgb, var(--op-badge-color, var(--warn)) 5%, var(--elev-3));
  transition: border-color .3s, background .3s;
}
/* 执行中：极轻呼吸（仅透明度），呼应 .ws-op-badge.is-active 同款节奏，克制不抢主内容。
   徽章进入 is-done 定格态后这层动效随之停止，只留静态虚线描边，直到随徽章一起淡出。 */
.ws-object-list > .ws-selectable.ws-has-op-badge:not(.is-selected):has(> .ws-op-badge.is-active) > .prompt-delivery-card,
.ws-object-list > .ws-selectable.ws-has-op-badge:not(.is-selected):has(> .ws-op-badge.is-active) > .ws-object-card {
  animation: ws-card-modifying-breathe 1.5s ease-in-out infinite;
}
/* 淡出：与徽章 is-fading 的 300ms 节奏同步收敛回卡片常态，不要边框比徽章早消失或跳变。 */
.ws-object-list > .ws-selectable:not(.is-selected):has(> .ws-op-badge.is-fading) > .prompt-delivery-card,
.ws-object-list > .ws-selectable:not(.is-selected):has(> .ws-op-badge.is-fading) > .ws-object-card {
  border-style: solid; border-color: var(--card-border); background: var(--elev-3);
}
@keyframes ws-card-modifying-breathe {
  0%, 100% { opacity: 1; }
  50% { opacity: .88; }
}
/* 同时选中 + 修改中：外层选中的实线描边与左侧色条原样保留（唯一、稳定的身份信号不能被让位），
   修改态退到内层次级信号——同色内发光叠在选中态的 box-shadow 之后，两个状态都能被读出来。
   注：外圈光晕（0 0 0 1px accent45%）已随选中态收敛一并移除，它与 border-color 同位重复。 */
.ws-object-list > .ws-selectable.is-selected.ws-has-op-badge > .prompt-delivery-card,
.ws-object-list > .ws-selectable.is-selected.ws-has-op-badge > .ws-object-card {
  position: relative;
  box-shadow: var(--card-shadow), var(--elev-edge), inset 2px 0 0 var(--accent), inset 0 0 0 2px color-mix(in srgb, var(--op-badge-color, var(--warn)) 25%, transparent);
}
/* 呼吸效果不再动画 box-shadow 本身（逐帧重画，性能审计 P2）：改为静态低亮度描边常驻，
   叠一层同形状 ::after 只动它的 opacity——opacity 是合成器属性，浏览器只需把预先栅格化好的
   这层像素调透明度，不必每帧重新画阴影。多张卡同时"修改中"时收益最明显。 */
.ws-object-list > .ws-selectable.is-selected.ws-has-op-badge:has(> .ws-op-badge.is-active) > .prompt-delivery-card::after,
.ws-object-list > .ws-selectable.is-selected.ws-has-op-badge:has(> .ws-op-badge.is-active) > .ws-object-card::after {
  content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--op-badge-color, var(--warn)) 55%, transparent);
  opacity: 0; animation: ws-card-modifying-inner-glow 1.5s ease-in-out infinite; will-change: opacity;
}
@keyframes ws-card-modifying-inner-glow { 0%, 100% { opacity: 0; } 50% { opacity: 1; } }

/* 去掉第二、三层描边：chip 与详情态的资产行改用背景色块区分层级。
   39 张卡 × 每卡 3 个带框chip = 满屏碎框，是"零散感"的主要来源之一。 */
.prompt-pack-chip { border-color: transparent; background: color-mix(in srgb, var(--text) 5%, transparent); }
.prompt-artifact-row { border-color: transparent; background: color-mix(in srgb, var(--text) 4%, transparent); }
.prompt-artifact-row:hover { background: color-mix(in srgb, var(--text) 7%, transparent); }

/* 列表态标题：给足两行空间并统一截断，避免长标题把卡片高度撑出参差。 */
.prompt-delivery-card.is-list .prompt-delivery-title h3 {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; font-size: 13px; line-height: 1.4;
}
.prompt-delivery-card.is-list .prompt-delivery-title > span {
  font-size: 10.5px; color: var(--text-3);
}
/* ── 无类型徽标时的头部重排（单一类型视图 / 按类型筛选中）──
   徽标撤掉后标题就是卡片第一行，视觉规格要跟着改，不能只是"少一行"：
   1) 标题升到 14px：原本 13px 是因为上面压着一行 10.5px 徽标、两行合起来才够重；
      现在标题独自承担卡片身份，还按 13px 写会让整卡的视觉重心塌到下面的摘要上；
   2) 只让标题块垂直居中（align-self，不是整行 align-items）：flex-start 是为
      "缩略图 vs 徽标+标题两行"对齐设计的，右侧只剩单行标题时顶对齐会让文字看起来
      吊在缩略图上沿；但若把整行 align-items 设成 center，行内的"更多操作"按钮也会
      被一起居中下压，跟卡片右上角固定在 top:10px 的选中钮（.ws-select-btn）错位——
      两颗本该同高的按钮就对不齐了。改成只对标题这一项用 align-self:center，
      缩略图与动作区仍留在行顶（flex-start），与选中钮保持同一条基线。
   3) 标题上方不再需要为徽标预留的呼吸位（.ws-kind-badge 的 margin-bottom随之消失）。 */
.prompt-delivery-card.is-list .prompt-delivery-title:not(:has(.ws-kind-badge)) {
  align-self: center;
}
.prompt-delivery-card.is-list .prompt-delivery-title:not(:has(.ws-kind-badge)) h3 {
  font-size: 14px; line-height: 1.42;
}

/* 顺利完成的结果行：降级为一行低对比状态标，不再占据正文级视觉权重。
   异常状态（failed/blocked/incomplete/claim-rejected）不套用此弱化，保持完整可读。*/
.turn-delivery-head.is-quiet {
  gap: 8px; padding: 2px 0; border: 0; background: transparent;
  font-size: 11.5px; color: var(--text-3);
}
.turn-delivery-head.is-quiet strong { font-weight: 600; font-size: 11.5px; color: var(--text-3); }
.turn-delivery-head.is-quiet .turn-delivery-count { color: var(--text-3); }

/* Agent 头像：侧栏刻意只留「头像 + 切换箭头」以避免与会话头部重名，
   但首字若缺乏头像语义（无圆形/无对比）会被误读成被截断的文字。这里强化其头像特征。 */
.side-agent-avatar {
  border-radius: 50%; color: #fff; font-weight: 700;
  display: inline-flex; align-items: center; justify-content: center;
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--bg) 55%, transparent);
}

/* 删除是不可逆动作：默认保持最低视觉权重（避免误点），hover 才显出危险色。 */
.ws-pack-delete { flex: 0 0 auto; padding: 5px 8px; font-size: 11.5px; color: var(--text-3); }
.ws-pack-delete:hover { color: var(--error); background: color-mix(in srgb, var(--error) 10%, transparent); }


/* ============ 资源变更确认卡 ============
   决策顺序=动作→目标→影响→字段；unified diff 退为折叠证据，指纹退为脚注。
   用户批准的是"哪些东西会怎样变"，不是一段等宽文本。 */
.mutation-card { border-color: color-mix(in srgb, var(--border) 80%, var(--text-3)); }
.mutation-card.sem-delete { border-color: color-mix(in srgb, var(--error) 32%, var(--border)); }
.mutation-head { gap: 6px; }
.mutation-head .interaction-capability-kicker { color: var(--text-3); letter-spacing: .02em; }
.mutation-card.sem-delete .mutation-head .interaction-capability-kicker { color: var(--error); }
.mutation-target { display: flex; align-items: baseline; gap: 8px; min-width: 0; font-size: 12.5px; }
.mutation-target-label { flex: 0 0 auto; color: var(--text-3); font-size: 11px; }
.mutation-target-value { min-width: 0; color: var(--text); font-weight: 600; overflow-wrap: anywhere; }
.mutation-sem.sem-delete { color: var(--error); border-color: color-mix(in srgb, var(--error) 35%, transparent); background: color-mix(in srgb, var(--error) 8%, transparent); }
.mutation-sem.sem-create { color: var(--success); border-color: color-mix(in srgb, var(--success) 35%, transparent); background: color-mix(in srgb, var(--success) 8%, transparent); }
.mutation-reason { font-size: 12px; color: var(--text-2); line-height: 1.55; }
.mutation-body { display: grid; gap: 12px; margin-top: 10px; padding: 0 14px; }
.mutation-block { display: grid; gap: 6px; }
.mutation-block-title { font-size: 11px; font-weight: 650; color: var(--text-3); letter-spacing: .04em; }
.mutation-impact { display: grid; gap: 4px; }
.mutation-impact-item {
  display: grid; grid-template-columns: 40px minmax(0, auto) minmax(0, 1fr);
  align-items: baseline; gap: 8px; padding: 5px 8px; border-radius: 8px;
  background: var(--surface-tint); font-size: 12px;
}
.mutation-op {
  justify-self: start; padding: 1px 5px; border-radius: 5px; font-size: 10.5px; font-weight: 650;
  color: var(--text-2); background: color-mix(in srgb, var(--text-3) 16%, transparent);
}
.mutation-impact-item.op-delete .mutation-op { color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); }
.mutation-impact-item.op-create .mutation-op { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.mutation-impact-item.op-none { opacity: .72; }
.mutation-path { min-width: 0; font:11.5px/1.5 var(--mono); color: var(--text); overflow-wrap: anywhere; }
.mutation-impact-item.op-delete .mutation-path { text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--error) 60%, transparent); }
.mutation-note { min-width: 0; color: var(--text-3); font-size: 11px; line-height: 1.5; }
.mutation-changes { display: grid; gap: 2px; }
.mutation-change {
  display: grid; grid-template-columns: minmax(72px, 22%) minmax(0, 1fr) 14px minmax(0, 1fr);
  align-items: baseline; gap: 8px; padding: 5px 8px; border-radius: 8px; font-size: 12px;
}
.mutation-change:nth-child(odd) { background: var(--surface-tint); }
.mutation-change-key { font: 11.5px/1.5 var(--mono); color: var(--text-2); overflow-wrap: anywhere; }
.mutation-change-val { min-width: 0; overflow-wrap: anywhere; line-height: 1.5; }
.mutation-change-val.before { color: var(--text-3); text-decoration: line-through; text-decoration-color: color-mix(in srgb, var(--text-3) 60%, transparent); }
.mutation-change-val.after { color: var(--text); }
.mutation-change-arrow { color: var(--text-3); font-size: 11px; text-align: center; }
.mutation-change.st-added { grid-template-columns: minmax(72px, 22%) 14px minmax(0, 1fr); }
.mutation-change.st-added .mutation-change-val.before { display: none; }
.mutation-change.st-removed { grid-template-columns: minmax(72px, 22%) minmax(0, 1fr) 14px; }
.mutation-change.st-removed .mutation-change-val.after { display: none; }
.mutation-change.st-added .mutation-change-val.before,
.mutation-change.st-removed .mutation-change-val.after { color: var(--text-3); text-decoration: none; font-style: italic; }
.mutation-change.has-expanded-value { align-items: start; }
.mutation-change.has-expanded-value .mutation-change-arrow { padding-top: 8px; }
.mutation-value-details { min-width: 0; border: 1px solid color-mix(in srgb, var(--border) 76%, transparent); border-radius: 7px; background: color-mix(in srgb, var(--surface-tint) 70%, transparent); }
.mutation-value-details > summary { display: flex; align-items: center; gap: 7px; min-width: 0; padding: 7px 8px; cursor: pointer; list-style: none; }
.mutation-value-details > summary::-webkit-details-marker { display: none; }
.mutation-value-summary { flex: 0 0 auto; color: var(--text); font-size: 11.5px; font-weight: 650; }
.mutation-value-keys { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); font: 10.5px/1.4 var(--mono); }
.mutation-value-expand { flex: 0 0 auto; margin-left: auto; color: var(--accent, var(--text-2)); font-size: 10.5px; }
.mutation-value-details[open] .mutation-value-expand { font-size: 0; }
.mutation-value-details[open] .mutation-value-expand::after { content: '收起'; font-size: 10.5px; }
.mutation-value-content { display: grid; grid-template-rows: auto minmax(0, 1fr); gap: 6px; padding: 0 8px 8px; border-top: 1px solid color-mix(in srgb, var(--border) 70%, transparent); }
.mutation-value-copy { justify-self: end; min-height: 24px; padding: 2px 7px; font-size: 10.5px; }
.mutation-value-code { max-height: 260px; margin: 0; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-2); font: 11px/1.55 var(--mono); }
.mutation-diff-primary { display: grid; gap: 6px; min-width: 0; }
.mutation-diff-primary .mutation-block-title { margin-bottom: 0; }
.mutation-diff-primary .wb-diff { margin: 0; max-height: min(46vh, 420px); overflow: auto; }
.mutation-raw { border: 1px solid var(--border); border-radius: 10px; background: var(--surface-tint); padding: 0 10px; }
@media (max-width: 640px) {
  .mutation-change { grid-template-columns: 68px minmax(0, 1fr) 12px minmax(0, 1fr); gap: 5px; padding: 6px; }
  .mutation-change.st-added { grid-template-columns: 68px 12px minmax(0, 1fr); }
  .mutation-change.st-removed { grid-template-columns: 68px minmax(0, 1fr) 12px; }
  .mutation-value-details > summary { align-items: flex-start; flex-wrap: wrap; }
  .mutation-value-keys { flex: 1 1 100%; order: 3; }
}
.mutation-raw > summary { cursor: pointer; padding: 8px 2px; color: var(--text-3); font-size: 11.5px; }
.mutation-raw[open] > summary { color: var(--text-2); border-bottom: 1px solid var(--border); margin-bottom: 8px; }
.mutation-raw .wb-diff { margin-bottom: 10px; }
.mutation-fingerprint { color: var(--text-3); font-size: 10.5px; line-height: 1.5; overflow-wrap: anywhere; }

/* ============ 中/右栏交界：从"静止分隔线"改为"仅在需要时出现的拖拽手柄" ============
   静止竖线 + 两栏 header 底线会在交界处画出一个十字，把连续界面切成表格。
   分栏靠底色层次表达，边界只在 hover/拖拽/键盘聚焦时显形。 */
.workspace-panel { border-left: 0 !important; border-right: 0 !important; }
.workspace-resize-handle { right: -4px; width: 9px; }
.workspace-resize-handle::after { left: 4px; border-radius: 1px; }
.workspace-resize-handle:hover::after,
.workspace-resize-handle:focus-visible::after,
.workspace-resizing .workspace-resize-handle::after {
  left: 3.5px; width: 2px; background: var(--text-3);
}
.workspace-resize-handle:focus-visible { outline: none; }
/* 手柄握点：hover/拖拽时在竖线中部出现短握把，明确"这里可拖"而非"这里是边框"。 */
.workspace-resize-handle::before {
  content: ''; position: absolute; top: 50%; left: 2px; width: 5px; height: 30px;
  margin-top: -15px; border-radius: 3px; background: transparent; transition: background .12s;
}
.workspace-resize-handle:hover::before,
.workspace-resizing .workspace-resize-handle::before { background: color-mix(in srgb, var(--text-3) 55%, transparent); }
/* header 底线不再延伸进交界热区，避免与竖线相交成十字。 */
.workspace-panel-head { border-bottom: 0; position: relative; }
.workspace-panel-head::after {
  content: ''; position: absolute; left: 11px; right: 11px; bottom: 0; height: 1px;
  background: color-mix(in srgb, var(--border) 60%, transparent);
}
.workspace-panel.collapsed .workspace-panel-head::after { display: none; }


/* ============ 会话区 / 工作区的分栏边界（修正上一版"全无分割"） ============
   分栏必须有可见边界，否则两栏内容糊成一片；但边界只能是一条 hairline，
   且由拖拽手柄自己承担——这样它既是"分割线"又是"可拖的把手"，不会和面板
   header 底线交叉成十字（header 底线已内缩，不进入手柄热区）。 */
.workspace-resize-handle::after { background: var(--border); }
.workspace-resize-handle:hover::after,
.workspace-resize-handle:focus-visible::after,
.workspace-resizing .workspace-resize-handle::after {
  left: 3.5px; width: 2px; background: var(--text-3);
}
@media (max-width: 1199px) {
  /* 移动端面板是浮层、手柄不存在，边界交回给面板自身。 */
  .workspace-panel { border-left: 1px solid var(--border) !important; }
}

/* ============ 列表态内容卡：去贴纸化 ============
   目标是"资料条目"而不是"彩色小卡片"：一个中性画幅框+ 标题 + 一行灰字 meta，
   动作在hover/聚焦时才显形。彩底、渐变、内嵌数字标签都会让39 张卡一起喊话。 */
.ws-pack-thumb {
  width: auto; height: 30px; border-radius: 4px;
  background: var(--surface-tint);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-3) 42%, transparent);
}
.ws-pack-thumb.is-landscape { width: auto; }
.prompt-delivery-card.is-list:hover .ws-pack-thumb {
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-2) 55%, transparent);
}

/* meta 从"带底色 pill 组"降级为一行中点分隔的灰字，避免和按钮抢层级。 */
.prompt-delivery-card.is-list .prompt-pack-meta { gap: 0; align-items: baseline; }
.prompt-delivery-card.is-list .prompt-pack-chip {
  padding: 0; border: 0; border-radius: 0; background: transparent;
  color: var(--text-3); font-size: 11px; line-height: 1.5;
  font-variant-numeric: tabular-nums;
}
.prompt-delivery-card.is-list .prompt-pack-chip + .prompt-pack-chip::before {
  content: '·'; margin: 0 6px; color: color-mix(in srgb, var(--text-3) 60%, transparent);
}

/* 动作条：静止只留最低限度的痕迹，hover/键盘聚焦才把动作交出来。 */
.prompt-delivery-card.is-list .ws-pack-copy {
  color: var(--text-2); background: transparent; border-color: transparent;
  font-weight: 500; transition: color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.prompt-delivery-card.is-list:hover .ws-pack-copy,
.prompt-delivery-card.is-list .ws-pack-copy:focus-visible {
  color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.prompt-delivery-card.is-list .ws-pack-detail,
.prompt-delivery-card.is-list .ws-pack-delete {
  opacity: 0; transition: opacity var(--dur-fast) var(--ease-standard);
}
.prompt-delivery-card.is-list:hover .ws-pack-detail,
.prompt-delivery-card.is-list:hover .ws-pack-delete,
.prompt-delivery-card.is-list .ws-pack-detail:focus-visible,
.prompt-delivery-card.is-list .ws-pack-delete:focus-visible { opacity: 1; }

/* 卡片：静止极轻，hover 才浮起一档，让"当前指向哪一条"成为唯一强调。 */
.prompt-delivery-card.is-list {
  gap: 8px; padding: 12px;
  border-color: color-mix(in srgb, var(--border) 70%, transparent);
  transition: border-color var(--dur-fast) var(--ease-standard), box-shadow var(--dur-fast) var(--ease-standard);
}
.prompt-delivery-card.is-list:hover {
  border-color: var(--border);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--text) 6%, transparent);
}

/* 系列头：等宽字号偏大且带底色时会盖过卡片标题，降为一行小标签。 */
.ws-series-head { padding: 5px 7px; background: transparent; }
.ws-series-name { font-size: 11px; font-weight: 600; letter-spacing: .01em; color: var(--text-3); }
.ws-series-head:hover { background: var(--surface-tint); }
.ws-series-head:hover .ws-series-name { color: var(--text-2); }
.ws-series-head.is-open { border-color: transparent; }
.ws-series-head.is-open .ws-series-name { color: var(--text-2); }
/* aspect-ratio 定宽依赖：flex 子项需显式禁止收缩并给最小宽度，9:16 才不会被压成一条线。 */
.ws-pack-thumb { flex: 0 0 auto; min-width: 14px; }


/* ============ 列表态内容卡（第三版：靠内容撑起卡片，不靠间距） ============
   三行各自承担一类信息：标题=身份、摘要=内容、meta=属性。
   取消动作行：单个次要按钮占整行会吃掉 1/3 卡高，还制造标题(左上)→按钮(右下)的对角空白；
   右下角本是"表单提交"的位置语义，不属于列表项。动作改为贴标题行右端、hover/聚焦显形。 */
.prompt-delivery-card.is-list { gap: 0; cursor: default; }
.prompt-delivery-card.is-list.is-openable { cursor: pointer; }
.prompt-delivery-card.is-list .prompt-delivery-head {
  align-items: flex-start; gap: 8px;
}
.prompt-delivery-card.is-list .prompt-delivery-title { flex: 1 1 auto; gap: 0; }
/* 摘要：标题下第二重要的内容，只降一档（12px/text-2）。若同时降字号又降到text-3，
   它会跌进"装饰性灰条"层级——用户不读，等于用真实内容制造了新噪音。 */
.ws-pack-summary {
  margin: 4px 0 0; color: var(--text-2); font-size: 12px; line-height: 1.55;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
/* meta 才是最弱的一层，与摘要之间必须拉开距离，否则两行灰字糊成一坨。 */
.prompt-delivery-card.is-list .prompt-pack-meta { margin-top: 10px; }
/* slug兜底标题：等宽 + 弱色 + 「未命名」标注，与真标题区分开，不让数据缺失伪装成内容。 */
.prompt-delivery-title h3.is-slug-title {
  font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--text-2);
}
.ws-pack-unnamed {
  align-self: start; margin-top: 3px; padding: 0 5px; border-radius: 4px;
  font-size: 10px; line-height: 1.6; color: var(--text-3);
  background: color-mix(in srgb, var(--text) 6%, transparent);
}
/* 行内动作：不占额外行高（用 visibility 而非 display，避免 hover 时布局跳动）。 */
.ws-pack-inline-actions { flex: 0 0 auto; display: flex; align-items: center; gap: 2px; margin: -2px -4px 0 0; }
.ws-pack-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; padding: 0; border-color: transparent; border-radius: 8px;
  color: var(--text-3); background: transparent;
  visibility: hidden; opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.prompt-delivery-card.is-list:hover .ws-pack-icon-btn,
.prompt-delivery-card.is-list:focus-within .ws-pack-icon-btn { visibility: visible; opacity: 1; }
.ws-pack-icon-btn:hover { color: var(--text); background: var(--surface-tint); }
.ws-pack-icon-btn.is-danger:hover { color: var(--error); background: color-mix(in srgb, var(--error) 10%, transparent); }
/* 键盘用户：聚焦到隐藏按钮时必须可见。 */
.ws-pack-icon-btn:focus-visible { visibility: visible; opacity: 1; outline: 2px solid var(--primary-a-45); outline-offset: 1px; }
/* 整卡可点：焦点环画在卡上，hover 只抬一档，避免边框/阴影/按钮/文字四处同时变化。 */
.prompt-delivery-card.is-list.is-openable:focus-visible {
  outline: 2px solid var(--primary-a-45); outline-offset: 1px;
}
/* 详情态摘要不截断：列表态给两行判断主题，详情里要能读全。 */
.ws-pack-summary.is-full { -webkit-line-clamp: unset; display: block; margin: 6px 0 0; font-size: 13px; }


/* ============ 列表卡动作：一个主动作 + 一个「更多」 ============
   两个同尺寸同色的线性图标只隔 2px 时会在小尺寸下互相干扰，读成一个"叠加图标"，
   同时把不可逆的删除摆到了和复制同等的误点距离上。删除因此收进「更多」菜单。 */
.ws-pack-inline-actions { gap: 4px; flex-wrap: nowrap; }
.ws-pack-icon-btn {
  flex: 0 0 auto; position: static;
  width: 26px; min-width: 26px; height: 26px; min-height: 26px;
}
.ws-pack-icon-btn > svg { flex: 0 0 auto; }
.ws-pack-icon-btn.is-copy-ok { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.ws-pack-icon-btn.is-copy-fail { color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); }

.ws-card-menu { position: relative; display: inline-flex; }
.ws-card-menu-list {
  display: none; position: absolute; top: calc(100% + 4px); right: 0; z-index: 30;
  min-width: 132px; padding: 4px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--panel); box-shadow: 0 8px 24px color-mix(in srgb, var(--text) 12%, transparent);
}
.ws-card-menu.is-open .ws-card-menu-list { display: grid; gap: 2px; }
.ws-card-menu-item {
  appearance: none; cursor: pointer; width: 100%; padding: 7px 9px;
  border: 0; border-radius: 7px; text-align: left;
  color: var(--text); background: transparent; font-size: 12.5px;
}
.ws-card-menu-item:hover { background: var(--surface-tint); }
.ws-card-menu-item.is-danger { color: var(--error); }
.ws-card-menu-item.is-danger:hover { background: color-mix(in srgb, var(--error) 10%, transparent); }
/* 菜单展开时触发按钮必须保持可见，否则鼠标移出卡片菜单还开着但按钮消失了。*/
.ws-card-menu.is-open .ws-pack-icon-btn { visibility: visible; opacity: 1; color: var(--text); background: var(--surface-tint); }

/* 复制用文字按钮而非图标：15px 的 copy 图标（两个交叠方框）与相邻图标会糊成
   一个"叠加图标"，用户认不出有几个按钮。文字没有这个歧义，且 hover 才出现不占常驻权重。 */
.ws-pack-text-btn {
  flex: 0 0 auto; padding: 4px 8px; min-height: 26px; border-color: transparent; border-radius: 7px;
  color: var(--text-2); background: transparent; font-size: 11.5px; font-weight: 500; white-space: nowrap;
  visibility: hidden; opacity: 0;
  transition: opacity var(--dur-fast) var(--ease-standard), color var(--dur-fast) var(--ease-standard), background var(--dur-fast) var(--ease-standard);
}
.prompt-delivery-card.is-list:hover .ws-pack-text-btn,
.prompt-delivery-card.is-list:focus-within .ws-pack-text-btn { visibility: visible; opacity: 1; }
.ws-pack-text-btn:hover { color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.ws-pack-text-btn:focus-visible { visibility: visible; opacity: 1; outline: 2px solid var(--primary-a-45); outline-offset: 1px; }
.ws-pack-text-btn.is-copy-ok { color: var(--success); background: color-mix(in srgb, var(--success) 12%, transparent); }
.ws-pack-text-btn.is-copy-fail { color: var(--error); background: color-mix(in srgb, var(--error) 12%, transparent); }

/* ============ 修正：卡片右上角是「选中钮」的既有领地 ============
   这块 24px 见方的角落同时有三个东西要用：
     1) .ws-select-btn 选中钮 —— absolute top:8/right:8，26px，hover 显现（既有）；
     2) .ws-op-badge 执行徽章 —— absolute top:10/right:40，已为选中钮让过位（既有）；
     3) 本轮新加的标题行动作区（复制 /更多）。
   我把 3 放到标题行右端时直接压在 1 上面，于是"更多"图标和选中钮的对勾叠成一团。
   分配方案：选中钮独占最右 8~34px；标题行整体让出 38px 安全区，动作区落在其左侧；
   徽章维持 right:40（z-index:3 在最上层，执行中短暂出现时盖住动作区，不会互相糊）。 */
.prompt-delivery-card.is-list .prompt-delivery-head { padding-right: 38px; }
.ws-pack-inline-actions { position: relative; z-index: 1; }
/* 菜单要压过选中钮，否则展开的下拉会被右上角那颗钮和徽章切开。 */
.ws-card-menu-list { z-index: 40; }

/* ============ 列表态缩略图 ============
   媒体内容的"哪一张"只能靠图回答——abc (4).png / abc (5).png 这种文件名区分不了任何东西。
   身份位这次放的是真正的身份信息（缩略图），而不是画幅这类属性。 */
.prompt-delivery-card.is-list .prompt-delivery-head.has-thumb { gap: 10px; }
.ws-list-thumb {
  position: relative; flex: 0 0 auto; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center;
  width: 46px; height: 46px; border-radius: 8px;
  background: var(--surface-tint);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--text-3) 28%, transparent);
}
.ws-list-thumb-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block; background: var(--surface-tint);
}
.ws-list-thumb-icon { position: relative; z-index: 1; color: var(--text-3); }
/* 图片加载重试后仍失败：降级为占位标记，不留原生裂图（同 prompt-shot-thumb.is-placeholder 语汇）。 */
.ws-list-thumb.is-broken { background: var(--surface-tint); }
.ws-list-thumb-mark { font-size: 15px; line-height: 1; color: var(--text-3); opacity: .55; }
/* 视频：图标压在封面上作为可播放标记（封面加载失败也仍有图标兜底）。 */
.ws-list-thumb.is-video .ws-list-thumb-icon {
  color: #fff; filter: drop-shadow(0 1px 2px rgb(0 0 0 / .55));
}
.ws-list-thumb.is-video .ws-list-thumb-img { z-index: 0; }

/* 系统代答的交互：与"你的回答"必须视觉可分——用户回来不能误以为是自己点的。 */
.interaction-answer-summary.is-autonomous { border-left: 2px solid color-mix(in srgb, var(--text-3) 55%, transparent); padding-left: 8px; }
.interaction-answer-summary.is-autonomous .interaction-answer-label { color: var(--text-3); font-style: italic; }

/* 双真相标题选择弹层 */
.ws-title-choose { display: grid; gap: 10px; }
.ws-title-choose-hint { color: var(--text-2); font-size: 13px; line-height: 1.6; margin: 0 0 4px; }
.ws-title-choose-btn {
  display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: center;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface-tint); cursor: pointer; text-align: left; transition: border-color .12s;
}
.ws-title-choose-btn:hover { border-color: var(--text-3); }
.ws-title-choose-label { font-size: 11px; color: var(--text-3); white-space: nowrap; }
.ws-title-choose-value { font-size: 14px; color: var(--text); font-weight: 500; overflow-wrap: anywhere; }


/* ============================================================
 * Codex 精致层（v4）—— 只调视觉，不改结构与功能
 *1. 主操作从高饱和强调色收敛为「墨色」：降低对比冲击，去花哨
 *   2. 三级线体系：栏分隔/常规边框/hover 强调，各司其职不混用
 *   3. 工作区列表 → 信息流：去卡框、去左边线，行间细线分隔
 *   4. 类型标识：色块 → 小色点
 *   5. 细节：描线粗细、字距、过渡统一
 * 注意：全部用主题变量，明暗主题各自成立；边栏宽度沿用 120px 不动。
 * ============================================================ */
:root {
  /* 墨色主操作：暗色主题下用亮墨（浅灰）确保可读 */
  --ink: #e8eaed;
  --ink-2: #d4d7dc;
  --ink-fg: #16181c;
  /* 三级线：结构线极淡 / 组件边界淡 / 交互强调。输入框仍直接用 --border 保持可见性。 */
  --line: color-mix(in srgb, var(--border) 40%, transparent);
  --line-2: color-mix(in srgb, var(--border) 70%, transparent);
  --line-3: color-mix(in srgb, var(--border) 88%, var(--text-3));
}
html.light {
  /* 浅色主题：石墨灰 + 暖白前景（对比度约 9:1，达标但不刺眼） */
  --ink: #3b3b37;
  --ink-2: #4c4c47;
  --ink-fg: #f7f7f4;
}

/* —— 三栏骨架：细线分隔（不加重边框，只把分隔线压淡）—— */
/* 浅色主题下会话区应是最亮的面（主视觉），但遗留规则
   `html.light .chat-main { background: var(--bg) }` 权重 (0,2,0)
   压过了后面表达设计意图的低权重规则。此处同权重靠后修正。
   2026-08 起统一走海拔令牌：会话轨 = --elev-2。*/
html.light .chat-main { background: var(--elev-2); }
/* 浅色左栏略加深为冷调浅灰，形成与白色会话区的稳定层级；暗色主题不受影响。
   旧浅色规则同时保留了 --border 实线和 1px 黑色阴影，两层叠加才会读成截图里的粗黑边。 */
html.light .side { background: var(--side-bg); border-right-color: var(--line); box-shadow: none; }
.side { border-right-color: var(--line); }
.workspace-panel { border-left-color: var(--line); }
.workspace-panel-head { border-bottom-color: var(--line); }
/* 头部分割线（由 ::after 伪元素绘制）按设计稿去掉：标题与 chips 之间靠间距分组即可，
   一根横线会把"工作区"标题读成独立区块头，与信息流的连续感冲突。*/
.workspace-panel-head::after { display: none; }
/* 顶栏不再单独画横线：会话头、工作区头均以留白分组；保留贯穿顶端的栏间竖线即可，
   否则横线与相邻区域遗留边界在同一像素附近叠画，会读成一条发灰的双线。 */
.chat-header { position: relative; border-bottom: 0; }
.chat-header::after { display: none; }
/* 分栏线贯穿到顶：三栏边界应是一条连续的极淡 hairline。
   会话头横线已左右内缩，不会与它撞成十字；hover 时才加强为拖拽手柄。 */
.workspace-resize-handle::after { top: 0; bottom: 0; background: var(--line); }
.workspace-resize-handle:hover::after,
.workspace-resize-handle:focus-visible::after,
.workspace-resizing .workspace-resize-handle::after { background: var(--line-3); }
/* 输入区是明确的编辑边界，保留一条比其他结构线略高一级的细线。
   浅色主题旧规则额外叠了一层 0 -1px 阴影，正是截图里读成粗双线的原因。 */
.chat-input,
html.light .chat-input { border-top-color: var(--line-2); box-shadow: none; }

/* —— 用户气泡：墨色 + 柔和前景，替代高饱和渐变 ——
   必须带上 html.light 版本：3855 行附近的浅色主题块用 html.light .msg.user .msg-content（0,4,1）
   写死了 var(--primary) 蓝底，权重高于本条（0,3,0），浅色模式下会压过覆写层。 */
.msg.user .msg-content,
html.light .msg.user .msg-content {
  background: var(--ink); color: var(--ink-fg); border: 1px solid transparent;
  border-radius: var(--r-lg, 14px); letter-spacing: .005em;
}

/* —— Agent 回复：编辑式内容流，而不是第二种大聊天气泡 ——
   外框会把取消/失败这种极短反馈撑成巨大空白卡片；保留小型识别符，
   正文、交付与状态自然垂直排列，只有真正可操作的子组件自行保留边界。 */
.msg.ai { gap: 12px; }
.msg.ai .msg-avatar,
html.light .msg.ai .msg-avatar {
  flex-basis: 24px; width: 24px; height: 24px; margin-top: 4px;
  border-color: var(--line-2); background: var(--surface-tint); color: var(--text-2);
  font-size: 12px;
}
.msg.ai .msg-body { gap: 6px; padding: 4px 2px 12px 0; }
.msg.ai .msg-content,
html.light .msg.ai .msg-content {
  padding: 6px 0 8px; border: 0; border-radius: 0; background: transparent;
}
/* 极短终态仍有呼吸感，但不借助整块描边卡片制造面积。 */
.msg.ai .turn-delivery { margin: 0; padding: 2px 0 8px; }
.msg.ai .turn-delivery-summary { margin-top: 8px; color: var(--text-2); }
.msg.ai .execution-record-dock { margin-top: 2px; }
/* 终态状态 badge 本身就是回复的首行；头像与内容流顶部对齐。
   不能按状态 badge 的视觉中心额外下移，否则会在“已完成”等短状态前明显坠落。 */
.msg.ai:has(.turn-delivery-head) .msg-avatar,
html.light .msg.ai:has(.turn-delivery-head) .msg-avatar { margin-top: 14px; }

/* 非输入的内容/选择组件采用极淡边界，避免创作工作区被一层层矩形框切碎。 */
.prompt-delivery-card,
.ws-type-chip,
.ws-select-btn,
.ws-pack-icon-btn { border-color: var(--line); }

/* —— 工作区类型 chip：active 用墨色实底，替代强调色描边 —— */
.ws-type-chip { border-color: var(--line-2); background: var(--panel); }
.ws-type-chip:hover { border-color: var(--line-3); background: var(--panel); color: var(--text); }
.ws-type-chip.is-active {
  color: var(--ink-fg); background: var(--ink); border-color: var(--ink);
}
/* 计数：纯文字等宽淡色，去掉色块背景与 700 粗体（设计稿是属性标注而非徽章） */
.ws-type-chip-count {
  padding: 0; background: transparent; font-weight: 500;
  font-family: var(--mono); color: var(--text-3);
}
.ws-type-chip.is-active .ws-type-chip-count {
  background: transparent;
  color: color-mix(in srgb, var(--ink-fg) 68%, transparent);
}
/* 标签字重：非选中常规、选中加粗，避免整行都是粗体 */
.ws-type-chip .ws-type-chip-label { font-weight: 500; }
.ws-type-chip.is-active .ws-type-chip-label { font-weight: 600; }
.ws-type-chip.is-technical { border-style: dashed; border-color: var(--line); background: transparent; }
/* 技术入口的基础规则在 active 规则之后，曾把选中态墨色底覆盖成透明，留下浅色文字在浅底上不可见。 */
.ws-type-chip.is-technical.is-active {
  border-style: solid; border-color: var(--ink); background: var(--ink); color: var(--ink-fg);
}

/* —— 工作区列表 → 信息流：连续列表，行间细线，无卡框无左边线——
   仅在【单栏】（窄侧栏）生效：.ws-object-list 在≥640px 容器下是 2-3 栏 grid，
   多栏时每格底边线会读成"网格下划线"、gap:0 会让卡片紧贴，故多栏保持卡片形态。 */
@container wsbody (max-width: 639px) {
  /* 真实直接子是 .ws-selectable；旧规则没有命中卡片却把 grid gap 清零，卡片就像粘在一起。 */
  .workspace-panel .ws-object-list { gap: 8px; }
  .workspace-panel .ws-object-list > .ws-selectable { min-width: 0; }
  .workspace-panel .ws-object-list > .ws-selectable > .prompt-delivery-card.is-list { margin-bottom: 0; }
}
/* 多栏：卡片形态，只把边框压淡、hover 收敛为边框变化（不位移不加阴影） */
@container wsbody (min-width: 640px) {
  .workspace-panel .ws-object-list > .prompt-delivery-card.is-list {
    border-color: var(--line-2); box-shadow: none;
  }
  .workspace-panel .ws-object-list > .prompt-delivery-card.is-list:hover {
    border-color: var(--line-3); transform: none; box-shadow: none;
  }
}

/* —— 卡片类型标记：小色点 + 淡文字（设计稿的信息流类型标识）—— */
.ws-kind-badge { display: inline-flex; align-items: center; gap: 5px;
  font-size: 10.5px; font-weight: 500; color: var(--text-3); letter-spacing: .01em; }
/* 对齐设计稿 feed-badge→feed-title 的呼吸感：badge 收紧行盒、与标题拉开 ~5px，
   并压住旧规则 .prompt-delivery-title span（0,1,1）把字号压成 10px 的副作用。 */
.prompt-delivery-title .ws-kind-badge { font-size: 10.5px; line-height: 1.2; margin-bottom: 4px; }
.ws-kind-badge::before { content: ''; width: 5px; height: 5px; border-radius: 50%; flex: 0 0 auto; }
/* 徽标文字前有 dot(5px)+gap(5px) 共 10px 的前导缩进，标题 h3 没有——之前用 margin-left:-10px
   把整个徽标盒子往左拉齐文字，结果圆点被顶出了标题容器：无缩略图时挤到只剩 2px 就贴卡片
   左边框（padding 仅 12px），有缩略图时直接怼上缩略图右边（gap 恰好也是 10px，0 缓冲）。
   反过来做：徽标保持原位不动，改给 h3 补一个同宽的 padding-left，两行文字在同一条竖线上
   对齐，圆点/间距该在哪就在哪，不会侵入相邻元素的地界。 */
.prompt-delivery-title:has(.ws-kind-badge) h3 { padding-left: 10px; }
/* 类型分色：低饱和，与三色 chip 标签同族但压淡 */
.ws-kind-badge--video_prompt_pack::before { background: #a9a3c4; }
.ws-kind-badge--scheduled_task::before { background: #9dbfa9; }
.ws-kind-badge--media::before, .ws-kind-badge--image::before, .ws-kind-badge--video::before { background: #9db0c4; }
.ws-kind-badge--object::before { background: var(--text-3); }

/* —— meta chip：等宽小字，弱化为属性标注（真实类名 .prompt-pack-chip）—— */
.prompt-pack-meta .prompt-pack-chip {
  font-family: var(--mono); font-size: 10px; letter-spacing: .01em;
  color: var(--text-3); background: var(--surface-tint); border: 1px solid var(--line);
  border-radius: 5px; padding: 1.5px 7px;
  /* 模型名可能很长（尤其是「实际生成模型」这类厂商全名），超长时省略而不是把整行胶囊撑爆。
   * 完整值仍可在详情页与 title 提示里看到。 */
  max-width: 15em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* —— 描线粗细统一：混用 2/2.4会显粗糙 —— */
.side svg, .workspace-panel svg, .chat-header svg { stroke-width: 1.7; }
.ws-pack-icon-btn > svg { stroke-width: 1.9; }

/* —— 字体细节：标题微收字距，等宽正字距 —— */
.workspace-panel .prompt-delivery-title h3 { letter-spacing: -.005em; }

/* ============ 去蓝收敛：浅色主题 --primary(#005f87) 的交互残留统一改墨色/中性灰 ============
   设计稿语义：主操作=墨色实底，选中/激活=墨色或中性灰，语义色(success/warn/error)保留。
   范围只覆盖主界面 chrome（对话/工作区/边栏/抽屉/通用控件）；登录页、后台、编辑器不动。
   凡 3855 附近浅色块已有 html.light 版本的规则，这里必须带同样前缀，否则权重压不过。 */

/* 焦点：边框走三级线（去蓝，这部分保留），但**焦点环不再改灰**——
   它是键盘用户唯一的位置指示，中性灰16% 在深色卡片上几乎不可见。
   焦点环的唯一定义已回到文件头 :root（accent 22%），此处刻意不再覆写。 */
input:focus, textarea:focus, select:focus,
html.light input:focus, html.light textarea:focus, html.light select:focus { border-color: var(--line-3); }
.composer textarea:focus, html.light .composer textarea:focus { border-color: var(--line-3); }
.detail-input:focus { border-color: var(--line-3); }
.ws-list-search-wrap:focus-within { border-color: var(--line-3); }
.ws-pack-icon-btn:focus-visible, .ws-pack-text-btn:focus-visible {
  outline-color: color-mix(in srgb, var(--text) 35%, transparent);
}

/* 主操作按钮：html.light 变体补权重（3846 行 html.light .btn.primary 写死了 color:#fff） */
.btn.primary, html.light .btn.primary { background: var(--ink); color: var(--ink-fg); border-color: var(--ink); }
.btn.primary:hover, html.light .btn.primary:hover { background: var(--ink-2); border-color: var(--ink-2); color: var(--ink-fg); }

/* 分段控件 / 开关：激活=墨色 */
.segmented-option.active, .segmented-option[aria-selected="true"] { color: var(--ink-fg); background: var(--ink); }
.switch input:checked + .switch-slider { background: var(--ink); }

/* 边栏 / 抽屉导航：激活=中性灰底 + 正文色（设计稿 .nav-item.is-active 同款） */
.side-nav-item.active, html.light .side-nav-item.active { background: var(--surface-tint); color: var(--text); font-weight: 600; }
html.light .drawer-project-card.current { background: var(--surface-tint); }
.drawer-link-row.active { color: var(--text); }

/* 工作区交互件：文字钮/排序/复制入口的 accent 蓝改中性。
   但.ws-select-btn.is-on **刻意不在此列**：墨色收敛的对象是"主操作按钮"的高饱和实底，
   而那颗钮表达的是**选中状态**，与它同步高亮的卡片边框用的正是 accent。
   曾经把它改成墨色，造成一张选中的卡上"右上角墨色实心钮 + 边缘 accent 描边"两套色彩语言
   同框，读感分裂；且深色档--ink 是近白 #e8eaed，用近白做选中填充与正文色几乎同色，
   语义反而更弱。状态指示统一交回 accent（见文件头「青色只用于焦点、链接和当前指示」）。 */
.ws-select-btn:hover { color: var(--text); border-color: var(--line-3); background: var(--panel); }
.ws-pack-text-btn:hover { color: var(--text); background: var(--surface-tint); }
.ws-sort-item.is-on { color: var(--text); }
.ws-pack-copy:hover { background: var(--surface-tint); }
button.prompt-artifact-label:hover { color: var(--text); }
.next-action-btn.primary { background: var(--surface-tint); border-color: var(--line-2); color: var(--text); }

/* 下划线 tab：激活描边=墨色 */
.tab.active { border-bottom-color: var(--ink); }

/* 状态 chip（运行/排队）：蓝是旧主题的信息色，设计稿里状态靠文字不靠色块 */
.git-status-chip.running,
.todo-summary-chip.queued, .todo-status-chip.queued,
.todo-summary-chip.running, .todo-status-chip.running,
.tag-picker-chip.active {
  color: var(--text-2); border-color: var(--line-2); background: var(--surface-tint);
}

/* 工具块左边条 / 压缩提示 / 执行记录开关：中性化，语义边条(ok/bad)保持不动 */
.tool.tool-use, html.light .tool.tool-use { border-left-color: var(--line-3); }
.context-compressed-hint, html.light .context-compressed-hint { background: var(--surface-tint); border-color: var(--line); }
.execution-record-dock.is-running .execution-record-toggle,
.execution-record-dock.is-waiting .execution-record-toggle {
  color: var(--text-2); border-color: var(--line-2); background: var(--surface-tint);
}

/* 回到底部按钮：去掉蓝描边蓝字 */
.scroll-bottom-btn.has-new, .scroll-bottom-btn.has-result {
  border-color: var(--line-3); background: var(--panel);
  box-shadow: 0 10px 30px color-mix(in srgb, var(--text) 14%, transparent);
}
.scroll-bottom-btn.has-result .scroll-bottom-text { color: var(--text); }

/* 类型选择卡（新建/编辑流程弹层）：激活=墨色描边 + 中性底 */
.type-option.active { border-color: var(--ink); background: var(--surface-tint); box-shadow: 0 0 0 1px var(--line-3) inset; }
.type-option.active .type-option-icon { background: var(--surface-tint); color: var(--text); }
.type-option-check { color: var(--ink); }
.type-card.active { border-color: var(--ink); box-shadow: 0 0 0 1px var(--line-3) inset; }

/* ============ 左栏：品牌区（顶） + Agent 清单（主体） + 更多（底） ============
   功能模块与账户已迁至右侧「⋯」橱窗；左栏只回答「我是谁的创作台 / 在用哪个 Agent」。
   选中样式沿用 .side-nav-item.active，不引入第二套高亮语言。 */
.side-brand {
  display: flex; align-items: center; gap: 8px; width: 100%; flex: 0 0 auto;
  padding: 5px 8px 9px; border: 0; background: transparent;
  color: var(--text); text-align: left; cursor: pointer;
}
.side-brand-glyph {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex: 0 0 24px; border-radius: 7px;
  /* 品牌圆形固定墨色+白字，不借用会随主题翻转的 --ink（同 .brand-mark-glyph 那次修复，
     此处是宽屏左栏独立的一套样式，此前漏改，深色主题下曾变成刺眼的浅色反色块）。 */
  background: var(--brand-mark-bg); font-size: 13px; font-weight: 700; color: var(--brand-mark-fg);
}
.side-brand-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; font-weight: 650; }
/* Agent 清单吃掉剩余高度并独立滚动：Agent 变多时不挤压品牌区与底部「更多」。*/
.side-agent-list-nav { display: flex; flex-direction: column; gap: 2px; flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.side-agent-item-row { gap: 8px; padding: 7px 9px; }
.side-agent-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: 0 0 22px; border-radius: 6px;
  font-size: 11px; font-weight: 700; color: #fff;
}
.side-agent-item-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* —— 左栏对齐与选中语言 ——
   原实现用::before 的 '›' 占 10px 内容流表达选中：它是 flex item，会把该行头像整体右推，
   与品牌区图标形成两条不同的垂直基线（截图里“怪”的根因），且字号/字体一变就重新错位。
   改为：指示器 absolute 脱离内容流，所有行的图标列严格共用一条 16px 基线。 */
.side-brand,
.side-agent-item-row { padding-left: 8px; padding-right: 8px; }
.side-agent-item-row { position: relative; gap: 8px; padding-top: 6px; padding-bottom: 6px; }
.side-nav-item.side-agent-item-row::before,
.side-nav-item.side-agent-item-row:not(.active)::before { content: none; width: 0; margin-left: 0; }
/* 选中：左侧 2px 墨色竖条 + 底色 + 字重，三者同向表达同一状态，不再叠加箭头。 */
.side-agent-item-row.active::after {
  content: ''; position: absolute; left: 0; top: 50%; width: 2px; height: 16px;
  border-radius: 0 2px 2px 0; background: var(--ink); transform: translateY(-50%);
}
/* —— Agent 头像：类型语义图标 + 低饱和身份色——
   旧实现是「名字首字 + 高饱和纯色块」，三个问题叠在一起：
   1) 汉字在 24px 容器 /12px 字面下笔画糊成墨块（首字母头像是拉丁语境的模式，中文照搬必糊）；
   2) 首字与右侧完整名字重复，这块 ink 承载 0 增量信息；
   3) #3b82f6 这类高饱和纯色落在低饱和暖底上是全屏色彩对比最强的元素 → 每一项都同等抢眼，
      等于没有一项抢眼，真正该被强调的「当前选中」反而被压制。
   现在底色/图标色由 JS 按稳定身份注入 inline style（色值取自代码内固定调色板，非用户输入），
   饱和度压到 tint 档后彩色从「注意力磁铁」退回「分类线索」。 */
.side-agent-dot { width: 24px; height: 24px; flex-basis: 24px; border-radius: 7px; font-size: 12px; }
.side-agent-dot > .icon { line-height: 0; }
/* 未选中降透明度而不是降饱和：tint 底本身已是低饱和，再saturate() 会糊成一团灰。 */
.side-agent-item-row .side-agent-dot { opacity: .72; transition: opacity .15s var(--ease-standard, ease); }
.side-agent-item-row:hover .side-agent-dot,
.side-agent-item-row.active .side-agent-dot { opacity: 1; }

/* —— 选中态：让它成为列表里唯一的「实心块」 ——
   原先底色是 --surface-tint(2.5%)，在暖底上几乎混不出来；竖条 16px 只覆盖38px 行高的 42%，
   读起来像残缺装饰而非状态指示。这里把底色抬到 4.5% 档并让竖条拉满行高。
   注意特异性：遗留规则 `html.light .side-nav-item.active{background:transparent}` 是 (0,3,0)，
   必须带 html.light 前缀的 (0,4,0) 才压得住，否则浅色/暖色主题下选中底色不生效。 */
.side-nav-item.side-agent-item-row.active,
html.light .side-nav-item.side-agent-item-row.active {
  background: var(--surface-tint-2); color: var(--text);
}
.side-agent-item-row.active::after {
  top: 6px; bottom: 6px; height: auto; transform: none;
}

/* —— 品牌区与 Agent 列表的层级区分 ——
   品牌是应用标题而非「列表第一项」，靠三点拉开：形状语言相反（小号圆形单色 vs 较大圆角方形彩色）、
   字号字重反差、留白分层（不加分割线）。 */
.side-brand {
  box-sizing: border-box; height: 44px; min-height: 44px; align-items: center;
  gap: 8px; padding: 0 8px; margin-bottom: 2px;
}
/* 左边缘对齐并不等于视觉对齐：18px 圆(中心 17px) 与 24px 方块(中心 20px) 差 3px，
   就是「总觉得有点歪」的残留来源。用 margin 把18px 圆撑进同一条 24px 图标列，
   中心线与文字起点(40px) 双双对齐，同时保留圆比方块小一号的形状反差。 */
.side-brand-glyph {
  width: 18px; height: 18px; flex-basis: 18px; margin: 0 3px; border-radius: 50%;
  background: var(--brand-mark-bg); font-size: 10px; font-weight: 700;
}
.side-brand-name { font-size: 13.5px; font-weight: 700; letter-spacing: -.01em; color: var(--text); }

/* 分组标签已移除：左栏只有一个分组，"AGENT" 抬头占约 20px 垂直空间却不传达新信息
   （下面是什么由内容自明）。分组标签是≥2 个分组或分组可折叠时才该出现的东西；
   品牌与列表的分层改由这里的留白 + 上面的形状/字重反差承担。 */
.side-agent-list-nav { margin-top: 8px; }

/* 条目文字比品牌轻一级，让品牌在视觉上稳定居于顶层。 */
.side-agent-item-name { font-size: 12.5px; font-weight: 500; }
.side-agent-item-row.active .side-agent-item-name { font-weight: 600; }
/* 行尾不放 Agent 编号：8 位数字在窄侧栏比名字本身还宽，会把名字压成"图片…"。
   名字是唯一真正用于识别的信息，不能被编号挤掉；编号保留在 title 与抽屉卡片里。 */

/* 新建入口：虚线大框的视觉权重高于 Agent 项本身，会抢走列表的注意力；降为静默文字行。
   注意：此前这条规则被一份同名选择器的副本（border:1px dashed）在下方覆盖，等于该修复被静默回退，
   截图里的虚线框就是那份副本。已合并为下面这一份唯一定义，勿再追加同名块。 */
/* 结构与上方 Agent 行一致：[24px 图标列]['+' 居中][8px][文字列]，
   这样品牌名 / Agent 名 / 「新建 Agent」三条文字共用同一条起始线。 */
.side-new-agent-btn {
  display: flex; align-items: center; gap: 8px;
  width: 100%; margin-top: 2px; padding: 7px 8px; border: 0; border-radius: 8px;
  background: transparent; color: var(--text-3);
  font-size: 12.5px; text-align: left; cursor: pointer;
}
.side-new-agent-plus {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; flex: 0 0 24px;
  font-size: 15px; font-weight: 400; line-height: 1;
}
.side-new-agent-text { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.side-new-agent-btn:hover { border: 0; color: var(--text-2); background: var(--surface-tint); }
/* 创作者在零 Agent 态的次要入口——按号码加入他人的 Agent：字号更轻、贴着主入口，
   不重复整行的图标网格权重，避免和上面「新建 Agent」抢视觉。 */
.side-new-agent-btn.secondary { margin-top: 0; padding-top: 5px; padding-bottom: 5px; font-size: 11.5px; opacity: .85; }
.side-new-agent-btn.secondary:hover { opacity: 1; }
/* 「更多」常驻底部：非会话页（工具/管理）没有会话头，靠它切功能模块与进账户。 */
.side-more-btn {
  display: flex; align-items: center; gap: 8px; width: 100%; flex: 0 0 auto;
  padding: 9px; border: 0; border-top: 1px solid var(--line); border-radius: 0;
  background: transparent; color: var(--text-2); font-size: 13px; text-align: left; cursor: pointer;
}
.side-more-btn:hover { color: var(--text); background: var(--surface-tint); }

/* Agent 的工具 / 管理等页面覆盖中栏，工作区/社区实例留在底层不销毁；回到创作无需重建筛选、滚动或实时状态。 */
.agent-center-route {
  position: absolute; inset: 0; z-index: 30; overflow: auto;
  padding: 0; background: var(--bg);
}
/* 覆盖期间底层必须整体不可见。
   为什么不能只靠覆盖层的不透明底色 + z-index：工作区内部有多个 sticky 层
   （类型筛选条 .ws-sticky-bar z-index:20、置顶活动坞、排序菜单），它们的 z-index
   在同一层叠上下文里与覆盖层直接比较，会把「全部 / 提示词包 / 原始文件」这排chips
   漏到「我的设置」等栏目页顶部，看起来像凭空悬浮的筛选条。
   用 visibility 而不是 display:none —— display 会让底层丢掉 scrollTop 与已完成的布局，
   违背"回到创作不重建筛选与滚动"的设计；visibility:hidden 保留布局、整棵子树（含所有
   sticky/fixed 后代）都不参与绘制。拖宽把手不隐藏：覆盖中栏时调整会话宽度仍然有效。 */
.workspace-panel.has-center-route > .workspace-panel-head,
.workspace-panel.has-center-route > .workspace-panel-body { visibility: hidden; }
.agent-center-route-head {
  position: sticky; top: 0; z-index: 2;
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 42px; padding: 7px 14px 7px 20px;
  background: color-mix(in srgb, var(--bg) 94%, transparent);
  border-bottom: 1px solid var(--line);
  backdrop-filter: blur(8px);
}
.is-safari .agent-center-route-head { backdrop-filter: none; -webkit-backdrop-filter: none; }
.agent-center-route-title {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: var(--text-2); font-size: 12px; font-weight: 600;
}
.center-return-workspace-btn {
  display: inline-flex; align-items: center; gap: 4px; flex: 0 0 auto;
  padding: 5px 8px; border: 0; border-radius: 6px;
  background: transparent; color: var(--text-2); font-size: 12px; cursor: pointer;
}
.center-return-workspace-btn:hover { background: var(--surface-tint); color: var(--text); }
.agent-center-route-content { min-height: calc(100% - 42px); padding: 20px; }
.agent-center-route-content > :first-child { min-height: 100%; }
@media (max-width: 900px) {
  .agent-center-route-head { padding-left: 12px; padding-right: 10px; }
  .agent-center-route-content { padding: 14px 12px; }
}

/* ============ 会话收起（右栏 → 44px 窄轨） ============
   收起的是会话而非工作区：中栏内容占满，会话只保留展开把手。
   DOM 不动、仅隐藏，避免重建会话视图丢失 SSE 与滚动位置。 */
.chat-collapse-btn,
.chat-expand-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex: 0 0 auto;
  border: 1px solid transparent; border-radius: 6px;
  background: transparent; color: var(--text-3); font-size: 12px; cursor: pointer;
}
.chat-collapse-btn:hover,
.chat-expand-btn:hover { color: var(--text); background: var(--surface-tint); }
.chat-expand-btn { display: none; }
.chat-main.collapsed .chat-collapse-btn { display: none; }
.chat-main.collapsed .chat-expand-btn { display: inline-flex; }
.chat-main.collapsed .chat-header-title,
.chat-main.collapsed .chat-header-actions,
.chat-main.collapsed .chat-messages,
.chat-main.collapsed .chat-input,
.chat-main.collapsed .scroll-bottom-btn,
.chat-main.collapsed .execution-record-dock { display: none !important; }
.chat-main.collapsed { background: transparent; }
.chat-main.collapsed .chat-header { height: auto; min-height: 0; padding: 7px 0; background: transparent; }
.chat-main.collapsed .chat-header-left { flex: 1 1 auto; justify-content: center; }
/* 窄屏默认收起会话；会话展开后左上角的同一按钮返回工作区/社区。 */
.mobile-chat-open-btn { display: none; }
@media (max-width: 1199px) {
  .chat-collapse-btn { display: inline-flex; }
  .chat-expand-btn { display: none !important; }
  .chat-header-left .brand-mark-mobile { display: none !important; }
}

/* 右上角「⋯」：圆形等宽热区（32px达到触控下限）+ 实心点图标。
   不给描边——旁边「版本」是带边框胶囊，若这里也描边，两颗会互相抢视觉权重；
   可点性交给 hover/active 底色表达。 */
.chat-more-btn {
  width: 32px; height: 32px; min-height: 32px; padding: 0;
  border-radius: 50%; color: var(--text-3);
}
.chat-more-btn:hover,
.chat-more-btn[aria-expanded="true"] { background: var(--surface-tint); color: var(--text); }
.chat-more-btn .icon { display: inline-flex; }

/* ============ 窄屏最终布局：中栏常驻，会话右侧滑出 ============
   必须位于所有 .chat-main 基础规则之后：靠前的 max-width:1199px 块会被后出现的
   .chat-main{position:relative} 覆盖，导致 901–1199px 区间会话重新落回网格流、
   被排到工作区下方（截图中的错乱）。断点须覆盖整个 1199px 以下区间，不能只写 900px。 */
@media (max-width: 1199px) {
  .chat-shell.ws-open,
  .chat-shell.ws-collapsed,
  .chat-shell.chat-collapsed {
    display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: minmax(0, 1fr);
    width: 100%; min-width: 0;
  }
  .chat-shell > .workspace-panel {
    position: relative; grid-column: 1; grid-row: 1;
    width: 100%; min-width: 0; min-height: 0;
    border-left: 0 !important; border-right: 0 !important;
  }
  /* 提升选择器级别，保证覆盖后置的 .chat-main{position:relative}。 */
  .chat-shell > .chat-main {
    position: fixed; inset: 0 0 0 auto;
    display: flex; width: min(92vw, 565px); min-width: 0; height: auto;
    z-index: 1200; transform: translateX(calc(100% + 12px));
    transition: transform .22s var(--ease-standard, ease);
    border-left: 1px solid var(--line-2);
    box-shadow: -10px 0 28px color-mix(in srgb, var(--text) 16%, transparent);
  }
  .chat-shell.mobile-chat-open > .chat-main { transform: translateX(0); }
  .chat-shell > .mobile-chat-open-btn { display: inline-flex; }
  .chat-shell.mobile-chat-open > .mobile-chat-open-btn { display: none; }
  /* 会话转为抽屉后，会话头里的「⋯」不再常驻可达，顶栏必须在整个窄屏区间提供功能入口。 */
  .shell.chat-mode { grid-template-rows: 48px minmax(0, 1fr); }
  .shell.chat-mode .topbar { display: flex !important; }
  .shell.chat-mode .content { min-height: 0; }
}
@media (max-width: 1199px) and (min-width: 901px) {
  /* 该区间左栏仍在，Agent 切换由左栏承担；顶栏（renderTopbar）此时唯一内容是切Agent 按钮，
     若只隐藏按钮而保留 48px 顶栏行，会露出一整条空白（顶栏内只剩空的 .spacer）。
     此区间顶栏没有任何该保留的内容，直接整体隐藏并把行高交还给会话区。 */
  .shell.chat-mode .topbar { display: none !important; }
  .shell.chat-mode { grid-template-rows: minmax(0, 1fr); }
}
@media (max-width: 900px) {
  /* ≤900px 左栏隐藏，工作区/社区成为首页，顶栏同时承载 Agent 橱窗与功能橱窗入口。 */
  .shell.chat-mode { grid-template-rows: 48px minmax(0, 1fr); }
  .shell.chat-mode .topbar { display: flex !important; }
  .shell.chat-mode .content { min-height: 0; }
}
@media (max-width: 640px) {
  /* 640px 旧规则曾将 chat-mode 顶栏清零，这里再次收口，避免 Agent 橱窗入口消失。 */
  .shell.chat-mode { grid-template-rows: 48px minmax(0, 1fr); }
  .shell.chat-mode .topbar { display: flex !important; }
  .chat-shell > .chat-main { width: 100vw; }
}

/* 品牌标识跨断点一致：左栏、窄屏顶栏、会话头、抽屉统一为墨色圆形单色。
   原覆写把 .brand-mark-glyph 设为渐变蓝方块并加蓝色外发光，与左栏墨色圆形不一致。
   2026-08 修复：曾借用 --ink/--ink-fg，但这两个变量在暗色主题下会翻转为浅灰底+近黑字
  （给按钮/气泡保对比度用），导致 logo 在深色背景下变成反色的浅色圆块。品牌圆形应固定
   外观，改用不随主题翻转的 --brand-mark-bg/--brand-mark-fg。 */
.brand-mark-glyph,
.brand-mark-mobile .brand-mark-glyph,
.drawer-brand-logo,
.drawer-brand-logo.sm {
  background: var(--brand-mark-bg) !important;
  color: var(--brand-mark-fg); border-radius: 50%; box-shadow: none;
}
