/* ============================================================================
 * apps/workbench/src/design-tokens.css —— 设计令牌的唯一真相源。
 *
 * 复现自 geo-tools 的落地令牌（console-styling-handoff.md:68-79、:123）。
 * 命名与值一一对应，**组件不得写字面色值**（交接:204-213 第 5 条）。
 * ==========================================================================*/

:root {
  /* ── 强调色：全站只两个用途（主动作 + 当前项），不得扩散 ──
   * ★ 2026-10-01（阶段 4「主题跟客户端走」）：挂进 DSH 客户端时，下面这几个**面与线**的令牌优先用客户端的
   *   `--dsw-alias-*`（浅色/深色由客户端定），取不到就退回工作台现在这套值——独立跑时观感一行不变。
   *   只映射**语义明确**的那几个（面、线、强调色）；文字四档客户端没有对应族，暂不自作主张映射。 */
  --accent: var(--dsw-alias-brand-primary, #2456d8);
  --accent-soft: #eef2fd;
  --accent-on: #fff;

  /* ── 面与线 ── */
  --bg: var(--dsw-alias-bg-base, #f6f7f9);
  --card: var(--dsw-alias-bg-layer-1, #fff);
  --line: var(--dsw-alias-border-l2, #e6e8ec);

  /* ── 文字四档（quaternary 只给「跳过 / 未执行」这类弱信息） ── */
  --text-primary: #1b1f24;
  --text-secondary: #4b5563;
  /* ★ 2026-09-22：tertiary / faint 两档**整体调深**了（原 #8b929c / #98a2b3）。
   *   由来：加对比度判据（tools/probes/theme.mjs）一量就露馅 —— 首页那排小灰字（品牌任务数、
   *   左栏小标题、输入框下的提示、版权）与底色的对比度只有 **2.3~3.1:1**，远低于正文该有的 4.5:1。
   *   「颜色太接近看不清」正是人这次点名要处理的，所以这两档以**可读性优先**重新取值。 */
  --text-tertiary: #5a616c;
  --text-quaternary: #c3c8d0;

  /* ── 语义色：只有三处（warning / danger / success） ──
   * ★ 2026-09-22（人：「已回答的文字和文字框应该变成绿色；未回答的该置为橙/红，信息才完整」）：
   *   三档语义色现在真的用在**卡片状态章**上：等你动手=warning（橙）、你已经做完=success（绿）、
   *   不用你管（已拒绝/已过期）=中性灰；红留给「卡住了/跑失败」，免得「待办」与「故障」同色。
   *   所以 success 也要有配对的底色（原来只有 warning/danger 有）。 */
  --warning: #b45309;
  --warning-bg: #fff7e6;
  --danger: #b91c1c;
  --danger-bg: #fdf0f0;
  /* 危险按钮上的字色：深红底用白字（对比度 ≥4.5:1）；深色系里 --danger 变亮红，字色要反过来用深字 */
  --danger-on: #fff;
  --success: #15803d;
  --success-bg: #eefaf2;
  /* ★ 2026-09-22（人：「『跳过』之后这张卡片就不需要再处理了，不应该还是橙色，应该是一种安全态；
   *   『已跳过』那颗章看着不像状态章」）——第三档「不用你管」（跳过 / 已拒绝 / 已过期）的**底色**。
   *   原来这一档只换字色（白底灰字灰边），看着像"禁用/失效"；给它一块浅灰底，它才是一颗正经的状态章。 */
  --muted-bg: #f1f2f4;

  /* ── 字级八档 ── */
  --fs-h1: 20px;        /* 页面唯一大标题 */
  --fs-brand: 16px;     /* 品牌台徽标条 */
  --fs-body: 14px;      /* 正文 / 消息 */
  --fs-card: 13px;      /* 卡内 */
  --fs-note: 12px;      /* 说明 */
  --fs-meta: 11px;      /* 元信息 / 矩阵 */
  --fs-col: 10px;       /* 列头 / 来源标签 */

  /* ── 品牌色（来自官网 logo 的蓝黑色图标）──
   * ★ 2026-09-22：人要求把 logo 的「倾」字标换成**官网那个蓝黑色 icon**。
   *   这两个色是 2026-09-22 从 www.kingyu.ai/img/logo-light.png 逐像素量的**代表色**
   *   （青色 #00BDE7 与深蓝 #0034B8，各自出现像素最多的那个值）。
   *   图标本体在 components/BrandIcon.js（用 .bm-cyan / .bm-navy 取这两个令牌），
   *   色值只在这里定义一次 ✓ */
  --brand-cyan: #00bde7;
  --brand-navy: #0034b8;

  /* ── 字体族：**全站只有这一份**（人 2026-09-21） ──
   * 由来：人问「首页 logo 和子页面 logo 不一样（是那个点不一样，还是有更多不一样？）」——
   *   实测两页 logo 的 markup 逐字相同、那个「·」两侧的空格也一样，差的是**字体族**：
   *   首页吃的是 home.css 里那句 `font: 15px/1.6 var(--font-sans, system-ui, …)` 的**兜底栈**，
   *   而 `--font-sans` 从来没被定义过；工作台吃的是本文件 `html, body` 里另一份栈
   *   （-apple-system / PingFang SC）。两份栈里 CJK 的落点不同 → 同一个字标
   *   量出来 114px vs 109.5px，看着就是两个 logo。
   * 现在：只在这里定义一次，两个页面都用 `var(--font-sans)`（判据：test/page-frame.test.mjs
   *   「字体族只许有一份定义」+ tools/frame-check.mjs 两页逐项比计算样式）。 */
  --font-sans: system-ui, -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;

  /* ── 尺度 ── */
  --radius: 12px;       /* 卡 / 面板 / 输入框（geo-tools 落地值；第一版误抄成 10） */
  --radius-bubble: 14px;/* 客户气泡 */
  --radius-sm: 4px;     /* chip 用 */
  --side-bg: #f0f2f5;   /* 左栏下沉面：与中栏 --bg 区分开，三栏才读得出层次 */
  --gap: 16px;
  /* ── 页面外框：**照 DSH Web GUI（127.0.0.1:3080）的量法**（人 2026-09-21：
   *    「参考这个链接页面的页边距和左侧边栏的宽度，以及 logo 所在的位置」）。
   *    出处是 GUI 自己的源码：dsh-client-ui-layout 的 .frame（height:100%; grid; grid-template-rows:100%，
   *    **无任何 padding** → 通栏）与 dsh-client-ui-sidebar 的 .root / .logoRow。 */
  --page-pad: 0;        /* 页面外边距：GUI 是通栏，所以是 0（两页共用同一个值） */
  --side-w: 280px;      /* 左栏宽度：GUI 默认 280px（可拖 264–420，收起 56px） */
  --side-w-collapsed: 56px; /* 收起后保留的轨道宽度：照 DSH GUI */
  /* ★ 2026-09-21：网格里**实际生效**的左栏宽度就是这一个值 —— 收起态由
   *   `html[data-side="collapsed"]` 把它换成 --side-w-collapsed。这样五种栏态（有无左栏 /
   *   面板开关 / 全页）**一条网格规则都不用为收起态再写一遍**。 */
  --side-actual: var(--side-w);
  --side-pad: 12px;     /* 左栏左右内边距：GUI 的 --dsh-sidebar-inline-padding */
  /* ★ 2026-09-22（人）：「左侧边栏的『© 2026 倾域AI 版权所有』…切页时为啥感觉抖了一下」——
   *   查出来就是这 8px：首页 `.side` 的底部内边距是 14px，工作台 `.side-nav` 只有 6px，
   *   于是版权行在切页时上下跳 8px（探针实测：首页距底 14px / 品牌页 6px）。
   *   提成令牌，两页共用 —— 位置一致性由 tools/probes/side-footer.mjs 盯着。 */
  --side-pad-bottom: 14px;
  --brand-row-h: 60px;  /* logo 那一行的高度：GUI 的 .logoRow */
  --brand-row-pad: 4px; /* logo 行的左内边距：GUI 的 .logoRow padding-left
                         * → **logo 的横向落点 = --side-pad + --brand-row-pad = 16px**（两页同源） */
  --topbar-h: 52px;
  --panel-w: 460px;
  /* 输入区宽度（首页）。照 DSH GUI 的算法：**列宽的 64%**，夹在 680–920px，再加 32px 卡片内边距
   *   （GUI：--dsh-chat-content-width: clamp(680px, 列宽 * .64, 920px)；
   *         --dsh-composer-card-max-width: calc(内容宽 + 32px)）。
   *   ⚠ 是**比例**不是绝对宽度：随页宽自适应（人 2026-09-21：「应该是随着页面整体宽度做适配」）。
   *   输入框下面的技能行共用这一个值，所以两者左边界永远对齐（人 2026-09-21 的另一条要求）。 */
  --composer-w: calc(clamp(680px, 64%, 920px) + 32px);
  /* ★ 2026-09-22（人）：「英文版首页输入框上面的大标题，缩小字体，确保总宽度不超过**输入框宽度**」——
   *   这条是给大标题算字号用的「真正可用宽」：**列宽与输入框宽取小者**。
   *   ⚠ 为什么不能直接用 `--composer-w`：它里面的 `64%` 在 `max-width` 上按**容器**解析（对的），
   *     可一旦用在 `font-size` 里，百分比按**父字号**解析 —— 于是字号恒定、窄屏溢出（实测 900px 下溢出
   *     118px，被 .main 的 overflow-x 裁掉）。所以这里用**列宽 × 0.64** 显式写一遍，不依赖百分比上下文。
   *   ⚠ 两处数字（680 / 64% / 920 / +32）必须一起改：判据会量「标题文本宽 ≤ 输入框实宽」，漂了就红。 */
  --col-w: calc(100vw - var(--side-actual) - 96px);
  --headline-fit: min(var(--col-w), clamp(680px, var(--col-w) * 0.64, 920px) + 32px);
  /* ── 阴影：只托起卡面（09-10 二稿放宽，交接:12） ── */
  --shadow-card: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06);
  --shadow-pop: 0 1px 3px rgba(16, 24, 40, 0.06);   /* 首页卡片/技能条那种轻轻浮起 */

  /* ══════════════════════════════════════════════════════════════════════
   * ★ 2026-09-22（人）：「目前页面的 style 是浅色系的，帮我再生成一套深色系 style。
   *   要求能处理好文字、背景的颜色关系，不至于过于颜色太接近导致看不清；logo 在深色系里，
   *   图片和文字也可以调整让页面能够适配好」——于是把**当前浅色系里所有写死的色值**都提成令牌，
   *   深色系只在下方的 `[data-theme="dark"]` 里覆盖这些令牌的值（不写 html：见那一处的说明）。
   *
   * 规矩（有判据守着，见 test/theme.test.mjs）：
   *   ① **色值只在本文件出现**：home.css / layout.css 里不许再有字面 hex（一律 var(--…)）；
   *   ② 两套色系必须覆盖**同一组**令牌 —— 只在浅色里定义的令牌，说明深色系漏了；
   *   ③ 文字与它背后的底色对比度 ≥ 4.5:1（正文）/ 3:1（大字与图形），真浏览器实测
   *      （tools/probes/theme.mjs）。
   * ⚠ 浅色系的**值一个都没改**（只是从字面值挪成令牌），所以浅色观感与改动前逐像素一致。
   * ══════════════════════════════════════════════════════════════════════ */

  /* ── 页面/表面：首页底、卡片、悬停面、左栏下沉面 ── */
  --bg-page: #f7f7f7;
  --hover-bg: #f4f6f8;

  /* ── 线与线（强）── */
  --line-strong: #d8d8dc;

  /* ── 文字再两档：muted（说明性标签）/ faint（更弱的小字）──
   * ★ 2026-09-22：与 tertiary 一样以**可读性优先**取值（见上面的说明）。 */
  --text-muted: #667085;
  --text-faint: #5f6672;

  /* ── 首页那支更亮的蓝（标题高亮 / 链接 / 当前项）与它的底色家族 ── */
  --accent-bright: #2f6bff;
  --accent-ink: #2445c4;     /* 引导语那种「深一档的蓝字」 */
  --accent-bg: #f5f8ff;      /* 当前项 / 引导语的底 */
  --accent-bg-2: #eef3ff;    /* 悬停时的底 */
  --accent-line: #dbe6ff;    /* 蓝底那一圈的边 */
  /* ★ 2026-09-22（人）：「快来呀」那圈动画的阴影值（**只有令牌块能写色值**，选择器里只许引用）。
   *   --invite-ring 是**元素自己的边框**在峰值时的颜色（不透明的灰/蓝，醒目度靠它）；
   *   --invite-rest / --invite-lift 是静止与峰值两条阴影（峰值 spread 为 0 → 是阴影不是第二圈框）。 */
  --invite-rest-field: 0 1px 2px rgba(16, 24, 40, 0.05);
  --invite-lift-gray: 0 8px 20px rgba(75, 85, 99, 0.32), 0 2px 6px rgba(75, 85, 99, 0.18);

  /* ── 主动作按钮的底（首页「发送」那颗深色圆钮）── */
  --send-bg: #1b1f24;
  --send-on: #fff;

  /* ── 智能体图标色档（八个技能的小方块）：深色系下要提亮，否则糊在深底里 ── */
  --tone-blue: #2f6bff;
  --tone-purple: #7c4dff;
  --tone-green: #12b76a;
  --tone-orange: #f7910b;
}

/* ══════════════════════════════════════════════════════════════════════
 * 深色系：**只覆盖令牌**（不动任何规则）。每一档都按对比度挑的：
 *   正文 #e9edf2 打在卡片 #171c22 上 ≈ 14:1；次级 ≈ 8.8:1；最弱的 faint ≈ 5:1；
 *   链接/高亮蓝 #7ba4ff ≈ 7:1；品牌图标那半深蓝在深底上会糊，所以提亮成 #6f8dff（≈ 5.8:1）。
 * ⚠ 别在这里写「某个具体选择器」的样式：那样深色系就会与浅色系各写一套、迟早漂开。
 * ══════════════════════════════════════════════════════════════════════ */
/* ⚠ 选择器**不带 html**（2026-10-01，阶段 4 甲）：写 `html[data-theme="dark"]` 时，
   作用域化会变成 `#agile-workbench html[data-theme="dark"]` —— 容器里根本没有 <html>，深色永远不生效。
   写成 `[data-theme="dark"]` 之后：页面模式下匹配 <html data-theme="dark">（观感不变），
   面板模式下匹配我们自己的挂载容器（客户端切深色，面板跟着切）。 */
[data-theme="dark"] {
  color-scheme: dark;          /* 让原生控件（滚动条、输入框内部）也跟着变深 */

  --accent: #5b8cff;
  /* ★ 这三支蓝底在深色系里**要压得比浅色系更暗**：它们上面放的是亮蓝字（--accent），
   *   底一浅、对比度就掉到 4.2:1（左栏那个当前项实测 4.16 ✗）。压暗后 ≈ 5:1 ✓ */
  --accent-soft: #1a2338;
  --accent-on: #0d1117;        /* 亮蓝底上用深字：对比度反而更高 */

  --bg: #1a1f26;
  --bg-page: #0f1216;
  --hover-bg: #222831;
  --card: #171c22;
  --line: #2a3138;
  --line-strong: #3a424b;
  --side-bg: #12161b;

  --text-primary: #e9edf2;
  --text-secondary: #b3bcc7;
  --text-tertiary: #9aa3b0;
  --text-quaternary: #5f6771;
  --text-muted: #a7b0bd;
  --text-faint: #98a1ae;

  --warning: #f0b16a;
  --warning-bg: #2e2415;
  --danger: #ff8a8a;
  --danger-bg: #331c1c;
  --danger-on: #0d1117;
  --success: #6ddc9a;
  --success-bg: #14291d;
  --muted-bg: #232a33;

  --accent-bright: #7ba4ff;
  --accent-ink: #a9c4ff;
  --accent-bg: #16203a;
  --accent-bg-2: #1a2542;
  --accent-line: #33456b;
  /* 深色下的同三条阴影（浮起的影子在深底上要更黑一点才看得见） */
  --invite-rest-field: 0 1px 2px rgba(0, 0, 0, 0.4);
  --invite-lift-gray: 0 8px 22px rgba(0, 0, 0, 0.55), 0 2px 6px rgba(0, 0, 0, 0.4);

  --send-bg: #5b8cff;
  --send-on: #0d1117;

  /* 品牌图标：青色照官网原样（它在深底上够亮）；深蓝那半提亮，否则与深底糊在一起 */
  --brand-cyan: #00bde7;
  --brand-navy: #6f8dff;

  --tone-blue: #6f9bff;
  --tone-purple: #a78bfa;
  --tone-green: #3ddc97;
  --tone-orange: #fbbf5c;

  --shadow-card: 0 1px 2px rgba(0, 0, 0, 0.5), 0 1px 3px rgba(0, 0, 0, 0.4);
  --shadow-pop: 0 1px 3px rgba(0, 0, 0, 0.5);
}

/* ── 基底 ───────────────────────────────────────────────────────────── */
* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--text-primary);
  font: var(--fs-body) / 1.6 var(--font-sans);
  -webkit-font-smoothing: antialiased;
}

button { font: inherit; cursor: pointer; }
a { color: var(--accent); }

/* ── 输入光标 + 空着时的「快来呀」（人 2026-09-22） ─────────────────────────
 * 人：「首页输入框里面文字光标，应该非常明显在那里闪烁，提示『快来呀』『这里可以问问题』
 *      『这里可以操作』；进入品牌子页面后，输入框也应该这样设计」。
 * 三件事一起做，缺一样都不成立：
 *   ① **光标颜色**：原生 caret 是系统细黑线，改成品牌蓝（caret-color）；
 *   ② **进页面就有光标**：没聚焦就根本没有光标 —— 由 JS 在启动时**一次性**聚焦
 *      （home-page.js 的 bootHome / controller.js 的 boot；⚠ 不许挂在每轮重绘上，那会每次抢焦点）；
 *   ③ **空着时轻轻呼吸**：`box-shadow` 一圈品牌蓝光晕，落笔（placeholder 消失）即停 —— 这就是「快来呀」。
 * 两页的输入框类名不同（首页 `.composer input` / 工作台 `.composer-input`），所以样式放这里共用。
 * ⚠ 动画只用 box-shadow（不动布局）；并尊重「减少动效」偏好。
 * ★ 2026-09-22（人）：「输入框的动画效果不够明显…请把动画的颜色处理得更明显一些」——
 *   原来两层都用 --accent-soft（浅色下 #eef2fd，对白底 1.1:1，等于没画）。现在常驻那圈与峰值都用
 *   **品牌蓝本体**（对白底 6.5:1），外圈再加一层很淡的光晕。
 * ★ 同日人又说：「改的过于抢眼，闪眼睛了，再调回一些」——所以**收幅度、不收颜色**：
 *   环宽 1px → 2px（原来 2px → 4px）、外圈光晕 6px/.3（原来 14px/.55）、周期 2.4s → 3.2s。
 *   判据仍然要求光晕色对比度 ≥ 3:1（颜色必须看得见），但「呼吸」的幅度小了，长时间看不刺眼。
 * ★ 同日人再改（品牌页）：「现在是蓝色动画，跟页面里很多蓝色的框太接近…把输入框改成灰色系，
 *   同时加强视觉（灰色比蓝色浅，用相同反差会更不明显）」——
 *   于是品牌页那支换成**中性灰**（`--text-secondary`：浅色 #4b5563 / 深色 #b3bcc7，对底色 6~9:1，
 *   仍然是「看得见的颜色」，只是不再是蓝）+ `--invite-halo-gray`，
 *   并把**幅度加强**补回灰的弱反差：环 1px→**3px**（蓝那支是 2px）、光晕 10px/2px，
 *   再加一条**边框色**跟着走（`--line` → 灰），让「这里能输入」在灰系里也一眼看得见。
 *   首页那张卡片仍是蓝（人只点了品牌页）—— 想一起改灰，改下面那两行的令牌即可。
 * ★ 同日人再改（第三轮）：「这个动画效果是在外面又套了一层框，两层框之间就产生了白色的『空心』，
 *   变成了圆环套圆环的视觉…能否变成『实心』，形成阴影效果，这样就比较醒目，而且比较自然」——
 *   根因：我用 `box-shadow` 的 **spread** 画了一圈硬边（`0 0 0 3px 灰`），它落在元素自己那圈**浅色边框**
 *   之外，于是「浅边框 → 硬边灰环」读起来就是两层框、中间像空了一圈。
 *   现在改成：**不打硬边环**，峰值是一条**模糊阴影**（无 spread、有 y 偏移与 blur → 自然的上浮感），
 *   醒目度交给**元素自己的边框变深**（`--line` → `--invite-ring`，不透明、对比度 6~7:1）。
 *   于是视觉上是「一个框 + 它自己的阴影」，不是两个框。 */
input:not([type="file"]):not([type="hidden"]), textarea { caret-color: var(--accent); }
@keyframes composer-invite {
  0%, 100% { box-shadow: var(--invite-rest); border-color: var(--line); }
  50% { box-shadow: var(--invite-lift); border-color: var(--invite-ring); }
}
/* ⚠ 两页的落点**不一样**，这是刻意的（人 2026-09-22 纠过一次）：
 *   · 首页 `.composer` **就是那个输入框**（白底圆角卡片，里面的 input 是无边框的）→ 光晕打在卡片上，
 *     打在里面的 input 上会像浮着一个小方块；
 *     ⚠ 选择器精确到 `#home-input`：`.composer` 里曾有第二个 input（「官网地址」那个 `.tool-input`，人 2026-10-04 撤了），
 *       它一直是空的，用 `input:placeholder-shown` 会**永远命中**，「落笔呼吸就停」就不成立（探针抓到过）——别再放宽；
 *   · 品牌页 `.composer` 是**底部整条输入区**（含提示行、发送按钮），真正的文本框是 `.composer-input`。
 *     打在 `.composer` 上等于让**整条底栏的边框**在闪 —— 人看到的正是这个（「你改的不是文本输入框，
 *     而是输入框外面的区域边框」），所以这里必须打在 `.composer-input` 自己身上。
 * 判据把三件事都钉住了（tools/probes/composer-caret.mjs）：闪的是**那个可见的输入框**；
 *   品牌页那圈必须是**中性灰**；峰值**不许有硬边环**（first shadow 的 spread 必须为 0）
 *   且**模糊半径要起来**（≥ 12px）＋ 边框色对底色 ≥ 3:1 —— 这三条合起来就是「实心阴影、不是两层框」。 */
.composer:has(#home-input:placeholder-shown) {
  /* ★ 2026-09-22（人）：「为了体验一致性，首页输入框也调成类似的灰色动画效果吧」——两页同色（灰）。 */
  --invite-ring: var(--text-secondary);
  --invite-rest: var(--invite-rest-field);
  --invite-lift: var(--invite-lift-gray);
  animation: composer-invite 3.2s ease-in-out infinite;
}
.composer-input:placeholder-shown {
  --invite-ring: var(--text-secondary);
  --invite-rest: var(--invite-rest-field);
  --invite-lift: var(--invite-lift-gray);
  animation: composer-invite 3.2s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
  .composer:has(#home-input:placeholder-shown),
  .composer-input:placeholder-shown { animation: none; }
}

/* ── 按钮：四种（primary / secondary / ghost / danger），禁止图标按钮 ──── */
/* danger 是给「不可逆」的动作用的（例：「确定停下」打断正在跑的一轮）——先提示后确认，别拿它当强调色 */
.btn {
  border: 1px solid var(--accent);
  background: var(--accent);
  color: var(--accent-on);
  border-radius: var(--radius-sm);
  padding: 7px 14px;
  font-size: var(--fs-card);
  line-height: 1.2;
}
.btn:hover { filter: brightness(0.96); }
.btn:disabled { opacity: 0.5; cursor: not-allowed; filter: none; }

.btn.secondary {
  background: var(--card);
  color: var(--accent);
  border-color: var(--accent);
}
.btn.ghost {
  background: transparent;
  color: var(--text-secondary);
  border-color: transparent;
  padding: 6px 8px;
}
.btn.ghost:hover { color: var(--text-primary); background: var(--bg); }

.btn.danger {
  background: var(--danger);
  border-color: var(--danger);
  color: var(--danger-on);
}

.btn.sm { padding: 4px 10px; font-size: var(--fs-note); }

/* ── 卡 ────────────────────────────────────────────────────────────── */
.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-card);
  padding: 12px 14px;
  margin-bottom: 10px;
}
.card > h2 {
  margin: 0 0 8px;
  font-size: var(--fs-card);
  font-weight: 600;
}

/* ── callout：诚实态与失败的容器（四种语气） ─────────────────────── */
.callout {
  border-radius: var(--radius-sm);
  padding: 8px 10px;
  font-size: var(--fs-note);
  margin: 8px 0;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--text-secondary);
}
.callout-neutral { background: var(--bg); }
.callout-warning { background: var(--warning-bg); border-color: var(--warning); color: var(--warning); }
.callout-danger  { background: var(--danger-bg);  border-color: var(--danger);  color: var(--danger); display: flex; align-items: center; gap: 10px; }

/* ── 通用文字类 ───────────────────────────────────────────────────── */
.muted    { color: var(--text-secondary); font-size: var(--fs-note); }
.tertiary { color: var(--text-tertiary); }
.num      { font-variant-numeric: tabular-nums; }
.term-doubtful { color: var(--warning); }

.stats { display: flex; flex-wrap: wrap; gap: 18px; margin: 6px 0 10px; }
.stat { display: flex; flex-direction: column; gap: 2px; }
.stat-label { font-size: var(--fs-meta); color: var(--text-tertiary); }
.stat-value { font-size: var(--fs-body); }
.stat-row { display: flex; flex-wrap: wrap; gap: 14px; }

/* ── Chip：全站唯一数字渲染器（七态） ────────────────────────────────
 * 视觉映射复现自规格:44-52 + 交接:85-91。
 * 类名 `chip chip-<state>` 与 data-state / data-source 不可改（交接:93）。
 * ─────────────────────────────────────────────────────────────────── */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  border-radius: var(--radius-sm);
  padding: 0 6px;
  line-height: 18px;
  font-size: var(--fs-note);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.chip sup { font-size: 9px; opacity: 0.8; }

.chip-real   { background: var(--bg); color: var(--text-primary); font-weight: 600; }
.chip-brand  { background: var(--bg); color: var(--text-primary); font-weight: 600; position: relative; }
.chip-brand::after {
  content: "";
  position: absolute;
  top: 0; right: 0;
  width: 4px; height: 4px;
  border-radius: 50%;
  background: var(--accent);
}
.chip-assumed { background: transparent; color: var(--text-secondary); font-weight: 500; border-bottom: 1px dashed var(--text-tertiary); border-radius: 0; }
.chip-missing,
.chip-not_computable,
.chip-pending_decision {
  background: transparent;
  color: var(--text-tertiary);
  font-style: italic;
  border: 1px dashed var(--line);
}
.chip-draft { background: transparent; color: var(--text-secondary); border: 1px solid var(--line); }

.desk-nav { display: inline-flex; gap: 6px; margin: 0 8px; }

/* ── logo 那一行（首页左栏 + 工作台左栏**共用这一条**；尺寸照 DSH GUI 的 .logoRow） ──
 * 行 = [品牌（真链接，占满剩余宽度）] + [收起/打开侧边栏的圆形图标按钮]。
 * 与 GUI 一致：`.logoRow{justify-content:flex-end}` + `.brand{flex:1}` → 按钮落在**行右端**。
 * 高 `--brand-row-h`（GUI 60px）、左内边距 `--brand-row-pad`（GUI 4px）；再叠上左栏的 `--side-pad`
 * → **logo 的横向落点 = 16px**（两页同源）。
 * ⚠ 悬停不加任何下划线（人 2026-09-21：「鼠标在 logo 上方时，不要出现任何下划线」）——
 *   所以既没有 :hover 的下划线规则，`text-decoration: none` 也不带任何状态例外。 */
.side-brand-row {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  flex: none;
  height: var(--brand-row-h);
  padding-left: var(--brand-row-pad);
  margin-bottom: 8px;                 /* 与 GUI 的 .logoRow 一致 */
  overflow: hidden;
}
.side-brand {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  overflow: hidden;
  font-size: var(--fs-brand);
}
a.side-brand { color: inherit; text-decoration: none; }
.side-brand strong { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* ── 图标按钮：照 DSH GUI 的 `.iconButton`（28×28 圆形、内边距 6px、图标 15px、悬停有底色） ──
 * ★ 2026-09-21（人）：「3080 那个页面右上角也有一个『打开/收起边栏』按钮，图形与左侧边栏里那个
 *   类似但 icon 是左右镜像的。请参考这个设计：①『产物面板』按钮完全模仿它；②右栏的 ✕ 关闭按钮
 *   也用这个设计」——三处（左栏收起 / 产物面板 / 面板关闭）**共用这一条**，谁也不许再写一遍。
 *   数值照 GUI：width/height 28、border-radius 28（圆）、padding 6、svg 15×15、
 *   hover 背景、focus-visible 描边（GUI 用 Tooltip，我们用原生 title，见各自的 markup）。 */
.icon-btn {
  width: 28px; height: 28px;
  flex: none;
  display: inline-flex; justify-content: center; align-items: center;
  padding: 6px;
  border: 0; border-radius: 28px;
  background: transparent;
  color: var(--text-tertiary);
  cursor: pointer;
  line-height: 1;
}
.icon-btn svg { width: 15px; height: 15px; display: block; }
.icon-btn:hover { background: var(--bg); color: var(--text-primary); }
.icon-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* 镜像：同一个图标换朝向（GUI 就是这么做的：`.icon{transform:scaleX(-1)}`）——
 * 右侧栏 / 右面板用镜像那份。**不要**为此再画一份 SVG：镜像是同一个形状的两种朝向，
 * 两份路径迟早会左右不一致（判据：test/icon-buttons.test.mjs 逐字比路径）。 */
.icon-flip-x { transform: scaleX(-1); }

/* 收起 / 打开左栏那个按钮：底座是 `.icon-btn`（markup 里两个 class 一起写），
 * 这里只留它**自己的**差异 —— 收起态的尺寸与「悬停时把品牌图标换成面板图标」。
 * ⚠ 原先这一条把 28×28/圆形/悬停底色都写了一遍：那就是第二份定义，已经挪进 `.icon-btn`。 */
.side-toggle { flex: none; }
/* 展开态：按钮里画的是「面板」图标；品牌图标那半只在收起态露出来 */
.side-toggle-mark { display: none; }
.side-toggle-panel { display: block; }

/* ── 左栏收起态（人 2026-09-21：照 GUI 「logo 右侧那个图标」） ──
 * 状态只有一处：`<html data-side="collapsed">`（由 side-toggle.js 直接改，**不重渲染**）。
 * 宽度换成 --side-actual（网格规则不用改）；logo 行照 GUI 的 .collapsed：36px 高、
 * 左内边距归零；**品牌链接整块不渲染**，36×36 那个按钮里装的是品牌图标（悬停才换成面板图标）
 * ——不这么做的话「图标 + 按钮」在 36px 宽的轨道里放不下（实测溢出到 x=78）。 */
html[data-side="collapsed"] { --side-actual: var(--side-w-collapsed); }
html[data-side="collapsed"] .side-brand-row { justify-content: flex-start; height: 36px; margin-bottom: 12px; padding: 0; }
html[data-side="collapsed"] .side-brand { display: none; }
html[data-side="collapsed"] .side-toggle { width: 36px; height: 36px; color: var(--text-primary); }
html[data-side="collapsed"] .side-toggle-mark { display: inline-flex; }
html[data-side="collapsed"] .side-toggle-panel { display: none; }
html[data-side="collapsed"] .side-toggle:hover .side-toggle-mark { display: none; }
html[data-side="collapsed"] .side-toggle:hover .side-toggle-panel { display: block; }
html[data-side="collapsed"] .side-copyright { display: none; }

/* ── 品牌图标（官网 logo 的蓝黑色 icon 部分）：首页左栏与工作台左栏**共用这一条** ──
 * ★ 2026-09-22（人）：「读一下 www.kingyu.ai 官网的 logo 信息，官网 logo 里面蓝黑色的 icon 部分。
 *   将现有擎天柱网站 logo 的『倾 icon』换成该 icon，要求尺寸仍保持原『倾』icon 的大小」——
 *   所以这里不再是「写着产品名首字的深色方块」，而是**官方图标本体**（components/BrandIcon.js）：
 *   盒子尺寸**不变**（22×22，与原「倾」方块一致），图标按 viewBox 铺满整个盒子 ✓。
 *   ⚠ 原先那套「深色底 + 白字 + 圆角」的样式随那个字一起删了：留着就是给「再放一个字母回去」留门。 */
.side-logo {
  display: grid; place-items: center;
  width: 22px; height: 22px;
}
.side-logo svg { display: block; width: 100%; height: 100%; }

/* 官方图标那两片的颜色（取上面的品牌色令牌；图标里不写死色值） */
.bm-cyan { fill: var(--brand-cyan); }
.bm-navy { fill: var(--brand-navy); }

/* ── 「深色系 / 浅色系」那颗小图标按钮（人 2026-09-22） ──────────────────
 * 按钮本体在 components/ThemeToggle.js；这里只管**按当前色系显示哪一枚图标**：
 *   浅色系 → 显示月亮（点它进深色）；深色系 → 显示太阳（点它回浅色）。
 * ⚠ 两枚都在 DOM 里、用 CSS 切显示：重绘不会把状态冲掉，JS 也不必改 DOM（只管 <html data-theme>）。
 * 位置：首页右上角（「开发档账号」左边）、品牌页任务栏「产物面板」按钮左边。 */
.theme-toggle .theme-to-dark, .theme-toggle .theme-to-light { display: none; }
.theme-toggle .theme-to-dark, .theme-toggle .theme-to-light { align-items: center; justify-content: center; }
/* 不能写 `:not([data-theme="dark"]) …`：深色下 <body> 等祖先也匹配 :not，月亮照样亮、两枚同时出现 */
.theme-toggle .theme-to-dark { display: inline-flex; }
[data-theme="dark"] .theme-toggle .theme-to-dark { display: none; }
[data-theme="dark"] .theme-toggle .theme-to-light { display: inline-flex; }

/* ── 「中 / EN」那颗（人 2026-09-22：加在色系图标**左侧**）──────────────────
 * 按钮是文字标签（不是 svg），所以单独给字号/字重；两枚标签都在 DOM 里，按 <html data-lang> 切显示。
 * 显示的是**点它会切到**的那个语言：中文界面显示 EN、英文界面显示 中。 */
.lang-toggle .lang-mark { display: none; font-size: 11px; font-weight: 700; letter-spacing: .02em; }
html:not([data-lang="en"]) .lang-toggle .lang-to-en { display: inline; }
html[data-lang="en"] .lang-toggle .lang-to-zh { display: inline; }

/* ── 左栏底部的版权行（首页左栏 + 工作台左栏**共用这一条**；人 2026-09-21 要求加） ──
 * 两个页面的左栏都是 flex 列，所以 `margin-top: auto` 把它顶到底部；
 * `position: sticky; bottom: 0` 让左栏内容超长（要滚动）时它也留在视野里——贴住时用
 * `background: inherit` 盖住下面滚过去的内容（左栏底色两页不同：首页 #fff / 工作台 --side-bg，
 * 所以用 inherit，不写死一个色）。
 * ⚠ 文案只在 `domain.js` 的 `PLATFORM.copyright` 定义一次，两个页面都从它派生。
 * 工作台左栏折叠态（44px）放不下它，由 `layout.css` 隐藏。 */
.side-copyright {
  margin: auto 0 0;
  padding: 10px 4px 2px;
  position: sticky;
  bottom: 0;
  background: inherit;
  font-size: var(--fs-meta);
  color: var(--text-tertiary);
  text-align: center;
}
