/* ── 字体:自托管,不外链 ─────────────────────────────────────────────
 *
 * 设计稿(`Zetta Agent 工作台.dc.html`)在 `<head>` 里挂了一条 Google Fonts
 * 的 css2 链接,点名两个族:IBM Plex Sans SC(400/500/600/700)与
 * IBM Plex Mono(400/500/600)。
 *
 * 这个仓不许外链字体(`test_不引外部字体`)—— 控制台不依赖外部主机。
 * 那条判据是**整文件的子串匹配,注释也算**:所以这一段只说服务名,
 * 不抄主机名。写宽一格,一条注释掉的外链就能溜过去。
 * 所以把 woff2 放进仓库自己发。IBM Plex 是 OFL,可以自托管。
 *
 * ## 照着取的时候发现的一件事:**Google 根本不发 IBM Plex Sans SC**
 *
 * 拿设计稿那条链接原样去取,回来的 CSS 里**只有 IBM Plex Mono**;
 * 单独按 SC 那个族名去取,回的是 400 错误页,不是 CSS。
 * 也就是说 —— **设计稿自己的中文一直是 system-ui 在画**(Mac 上是苹方),
 * 那条 SC 从来没生效过。
 *
 * 记在这里是为了别再被「修」一次:往 `index.html` 里补一条外链
 * 既过不了判据、也不会让中文变样,只是把「没生效」藏起来。
 *
 * 于是这里的做法:
 *
 *     'IBM Plex Sans SC'   留在栈首 —— 谁本机装了就用他的,不装就跳过
 *     'IBM Plex Sans'      自托管(latin / latin-ext)。屏上大量的 id、
 *                          英文标签、数字走它 —— 这一半是设计稿真要的 Plex
 *     system-ui            中文落到它,与设计稿今天渲染出来的样子一致
 *
 * ## 两个族的文件数不一样,不是漏了
 *
 * Sans 在 Google 上是**可变字体**:400/500/600 三个字重回的是同一个文件
 * (三份 sha256 一模一样,量过)。所以只存一份,`font-weight: 400 600`
 * 由浏览器插值。Mono 是静态的,三个字重三份文件。
 *
 * 只留 latin + latin-ext 两个子集:这一屏没有西里尔与越南文,
 * 存进来也不会有人下载,只是让仓库大一圈。
 */

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  /* 可变字体:一份文件盖住我们用到的三档字重。 */
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-var-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  /* 可变字体:一份文件盖住我们用到的三档字重。 */
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-var-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-400-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-400-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-500-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-500-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-600-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-600-latin-ext.woff2') format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* Zetta 业务面 —— **照搬业主 2026-09-01 的 Claude Design 设计稿。**
 *
 * 源:`Zetta Agent 工作台.dc.html`(项目 d4114f0b)。业主的话:
 *
 * > 我就需要你直接照搬我在 Claude Design 里面的整体的业务层的架构和流程。
 * > 你不要有自己的发挥,你就直接照搬就可以了。
 *
 * 所以这份样式表的取值**逐个来自设计稿的内联 style**,不是我按控制台
 * 那套 token 换算的。控制台其余各页是冷灰的后台(`tokens.css`);
 * 业务面是另一套暖白 —— 两套并存,不互相覆盖。
 *
 * ## 为什么单开一个文件,不并进 tokens.css
 *
 * 并进去的话,两套 token 会在同一个 `:root` 上打架:设计稿的
 * `#E0DCD2` 与控制台的 `--c-line` 是同一件事的两个值,谁后写谁赢,
 * 而那是**按文件顺序**决定的 —— 加一行 CSS 就可能换掉半个控制台的分割线。
 *
 * ## 2026-09-02:反过来了 —— 这一份升成全站的色板
 *
 * 业主:
 *
 * > 这个页面实际上也要跟那个 Chat 页面变成整体一样的风格……
 * > 包括风格上、数据资源上、整体流程管控上,都可以沿用业务层那套。
 *
 * 上面那段担心的是「**两套各写各的值**」—— 那个担心是对的,而解法不是
 * 把其中一套锁起来,是让**只有一处出处**:这一份定颜色,
 * `tokens.css` 的 `--c-*` 一律写成 `var(--zt-*)`,不再自己写色号。
 *
 * 于是同一件事只有一个值,谁先谁后都一样(CSS 自定义属性在**用的时候**
 * 才解析,不按文件顺序)。而「同一个颜色两处写着两个值」这件事 ——
 * 这个仓最熟的那种缺陷 —— 从根上没有了。
 *
 * 所以作用域从 `.zt` 提到 `:root`。判据 `test_两套色板只有一处出处`
 * 钉着 `tokens.css` 里不许再出现色号。
 */

/* ── 设计稿用到的颜色,按出现次数排 ────────────────────────────────────
 *
 * 名字取自它在设计里干的事,不是色号本身 —— `--zt-line` 改成别的颜色时
 * 用它的地方不用跟着改名。
 */
:root {
  --zt-ink: #EAF0F6;          /* 正文 */
  --zt-ink-2: #C6D0DA;        /* 侧栏正文 */
  --zt-ink-3: #96A3B0;        /* 次级 */
  /* 说明文字。**2026-09-14 压深了一档**（#767C84 → #646970）：
     它是「要读的」那一档（标签、ID、说明），而在最深的那个底
     （#EBE8E0，侧栏与顶栏）上只有 3.44 —— 10–12px 的字压在 3.44
     上是真读不清。压到 4.52 刚过 AA，正文与次级那两档没动，
     所以层级还是 13.25 / 6.65 / 4.52 / 2.55 四级。 */
  /* **设计稿给的是 #75828E,提到 #7D8994。**（2026-09-15 换底盘时实测）
   *
   * 交接包 README 自己写着「结构性文字对比度 ≥ 4.5」,而 #75828E 压在它
   * 自己的抬升层上只有 **4.12**(`--zt-tint`)、4.36(`--zt-white`)、
   * 4.45(`--zt-tint-2`)—— 三处不到线。这一档是「要读的」那三档之一
   * (说明文字、表格次级字),不是记号。
   *
   * 同色相只提亮度,最差底上 4.12 → 4.54;四档的深浅顺序没变、也没并档
   * (`test_极弱那一档还在_四档没并成三档` 钉着)。
   * **这一条要回给设计那一侧** —— 他们那份 token 表里也该改。 */
  --zt-mute: #7D8994;
  --zt-mute-2: #59646E;       /* 未选中的页签 */
  --zt-accent: #4FB8E8;       /* 主色:Z 标、主按钮、链接 */
  --zt-hud: #46E6CE;          /* HUD 大盘专用高亮青 —— 只给发光/仪表环 */
  --zt-hud-dim: #1B4A45;      /* HUD 青的暗档:仪表空槽、弱发光 */
  --zt-accent-wash: #0E2530;  /* 主色浅底 */
  --zt-accent-line: #1C4356;  /* 主色浅边 */
  --zt-line: #1F272F;         /* 分割线 */
  --zt-line-2: #2C3641;       /* 按钮边 */
  --zt-line-3: #171E25;       /* 侧栏分割 */
  --zt-canvas: #0B0F14;       /* 整屏底 */
  --zt-panel: #11161C;        /* 主区底 */
  --zt-side: #080B10;         /* 侧栏底 */
  --zt-tint: #1A212A;         /* 选中态 / 人说的话的底 */
  --zt-tint-2: #141A21;       /* 更浅的分块底 */
  --zt-warn: #E0A63C;         /* 提醒字 */
  --zt-warn-line: #4A3917;
  --zt-warn-wash: #211A0C;
  --zt-warn-2: #B3822A;
  --zt-bad: #E4705B;          /* 失败 */
  --zt-white: #161C23;

  /* ── 2026-09-02 从 tokens.css 收上来的几档 ─────────────────────────
   *
   * 它们原来在控制台那一份里自己写着色号。收上来是为了让
   * **「同一个颜色只有一个值」成为绝对的** —— 留一个在那边,
   * 下次调色就又是两处各调各的。
   */
  --zt-accent-deep: #8FD5F5;   /* 主色更深:hover、主色底上的字 */
  --zt-accent-mid: #2E7898;    /* 主色中调:第二色、条形 */
  --zt-bad-wash: #291411;      /* 失败的浅底 */

  /* ── 2026-09-02 第二轮:**令牌文件自己**的 `:root` 之外还写着 19 处 ──
   *
   * 上一轮把 `tokens.css` 的色号一律换成 `var(--zt-*)`,判据也钉住了
   * 那一份 —— 而**没有任何东西量这一份自己**。于是这个文件的规则体里
   * 一直留着 19 处字面色号,判据全绿。量程放宽见
   * `test_色号只许写在root里`:任何一份控制台样式表的 `:root` 之外
   * 都不许出现色号。
   *
   * `#183A53` 本来就是 `--zt-accent-deep`,直接换成引用。下面这几个
   * 原来没有名字 —— 按它在设计里干的事命名,不按色号。
   */

  /* **纯白,不是 `--zt-white`(#FFFDF7)。** 两个都是「白」,值不一样,
   * 而它们压在不同的东西上:`--zt-white` 是暖白的**面**(输入框、证据块),
   * 这两个是设计稿在实色底上用的**正白**。合并会动到屏上的样子,
   * 所以各留各的 —— 名字说清各自干什么,不留给下一个人猜。 */
  --zt-on-accent: #0B121B;        /* 主色/实色底上的字 */
  --zt-panel-hi: #1D2836;         /* 抬高一层的底:产物栏、编辑器顶栏、质检右栏 */

  --zt-rail: #121A25;          /* 左轨底:编辑器的原语列、质检的任务列 */
  --zt-avatar: #2A3648;        /* 头像底:没有头像时那颗写着字的圆 */
  /* **与上面的 `--zt-bad-wash`(#F7EBE8)是同一个角色的两个值。**
   * 控制台那半边(`--c-danger-wash`:停用标签、超期提示)走 #F7EBE8,
   * 业务面这半边(失败角标、坏读数、回溯里那一行、diff 的旧值)走 #FDF7F6。
   * 两个值都是设计里真在用的,收成一个是**改样子**,不在这一轮的范围里 ——
   * 先都摆到 `:root` 上,让「一个角色两个值」看得见,而不是散在四条规则里。 */
  --zt-bad-wash-2: #231311;    /* 失败的浅底,更淡的一档 */
  --zt-code-wash: #111A26;     /* 等宽块的底:代码、diff 的新值 */
  --zt-code-ink: #9BD0F2;      /* 等宽块的字 */

  /* 三层各一色。**层是语义,不是装饰** —— 同一层的东西在任何一页上
   * 都得是同一个颜色,不然人得靠位置去认层。 */
  --zt-layer-data: var(--zt-accent-mid);
  --zt-layer-analy: var(--zt-accent);
  --zt-layer-exp: var(--zt-warn);
  /* 条形里「没有语义」的那一段 —— 与暖灰底同族,不用冷灰。 */
  --zt-bar-neutral: #2E3842;
  /* SC 在栈首是「装了就用」—— Google 不发它,见文件头。 */
  --zt-sans: 'IBM Plex Sans SC', 'IBM Plex Sans', system-ui, sans-serif;
  --zt-mono: 'IBM Plex Mono', ui-monospace, monospace;
}

/* ── 整屏 ────────────────────────────────────────────────────────────
 *
 * 设计稿是 1440×900 的定尺画板;这里是真界面,所以宽高吃满可用空间,
 * 别的(内边距、字号、行高、圆角)照抄。
 */
/* **吃满主区的高度。** `flex:1` 只在父级是 flex 容器时有用,而这一屏
   有时挂在普通块里(`.main` 不是 flex)—— 那时它按内容高,底下空一大片。
   `height:100%` 两种情况都成立。`.chatpage` 早有同一条先例。 */
.zt { display: flex; flex: 1 1 auto; height: 100%; min-height: 0;
      background: var(--zt-canvas); color: var(--zt-ink);
      font-family: var(--zt-sans); font-size: 13px; line-height: 1.5; }
.zt a { color: var(--zt-accent); text-decoration: none; }
.zt a:hover { color: var(--zt-accent-deep); text-decoration: underline; }

/* ── 左侧栏 196px ────────────────────────────────────────────────── */
.zt-aside { width: 196px; flex-shrink: 0; background: var(--zt-side);
            border-right: 1px solid var(--zt-line-3);
            display: flex; flex-direction: column;
            padding: 14px 12px; color: var(--zt-ink-2); min-height: 0; }
.zt-brand { display: flex; align-items: center; gap: 9px; padding: 2px 4px 14px; }
.zt-mark { width: 24px; height: 24px; border-radius: 5px;
           background: var(--zt-accent); color: var(--zt-canvas);
           display: grid; place-items: center;
           font-weight: 600; font-size: 13px; font-family: var(--zt-mono); }
.zt-brand-name { font-weight: 600; font-size: 14px; }
.zt-new { border: 1px solid var(--zt-line-2); background: var(--zt-panel);
          color: var(--zt-ink-2); border-radius: 8px; padding: 8px 10px;
          font-family: inherit; font-size: 12.5px; font-weight: 500;
          cursor: pointer; text-align: left; }
.zt-new:hover { border-color: var(--zt-accent); color: var(--zt-accent); }
.zt-sec { font-size: 11px; color: var(--zt-mute); padding: 14px 4px 6px;
          letter-spacing: .04em; }
.zt-sess { flex: 1 1 auto; min-height: 0; overflow: auto;
           display: flex; flex-direction: column; gap: 2px; }
.zt-sess-item { border: 0; background: none; text-align: left; cursor: pointer;
                border-radius: 7px; padding: 7px 8px; font-family: inherit;
                color: var(--zt-ink-2); display: flex; flex-direction: column; gap: 2px; }
.zt-sess-item:hover { background: var(--zt-tint); }
.zt-sess-item[aria-current="page"] { background: var(--zt-tint); }
.zt-sess-t { font-size: 12.5px; font-weight: 500;
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zt-sess-s { font-size: 11px; color: var(--zt-mute);
             overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.zt-foot { border-top: 1px solid var(--zt-line-3); margin-top: 10px;
           padding-top: 10px; display: flex; flex-direction: column; gap: 5px;
           font-size: 11px; color: var(--zt-mute); }
.zt-me { display: flex; align-items: center; gap: 7px; padding-top: 10px;
         font-size: 12px; color: var(--zt-ink-2); }
.zt-me-av { width: 22px; height: 22px; border-radius: 99px;
            background: var(--zt-avatar); color: var(--zt-ink-2);
            display: grid; place-items: center; font-size: 10.5px; font-weight: 600; }

/* ── 主区 ────────────────────────────────────────────────────────── */
.zt-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column;
           min-height: 0; }
/* 科学家那一屏:**一列**。2026-09-07 撤掉右边那半屏(检索)之后，
   对话独占整块 —— 拿 `.zt-two` 装一个孩子的话，右边会空出 472px。 */
.zt-one { flex: 1 1 auto; min-height: 0; display: grid;
          grid-template-columns: minmax(0, 1fr); }
/* 模式一「检索」:左对话 + 右产物 472px。设计稿原样。 */
.zt-two { flex: 1 1 auto; min-height: 0; display: grid;
          grid-template-columns: minmax(0, 1fr) 472px; }
/* **窄屏收掉右栏。** 472px 压不下去 —— 里面是表格与证据段落,
   压扁之后每一行都要横着滚,不如整块收起。 */
@media (max-width: 1120px) { .zt-two { grid-template-columns: minmax(0, 1fr); }
                             .zt-prod { display: none; } }

.zt-col { min-width: 0; display: flex; flex-direction: column;
          background: var(--zt-panel); min-height: 0; }
.zt-head { height: 50px; flex-shrink: 0; display: flex; align-items: center;
           gap: 10px; padding: 0 20px; border-bottom: 1px solid var(--zt-line);
           background: var(--zt-panel); }
.zt-head-t { font-weight: 600; font-size: 13.5px; white-space: nowrap; }
/* **头这一行不换行。** 换行的话 50px 的头被顶高,下面整列跟着错位 ——
   而顶出来的那个东西通常是个 id,它除了「哪一场」之外不承载信息。 */
.zt-head { white-space: nowrap; }
.zt-head-s { overflow: hidden; text-overflow: ellipsis; }
.zt-chip { font-size: 11px; padding: 2px 8px; border-radius: 999px;
           background: var(--zt-tint); color: var(--zt-ink-3);
           font-family: var(--zt-mono); }
.zt-grow { flex: 1; }
.zt-head-s { font-size: 12px; color: var(--zt-mute); }

/* 对话流 */
.zt-flow { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 16px 20px;
           display: flex; flex-direction: column; gap: 14px; }
/* 人说的话:右对齐的气泡 */
.zt-said { align-self: flex-end; max-width: 80%; background: var(--zt-tint);
           border: 1px solid var(--zt-line); border-radius: 12px 12px 4px 12px;
           padding: 10px 13px; }
/* 平台答复:左侧 Z 标 + 正文 */
.zt-turn { display: flex; gap: 11px; }
.zt-av { width: 24px; height: 24px; flex-shrink: 0; border-radius: 6px;
         background: var(--zt-accent); color: var(--zt-canvas);
         display: grid; place-items: center; font-weight: 600; font-size: 12px;
         font-family: var(--zt-mono); }
.zt-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 10px; }
.zt-acts { display: flex; gap: 7px; flex-wrap: wrap; font-size: 12px; }
.zt-act { border: 1px solid var(--zt-line-2); background: var(--zt-panel);
          color: var(--zt-ink-2); border-radius: 7px; padding: 5px 11px;
          font-family: inherit; font-size: 12px; cursor: pointer; }
.zt-act:hover { border-color: var(--zt-accent); color: var(--zt-accent); }

/* 两个入口那两颗钮（2026-09-10）。**选中那一颗不能只靠颜色区分** ——
   色觉差异之外，边框加粗与底色一起变，读屏那边靠 aria-pressed。 */
.zt-modes { display: flex; flex-direction: column; gap: 5px; margin-bottom: 8px; }
.zt-modes .zt-act[data-on="1"] {
  border-color: var(--zt-accent); color: var(--zt-on-accent);
  background: var(--zt-accent); font-weight: 600;
}
.zt-modes .zt-act[data-on="1"]:hover { background: var(--zt-accent-deep);
                                        color: var(--zt-on-accent); }
.zt-act[data-main="1"] { background: var(--zt-accent); border-color: var(--zt-accent);
                         color: var(--zt-on-accent); font-weight: 600; }
.zt-act[data-main="1"]:hover { background: var(--zt-accent-deep);
                              color: var(--zt-on-accent); }

/* ══ 结构收拾（2026-09-11，业主：「两个入口看着结构非常乱，布局不清晰」）══
   
   三件事，都不是换皮：
   
   ① **两颗钮读起来要像一个开关，不像两句话。** 原来它们是两颗松散的
      小钮 + 一行与正文同色的说明，夹在对话与输入框之间 —— 读起来像
      又一段内容，而它其实是**这一屏最重要的那个选择**。收成一个
      分段控件（连体、共用一圈边框、选中那半有底色）。
      **选中态仍旧不只靠颜色**：字重与底色一起变，读屏那边靠 aria-pressed。
   
   ② **正文要有行宽。** 满宽 1400px 的中文正文一行能排七八十个字，
      眼睛回到行首会找错行。给对话正文一个阅读宽度（已有的
      `--zt-reading` 变量本来就在这一屏上，只是没用到正文上）。
   
   ③ **一问一答要分得出层次。** 原来进度、问题、依据、抽屉全是同一号字
      平铺，看不出谁统属谁。给引导那一块一条左边线 + 缩进，
      让「这几行是同一件事」在余光里就成立。 */

/* ① 进门两条路 —— 两张并排的卡片（2026-09-11，业主：开关「偏、不好用」）
   在这之前是一个 segmented 开关 + 底下一句说明。改成卡片：每张自己带说明，
   当前那张描边高亮 + 一句「现在走这条」。两卡等宽，窄屏落成上下两张。 */
.zt-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 10px;
            margin-bottom: 12px; }
.zt-door {
  text-align: left; font-family: inherit; cursor: pointer;
  display: flex; flex-direction: column; gap: 4px;
  background: var(--zt-white); border: 1px solid var(--zt-line-2);
  border-radius: 12px; padding: 12px 14px;
  transition: border-color .15s ease, box-shadow .15s ease, transform .1s ease;
}
.zt-door:hover { border-color: var(--zt-accent);
                 box-shadow: 0 2px 10px rgba(36, 80, 110, .08); }
.zt-door:active { transform: translateY(1px); }
/* 当前那张：描边 + 一圈浅色光环 —— 不只靠底色，读屏另有 aria-pressed。 */
.zt-door[data-on="1"] { border-color: var(--zt-accent); background: var(--zt-panel);
                        box-shadow: 0 0 0 3px var(--zt-accent-line); }
.zt-door:disabled { opacity: .5; cursor: not-allowed; }
.zt-door:disabled:active { transform: none; }
.zt-door-t { display: flex; align-items: baseline; gap: 8px;
             font-size: 14px; font-weight: 600; color: var(--zt-ink); }
.zt-door-now { font-size: 11px; font-weight: 600; color: var(--zt-accent);
               white-space: nowrap; }
.zt-door-d { font-size: 12px; line-height: 1.55; color: var(--zt-mute); }
@media (max-width: 640px) { .zt-modes { grid-template-columns: 1fr; } }

/* 肽设计「工单预览」—— 边填边成形的一张小卡（2026-09-11，业主的工单助手方向）。
   填了的显值、正在问的高亮、没填的说待填；底下一句进度。 */
.zt-ticket { border: 1px solid var(--zt-line); border-radius: 12px;
             background: var(--zt-panel); padding: 12px 14px; margin: 8px 0; }
.zt-ticket-h { display: flex; align-items: baseline; justify-content: space-between;
               gap: 10px; margin-bottom: 6px; }
.zt-ticket-t { font-size: 12px; font-weight: 600; letter-spacing: .03em;
               color: var(--zt-ink-3); text-transform: uppercase; }
.zt-ticket-prog { font-size: 12px; color: var(--zt-ink-3); }
.zt-ticket-rows { display: flex; flex-direction: column; }
.zt-ticket-row { display: flex; align-items: baseline; justify-content: space-between;
                 gap: 12px; padding: 6px 0; border-bottom: 1px dashed var(--zt-line); }
.zt-ticket-row:last-child { border-bottom: 0; }
.zt-ticket-lab { font-size: 12.5px; color: var(--zt-ink-3); flex: 0 0 auto; }
.zt-ticket-val { font-family: var(--zt-mono, ui-monospace, Menlo, monospace);
                 font-size: 12.5px; text-align: right; min-width: 0;
                 overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 填了 = 正文色；正在问 = 主色加粗；待填 / 可回头补 = 灰。 */
.zt-ticket-row[data-t="填了"] .zt-ticket-val { color: var(--zt-ink); }
.zt-ticket-row[data-t="问"]   .zt-ticket-val { color: var(--zt-accent); font-weight: 600; }
.zt-ticket-row[data-t="问"]   .zt-ticket-lab { color: var(--zt-accent); }
.zt-ticket-row[data-t="待填"] .zt-ticket-val { color: var(--zt-mute); }

/* 有限选项做成 chips —— 点一下就填（2026-09-12，业主）。一排药丸钮，
   点一下把那个词当答案提交；想自己写的仍旧用底下那个框打字。 */
.zt-chips { display: flex; flex-wrap: wrap; gap: 7px; margin: 6px 0 4px; }
.zt-chip { border: 1px solid var(--zt-line-2); background: var(--zt-white);
           border-radius: 16px; padding: 5px 13px; font-size: 12.5px;
           color: var(--zt-ink); cursor: pointer; font-family: inherit;
           transition: border-color .15s ease, color .15s ease, transform .1s ease; }
.zt-chip:hover { border-color: var(--zt-accent); color: var(--zt-accent); }
.zt-chip:active { transform: translateY(1px); }

/* ② 正文行宽 —— 只管对话正文，不动表格与命中行（那两样本来就要宽）。 */
.zt-query .zt-answer, .zt-query .zt-turn > .zt-body > .s,
.zt-query .zt-turn > .zt-body > .m { max-width: var(--zt-reading); }

/* ③ 引导那一块：一条左边线把「同一件事」圈起来。
   落在 `zt-ask` 上 —— 它是「进度 + 这一问 + 依据 + 抽屉」的容器。
   （**订正**：这儿一度写着「问什么归 `askbox` 一处」——
   那一版 13 条判据当场红，当天就撤了。必答那两问的问句与框在
   `chat.js::派活那一块`，`askbox` 只在那一支印进度与依据。） */
.zt-query .zt-ask {
  border-left: 2px solid var(--zt-line-2); padding-left: 14px;
  margin-top: 10px !important; gap: 6px !important;
}
/* 正文行宽 **落在容器上**，不逐个管子元素 —— 子元素那一路我先写过，
   边线出来了而宽度没生效（多半被更具体的一条盖住）。管容器一定管得住，
   而且新加的子块自动就有行宽，不用记得再补一条。
   输入框照旧占满容器（它要填字，不是读字）。 */
.zt-query .zt-ask { max-width: calc(var(--zt-reading) + 16px); }
.zt-query .zt-ask .capsearch { width: 100%; }
/* 「这一问」比进度那一行重一档 —— 用字重与颜色分，不靠字号跳。
   **按名字认，不按位置认**：这一行在「让位」那一支整行不画，
   按 `nth-child(2)` 认的话这一档字重会落到「依据」上（屏上看着像好的）。 */
.zt-query .zt-ask > .zt-ask-q { color: var(--zt-ink); font-weight: 600; }
/* 抽屉的标题降一档 —— 它是「要用时再看」，不该跟当前那一问抢。 */
.zt-query .chat-ask-options > summary { font-size: 12px; color: var(--zt-mute); }
.zt-query .chat-ask-options[open] > summary { margin-bottom: 6px; }

/* ④ 「该你了」——一句话底下，把要他动手的圈成一块（2026-09-11）

   业主：「两个入口……看着结构非常乱，整体布局也不是特别清晰」。
   他自己说的每一句底下平铺着五块同级的东西（需求单表 · 进度与依据 ·
   先查一眼 · 命中表 · 这一轮的账），五块一样重，
   于是**「哪一块在等我」看不出来**。

   按**谁动手**分层，不按块的种类分：要他动手的两块圈进来，
   给他看的（先查一眼、命中表）留在流水里不折
   —— 「命中的材料就是那句答案本身」。

   一条 accent 色的左边线 = 「这一段在等你」。灰线是「给你看的」，
   两者在余光里就分得开，不靠读字。 */
.zt-query .zt-todo {
  border-left: 2px solid var(--zt-accent); padding-left: 14px;
  margin-top: 12px; display: flex; flex-direction: column;
}
/* 圈进来之后，里面那一块不再自己画一条线 —— 两条平行竖线看着像两件事。
   缩进也收掉：外面那一层已经缩过了。 */
.zt-query .zt-todo > .zt-ask {
  border-left: 0; padding-left: 0; margin-top: 8px !important;
}

/* 折起来的那一段 —— 一行摘要 + 一颗展开钮(2026-09-07,业主:「展示看起来会整体很乱」)。
   摘要与钮在同一行:摘要占满、钮靠右,窄屏时钮换行不挤字。
   展开出来的内容自己带样式(命中表用 `.chat-hits`,与对话页同一份)。 */
.zt-fold { display: flex; flex-direction: column; gap: 6px; }
.zt-fold-h { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.zt-code-said { margin-top: 6px; padding: 8px 10px; white-space: pre-wrap;
                border-left: 2px solid var(--zt-line, #d8d8d8);
                color: var(--zt-ink-2, #555); font-size: 13px; line-height: 1.7;
                overflow-wrap: anywhere; }
.zt-fold-h > :is(.s, .zt-meta) { flex: 1; min-width: 0; }
.zt-fold-h > .zt-act { flex-shrink: 0; align-self: center; }

/* 输入区 */
.zt-say { flex-shrink: 0; border-top: 1px solid var(--zt-line); padding: 12px 20px;
          display: flex; flex-direction: column; gap: 9px; background: var(--zt-panel); }
/* ## 输入框、附件、发送收成一个框(2026-09-11,业主)
   在这之前:输入框一块、底下一排里虚线拖拽区 + 发送钮各占一头,三样平铺,
   排版乱在这里。业主:「发送放进框里、别再单独一个大上传钮、直接拖到框里。」
   改成一个 `.zt-composer`:文本框在上、框底一条(附件左·发送右),整框收拖拽。 */
.zt-composer { position: relative; display: flex; flex-direction: column;
               border: 1px solid var(--zt-line-2); border-radius: 12px;
               background: var(--zt-white); overflow: hidden;
               transition: border-color .15s ease, box-shadow .15s ease; }
.zt-composer:focus-within { border-color: var(--zt-accent);
                            box-shadow: 0 0 0 3px var(--zt-accent-line); }
/* 拖到框上:边框变虚线高亮,配 `.zt-drop-over` 那层「松手就传」。 */
.zt-composer[data-over="1"] { border-color: var(--zt-accent); border-style: dashed;
                              box-shadow: 0 0 0 3px var(--zt-accent-line); }
.zt-composer textarea { width: 100%; resize: none; border: 0; background: transparent;
                        padding: 10px 12px 4px; font-family: inherit; font-size: 13px;
                        line-height: 1.5; color: var(--zt-ink); min-height: 52px; }
.zt-composer textarea:focus { outline: none; }
/* 框底那一条:附件(左)· 说明 · 发送(右),都在框内。 */
.zt-composer-bar { display: flex; align-items: center; gap: 8px;
                   padding: 4px 8px 6px 10px; }
/* 附件缩成框内一个小图标钮,不再是一整块虚线区。 */
.zt-attach-wrap { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.zt-attach { display: inline-flex; align-items: center; cursor: pointer;
             border-radius: 7px; padding: 3px 9px; color: var(--zt-ink-2);
             border: 1px solid var(--zt-line-2); background: var(--zt-canvas);
             font-size: 11.5px; white-space: nowrap;
             transition: color .15s ease, border-color .15s ease; }
.zt-attach:hover { color: var(--zt-accent); border-color: var(--zt-accent); }
/* 看不见的原生 input 键盘聚焦时,把落点画在它的图标上(input 排在 label 之后)。 */
.zt-attach:has(+ .zt-drop-input:focus-visible) { outline: 2px solid var(--zt-accent);
                                                 outline-offset: 2px; }
.zt-send { padding: 5px 14px; border-radius: 8px; background: var(--zt-accent);
           color: var(--zt-on-accent); font-size: 12px; font-weight: 600;
           cursor: pointer; border: 0; font-family: inherit; flex-shrink: 0; }
.zt-send:disabled { background: var(--zt-line-2); cursor: not-allowed; }
/* 拖到框上时盖一层「松手就传」,让他知道松手会发生什么。 */
.zt-drop-over { position: absolute; inset: 0; display: flex; align-items: center;
                justify-content: center; background: rgba(255, 253, 247, .88);
                color: var(--zt-accent); font-size: 13px; font-weight: 600;
                pointer-events: none; }
.zt-note { font-size: 11.5px; color: var(--zt-mute); }

/* 科学家唯一入口：答案 → 材料与费用 → 下一步。只限定 /query，不改变工程屏。
   沿用自托管 Plex 与现有色板；不用缩小安全提示来换取“简洁”。 */
.zt-query {
  --zt-reading: 52rem;
  --zt-meta-size: .8125rem;
  height: 100dvh;
  min-height: 32rem;
}
.zt-query .zt-aside { width: 15rem; padding: 20px 16px 16px; gap: 10px;
                      /* 整条侧栏自己滚 —— 底下那两块不再各自抢高度。 */
                      overflow: auto; }
/* ## 「以前的对话」被推到栏底，中间空一大片(2026-09-09,ai4s-c4 走查读屏)
 *
 * 根子是 `.zt-sess`(我的需求单那一列)带着 `flex: 1 1 auto` —— 它**把剩下的
 * 高度全吃掉**。需求单只有两三条时那一列照旧撑满，于是「以前的对话」被
 * 顶到最底下，和「＋ 新对话」之间空出一大片。
 *
 * 改成按内容占高(`flex: 0 1 auto`)：两块挨着排，空的地方留在底下。
 * 内容多了整条侧栏自己滚(上面那条 `overflow: auto`)，不再靠某一块内部滚。
 *
 * **只在科学家这扇门上改** —— `.zt-sess` 那条基础规则别的屏也在用。
 * **默认展开那条逻辑一个字没动**：`open: !c.s.ztId`(没在任何一场里时摊开)
 * 是业主自己提的诉求，ai4s-c4 报的「默认折叠是个毛病」那半我量过，不成立。
 */
.zt-query .zt-sess { flex: 0 1 auto; }
.zt-query .zt-brand { padding: 0 4px 10px; }
.zt-query .zt-brand-name { font-size: 16px; }
.zt-query .zt-new { min-height: 40px; padding: 9px 12px; font-size: 13px; }
.zt-query .zt-scope { display: flex; align-items: center; flex-wrap: wrap; gap: 2px 8px;
                       font-size: 12px; color: var(--zt-ink-3); padding: 0 4px; }
.zt-query .zt-scope > .zt-act { border: 0; padding: 4px 0; min-height: 32px;
                               background: none; color: var(--zt-accent); }
.zt-query .zt-aside > .note { margin: 0; padding: 12px; background: var(--zt-panel);
                             border: 1px solid var(--zt-line); border-radius: 8px;
                             color: var(--zt-ink-3); font-size: 12px;
                             display: flex; flex-wrap: wrap; gap: 6px; }
.zt-query .zt-aside > .note > span { margin: 0 !important; }
.zt-query .zt-aside > .note .btn { min-height: 32px; padding: 5px 8px;
                                  background: none; border-color: var(--zt-line-2);
                                  color: var(--zt-accent); font-size: 12px; }
.zt-query .zt-sec { padding: 10px 8px 0; font-size: 12px; letter-spacing: 0; }
.zt-library-toggle { display: none; }
.zt-query .zt-sess { gap: 4px; }
.zt-query .zt-sess-item { padding: 10px; flex-shrink: 0; gap: 5px; }
.zt-query .zt-sess-t { font-size: 13px; line-height: 1.55; white-space: normal;
                      display: -webkit-box; -webkit-line-clamp: 2;
                      -webkit-box-orient: vertical; overflow-wrap: anywhere; }
.zt-query .zt-sess-s { font-size: 12px; color: var(--zt-ink-3); }
.zt-query .zt-sess-item[aria-current="page"] { box-shadow: inset 2px 0 var(--zt-accent);
                                              background: var(--zt-panel); }
.zt-status { font-size: 12px; color: var(--zt-ink-3); border-top: 1px solid var(--zt-line-3);
             padding-top: 12px; }
.zt-status > summary { cursor: pointer; min-height: 28px; }
.zt-status > div { padding: 4px 0; overflow-wrap: anywhere; }
.zt-query .zt-me { padding: 0; min-height: 28px; }
.zt-query .zt-head { height: auto; min-height: 64px; padding: 14px 32px;
                     gap: 8px 12px; flex-wrap: wrap; }
.zt-query .zt-head-t { font-size: 16px; }
.zt-query .zt-head-s { font-size: 12px; color: var(--zt-ink-3); white-space: normal; }
.zt-query .zt-chip { background: none; padding: 0; font-size: 11px; }
.zt-query .zt-flow { padding: 32px max(24px, calc((100% - var(--zt-reading)) / 2)) 36px;
                     gap: 28px; scrollbar-gutter: stable; }
.zt-question { min-width: 0; display: flex; flex-direction: column; gap: 16px; }
.zt-query .zt-said { max-width: 85%; padding: 12px 16px; font-size: 15px;
                     line-height: 1.7; white-space: pre-wrap; overflow-wrap: anywhere;
                     border: 0; margin-left: auto; }
.zt-query .zt-context { border-left: 2px solid var(--zt-line); padding: 2px 0 2px 12px;
                        margin-left: 36px; overflow-wrap: anywhere; }
.zt-query .zt-context .s { font-size: var(--zt-meta-size); line-height: 1.7;
                           color: var(--zt-ink-3); }
.zt-query .zt-context [data-t="stop"] { color: var(--zt-bad); }
.zt-query .zt-turn { gap: 12px; }
.zt-query .zt-av { margin-top: 3px; }
.zt-query .zt-body { gap: 20px; }
.zt-query .zt-answer { font-size: 16px; line-height: 1.85; overflow-wrap: anywhere;
                       text-wrap: pretty; }
.zt-query .zt-answer > :first-child { margin-top: 0; }
.zt-query .zt-answer > :last-child { margin-bottom: 0; }
.zt-support { display: flex; flex-direction: column; gap: 4px; }
.zt-support:empty, .zt-next:empty { display: none; }
.zt-query .zt-support { border-top: 1px solid var(--zt-line); padding-top: 10px; }
.zt-meta { font-size: var(--zt-meta-size, 13px); line-height: 1.65; color: var(--zt-ink-3);
           overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.zt-query .zt-fold { gap: 0; }
.zt-query .zt-fold-h { align-items: center; gap: 4px 16px; min-height: 38px; }
.zt-query .zt-fold-h > .zt-meta { flex: 1 1 16rem; }
.zt-disclosure { background: none; border-color: transparent; color: var(--zt-accent); }
.zt-query .zt-disclosure { min-height: 36px; padding: 6px 0 6px 8px; font-size: 13px; }
.zt-disclosure::after { content: ''; display: inline-block; width: 5px; height: 5px;
                        margin: 0 2px 3px 8px; border-right: 1px solid currentColor;
                        border-bottom: 1px solid currentColor; transform: rotate(45deg);
                        transition: transform 180ms ease; }
.zt-disclosure[aria-expanded="true"]::after { transform: rotate(225deg); }
.zt-query .zt-disclosure:hover { border-color: transparent; background: var(--zt-tint); }
.zt-detail[hidden] { display: none; }
.zt-query .zt-detail { margin: 8px 0 12px; min-width: 0; }
.zt-query .zt-bill-detail { border-left: 2px solid var(--zt-line); padding: 4px 12px;
                           display: flex; flex-direction: column; gap: 8px; }
.zt-query .zt-bill-detail[hidden] { display: none; }
.zt-query .zt-bill-detail .s { font-size: var(--zt-meta-size); color: var(--zt-ink-3);
                              line-height: 1.7; overflow-wrap: anywhere; }
.zt-query .zt-bill-detail [data-t="stop"] { color: var(--zt-bad); }
.zt-next { display: flex; flex-direction: column; gap: 16px; align-items: flex-start; }
.zt-approval { border-left: 2px solid var(--zt-warn-line); padding: 2px 0 2px 12px;
               display: flex; flex-direction: column; gap: 6px; }
.zt-approval-title { font-size: var(--zt-meta-size, 13px); font-weight: 600;
                     line-height: 1.65; color: var(--zt-warn); }
.zt-query .zt-acts { gap: 10px; align-items: center; }
.zt-query .zt-acts > .zt-act { min-height: 40px; padding: 9px 14px; font-size: 13px; }
.zt-query .zt-note { font-size: var(--zt-meta-size); line-height: 1.65;
                     color: var(--zt-ink-3); overflow-wrap: anywhere; }
.zt-query .zt-note[data-warn="1"] { color: var(--zt-warn); }
.zt-query .zt-say { padding: 16px max(24px, calc((100% - var(--zt-reading)) / 2)) 20px;
                    gap: 10px; }
/* 两颗入口钮与输入框**左边对齐**(2026-09-11,业主:「这个按钮偏的」)——
   `.zt-modes` 原来贴着容器左缘,而 `.zt-say` 内缩到行宽列里,两者左缘对不齐。
   给 `.zt-modes` 同一份行宽内缩,两条左缘就落在同一条线上。 */
.zt-query .zt-modes { padding: 0 max(24px, calc((100% - var(--zt-reading)) / 2)); }
.zt-query .zt-composer textarea { font-size: 15px; line-height: 1.7;
                                  padding: 12px 14px 6px; min-height: 84px; }
.zt-query .zt-send { min-height: 34px; padding: 7px 18px; font-size: 13px; }
.zt-query .zt-send:hover:not(:disabled) { background: var(--zt-accent-deep); }
.zt-query :is(button, a, summary) { transition: background-color 160ms ease, color 160ms ease; }
.zt-query button:disabled { cursor: not-allowed; }
.zt-query :is(button, a, summary, textarea):focus-visible {
  outline: 2px solid var(--zt-accent); outline-offset: 3px;
}
.zt-query button:active:not(:disabled) { transform: translateY(1px); }
.zt-query .zt-empty { max-width: 36rem; margin: auto; line-height: 1.8; }
.zt-query .zt-task-loading { margin: auto; display: flex; flex-direction: column;
  gap: 12px; align-items: flex-start; font-size: 14px; line-height: 1.7; }
.zt-query .zt-task-content { display: flex; flex-direction: column; gap: 16px; min-width: 0; }
.zt-query .zt-task-content > .card { background: none; box-shadow: none; border: 0;
  padding: 0; margin: 0; }
.zt-query .zt-task-content > .zt-disclosure { align-self: flex-start; }
.zt-query .zt-task-spec { border-top: 1px solid var(--zt-line); padding-top: 12px; }
.zt-query .zt-task-spec[hidden] { display: none; }
.zt-query .zt-team-message .zt-body { gap: 4px; }
.zt-query .zt-message { font-size: 15px; line-height: 1.8; overflow-wrap: anywhere; }
.zt-query .zt-reply-context { display: flex; gap: 12px; align-items: center; }
.zt-query .zt-reply-context > .zt-note { flex: 1; }

/* 命中数据与判定仍只由 chat.js 画；这里仅适配科学家阅读列的版式。 */
.zt-query .chat-hits { max-width: none; width: 100%; margin: 0; gap: 0;
                       background: none; border: 1px solid var(--zt-line); border-radius: 6px; }
.zt-query .chat-hits-h { padding: 12px 14px; gap: 4px 12px; background: var(--zt-tint); }
.zt-query .chat-hits-h b { font: 500 13px/1.65 var(--zt-sans); }
.zt-query .chat-hits-h .s { font: 12px/1.65 var(--zt-sans); color: var(--zt-ink-3);
                           overflow-wrap: anywhere; }
.zt-query .chat-hit { padding: 14px; gap: 8px; background: none;
                      border-top: 1px solid var(--zt-line); }
.zt-query :is(.chat-hit-1, .chat-hit-2) { gap: 6px 12px; }
.zt-query .chat-hit-1 b { font: 500 14px/1.6 var(--zt-sans); }
.zt-query .chat-hit-1 code { font: 12px/1.6 var(--zt-mono); background: none; padding: 0;
                            overflow-wrap: anywhere; }
.zt-query :is(.chat-hit-rel, .chat-hit-2, .chat-hit-2 .s, .chat-hit-why) {
  font: var(--zt-meta-size)/1.65 var(--zt-sans); color: var(--zt-ink-3);
  overflow-wrap: anywhere;
}
.zt-query .chat-hit-cite { margin-left: auto; border-radius: 4px;
                          font: 500 var(--zt-meta-size)/1.65 var(--zt-sans); }
.zt-query .chat-hit-no { font-style: normal; color: var(--zt-ink-3); }
.zt-query .chat-hit-kd { font-family: var(--zt-sans); }
.zt-query .chat-hit-why { border: 0; padding: 10px 14px; background: var(--zt-tint);
                         border-top: 1px solid var(--zt-line); }
.zt-query .chat-hits > .note { margin: 0; border-radius: 0; font-size: var(--zt-meta-size); }

@media (max-width: 760px) {
  .zt-query { flex-direction: column; }
  .zt-query .zt-aside { width: 100%; max-height: 45dvh; overflow: auto;
                        display: grid; grid-template-columns: minmax(0, 1fr) auto;
                        padding: 12px; gap: 6px 12px;
                        border-right: 0; border-bottom: 1px solid var(--zt-line); }
  .zt-query .zt-brand { padding: 0; }
  .zt-query .zt-new { text-align: center; }
  .zt-query :is(.zt-scope, .zt-aside > .note, .zt-sec, .zt-sess) { grid-column: 1 / -1; }
  .zt-query .zt-aside > .note { padding: 8px 10px; align-items: center; }
  .zt-query .zt-sec { display: none; }
  .zt-query .zt-library-toggle { display: block; border: 0; background: none;
                                font: 500 12px/1.5 var(--zt-sans); color: var(--zt-accent);
                                min-height: 32px; padding: 0; text-align: left; cursor: pointer; }
  .zt-query .zt-sess { display: none; flex-direction: row; overflow-x: auto; max-height: 84px; }
  .zt-query[data-library-open="1"] .zt-sess { display: flex; }
  .zt-query .zt-sess-item { flex: 0 0 12rem; padding: 6px 8px; }
  .zt-query .zt-status { display: none; border: 0; padding: 0; }
  .zt-query[data-library-open="1"] .zt-status { display: block; }
  .zt-query .zt-me { font-size: 11px; justify-self: end; }
  .zt-query .zt-head { min-height: 48px; padding: 10px 16px; }
  .zt-query .zt-head-s { flex-basis: 100%; font-size: 12px; }
  .zt-query .zt-flow { padding: 22px 16px; gap: 24px; }
  .zt-query .zt-said { max-width: 92%; font-size: 14px; }
  .zt-query .zt-turn { gap: 8px; }
  .zt-query .zt-av { width: 20px; height: 20px; font-size: 10px; }
  .zt-query .zt-context { margin-left: 28px; }
  .zt-query .zt-body { gap: 16px; }
  .zt-query .zt-answer { font-size: 15px; }
  .zt-query .zt-fold-h { gap: 0 8px; }
  .zt-query .zt-fold-h > .zt-meta { flex-basis: 100%; }
  .zt-query .zt-disclosure { padding-left: 0; }
  .zt-query .zt-say { padding: 12px 16px; }
  .zt-query .zt-modes { padding: 0 16px; }
  .zt-query .zt-composer textarea { min-height: 68px; height: 68px; font-size: 16px; }
  .zt-query .chat-hit-cite { margin-left: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .zt-query :is(button, a, summary), .zt-query .zt-disclosure::after { transition: none; }
}

/* ── 右侧产物栏 ──────────────────────────────────────────────────── */
.zt-prod { border-left: 1px solid var(--zt-line); background: var(--zt-panel-hi);
           display: flex; flex-direction: column; min-height: 0; }
.zt-tabs { height: 50px; flex-shrink: 0; display: flex; align-items: center;
           gap: 2px; padding: 0 12px; border-bottom: 1px solid var(--zt-line); }
.zt-tab { border: 0; cursor: pointer; font-family: inherit; font-size: 12.5px;
          font-weight: 600; padding: 7px 10px; border-radius: 7px;
          color: var(--zt-mute-2); background: transparent; }
.zt-tab[aria-current="true"] { color: var(--zt-ink); background: var(--zt-tint); }
.zt-prod-body { flex: 1 1 auto; min-height: 0; overflow: auto; padding: 16px; }

/* ── 科学原语那一页 ──────────────────────────────────────────────── */
.zt-prim-head { display: flex; align-items: center; gap: 8px; padding-bottom: 10px; }
.zt-prim-title { font-weight: 600; font-size: 12.5px; }
.zt-prim-row { display: grid; grid-template-columns: 116px 1fr auto; gap: 10px;
               align-items: start; padding: 10px 0;
               border-top: 1px solid var(--zt-line); }
.zt-prim-row:first-of-type { border-top: 0; }
.zt-prim-k { display: flex; flex-direction: column; gap: 2px; }
.zt-prim-key { font-family: var(--zt-mono); font-size: 12px; color: var(--zt-ink-3); }
.zt-prim-zh { font-size: 11px; color: var(--zt-mute); }
.zt-prim-v { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.zt-prim-val { font-size: 12.5px; }
/* 他自己那句话 —— 与平台的话分开,不能读成同一个人说的。 */
.zt-prim-said { font-size: 11.5px; color: var(--zt-mute);
                padding-left: 8px; border-left: 2px solid var(--zt-line); }
.zt-prim-why { font-size: 11.5px; color: var(--zt-mute); }
/* 两档来源标签,照设计稿的配色。 */
.zt-from { font-size: 11px; padding: 2px 7px; border-radius: 999px; white-space: nowrap; }
.zt-from[data-k="said"] { background: var(--zt-accent-wash); color: var(--zt-accent);
                          border: 1px solid var(--zt-accent-line); }
.zt-from[data-k="model"] { background: var(--zt-warn-wash); color: var(--zt-warn);
                           border: 1px solid var(--zt-warn-line); }

/* 空态与故障:设计稿里没有这两屏(它是理想态的样子),但真界面必须有。
   **样式照它的既有元素拼**,不新造一套外观。 */
.zt-empty { display: flex; flex-direction: column; gap: 9px;
            padding: 14px; border: 1px solid var(--zt-line);
            border-radius: 9px; background: var(--zt-tint-2);
            font-size: 12.5px; color: var(--zt-ink-3); }
.zt-empty[data-bad="1"] { background: var(--zt-warn-wash);
                          border-color: var(--zt-warn-line); color: var(--zt-warn); }
/* 空态里的那一行标题。**2026-09-16 补** —— 在这之前 `zt-empty-t` 这个类
   两份样式表里都没有，写了它的那一页标题会照 `.zt-empty` 的 12.5px 弱色画，
   读出来不像标题。本仓「写了一个不存在的类名，屏上不报错只是不好看」那一族。 */
.zt-empty-t { font: 600 15px/1.45 var(--f-sans); color: var(--zt-ink); }
.zt-empty p { margin: 0; max-width: 60ch; line-height: 1.75; }

/* ── 工作流草案那一页的格子 ────────────────────────────────────────── */
.zt-node { border: 1px solid var(--zt-line); border-radius: 9px;
           padding: 10px 12px; margin-bottom: 8px; background: var(--zt-panel); }
.zt-node-h { display: flex; align-items: center; gap: 8px; }
.zt-node-t { font-weight: 500; font-size: 12.5px; flex: 1; min-width: 0; }
/* 会话栏在页内时不画自己的右边线 —— 外面那层 `.zt` 已经分好栏了。 */
.zt .zt-aside { border-right: 1px solid var(--zt-line-3); }
/* 管线选择器与出口 —— 外壳撤掉之后这两样落到 aside 上。 */
/* 两张卡之间的插入点。**平时轻**,别把「加一格」做得比卡片本身还显眼 ——
 * 这一列要读的是「这条链上第几步做什么」。 */
.zt-ins { display: flex; align-items: center; gap: 8px;
          padding: 3px 0 3px 26px; }
.zt-ins .zt-sel { max-width: 300px; font-size: 11.5px; opacity: .72; }
.zt-ins .zt-sel:hover, .zt-ins .zt-sel:focus { opacity: 1; }

/* 分叉那几支:一支一行,左边写出口名。 */
.zt-ports { display: flex; flex-direction: column; gap: 4px; margin-top: 6px; }
.zt-port-row { display: flex; align-items: center; gap: 8px; }
.zt-port-row .zt-sel { max-width: 220px; }

/* 跑完之后格子上那颗状态。**五态各一个颜色** —— 一色到底的话,
 * 「成了」和「没跑成」在扫一眼时分不出来,而那正是要一眼看出的东西。 */
.zt-chip[data-st="ok"] { border-color: var(--zt-accent); color: var(--zt-accent); }
.zt-chip[data-st="failed"] { border-color: var(--zt-bad); color: var(--zt-bad);
                             background: var(--zt-bad-wash-2); }
.zt-chip[data-st="paid"], .zt-chip[data-st="human"] {
  border-color: var(--zt-warn); color: var(--zt-warn); }
.zt-chip[data-st="skipped"] { color: var(--zt-mute); }

/* 顶栏上的选择器。**与侧栏那颗 `.zt-pipe` 分开** —— 那一颗是
 * `width:100%` 的整列宽,摆进顶栏会把别的按钮挤没。 */
.zt-sel { max-width: 260px; border: 1px solid var(--zt-line-2);
          border-radius: 7px; padding: 4px 8px; font-size: 12px;
          background: var(--zt-panel); color: var(--zt-ink); }
.zt-pipe { width: 100%; margin-bottom: 8px; border: 1px solid var(--zt-line-2);
           border-radius: 8px; padding: 6px 8px; font-family: inherit;
           font-size: 12px; background: var(--zt-panel); color: var(--zt-ink-2); }
.zt-out { margin-top: 8px; border: 1px solid var(--zt-line-2); background: none;
          color: var(--zt-mute); border-radius: 7px; padding: 5px 8px;
          font-family: inherit; font-size: 11.5px; cursor: pointer; text-align: left; }
.zt-out:hover { border-color: var(--zt-accent); color: var(--zt-accent); }

/* ── 工作流编辑器(设计稿第三屏)────────────────────────────────────
 *
 * 顶栏 + 三栏 `150px minmax(0,1fr) 372px`,取值照设计稿。
 */
.zt-bar { height: 50px; flex-shrink: 0; display: flex; align-items: center;
          gap: 12px; padding: 0 18px; background: var(--zt-panel-hi);
          border-bottom: 1px solid var(--zt-line); white-space: nowrap; }
.zt-three { flex: 1 1 auto; min-height: 0; display: grid;
            grid-template-columns: 150px minmax(0, 1fr) 372px; }
/* **窄屏先收左栏,再收右栏。** 中间那一列是节点本身,最后才让。 */
@media (max-width: 1180px) { .zt-three { grid-template-columns: minmax(0,1fr) 372px; }
                             .zt-rail { display: none; } }
@media (max-width: 860px) { .zt-three { grid-template-columns: minmax(0,1fr); }
                            .zt-three > .zt-prod { display: none; } }

.zt-rail { border-right: 1px solid var(--zt-line); background: var(--zt-rail);
           display: flex; flex-direction: column; min-height: 0;
           overflow: auto; padding: 10px 10px 14px; }
.zt-rail-list { display: flex; flex-direction: column; gap: 2px; }
.zt-rail-item { display: flex; align-items: center; gap: 6px;
                border: 1px solid var(--zt-line); border-radius: 7px;
                padding: 5px 8px; font-size: 11.5px; background: var(--zt-panel); }
.zt-rail-item.mono { font-family: var(--zt-mono); font-size: 11px;
                     color: var(--zt-ink-3); }
.zt-rail-n { margin-left: auto; color: var(--zt-mute); font-family: var(--zt-mono); }

.zt-canvas { min-height: 0; overflow: auto; padding: 16px 18px;
             background: var(--zt-canvas); }
/* 节点卡:编号 + 标题 + 类型。选中的压一道主色边。 */
.zt-node[data-on="1"] { border-color: var(--zt-accent);
                        box-shadow: inset 2px 0 0 var(--zt-accent); }
.zt-node-no { font-family: var(--zt-mono); font-size: 11px;
              color: var(--zt-mute); flex-shrink: 0; }

/* ── 质检台(设计稿第四屏)────────────────────────────────────────── */
.zt-qc { flex: 1 1 auto; min-height: 0; display: grid;
         grid-template-columns: 266px minmax(0, 1fr) 356px; }
@media (max-width: 1200px) { .zt-qc { grid-template-columns: 266px minmax(0,1fr); }
                             .zt-qc-right { display: none; } }
@media (max-width: 880px) { .zt-qc { grid-template-columns: minmax(0,1fr); }
                            .zt-qc-left { display: none; } }
.zt-qc-left { border-right: 1px solid var(--zt-line); background: var(--zt-rail);
              display: flex; flex-direction: column; min-height: 0;
              padding: 12px 12px 0; }
.zt-qc-mid { min-height: 0; overflow: auto; padding: 14px 18px;
             background: var(--zt-panel); }
.zt-qc-right { border-left: 1px solid var(--zt-line);
               background: var(--zt-panel-hi);
               min-height: 0; overflow: auto; padding: 14px 16px; }
.zt-qc-head { display: flex; align-items: center; gap: 8px; padding-bottom: 8px; }
.zt-qc-tabs { display: flex; gap: 2px; padding-bottom: 8px; }
.zt-qc-list { flex: 1 1 auto; min-height: 0; overflow: auto;
              display: flex; flex-direction: column; gap: 6px; }
.zt-qc-item { border: 1px solid var(--zt-line); border-radius: 8px;
              background: var(--zt-panel); padding: 8px 10px; cursor: pointer;
              font-family: inherit; text-align: left;
              display: flex; flex-direction: column; gap: 3px; }
.zt-qc-item:hover { border-color: var(--zt-accent); }
.zt-qc-item[aria-current="page"] { border-color: var(--zt-accent);
                                   box-shadow: inset 2px 0 0 var(--zt-accent); }
.zt-qc-item-h { display: flex; align-items: center; gap: 8px; }
.zt-qc-id { font-family: var(--zt-mono); font-size: 12px; font-weight: 600; }
.zt-qc-flag { font-size: 11px; padding: 1px 7px; border-radius: 999px;
              background: var(--zt-warn-wash); color: var(--zt-warn);
              border: 1px solid var(--zt-warn-line); }
.zt-qc-foot { border-top: 1px solid var(--zt-line-3); margin-top: 8px;
              padding: 10px 2px; font-size: 11.5px; color: var(--zt-mute); }
/* 原文证据:命中那一段高亮,上下文压暗 —— 「回得到原文」的样子。 */
.zt-ev { border: 1px solid var(--zt-line); border-radius: 8px; padding: 10px 12px;
         background: var(--zt-white); font-size: 12.5px; line-height: 1.85; }
.zt-ev-dim { color: var(--zt-mute); }
.zt-ev-hit { background: var(--zt-warn-wash); color: var(--zt-warn);
             padding: 1px 3px; border-radius: 3px; font-weight: 500; }
.zt-kv { display: flex; flex-direction: column; }
.zt-kv-row { display: grid; grid-template-columns: 120px 1fr; gap: 10px;
             padding: 6px 0; border-top: 1px solid var(--zt-line); }
.zt-kv-row:first-child { border-top: 0; }
.zt-kv-k { font-family: var(--zt-mono); font-size: 11.5px; color: var(--zt-mute); }
.zt-kv-v { font-size: 12.5px; }
.zt-qc-issue { border-left: 2px solid var(--zt-bad); padding-left: 9px;
               color: var(--zt-bad); font-size: 12px; margin-top: 8px; }
/* 回溯:三档配色照设计稿(正常 / 未拦截 / 问题节点)。 */
.zt-trace { display: flex; flex-direction: column; gap: 7px; }
.zt-trace-row { border: 1px solid var(--zt-line); border-radius: 8px;
                padding: 8px 10px; background: var(--zt-panel); }
.zt-trace-row[data-k="warn"] { border-color: var(--zt-warn-line);
                               background: var(--zt-warn-wash); }
.zt-trace-row[data-k="bad"] { border-color: var(--zt-bad);
                              background: var(--zt-bad-wash-2); }
.zt-trace-h { display: flex; align-items: center; gap: 8px; }
.zt-trace-n { font-size: 12px; font-weight: 500; flex: 1; min-width: 0; }
.zt-trace-s { font-size: 11px; color: var(--zt-mute); }
.zt-trace-row[data-k="bad"] .zt-trace-s { color: var(--zt-bad); }
.zt-diff { border: 1px solid var(--zt-line); border-radius: 8px;
           overflow: hidden; margin-bottom: 8px; }
.zt-diff-h { padding: 6px 10px; background: var(--zt-tint-2);
             font-size: 11px; color: var(--zt-mute); }
.zt-diff-old, .zt-diff-new { padding: 7px 10px; font-family: var(--zt-mono);
                             font-size: 11px; line-height: 1.7; }
.zt-diff-old { background: var(--zt-bad-wash-2); color: var(--zt-bad); }
.zt-diff-new { background: var(--zt-code-wash); color: var(--zt-code-ink); }
.zt-qc-acts { display: flex; flex-direction: column; gap: 7px; margin-top: 12px; }
/* 来源标记在这一套里的样子 —— 与 tokens.css 那份同义,配色照设计稿。 */
.zt .src { border-radius: 999px; padding: 1px 7px; font-size: 10.5px;
           border: 1px solid var(--zt-line-2); color: var(--zt-mute); }
.zt .src[data-w="demo"] { border-color: var(--zt-warn-line); color: var(--zt-warn);
                          background: var(--zt-warn-wash); }
.zt .src[data-w="live"] { border-color: var(--zt-accent-line); color: var(--zt-accent);
                          background: var(--zt-accent-wash); }

/* ── 结果看板 / 证据明细 / 检索结果 / 预跑结果 ────────────────────── */
.zt-stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
            gap: 8px; margin: 10px 0 4px; }
.zt-stat { border: 1px solid var(--zt-line); border-radius: 9px;
           padding: 9px 10px; background: var(--zt-panel); }
.zt-stat-n { font-family: var(--zt-mono); font-size: 19px; font-weight: 600;
             line-height: 1.2; }
.zt-stat-l { font-size: 11px; color: var(--zt-mute); margin-top: 2px; }
/* 三档配色 —— 通过 / 待质检 / 失败是三件事,一个颜色就得逐个读数字。 */
.zt-stat[data-k="warn"] { border-color: var(--zt-warn-line); background: var(--zt-warn-wash); }
.zt-stat[data-k="warn"] .zt-stat-n { color: var(--zt-warn); }
.zt-stat[data-k="bad"] { border-color: var(--zt-bad);
                         background: var(--zt-bad-wash-2); }
.zt-stat[data-k="bad"] .zt-stat-n { color: var(--zt-bad); }
/* 分布条那几条**整段删了**(2026-09-02),而且它删掉的是一个真 bug。
 *
 * ## `.zt-bar` 被两样东西共用,而后写的那条赢了
 *
 *     第 346 行   编辑器/质检台的**顶栏**   height:50px  flex-shrink:0
 *     这里(原)     结果看板里的**分布条**    position:absolute
 *
 * 同一个类名、两个毫不相干的东西。CSS 按书写顺序,后者赢 ——
 * 于是**编辑器的顶栏变成了 absolute**:它不占位,底下那三栏整个
 * 从 y=0 起,节点卡被顶栏切掉一截。
 *
 * 实测(真浏览器,1280x720):
 *
 *     .zt-bar     0,0 790x50   position=absolute   ← 该是 1280 宽、占 50px
 *     .zt-three   0,0 1280x720                     ← 该从 y=50 起、高 670
 *
 * 光看任何一处 CSS 都看不出问题,两处各自都对 —— 叠起来才错。
 *
 * 这几条现在**一个用户都没有**:它们只服务于「结果看板」那块演示数据,
 * 而那一块同日翻成了真数据(见 `pages/query.js`)。所以是删,不是改名。
 * 判据钉住 `.zt-bar` 只许有一处定义。
 */
/* 结果表 */
.zt-tbl { margin-top: 12px; border: 1px solid var(--zt-line); border-radius: 9px;
          overflow: hidden; }
.zt-tr { display: grid; grid-template-columns: 1.5fr 1fr 1fr .9fr; gap: 8px;
         padding: 7px 10px; font-size: 11.5px;
         border-top: 1px solid var(--zt-line); }
.zt-tr:first-child { border-top: 0; }
.zt-th { background: var(--zt-tint-2); color: var(--zt-mute); font-size: 11px; }
.zt-tr .mono { font-family: var(--zt-mono); }
/* 证据明细 */
.zt-layers { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 10px 0; }
.zt-layer { border: 1px solid var(--zt-line); border-radius: 9px;
            padding: 9px 10px; background: var(--zt-panel); }
.zt-layer-n { font-size: 11.5px; color: var(--zt-mute); }
.zt-layer-v { font-family: var(--zt-mono); font-size: 13px; font-weight: 600;
              margin: 2px 0; }
.zt-eitem { border: 1px solid var(--zt-line); border-radius: 9px;
            padding: 10px 12px; margin-bottom: 8px; background: var(--zt-panel); }
.zt-eitem-h { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.zt-eitem-n { font-weight: 600; font-size: 12.5px; }
/* 论文与专利 */
.zt-lit { display: flex; gap: 9px; align-items: flex-start; padding: 7px 0;
          border-top: 1px solid var(--zt-line); }
.zt-lit:first-of-type { border-top: 0; }
.zt-lit-k { font-family: var(--zt-mono); font-size: 9.5px; letter-spacing: .06em;
            padding: 2px 6px; border-radius: 4px; flex-shrink: 0;
            background: var(--zt-tint-2); color: var(--zt-mute); }
.zt-lit-k[data-k="PATENT"] { background: var(--zt-warn-wash); color: var(--zt-warn); }
.zt-lit-b { min-width: 0; }
.zt-lit-t { font-size: 12px; }

/* ── 编辑器右栏:单步调试 / 版本与批注 ────────────────────────────── */
.zt-code { margin: 6px 0 0; padding: 10px 12px; border-radius: 8px;
           background: var(--zt-code-wash); color: var(--zt-code-ink);
           overflow: auto;
           font-family: var(--zt-mono); font-size: 11px; line-height: 1.75;
           white-space: pre; }
/* 结论那一块是判定,不是说明 —— 给它主色边,与说明文字分开。 */
.zt-verdict { margin-top: 10px; border: 1px solid var(--zt-accent-line);
              background: var(--zt-accent-wash); border-radius: 9px;
              padding: 9px 11px; }
.zt-verdict-t { font-size: 12.5px; font-weight: 600; color: var(--zt-accent); }
.zt-ver { border-top: 1px solid var(--zt-line); padding: 8px 0; }
.zt-ver:first-of-type { border-top: 0; }
.zt-ver-h { display: flex; align-items: baseline; gap: 8px; }
.zt-ver-n { font-family: var(--zt-mono); font-size: 12px; font-weight: 600;
            color: var(--zt-accent); flex-shrink: 0; }
.zt-ver-s { font-size: 12px; }
.zt-anno { border: 1px solid var(--zt-line); border-radius: 9px;
           padding: 9px 11px; background: var(--zt-panel); }
.zt-anno-b { font-size: 12px; line-height: 1.7; }

/* ── 会话列的演示态与产物摘要 ─────────────────────────────────────── */
/* 摆着的那四条**不可点** —— 点了会开一场不存在的会话。压一档不透明度,
   与真会话在屏上分得开。 */
.zt-sess-item[data-demo="1"] { opacity: .62; cursor: default; }
.zt-sess-item[data-demo="1"]:hover { background: none; }
/* 四种摘要是四种不同的东西:产物计数 / 待人处置 / 进行中 / 时间。 */
.zt-sess-s[data-k="warn"] { color: var(--zt-warn); }
.zt-sess-s[data-k="run"] { color: var(--zt-accent); }
.zt-foot-demo { display: flex; align-items: center; gap: 6px; opacity: .8; }

/* ── 质检台:平台确实没有的那几块 ──────────────────────────────────── */
/* **「还没接」与「后端没有」不是一回事**,所以不与 `.zt-note` 同款:
   前者等着接,后者要先出方案。给它一条竖边,人一眼看出这是缺口不是数据。 */
.zt-qc-gap { border-left: 2px solid var(--zt-line); padding: 8px 0 8px 10px;
             margin: 6px 0; color: var(--zt-ink-3); font-size: 12px;
             display: flex; flex-direction: column; gap: 4px;
             align-items: flex-start; }
.zt-note[data-warn="1"] { color: var(--zt-warn); }

/* 不合格行号的全集 —— 屏上先给几条,按「看全部」把其余列出来。
   等宽是必须的:这一列全是 id,对齐了才扫得动。 */
.zt-ids { margin-top: 8px; display: flex; flex-direction: column; gap: 6px; }
.zt-mono { font-family: var(--zt-mono); font-size: 12px; line-height: 1.7;
           word-break: break-all; max-height: 200px; overflow-y: auto;
           background: var(--zt-panel); border: 1px solid var(--zt-line);
           border-radius: 3px;
           padding: 8px; }

/* ── 单步调试的输入框 ─────────────────────────────────────────────── */
/* 喂给这一格的东西是 JSON,所以用等宽 —— 括号对不对齐、逗号在哪,
   比例字体下看不出来,而这一格正是拿来看它填对没有的。 */
.zt-in { width: 100%; box-sizing: border-box; margin-top: 6px;
         border: 1px solid var(--zt-line); border-radius: 7px;
         padding: 7px 8px; font-family: var(--zt-mono); font-size: 11.5px;
         line-height: 1.5; color: var(--zt-ink); background: var(--zt-white);
         resize: vertical; }
.zt-in:focus { outline: 2px solid var(--zt-accent); outline-offset: -1px; }
/* 「这一次用的参数」每一格 */
.zt-arg { margin-top: 8px; }
.zt-arg-h { display: flex; align-items: baseline; gap: 8px; }
.zt-query .chat-ask-options { margin-block: 6px; }
.zt-query .chat-ask-options > summary { cursor: pointer; color: var(--c-primary); font-size: 13px; padding-block: 6px; }
.zt-query .chat-ask-options > summary:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 3px; }
.zt-query .chat-ask-options[open] > summary { margin-bottom: 8px; }

/* ═══════════════════════════════════════════════════════════════════════
   全景 —— 对外展示那一屏（`pages/panorama.js`）
   ═══════════════════════════════════════════════════════════════════════

   业主 2026-09-13：这条流程要拿去给投资人与合作方看。

   **不另起一套颜色。** 用的是上面那份 `--zt-*`：暖纸底、深蓝一个强调色、
   等宽字排数。换的只是**字号与留白的档位** —— 对外看的那一屏要读得远，
   而控制台其余部分是贴着屏幕用的。作用域钉在 `.bp` 上。

   形状上只有一条脊：一条竖线从「并行计算」贯到「结果回流」，干实验那截
   是实线、湿实验那截是虚线 —— 那正是今天的实情（接口已定，内部还没定）。
   虚实之分是**说出来的一件事**，不是装饰。 */

.bp { font-family: var(--zt-sans); color: var(--zt-ink);
      max-width: 1180px; }
.bp-mono { font-family: var(--zt-mono); font-variant-numeric: tabular-nums; }

/* ── 页头 ───────────────────────────────────────────────────────────── */
.bp-head { display: grid; grid-template-columns: minmax(0, 1fr) auto;
           gap: 20px 32px; align-items: end;
           padding-bottom: 20px; border-bottom: 1px solid var(--zt-line); }
.bp-eyebrow { font-family: var(--zt-mono); font-size: 10.5px;
              letter-spacing: .18em; text-transform: uppercase;
              color: var(--zt-mute); }
.bp-title { font-size: 34px; line-height: 1.08; letter-spacing: -.022em;
            font-weight: 600; margin: 7px 0 0; text-wrap: balance; }
.bp-lede { margin: 10px 0 0; max-width: 58ch; font-size: 13.5px;
           line-height: 1.62; color: var(--zt-ink-3); }
.bp-head-meta { font-family: var(--zt-mono); font-size: 11px; margin-top: 9px;
                color: var(--zt-ink-3); letter-spacing: .01em; }
.bp-head-policy { font-family: var(--zt-mono); font-size: 10.5px; margin-top: 11px;
                  padding-top: 9px; border-top: 1px solid var(--zt-line);
                  color: var(--zt-mute); max-width: 62ch; line-height: 1.6; }
.bp-head-side { display: flex; flex-direction: column; align-items: flex-end;
                gap: 7px; }
.bp-pick { display: flex; flex-wrap: wrap; gap: 6px; justify-content: flex-end; }

/* ── 脊 ─────────────────────────────────────────────────────────────── */
.bp-spine { position: relative; margin-top: 30px; padding-left: 30px; }
.bp-spine::before { content: ''; position: absolute; left: 4px; top: 7px;
                    bottom: 34px; width: 1px; background: var(--zt-line-2); }
.bp-seg { position: relative; padding-bottom: 30px; }
.bp-seg::before { content: ''; position: absolute; left: -30px; top: 3px;
                  width: 9px; height: 9px; border-radius: 50%;
                  background: var(--zt-accent);
                  box-shadow: 0 0 0 4px var(--zt-canvas); }
/* 湿实验那一截：空心点 + 虚线脊。**还没建的东西不画成实心的。** */
.bp-seg[data-kind="wet"]::before { background: var(--zt-canvas);
                                   border: 1.5px solid var(--zt-accent-mid); }
.bp-seg[data-kind="wet"]::after { content: ''; position: absolute;
                                  left: -26px; top: 14px; bottom: 0; width: 0;
                                  border-left: 1px dashed var(--zt-accent-mid); }

.bp-seg-h { display: grid; grid-template-columns: minmax(0, 1fr) auto;
            gap: 14px; align-items: baseline; }
.bp-seg-n { font-size: 17px; font-weight: 600; letter-spacing: -.012em; }
.bp-seg-i { font-family: var(--zt-mono); font-size: 10.5px;
            color: var(--zt-mute); letter-spacing: .06em; }

/* ── 起点：这一轮算什么 ───────────────────────────────────────────────
 *
 * 业主 2026-09-14：「起码你是 just start 链路…… 它是需要有特定的输入的
 * …… 前置的这个输入的环节帮我做进去。」这一块是那个入口。
 *
 * **长相要像一张交代单，不像一个启动按钮** —— 它不触发任何计算，
 * 平台不跑 GPU。做成显眼的主色大钮的话，人点完会坐等。 */
.bp-round { margin-top: 12px; border: 1px solid var(--zt-line);
            border-left: 2px solid var(--zt-accent); border-radius: 3px;
            background: var(--zt-panel); padding: 11px 13px; }
.bp-round-h { display: flex; align-items: baseline; gap: 10px;
              justify-content: space-between; }
.bp-round-h b { font-size: 13.5px; }
.bp-round-id { font-family: var(--zt-mono); font-size: 10.5px;
               color: var(--zt-mute); }
.bp-round-kv { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
               gap: 4px 18px; margin-top: 8px; }
@media (max-width: 860px) { .bp-round-kv { grid-template-columns: 1fr; } }
.bp-kv { display: flex; gap: 8px; font-size: 12px; min-width: 0; }
.bp-kv .k { color: var(--zt-mute); flex: none; }
.bp-kv .v { color: var(--zt-ink-2); overflow: hidden;
            text-overflow: ellipsis; white-space: nowrap; }

/* 「指到这一轮」那几颗 —— 摆在交代单与开新一轮之间，
   那正是动线上的位置：已经有行的先指过去，没有的才开新的。 */
.bp-round-pick { margin-top: 12px; padding-top: 10px;
                 border-top: 1px dashed var(--zt-line-2); }
.bp-round-form { margin-top: 12px; }
.bp-round-row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
                gap: 10px; }
@media (max-width: 860px) { .bp-round-row { grid-template-columns: 1fr; } }
.bp-lab { display: flex; flex-direction: column; gap: 4px; margin-top: 10px;
          font-size: 12px; color: var(--zt-ink-3); }
.bp-lab .zt-in { width: 100%; }
/* 交给工作站那一句 —— **照抄用的**，所以能选中、会换行、等宽。 */
.bp-cmd { font-family: var(--zt-mono); font-size: 11.5px; line-height: 1.65;
          background: var(--zt-panel); border: 1px solid var(--zt-line);
          border-radius: 3px; padding: 10px 12px; margin-top: 10px;
          white-space: pre-wrap; word-break: break-all;
          color: var(--zt-ink-2); user-select: all; }

/* ── 单元卡 ─────────────────────────────────────────────────────────── */
.bp-units { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
            gap: 10px; margin-top: 12px; }
@media (max-width: 1080px) { .bp-units { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.bp-unit { border: 1px solid var(--zt-line); border-radius: 3px;
           background: var(--zt-panel); padding: 12px 13px 13px;
           display: flex; flex-direction: column; gap: 7px;
           transition: border-color .18s, transform .18s; }
.bp-unit:hover { border-color: var(--zt-accent-line);
                 transform: translateY(-1px); }
.bp-unit-h { display: flex; align-items: baseline; gap: 8px;
             justify-content: space-between; }
.bp-unit-n { font-size: 13.5px; font-weight: 600; }
.bp-unit-w { font-size: 12px; line-height: 1.58; color: var(--zt-ink-3);
             margin: 0; }
.bp-io { font-family: var(--zt-mono); font-size: 10.5px; color: var(--zt-mute);
         letter-spacing: .02em; }

/* ── 收窄：条宽按真条数，不按好看 ───────────────────────────────────── */
.bp-bar { margin-top: 9px; display: grid;
          grid-template-columns: 1fr minmax(84px, auto); gap: 12px;
          align-items: center; }
.bp-bar-t { height: 6px; background: var(--zt-tint-2); border-radius: 3px;
            overflow: hidden; }
.bp-bar-f { height: 100%; background: var(--zt-accent);
            border-radius: 3px; min-width: 3px;
            transform-origin: left; }
.bp-bar-v { font-family: var(--zt-mono); font-variant-numeric: tabular-nums;
            font-size: 12.5px; text-align: right; color: var(--zt-ink); }
.bp-bar-none { font-size: 11.5px; color: var(--zt-mute); margin-top: 9px; }

/* ── 交接与回流 ─────────────────────────────────────────────────────── */
.bp-hand { border: 1px dashed var(--zt-accent-line); border-radius: 3px;
           background: var(--zt-accent-wash); padding: 13px 14px;
           margin-top: 12px; display: grid; gap: 8px; }
.bp-hand-r { display: grid; grid-template-columns: 92px minmax(0, 1fr);
             gap: 12px; align-items: baseline; font-size: 12.5px;
             line-height: 1.58; }
.bp-hand-k { font-family: var(--zt-mono); font-size: 10.5px;
             letter-spacing: .1em; text-transform: uppercase;
             color: var(--zt-accent); }

/* 工作站那条：进度是别人报的，说法要跟别处不一样 */
.bp-ws { margin-top: 11px; border: 1px solid var(--zt-line);
         border-left: 2px solid var(--zt-accent-mid); border-radius: 3px;
         background: var(--zt-white); padding: 11px 13px; }
.bp-ws-h { display: flex; gap: 10px; align-items: baseline;
           justify-content: space-between; }
.bp-ws-w { font-size: 11.5px; color: var(--zt-ink-3); margin: 6px 0 0;
           line-height: 1.55; }

/* ── 空态 / 骨架 ────────────────────────────────────────────────────── */
.bp-empty { margin-top: 30px; border: 1px dashed var(--zt-line-2);
            border-radius: 3px; padding: 34px 30px; background: var(--zt-panel);
            max-width: 620px; }
.bp-skel { margin-top: 30px; display: grid; gap: 22px; }
.bp-skel-r { display: grid; grid-template-columns: 190px 1fr; gap: 20px; }
.bp-skel-b { height: 11px; border-radius: 3px; background: var(--zt-tint-2); }
.bp-skel-b.w2 { height: 58px; }

/* ── 动 ─────────────────────────────────────────────────────────────
   一次装载编排：脊自上而下画出来，每一段跟着抬进来。
   **动的是流向本身** —— 这条线就是从上往下走的。除此之外一处不动，
   没有常驻循环。 */
@media (prefers-reduced-motion: no-preference) {
  .bp-spine::before { animation: bp-draw .62s cubic-bezier(.16,1,.3,1) both;
                      transform-origin: top; }
  .bp-seg { animation: bp-rise .52s cubic-bezier(.16,1,.3,1) backwards;
            animation-delay: calc(var(--i, 0) * 78ms + 90ms); }
  .bp-bar-f { animation: bp-grow .6s cubic-bezier(.16,1,.3,1) backwards;
              animation-delay: calc(var(--i, 0) * 78ms + 260ms); }
}
@keyframes bp-draw { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes bp-rise { from { opacity: 0; transform: translateY(9px); }
                     to   { opacity: 1; transform: none; } }
@keyframes bp-grow { from { transform: scaleX(0); } to { transform: scaleX(1); } }

@media (max-width: 720px) {
  .bp-head { grid-template-columns: 1fr; }
  .bp-head-side { align-items: flex-start; }
  .bp-pick { justify-content: flex-start; }
  .bp-title { font-size: 26px; }
  .bp-units { grid-template-columns: 1fr; }
  .bp-hand-r { grid-template-columns: 1fr; gap: 3px; }
  .bp-skel-r { grid-template-columns: 1fr; }
}

/* ── 业务面作业区（2026-09-14）──────────────────────────────────────────
   业主：「先选业务 → 跳进去 → 顶部标签栏切页，不要左侧树。」
   `.biz-ws` 是顶部标签栏（.phead-bar）+ 页面的那一屏。整屏那几页
   （检索 .zt-query / 对话 .chatpage）原来按 100dvh 铺满视口；收进作业区
   之后，视口高度里顶栏与标签栏各占一截，得改成「填满标签栏以下的剩余」。 */
.main.biz-ws { display: flex; flex-direction: column; min-height: 0; padding: 0; }
.main.biz-ws > .phead-bar { flex: 0 0 auto; }
/* 检索 / 对话：填满剩余高度，各自内部再滚，不再自己撑到 100dvh。 */
.main.biz-ws > .zt,
.main.biz-ws > .zt-query { flex: 1 1 auto; height: auto; min-height: 0; }
.main.biz-ws > .chatpage,
.main.biz-ws > .stack.chatpage { flex: 1 1 auto; min-height: 0; overflow: auto; }
/* 索引库这类普通 .stack：正常文档流，主区自己滚。 */
.main.biz-ws > .stack:not(.chatpage):not(.ws) {
  flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 20px 26px 28px;
}
/* 工作站那一屏**整页不滚**：顶部一条上下文钉住，左右两列各自滚
   （见 `tokens.css` 的 `.ws`）。跟 `.chatpage` 同一个先例 ——
   整页滚的话「内容一变高就丢滚动位置」那一族会一直长回来。 */
.main.biz-ws > .stack.ws { flex: 1 1 auto; min-height: 0; overflow: hidden; padding: 0; }

/* ══ 算力资源（`pages/ws5ws.js`）· 登记表（2026-09-16 改版）════════════
 *
 * 业主：「它应该是已经注册登记上的计算资源的状态管控，写成一段一段话的
 * 形式不合适。」—— 上一版三块都是「一行一段话」，这一版改成概览 + 三张表。
 *
 * **放在这个文件、类名走 `cpr-`**，不改 `tokens.css` 里的 `w5f-*`：
 * 改版那天 `tokens.css` 正被另一个 session 改着（没提交）。同一个文件两边
 * 各改一处，后提交的那一方整份一交，先提交的那处就**静默没了**。
 * `w5r-` 已被运行台占用，所以也不用它。
 * 旧的 `w5f-*` 规则这一屏除 `.w5f-page`（外层滚动容器）外已不再使用。
 *
 * 状态**同时用形与色编码**（PRODUCT.md，色觉差异的人也读得出）：
 *     实心点 = 已接通 / 在线      空心环 = 待接入 / 心跳超时（琥珀，不是红）
 *     虚线环 = 判不出             短杠   = 未上报
 */
.cpr-head h1 { margin: 0; font: 600 var(--t-page)/1.2 var(--f-sans); color: var(--c-ink); }

.cpr-stats { flex: none; display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.cpr-stat { border: 1px solid var(--c-line); border-radius: 5px; background: var(--c-card); padding: 10px 14px; }
.cpr-stat-l { font: 400 var(--t-micro)/1.4 var(--f-sans); color: var(--c-text-3); }
.cpr-stat-v { margin-top: 4px; font: 600 var(--t-base)/1.2 var(--f-sans); color: var(--c-text);
  font-variant-numeric: tabular-nums; }
.cpr-stat-u { margin-left: 6px; font: 400 var(--t-micro)/1 var(--f-sans); color: var(--c-text-3); }

.cpr-sec { flex: none; border: 1px solid var(--c-line); border-radius: 5px; background: var(--c-card); overflow: hidden; }
.cpr-h { display: flex; align-items: baseline; gap: 10px; padding: 10px 14px; border-bottom: 1px solid var(--c-line); }
.cpr-h-t { font: 600 var(--t-base)/1 var(--f-sans); color: var(--c-text); }
.cpr-h-m { margin-left: auto; font: 400 var(--t-micro)/1 var(--f-sans); color: var(--c-text-3);
  font-variant-numeric: tabular-nums; }
.cpr-h-m[title] { cursor: help; border-bottom: 1px dotted var(--c-line-mid); }
.cpr-none { padding: 14px; font: 400 var(--t-aux)/1.6 var(--f-sans); color: var(--c-text-2); }

.cpr-tb { width: 100%; border-collapse: collapse; }
.cpr-tb th { text-align: left; padding: 7px 14px; white-space: nowrap;
  font: 400 var(--t-micro)/1.3 var(--f-sans); color: var(--c-text-3);
  border-bottom: 1px solid var(--c-line-weak); }
.cpr-tb td { padding: 8px 14px; vertical-align: middle;
  font: 400 var(--t-aux)/1.4 var(--f-sans); color: var(--c-text);
  border-bottom: 1px solid var(--c-line-weak); }
.cpr-tb tbody tr:last-child td { border-bottom: 0; }
.cpr-name { font-weight: 600; }
.cpr-num { font-variant-numeric: tabular-nums; }
.cpr-sub { color: var(--c-text-2); font-size: var(--t-micro); }

/* ── 这一台的细账（2026-09-17：点一台机器 → 它的卡 / 日志 / 节点）────
   机器那一行整行可点,所以它要有 hover / 选中 / 焦点三种样子 —— 只靠
   鼠标指针说「这行能点」的话,键盘与触摸都读不出（本仓 dead-affordance）。 */
.cpr-row { cursor: pointer; }
.cpr-row:hover td { background: var(--c-surface-2); }
.cpr-row[data-on="1"] td { background: var(--c-primary-wash); }
.cpr-row:focus-visible { outline: 2px solid var(--c-primary); outline-offset: -2px; }
.cpr-go { color: var(--c-primary); white-space: nowrap; }
.cpr-one { border-top: 1px solid var(--c-line); background: var(--c-surface); }
.cpr-one-h { display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 10px 14px; border-bottom: 1px solid var(--c-line-weak); }
.cpr-one-h .t { font: 600 var(--t-base)/1 var(--f-sans); color: var(--c-ink); }
.cpr-one-h .i { font: 400 var(--t-micro)/1 var(--f-mono); color: var(--c-text-3); }
.cpr-one-h .cpr-more { margin-inline-start: auto; }
.cpr-one-t { padding: 12px 14px 4px; font: 600 var(--t-aux)/1 var(--f-sans);
  color: var(--c-text-2); }
.cpr-one-kv { display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
  gap: 6px 16px; padding: 10px 14px; }
.cpr-one-r { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.cpr-one-r .k { flex: none; font: 400 var(--t-micro)/1.5 var(--f-sans); color: var(--c-text-3); }
.cpr-one-r .v { font: 400 var(--t-aux)/1.5 var(--f-mono); color: var(--c-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cpr-one-s { margin: 0; padding: 0 14px; max-width: 78ch;
  font: 400 var(--t-micro)/1.65 var(--f-sans); color: var(--c-text-3); }
/* 日志:**自己滚的一块,带 id** —— `记住滚动` 只认带 id 的节点。
   最新的在最上面(渲染时已经 reverse),所以不必自动滚到底。 */
.cpr-one-log { max-height: 260px; overflow-y: auto; margin: 8px 14px 14px;
  border: 1px solid var(--c-line-weak); border-radius: 4px; }
.cpr-one-log .ln { display: flex; gap: 10px; align-items: baseline;
  padding: 5px 10px; border-bottom: 1px solid var(--c-line-weak);
  font: 400 var(--t-micro)/1.6 var(--f-mono); }
.cpr-one-log .ln:last-child { border-bottom: 0; }
.cpr-one-log .lv { flex: none; width: 34px; color: var(--c-text-3); }
.cpr-one-log .lv[data-lv="warn"] { color: var(--c-amber); }
.cpr-one-log .lv[data-lv="error"] { color: var(--c-danger); }
.cpr-one-log .tx { color: var(--c-text); overflow-wrap: anywhere; }
.cpr-one-log .by { margin-inline-start: auto; flex: none; color: var(--c-text-3); }
.cpr-one-nodes { display: flex; flex-wrap: wrap; gap: 8px; padding: 8px 14px 14px; }
.cpr-node { display: inline-flex; align-items: baseline; gap: 6px;
  padding: 4px 9px; border-radius: 4px; border: 1px solid var(--c-line); }
.cpr-node b { font: 600 var(--t-micro)/1.4 var(--f-mono); color: var(--c-text); }
.cpr-node i { font-style: normal; font: 400 var(--t-micro)/1.4 var(--f-sans);
  color: var(--c-text-3); }
.cpr-node[data-可="y"] { border-color: var(--c-hud-dim); }
.cpr-node[data-可="y"] i { color: var(--c-hud); }
.cpr-node[data-可="n"] i { color: var(--c-danger); }

.cpr-st, .cpr-lg { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.cpr-dot { flex: none; box-sizing: border-box; width: 8px; height: 8px; border-radius: 50%;
  background: var(--c-text-3); }
.cpr-st[data-lv="ok"] .cpr-dot, .cpr-lg[data-lv="ok"] .cpr-dot { background: var(--c-primary); }
.cpr-st[data-lv="todo"], .cpr-lg[data-lv="todo"] { color: var(--c-amber); }
.cpr-st[data-lv="todo"] .cpr-dot, .cpr-lg[data-lv="todo"] .cpr-dot {
  background: transparent; border: 2px solid var(--c-amber); }
.cpr-st[data-lv="unknown"] .cpr-dot, .cpr-lg[data-lv="unknown"] .cpr-dot {
  background: transparent; border: 1.5px dashed var(--c-text-3); }
/* 「已关机 · 按任务起」「未运行 · 模拟」（2026-09-19）：离线是常态，**不是故障**
   —— 中性空心点，既不走琥珀也不走红。 */
.cpr-st[data-lv="idle"], .cpr-lg[data-lv="idle"] { color: var(--c-text-2); }
.cpr-st[data-lv="idle"] .cpr-dot, .cpr-lg[data-lv="idle"] .cpr-dot {
  background: transparent; border: 1.5px solid var(--c-text-3); }
.cpr-st[data-lv="none"], .cpr-lg[data-lv="none"] { color: var(--c-text-3); }
.cpr-st[data-lv="none"] .cpr-dot, .cpr-lg[data-lv="none"] .cpr-dot {
  width: 9px; height: 2px; border-radius: 1px; background: var(--c-line-mid); }

/* 「缺 N 项」是一颗真钮 —— 点开明细。琥珀：它是待办，不是报错。 */
.cpr-more { display: inline-flex; align-items: center; gap: 5px; cursor: pointer;
  border: 1px solid var(--c-line-mid); border-radius: 3px; background: transparent;
  padding: 2px 7px; font: 400 var(--t-micro)/1.4 var(--f-sans); color: var(--c-text-2); }
.cpr-more[data-lv="todo"] { border-color: var(--c-amber-line); color: var(--c-amber);
  background: var(--c-amber-wash); }
.cpr-more:focus-visible { outline: 2px solid var(--c-primary); outline-offset: 1px; }
.cpr-chev { width: 0; height: 0; border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent; border-top: 4px solid currentColor; }
.cpr-more[aria-expanded="true"] .cpr-chev { transform: rotate(180deg); }
.cpr-detail td { padding-top: 0; padding-left: 28px; }
.cpr-why { max-width: 78ch; font: 400 var(--t-micro)/1.6 var(--f-sans); color: var(--c-text-2); }
.cpr-miss { margin: 4px 0 0; padding-left: 16px; max-width: 78ch;
  font: 400 var(--t-micro)/1.7 var(--f-sans); color: var(--c-text-2); }

.cpr-legend { flex: none; display: flex; flex-wrap: wrap; gap: 18px; padding: 0 2px;
  font: 400 var(--t-micro)/1 var(--f-sans); color: var(--c-text-3); }

/* 查询页结果与输入框分行：第一行容纳完整输入区，第二行为独立的可滚动结果框。 */
.zt-query .zt-one { grid-template-rows: minmax(400px, auto) auto; align-content: start; }
/* 科学家分析结果在查询页中独立滚动。 */
.zt-query .zt-one { min-height: 0; overflow: auto; }
.zt-query .zt-platform-message { margin: 0 max(24px, calc((100% - var(--zt-reading)) / 2)) 24px; }
.zt-query .zt-research-result { max-height: min(56vh, 620px); overflow: auto; overscroll-behavior: contain; padding: 16px; border: 1px solid var(--zt-line); border-radius: 12px; background: var(--zt-panel); }
.zt-query .zt-research-result h3 { position: sticky; top: -16px; margin: -16px -16px 14px; padding: 14px 16px; background: var(--zt-panel); border-bottom: 1px solid var(--zt-line); }
.zt-query .zt-research-result pre { max-width: 100%; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }

/* 结果卡与查询输入框使用同一阅读宽度。 */
.zt-query .zt-platform-message .zt-research-result { width: 100%; flex: 1 1 auto; }

/* 检索提示置于结果卡下方，避免占用结果展示宽度。 */
.zt-query .zt-platform-message { flex-direction: column; align-items: stretch; }

/* 科研结果工作区：长回答不再塞进一条聊天气泡。两列分别承载结论/计划和
   资料/缺口；每个面板单独展开并滚动，阅读时不会丢失输入区或其他结果。 */
.zt-query .zt-research-workspace {
  width: min(var(--zt-reading), calc(100% - 48px)); margin: 0 auto 28px;
  display: grid; gap: 12px;
}
.zt-query .zt-research-workspace-head {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 16px;
  padding: 16px; border: 1px solid var(--zt-line); border-radius: 12px; background: var(--zt-panel);
}
.zt-query .zt-research-workspace-head h3 { margin: 4px 0 8px; }
.zt-query .zt-research-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; align-items: start; }
.zt-query .zt-research-panel {
  min-width: 0; border: 1px solid var(--zt-line); border-radius: 12px; background: var(--zt-panel);
}
.zt-query .zt-research-panel-summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; cursor: pointer; list-style: none;
}
.zt-query .zt-research-panel-summary::-webkit-details-marker { display: none; }
.zt-query .zt-research-panel-summary::after { content: '展开'; color: var(--zt-mute); font-size: 12px; }
.zt-query .zt-research-panel[open] .zt-research-panel-summary { border-bottom: 1px solid var(--zt-line); }
.zt-query .zt-research-panel[open] .zt-research-panel-summary::after { content: '收起'; }
.zt-query .zt-research-panel-body { max-height: min(48vh, 520px); overflow: auto; overscroll-behavior: contain; padding: 14px 16px 16px; }
.zt-query .zt-research-panel-body .zt-research-section:first-child { margin-top: 0; }
.zt-query .zt-research-panel-body h4 { margin-top: 0; }
.zt-query .zt-research-panel-body pre { max-width: 100%; overflow: auto; white-space: pre-wrap; overflow-wrap: anywhere; }

@media (max-width: 820px) {
  .zt-query .zt-research-workspace { width: min(var(--zt-reading), calc(100% - 28px)); }
  .zt-query .zt-research-workspace-head { flex-direction: column; }
  .zt-query .zt-research-panel-body { max-height: none; }
}

/* Shared capability tree: connectors express hierarchy, native details own disclosure. */
.discovery-tree { --tree-ink:var(--zt-ink); --tree-copy:var(--zt-ink-2); --tree-muted:var(--zt-ink-3); --tree-line:var(--zt-line-2); --tree-accent:var(--zt-accent); --tree-name:16px; --tree-stage:25px; --tree-label:14px; --tree-status:12px; color:var(--tree-ink); }
.discovery-tree-root { display:flex; align-items:baseline; flex-wrap:wrap; gap:12px 24px; padding-bottom:24px; position:relative; }
.discovery-tree-root h3,.discovery-tree-root h4 { margin:0; font-size:var(--tree-stage); font-weight:500; line-height:1.4; }
.discovery-tree-root > span { font-size:var(--tree-label); color:var(--tree-muted); }
.discovery-tree-root::after { content:''; position:absolute; bottom:-24px; left:12px; height:24px; border-left:1px solid var(--tree-line); }
.discovery-tree-stages { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:32px; list-style:none; padding:24px 0 0; margin:24px 0 0; position:relative; }
.discovery-tree-stages::before { content:''; position:absolute; top:0; left:12px; right:calc((100% - 64px)/3 - 12px); border-top:1px solid var(--tree-line); }
.discovery-tree-stages > li { min-width:0; position:relative; }
.discovery-tree-stages > li::before { content:''; position:absolute; left:12px; top:-24px; height:24px; border-left:1px solid var(--tree-line); }
.discovery-tree-stage > summary { cursor:pointer; min-height:72px; padding:12px 0 20px; line-height:1.4; list-style-position:inside; }
.discovery-tree summary::marker { color:var(--tree-accent); }
.discovery-tree summary:hover { color:var(--tree-accent); }
.discovery-tree summary:focus-visible { outline:2px solid var(--tree-accent); outline-offset:4px; }
.discovery-stage-title { font-size:var(--tree-stage); font-weight:500; }
.discovery-stage-focus { display:block; margin:8px 0 0 20px; color:var(--tree-muted); font-size:var(--tree-label); }
.discovery-branches { list-style:none; margin:0 0 0 12px; padding:0; }
.discovery-branches > li { position:relative; padding:0 0 8px 24px; border-left:1px solid var(--tree-line); }
.discovery-branches > li::before { content:''; position:absolute; left:0; top:22px; width:16px; border-top:1px solid var(--tree-line); }
.discovery-tree-branch > summary { cursor:pointer; min-height:44px; padding:10px 0; line-height:24px; font-size:var(--tree-label); font-weight:500; list-style-position:inside; }
.discovery-leaves { list-style:none; margin:0 0 8px 8px; padding:0; border-left:1px solid var(--tree-line); }
.discovery-leaf { min-width:0; position:relative; padding:8px 8px 8px 20px; font-size:var(--tree-name); line-height:1.5; }
.discovery-leaf::before { content:''; position:absolute; left:0; top:20px; width:12px; border-top:1px solid var(--tree-line); }
.discovery-leaf-name { display:block; overflow-wrap:anywhere; color:var(--tree-copy); }
.discovery-node-status { display:block; margin-top:4px; font-size:var(--tree-status); color:var(--tree-muted); line-height:1.5; }
.discovery-node-status::before,.discovery-legend > li::before { content:''; display:inline-block; width:6px; height:6px; margin-right:8px; border:1px solid currentColor; border-radius:50%; vertical-align:middle; }
[data-integration='connected'] > .discovery-node-status { color:var(--zt-accent); }
[data-integration='connected'] .discovery-node-status::before,.discovery-legend > [data-integration='connected']::before { background:var(--zt-accent); border-color:var(--zt-accent); }
[data-integration='planned'] > .discovery-node-status::before,.discovery-legend > [data-integration='planned']::before { border-width:0; border-top:1px solid currentColor; border-radius:0; height:0; }
.discovery-legend { display:flex; flex-wrap:wrap; gap:8px 28px; list-style:none; padding:0; margin:0 0 32px; font-size:13px; color:var(--zt-ink-3); }
.discovery-legend > li { min-height:24px; line-height:24px; }
.discovery-tree .workspace-capability { border:0; margin:0; }
.discovery-tree .workspace-capability.discovery-leaf { padding:8px 8px 8px 20px; }
.discovery-tree .workspace-capability-title { display:block; }
.discovery-tree .workspace-capability-title a { display:inline-block; font-size:var(--tree-name); line-height:1.5; min-height:24px; overflow-wrap:anywhere; }
.discovery-tree .workspace-capability-title .workspace-access-state { display:block; margin-top:4px; font-size:var(--tree-status); }
.discovery-tree .workspace-capability p { font-size:var(--tree-status); margin:4px 0 0; }
@media(max-width:900px) {
 .discovery-tree-stages { grid-template-columns:1fr; gap:24px; margin-top:0; padding:0 0 0 24px; border-left:1px solid var(--tree-line); }
 .discovery-tree-stages::before,.discovery-tree-root::after { display:none; }
 .discovery-tree-stages > li::before { left:-24px; top:28px; width:16px; height:0; border-left:0; border-top:1px solid var(--tree-line); }
 .discovery-tree-stage > summary { min-height:64px; }
 .discovery-tree .workspace-capability-title a { min-height:44px; display:flex; align-items:center; }
}

/* Domain siblings precede the current biopharma expansion on both surfaces. */
.discovery-domains { display:grid; grid-template-columns:repeat(6,minmax(0,1fr)); gap:24px; list-style:none; margin:24px 0 0; padding:0; border-top:1px solid var(--tree-line); }
.discovery-domains > li { position:relative; min-width:0; padding:20px 0 0 12px; }
.discovery-domains > li::before { content:''; position:absolute; left:12px; top:0; height:12px; border-left:1px solid var(--tree-line); }
.discovery-domain-name,.discovery-domains a { display:block; font-size:var(--tree-name); line-height:1.5; color:var(--tree-copy); overflow-wrap:anywhere; }
.discovery-domains a { text-underline-offset:5px; text-decoration-thickness:1px; color:var(--tree-accent); }
.discovery-domains a:hover { text-decoration:none; }
.discovery-domains a:focus-visible { outline:2px solid var(--tree-accent); outline-offset:4px; }
.discovery-domain-status { display:block; margin-top:8px; font-size:var(--tree-status); line-height:1.5; color:var(--tree-muted); }
[data-domain-status='focus'] > .discovery-domain-status { color:var(--tree-accent); }
.discovery-focus { margin-top:40px; }
.discovery-focus > h4 { margin:0; font-size:var(--tree-name); font-weight:500; line-height:1.5; scroll-margin-top:96px; }
.discovery-focus { scroll-margin-top:96px; }
@media(max-width:1000px) {
 .discovery-domains { grid-template-columns:repeat(3,minmax(0,1fr)); border-top:0; }
 .discovery-domains > li { border-top:1px solid var(--tree-line); }
}
@media(max-width:600px) {
 .discovery-domains { grid-template-columns:repeat(2,minmax(0,1fr)); gap:20px; }
 .discovery-domains a { min-height:44px; display:flex; align-items:center; }
 .discovery-focus { margin-top:32px; }
 .discovery-focus > h4 { margin-bottom:16px; }
}

.discovery-phase-overview { display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:24px; list-style:none; padding:0; margin:20px 0 0; }
.discovery-phase-overview > li { border-top:1px solid var(--tree-line); padding:16px 0; }
.discovery-phase-overview > li > span { display:block; font-size:var(--tree-name); line-height:1.5; }
.discovery-phase-overview > li > span + span { color:var(--tree-muted); font-size:var(--tree-label); margin-top:8px; }
@media(max-width:600px) { .discovery-phase-overview { grid-template-columns:1fr; gap:0; } }
