/* =========================================================================
   Workbench UI 大改版 · 交互稿样式表 —— 第 2 轮修订
   design-agent · 2026-08-16

   本轮的结构性改动（用户 2026-08-16 拍板）：
     · 行尾槽位按**五种条件**取值，不是「几种运行状态视觉」——绿/红/中性点
       都是**会话行的未读提示**，不是 Run 终态视觉（见 B1 段）。
       queued / waiting_for_worker / waiting_for_rate_limit 与 running 共用「在途」转圈
       （不是「并入在跑」——三者分别是未开始、等 Worker、暂停中）。
     · 删除左栏注意力区、落地看板四分组、会话行多态 chip、任务中心、
       身份头的 runner pill 与「＋新对话」。
     · 会话行状态是**行尾一个固定宽度的槽位**，所有行的点纵向对齐成一列；
       hover 时该槽位让位给三点菜单。
     · composer 改成实体容器：控件在容器内底边一行，容器上方无分隔线。

   两段：
     [A] 稿子外壳（doc chrome）—— 看稿工具，不是产品的一部分。
     [B] 产品侧（product）—— 装在设备框里的真界面。

   产品侧自查（DESIGN.md v2.2）：
     · 零 --wash-* / --gradient-sky / --decor-* / --forest-edge / --display
     · 主按钮 = --ink 实底 + --on-brand（随主题翻转）
     · --brand 不作任何文字色；绿字一律 --diff-add
     · 过程时间线无卡无影；只有 diff / code 块允许有边界
     · 焦点环 2px 实色 --brand，禁裸 outline:none
     · 圆角只取 4 / 8 / 14 / 18 / 9999 五档
     · 唯一新增动效 = 状态槽的转圈（用户指定），已配 reduced-motion 降级

   断点用 @container 而非 @media —— 桌面框与 H5 框并排跑同一份 CSS。
   ========================================================================= */

/* ===================================================================== */
/* [A] 稿子外壳                                                          */
/* ===================================================================== */

* { box-sizing: border-box; }
html { color-scheme: light dark; }

body {
  margin: 0;
  background: var(--shell);
  color: var(--ink);
  font-family: var(--sans);
  font-size: var(--fs-14);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

.doc { display: grid; grid-template-columns: 280px minmax(0, 1fr); min-height: 100vh; }

.doc-nav {
  border-right: 1px solid var(--border-soft);
  background: var(--shell);
  padding: var(--sp-5) 0 var(--sp-8);
  position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.doc-nav h1 { margin: 0 var(--sp-5) var(--sp-1); font-size: var(--fs-17); font-weight: var(--fw-title); letter-spacing: var(--ls-title); }
.doc-nav .sub { margin: 0 var(--sp-5) var(--sp-5); font-size: var(--fs-12); color: var(--ink-2-deep); line-height: 1.5; }

.doc-tabs { display: flex; gap: var(--sp-1); margin: 0 var(--sp-4) var(--sp-4); padding: 3px; background: var(--hover); border-radius: var(--r-sm); }
.doc-tab {
  flex: 1; border: 0; background: transparent; border-radius: 6px; padding: 6px 4px;
  font: inherit; font-size: var(--fs-12); font-weight: var(--fw-label); color: var(--ink-2-deep); cursor: pointer;
}
.doc-tab[aria-selected="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--sh-1); }

.doc-eyebrow {
  display: block; padding: var(--sp-3) var(--sp-5) var(--sp-1);
  font-size: var(--fs-10); letter-spacing: var(--ls-caps); text-transform: uppercase;
  color: var(--ink-3); font-weight: var(--fw-label);
}
.doc-link {
  display: flex; gap: var(--sp-2); align-items: baseline;
  width: calc(100% - var(--sp-4)); margin: 1px var(--sp-2); padding: 6px 10px;
  border: 0; border-radius: var(--r-sm); background: transparent;
  font: inherit; font-size: var(--fs-13); color: var(--ink-2-deep); text-align: left; cursor: pointer;
}
.doc-link:hover { background: var(--hover); }
.doc-link[aria-current="true"] { background: var(--hover); color: var(--ink); font-weight: var(--fw-ui); }
.doc-link .id { flex: none; width: 26px; font-family: var(--mono); font-size: 11px; color: var(--ink-3); }
.doc-link[aria-current="true"] .id { color: var(--brand-ink); }

.doc-stage { min-width: 0; padding: var(--sp-5) var(--sp-6) var(--sp-8); }
.stage-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-4); }
.stage-title { font-size: var(--fs-15); font-weight: var(--fw-title); }
.stage-spacer { margin-left: auto; }

.seg { display: inline-flex; padding: 3px; gap: 2px; background: var(--hover); border-radius: var(--r-sm); }
.seg button {
  border: 0; background: transparent; border-radius: 6px; padding: 5px 10px;
  font: inherit; font-size: var(--fs-12); font-weight: var(--fw-label); color: var(--ink-2-deep); cursor: pointer;
}
.seg button[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--sh-1); }

.stage-note {
  margin: 0 0 var(--sp-4); padding: var(--sp-3) var(--sp-4);
  background: var(--surface); border: 1px solid var(--border-soft);
  border-left: 3px solid var(--brand); border-radius: var(--r-sm);
  font-size: var(--fs-13); color: var(--ink-2-deep); line-height: 1.6; max-width: 76ch;
}
.stage-note b { color: var(--ink); font-weight: var(--fw-ui); }
.stage-note code { font-family: var(--mono); font-size: var(--fs-mono); background: var(--hover); padding: 1px 5px; border-radius: var(--r-xs); }
.stage-note--warn { border-left-color: var(--warn); }

.frames { display: flex; flex-wrap: wrap; gap: var(--sp-6); align-items: flex-start; }
.frame-slot { flex: none; }
.frame-cap { margin-bottom: var(--sp-2); font-size: var(--fs-12); font-weight: var(--fw-label); color: var(--ink-2-deep); }
.frame-cap .dim { font-family: var(--mono); color: var(--ink-3); font-weight: 400; }
.frame-box { overflow: hidden; }
.frame {
  transform-origin: top left;
  border: 1px solid var(--border); border-radius: var(--r-lg); overflow: hidden;
  background: var(--shell); box-shadow: var(--sh-2);
}

.spec-grid { display: grid; gap: var(--sp-5); max-width: 1100px; }
.spec { border: 1px solid var(--border-soft); border-radius: var(--r-lg); background: var(--surface); overflow: hidden; }
.spec > header {
  display: flex; align-items: baseline; gap: var(--sp-2);
  padding: var(--sp-3) var(--sp-4); border-bottom: 1px solid var(--border-soft); background: var(--shell);
}
.spec > header .id { font-family: var(--mono); font-size: var(--fs-12); color: var(--brand-ink); font-weight: var(--fw-label); }
.spec > header .name { font-size: var(--fs-13); font-weight: var(--fw-ui); }
.spec > header .why { margin-left: auto; font-size: var(--fs-12); color: var(--ink-2-deep); text-align: right; max-width: 46ch; }
.spec-body { padding: var(--sp-4); background: var(--canvas); }
.spec-body + .spec-body { border-top: 1px dashed var(--border-soft); }
.spec-cap { font-size: var(--fs-12); color: var(--ink-3); margin-bottom: var(--sp-2); }
/* 图鉴样张是简化 DOM：浮层类组件在这里是**摊平的静态外观**，按钮没有接线。
   不标出来，评审者会以为交互坏了。 */
.spec-static {
  display: inline-flex; align-items: center; gap: 5px;
  margin-bottom: var(--sp-2); padding: 3px 9px;
  border-radius: var(--r-full); background: var(--warn-soft);
  font-size: 11px; font-weight: var(--fw-label); color: var(--ink);
}
.spec-w { max-width: 620px; }
.spec-w--narrow { max-width: 343px; }

.doc-table { width: 100%; border-collapse: collapse; font-size: var(--fs-13); max-width: 1100px; }
.doc-table th, .doc-table td { text-align: left; vertical-align: top; padding: 8px 10px; border-bottom: 1px solid var(--border-soft); line-height: 1.55; }
.doc-table th { font-size: var(--fs-12); font-weight: var(--fw-label); color: var(--ink-2-deep); background: var(--hover); position: sticky; top: 0; }
.doc-table td.ref { font-family: var(--mono); font-size: var(--fs-mono); color: var(--brand-ink); white-space: nowrap; }
.doc-table td.cut { color: var(--ink-2-deep); }
.rev5 { color: var(--danger); font-weight: var(--fw-label); white-space: nowrap; }
.doc-table tr.is-cut td:first-child { color: var(--ink-2-deep); }
.doc-h2 { margin: var(--sp-8) 0 var(--sp-3); font-size: var(--fs-15); font-weight: var(--fw-title); }
.doc-h2:first-child { margin-top: 0; }
.doc-p { max-width: 76ch; font-size: var(--fs-13); color: var(--ink-2-deep); line-height: 1.65; }
.doc-p b { color: var(--ink); }
.doc-q { max-width: 90ch; border: 1px solid var(--border-soft); border-radius: var(--r); background: var(--surface); padding: var(--sp-4); margin-bottom: var(--sp-4); }
.doc-q h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-14); font-weight: var(--fw-ui); }
.doc-q h3 .id { font-family: var(--mono); color: var(--brand-ink); margin-right: 6px; }
.doc-q dl { margin: 0; font-size: var(--fs-13); line-height: 1.65; }
.doc-q dt { font-size: var(--fs-12); font-weight: var(--fw-label); color: var(--ink-3); letter-spacing: var(--ls-caps); text-transform: uppercase; margin-top: var(--sp-3); }
.doc-q dd { margin: 2px 0 0; color: var(--ink-2-deep); }
.doc-q dd b { color: var(--ink); font-weight: var(--fw-ui); }

.doc :focus-visible, .wb :focus-visible { outline: none; box-shadow: var(--focus-ring); border-radius: var(--r-xs); }

/* ---------------------------------------------------------------------
   稿子外壳的窄屏收敛。
   这一段修的是**稿子外壳**的横向溢出，不是产品界面：
   .doc 的栅格第一列写死 280px，窗口 375 时舞台只剩 95px，
   顶部工具条那几组 .seg 直接顶出去（实测 right=460，溢出 85px）。
   工具条本身已经 flex-wrap，但父级宽度不够，wrap 也救不回来。
   --------------------------------------------------------------------- */
@media (max-width: 900px) {
  .doc { grid-template-columns: minmax(0, 1fr); }
  .doc-nav {
    position: static; height: auto; max-height: 46vh;
    border-right: 0; border-bottom: 1px solid var(--border-soft);
    padding-bottom: var(--sp-4);
  }
  .doc-stage { padding: var(--sp-4) var(--sp-3) var(--sp-8); }
  /* 工具条：先允许换行，实在放不下再横滚，绝不外溢 */
  .stage-bar { overflow-x: auto; padding-bottom: 2px; }
  .stage-spacer { display: none; }
  .seg { flex: none; }
  .spec > header { flex-wrap: wrap; }
  .spec > header .why { margin-left: 0; text-align: left; max-width: none; }
  .spec-body { padding: var(--sp-3); }
  .doc-q { padding: var(--sp-3); }
  .frames { gap: var(--sp-4); }
}

/* 表格在窄屏必然比 375 宽——给它一个横滚容器，而不是让它撑破页面 */
.doc-tablewrap { overflow-x: auto; max-width: 1100px; }
.doc-tablewrap .doc-table th { position: static; }

/* ===================================================================== */
/* [B] 产品侧                                                            */
/* ===================================================================== */

.wb {
  container-type: inline-size; container-name: app;
  position: relative; display: flex; height: 100%; overflow: hidden;
  background: var(--shell); color: var(--ink);
  font-family: var(--sans); font-size: var(--fs-14); line-height: var(--lh-body);
  isolation: isolate;
}
.wb [hidden] { display: none !important; }

/* --------------------------------------------------------------------- */
/* B1. 行尾槽位 —— 五种条件                                                */
/*                                                                        */
/*     按顺序取第一个成立的条件，不是「几种运行状态视觉」：                */
/*       1. active_run_id 指针非空            → 转圈                       */
/*       2. 未读 gm_unread_kind === done      → 绿点                       */
/*       3. 未读 gm_unread_kind === stopped   → 红点                       */
/*       4. 未读 needs_you 或未知 kind        → 中性点                     */
/*       5. 无未读                            → 空槽                       */
/*                                                                        */
/*     ★ 空槽只称「无未读提示」。不得称「无事」，也不得从空槽反推           */
/*       「没有在途 Run」—— on_busy=queue 会让 active_run_id 漏报，        */
/*       指针为空证明不了不存在非终态 Run。                                */
/*                                                                        */
/*     ★ 绿 / 红 / 中性点**只用于会话行**，是未读提示不是 Run 终态视觉。    */
/*       其它位置的终态一律用文字徽章。已读之后活儿依然在，                */
/*       只是不再提示你；点进会话即调 POST /sessions/:id/read 清零。       */
/*                                                                        */
/*     行尾固定宽度，所有行的点纵向对齐成一列（用户参考图 ref-01b）。       */
/*     转圈刻意不上语义色：在途既不是好也不是坏；只有未读点有颜色。         */
/*     三种点与转圈的视觉重量刻意拉平：点 7px，圈 12px 细描边中性色。       */
/* --------------------------------------------------------------------- */
.wb-st {
  width: 20px; height: 20px; flex: none;
  display: grid; place-items: center;
}
.wb-st__dot { width: 7px; height: 7px; border-radius: var(--r-full); display: block; }
.wb-st--done .wb-st__dot { background: var(--ok); }
.wb-st--fail .wb-st__dot { background: var(--danger); }
/* gm_unread_kind 的真实取值是 needs_you / stopped / done。
   needs_you 与任何未知 kind 一律降级为中性点：它确实是「有未读」，
   但既不是成功也不是失败，拿绿点或红点顶替就是替后端下结论。 */
.wb-st--todo .wb-st__dot { background: var(--ink-2-deep); }
.wb-st--run .wb-st__dot {
  width: 12px; height: 12px;
  background: none;
  border: 1.5px solid var(--border);
  border-top-color: var(--ink-3);
  animation: wb-spin 900ms linear infinite;
}
@keyframes wb-spin { to { transform: rotate(360deg); } }

/* 正文里永远配文字标签；会话行是例外，那里只有点。
   点与点之间仅色相区分，是用户 2026-08-16 明确选定的方案。
   .wb-st--read 是「无未读提示」的空槽（不叫「无事」——已读过的 needs_you
   仍可能待处理）。它必须真的占位，
   否则同一列里有点的行和没点的行会左右错开。 */
.wb-st--read { visibility: hidden; }
.wb-stx { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-13); color: var(--ink-2-deep); }
.wb-stx b { color: var(--ink); font-weight: var(--fw-ui); }

@media (prefers-reduced-motion: reduce) {
  .wb-st--run .wb-st__dot { animation: none; border-top-color: var(--border); border-left-color: var(--ink-3); }
  * { animation-duration: 1ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; }
}

/* --------------------------------------------------------------------- */
/* B2. 左栏                                                               */
/* --------------------------------------------------------------------- */
.wb-rail {
  width: 264px; flex: none; display: flex; flex-direction: column;
  background: var(--shell); border-right: 1px solid var(--border-soft); min-height: 0;
}
.wb-rail__head { padding: var(--sp-5) var(--sp-4) var(--sp-2); }
.wb-wordmark { margin: 0; font-size: var(--fs-17); font-weight: var(--fw-title); letter-spacing: var(--ls-title); line-height: 1.2; }
.wb-wordmark i { color: var(--brand-ink); font-style: normal; }

/* AGENTS 是最顶层的分组目录。照用户指定的 Notion 侧栏做法：
   标题本身是**弱化的小字**（不是强调色块），**折叠语义由那枚很轻的箭头承担**，
   整行可点、hover 才给底色。做强靠的是「箭头 + 位置 + 留白」，不是加重它。
   刻意不加 border-top —— Notion 分层靠留白与对齐，不靠边框。 */
.wb-dir {
  display: flex; align-items: center; gap: 6px;
  width: calc(100% - var(--sp-4)); min-height: 28px;
  margin: var(--sp-3) var(--sp-2) 2px;
  /* 右内距取 6px 而不是 8px：让 AGENTS 的计数右缘与下面每个 agent 行
     槽位的右缘落在同一条线上（agent 行是 padding-right 6px）。 */
  padding: 4px 6px 4px 8px;
  border: 0; border-radius: var(--r-sm);
  background: transparent;
  font: inherit; font-size: var(--fs-12); font-weight: var(--fw-label);
  color: var(--ink-3);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  text-align: left; cursor: pointer;
}
.wb-dir:hover { background: var(--hover); color: var(--ink-2-deep); }
/* 箭头：折叠语义的唯一载体，所以它常显；但很轻，不与标题争。 */
.wb-dir__caret {
  flex: none; width: 12px; text-align: center;
  color: var(--ink-3); font-size: 9px; letter-spacing: 0;
  transition: transform var(--dur-2) var(--ease-standard);
}
.wb-dir:hover .wb-dir__caret { color: var(--ink-2-deep); }
/* 收起 = › 指右，展开 = 转 90° 指下。与过程折叠用同一枚字形，全站折叠语义一致。
   选择器不绑 .wb-rail —— 图鉴样张容器只有 343px，套上 .wb-rail 会被
   ≤640 的容器查询整块 display:none 掉。挂在 [data-dir] 上即可。 */
[data-dir="open"] .wb-dir__caret { transform: rotate(90deg); }
[data-dir="closed"] .wb-rail__scroll { display: none; }
/* 右侧留操作位：目前 agents 这一层没有真实动作可放，所以只放计数，
   不发明一个 ⋯ 菜单（发明出来就是假功能）。槽位宽度先占住，
   将来真有动作时不会让整行跳动。 */
.wb-dir__n {
  margin-left: auto; flex: none; min-width: 16px; text-align: right;
  font-family: var(--mono); font-size: 11px; font-weight: 400;
  letter-spacing: 0; color: var(--ink-3);
}

.wb-rail__scroll { flex: 1; overflow-y: auto; padding: var(--sp-1) 0 var(--sp-4); min-height: 0; }

/* ---- Agent 行：无箭头，图标左收，点整行折叠 ---- */
/* 行 = 容器（div），里面是「主命中按钮 + 同级三点按钮」。
   不能把三点做成嵌在行按钮里的 <button> —— 按钮套按钮是非法 HTML，
   解析器会提前闭合外层按钮，整行结构会塌。 */
.wb-agent { padding: 0 var(--sp-2); }
.wb-agent__row {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; min-height: 32px; padding-right: 6px;
  border-radius: var(--r-sm); position: relative;
}
.wb-agent__row:hover { background: var(--hover); }
.wb-agent__hit,
.wb-sess__hit {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: var(--sp-2);
  min-height: 32px; padding: 5px 0 5px 8px;
  border: 0; background: transparent; border-radius: var(--r-sm);
  font: inherit; color: inherit; text-align: left; cursor: pointer;
}
.wb-agent__mono {
  width: 20px; height: 20px; flex: none; border-radius: var(--r-xs);
  font-size: 10px; font-weight: var(--fw-label);
  display: grid; place-items: center; letter-spacing: 0;
}
.wb-agent__name { font-size: var(--fs-13); font-weight: var(--fw-ui); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 计数住在 .wb-slot 里（不在 hit 按钮里）——只有同处一格，
   它和三点切换时才可能零位移。右对齐，与会话行的状态点共用同一条右缘。 */
.wb-agent__n {
  font-family: var(--mono); font-size: 11px; color: var(--ink-3);
  display: flex; align-items: center; justify-content: flex-end;
  pointer-events: none;
}
.wb-agent[data-open="false"] .wb-agent__sessions { display: none; }

/* 角色色只作分类语义，同屏 ≤3 种（DESIGN §3.5）。
   GM 不占彩色档：编排者用「重量」区分，彩色角色档保持 5 枚。 */
.role-gm      { background: var(--ink);              color: var(--on-brand); }
.role-dev     { background: var(--role-dev-soft);    color: var(--ink); }
.role-design  { background: var(--role-design-soft); color: var(--ink); }
.role-neutral { background: var(--hover);            color: var(--ink-2-deep); }

/* ---- 会话行 ---- */
/* 缩进：会话文字与 agent 名左缘对齐（agent 行 padding 8 + 图标 20 + gap 8 = 36）。
   箭头删掉之后，缩进是唯一的父子信号，所以它必须落在这个精确值上。 */
.wb-agent__sessions { padding-bottom: 2px; }
.wb-sess {
  display: flex; align-items: center; gap: var(--sp-2);
  width: calc(100% - 28px); margin-left: 28px;
  min-height: 32px; padding-right: 6px;
  border-radius: var(--r-sm);
  font-size: var(--fs-13); color: var(--ink);
  position: relative;
}
.wb-sess:hover { background: var(--hover); }
.wb-sess__label { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-sess[aria-current="true"] { background: var(--surface); box-shadow: var(--sh-ring), var(--sh-1); font-weight: var(--fw-ui); }
.wb-sess[aria-current="true"]::before {
  content: ""; position: absolute; left: -10px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 16px; border-radius: var(--r-full); background: var(--brand);
}

/* 行尾槽位：状态 ↔ 三点菜单同占一格，桌面 hover 时互换，
   触屏没有 hover，所以 ≤640 改成两格并列（见 @container 段）。 */
.wb-slot { position: relative; width: 20px; height: 20px; flex: none; }
/* 槽里的东西全部叠在同一格，谁显谁隐都不会推动布局 */
.wb-slot > .wb-st, .wb-slot > .wb-more, .wb-slot > .wb-agent__n { position: absolute; inset: 0; }
/* 三点菜单挂进触发它的那个槽位里，避免跨缩放设备框做坐标换算 */
.wb-slot > .wb-menu { position: absolute; inset: auto 0 auto auto; top: calc(100% + 4px); }
.wb-more {
  display: none;
  width: 20px; height: 20px; padding: 0;
  border: 0; border-radius: var(--r-xs); background: transparent;
  color: var(--ink-2-deep); font: inherit; font-size: 13px; line-height: 1;
  cursor: pointer; place-items: center;
}
.wb-more:hover { background: var(--border-soft); color: var(--ink); }
/* 悬停 / 键盘聚焦时，槽里的常驻内容让位给三点。
   会话行让位的是状态点，agent 行让位的是计数（用户 2026-08-16 批注）。
   两者都用 visibility 而不是 display —— 位置照旧被占住，右边界一动不动。 */
.wb-sess:hover .wb-slot > .wb-st,
.wb-sess:focus-within .wb-slot > .wb-st,
.wb-agent__row:hover .wb-slot > .wb-agent__n,
.wb-agent__row:focus-within .wb-slot > .wb-agent__n { visibility: hidden; }
.wb-sess:hover > .wb-slot > .wb-more,
.wb-sess:focus-within > .wb-slot > .wb-more,
.wb-agent__row:hover > .wb-slot > .wb-more,
.wb-agent__row:focus-within > .wb-slot > .wb-more { display: grid; }

/* 历史枝：弱化、排最后、无新建入口 */
.wb-agent--history .wb-agent__name { color: var(--ink-2-deep); font-weight: var(--fw-body); }
.wb-agent--history .wb-sess { color: var(--ink-2-deep); }

/* ---- 左栏页脚：Mac 心跳灯常驻，钉在左栏最底部 ----
   margin-top: auto 是关键。之前靠 .wb-rail__scroll 的 flex:1 撑着，
   一旦 AGENTS 目录折叠（scroll 变 display:none），页脚就跟着往上跑。 */
.wb-rail__foot {
  margin-top: auto;
  flex: none; border-top: 1px solid var(--border-soft);
  padding: var(--sp-2) var(--sp-3);
  padding-bottom: max(var(--sp-2), env(safe-area-inset-bottom));
  display: flex; align-items: center; gap: var(--sp-2);
}
.wb-me { display: flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-13); color: var(--ink-2-deep); }
.wb-me__avatar {
  width: 22px; height: 22px; border-radius: var(--r-full);
  background: var(--hover); color: var(--ink);
  font-size: 10px; font-weight: var(--fw-label); display: grid; place-items: center;
}
.wb-hb {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  min-height: 24px; padding: 3px 8px;
  border: 0; border-radius: var(--r-full); background: var(--hover);
  font: inherit; font-size: 11px; font-weight: var(--fw-label); color: var(--ink-2-deep); cursor: pointer;
}
.wb-hb i { width: 6px; height: 6px; border-radius: var(--r-full); background: var(--ink-3); flex: none; }
.wb-hb[data-health="online"] i { background: var(--ok); }
.wb-hb[data-health="busy"] i { background: var(--brand); }
.wb-hb[data-health="recently_lost"] i { background: var(--warn); }
.wb-hb[data-health="offline"] i { background: var(--danger); }
.wb-hb[data-health="offline"] { background: var(--danger-soft); color: var(--danger); }
.wb-hb[data-health="recently_lost"] { background: var(--warn-soft); color: var(--ink); }

/* --------------------------------------------------------------------- */
/* B3. 主区 · 身份头                                                      */
/*     主标题 = Session 名；Agent 名退成旁边的小字备注。                   */
/*     runner 已移进详情层；「＋新对话」已移到左栏 Agent 的三点菜单。       */
/* --------------------------------------------------------------------- */
.wb-main { flex: 1; min-width: 0; display: flex; flex-direction: column; background: var(--canvas); }

.wb-idbar {
  flex: none; display: flex; align-items: center; gap: var(--sp-2);
  min-height: 48px; padding: var(--sp-2) var(--sp-5);
  background: var(--shell); border-bottom: 1px solid var(--border-soft);
}
.wb-idbar__main { min-width: 0; display: flex; align-items: baseline; gap: var(--sp-2); }
.wb-idbar__title {
  font-size: var(--fs-15); font-weight: var(--fw-ui); letter-spacing: var(--ls-title);
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Agent 名 + 详情键是一组：详情说明的是这个 agent，所以它跟着名字走，
   不再是身份头右端一个孤立的文字按钮（用户 N-4）。 */
.wb-idbar__by {
  flex: none; display: inline-flex; align-items: center; gap: 3px;
  font-size: var(--fs-12); color: var(--ink-3);
}
/* 身份头右端已清空（N-4 把详情挪到左侧、N-5 删了桌面 ☰、rev2 已删 runner 与＋新对话），
   所以不再有 .wb-idbar__actions 这一组。 */

/* 小感叹号：细圆环 + ! 字形。中性色不用 warn 色——它是「看详情」不是「出问题」。 */
.wb-info {
  flex: none; position: relative;
  width: 16px; height: 16px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--r-full);
  background: transparent; color: var(--ink-2-deep);
  font: inherit; font-size: 10px; font-weight: var(--fw-label); line-height: 1;
  display: grid; place-items: center; cursor: pointer;
  align-self: center;
}
.wb-info:hover { background: var(--hover); color: var(--ink); border-color: var(--ink-3); }
/* 16px 图形达不到触控下限，用不可见的伪元素把命中区撑到 --tap-aa / --tap-min，
   不靠放大图形本身——放大会让它在文字旁边显得很笨重。 */
.wb-info::after {
  content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: var(--tap-aa); height: var(--tap-aa);
}
/* ☰ 只在 ≤640 出现。必须写成 .wb-x.wb-burger（两个类）——
   .wb-x 的 display:grid 定义在本文件更靠后的浮层段，单类选择器同权重、
   后者胜出，会让 ☰ 在桌面端显形。这是用户 N-5 点到的那个按钮。 */
.wb-x.wb-burger { display: none; }

/* --------------------------------------------------------------------- */
/* B4. 对话画布                                                           */
/* --------------------------------------------------------------------- */
.wb-conv { flex: 1; overflow-y: auto; padding: var(--sp-6) var(--sp-5) var(--sp-2); min-height: 0; }
.wb-thread { max-width: 860px; margin: 0 auto; }

.wb-daysep, .wb-turnsep {
  display: flex; align-items: center; gap: var(--sp-3);
  font-size: var(--fs-10); letter-spacing: var(--ls-caps); text-transform: uppercase;
  color: var(--ink-3); margin: 0 0 var(--sp-5);
}
.wb-daysep::before, .wb-daysep::after,
.wb-turnsep::before, .wb-turnsep::after { content: ""; height: 1px; flex: 1; background: var(--border-soft); }
.wb-turnsep { margin: var(--sp-6) 0 var(--sp-5); }
.wb-unreadsep { color: var(--danger); margin: var(--sp-6) 0 var(--sp-5); }
.wb-unreadsep::before, .wb-unreadsep::after { background: var(--danger-soft); }

.wb-user { display: flex; justify-content: flex-end; margin-bottom: var(--sp-5); }
.wb-user__b {
  max-width: 78%; background: var(--brand-soft);
  border-radius: var(--r) var(--r) var(--r-xs) var(--r);
  padding: var(--bubble-pad); font-size: var(--fs-14); line-height: var(--lh-body);
  overflow-wrap: anywhere;
}
.wb-user__att { display: flex; flex-wrap: wrap; gap: 6px; margin-top: var(--sp-2); padding-top: var(--sp-2); border-top: 1px solid var(--border-soft); }

.wb-note { display: flex; gap: var(--sp-2); margin: 0 0 var(--sp-4); padding: 9px 12px; border-radius: var(--r-sm); font-size: var(--fs-13); line-height: 1.6; }
.wb-note b { font-weight: var(--fw-ui); }
.wb-note--info { background: var(--info-soft); color: var(--ink); }
.wb-note--warn { background: var(--warn-soft); color: var(--ink); }
.wb-note--err { background: var(--danger-soft); color: var(--ink); }
.wb-sys { margin: 0 0 var(--sp-4); font-size: var(--fs-12); color: var(--ink-2-deep); text-align: center; }
.wb-raw { margin: 0 0 var(--sp-4); font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-3); white-space: pre-wrap; overflow-wrap: anywhere; }

/* --------------------------------------------------------------------- */
/* B5. 过程（第二层）—— 无卡无影；八个状态一律默认折叠                     */
/* --------------------------------------------------------------------- */
.wb-proc { margin: 0 0 var(--sp-5); }
.wb-proc__sum {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; min-height: 30px; padding: 4px 8px 4px 4px;
  border: 0; background: transparent; border-radius: var(--r-sm);
  font: inherit; font-size: var(--fs-13); color: var(--ink-2-deep);
  text-align: left; cursor: pointer;
}
.wb-proc__sum:hover { background: var(--hover); }
.wb-proc__chev { flex: none; width: 12px; color: var(--ink-3); font-size: 10px; transition: transform var(--dur-2) var(--ease-standard); }
.wb-proc[data-open="true"] .wb-proc__chev { transform: rotate(90deg); }
.wb-proc[data-open="false"] .wb-proc__body { display: none; }
.wb-proc__sum .k { color: var(--ink); font-weight: var(--fw-ui); }
.wb-proc__sum .fail { color: var(--danger); }

.wb-proc__body { border-left: 2px solid var(--border); padding: var(--sp-1) 0 var(--sp-1) var(--sp-3); margin: 2px 0 0 6px; }

.wb-step { font-size: var(--fs-13); line-height: 1.6; overflow-wrap: anywhere; }
.wb-step__i { display: inline-block; width: 14px; flex: none; color: var(--diff-add); font-size: 11px; }
.wb-step__t { font-weight: var(--fw-ui); margin-right: 6px; }
.wb-step__a { font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-2-deep); }
.wb-step--err .wb-step__i, .wb-step--err .wb-step__t { color: var(--danger); }
.wb-step--run .wb-step__i { color: var(--brand-ink); }
.wb-out { margin: 1px 0 5px 20px; font-family: var(--mono); font-size: var(--fs-mono); line-height: var(--lh-mono); color: var(--ink-2-deep); white-space: pre; overflow-x: auto; }
.wb-out .fail { color: var(--danger); }
.wb-narr { font-size: var(--fs-13); color: var(--ink-2-deep); margin: 2px 0 5px; }

.wb-fold { margin: 4px 0 6px; }
.wb-fold__t {
  display: inline-flex; align-items: center; gap: 6px; min-height: 24px;
  padding: 2px 6px 2px 2px; border: 0; background: transparent; border-radius: var(--r-xs);
  font: inherit; font-size: var(--fs-12); color: var(--ink-2-deep); cursor: pointer;
}
.wb-fold__t:hover { background: var(--hover); color: var(--ink); }
.wb-fold__t i { color: var(--ink-3); font-size: 10px; font-style: normal; transition: transform var(--dur-2) var(--ease-standard); }
.wb-fold[data-open="true"] .wb-fold__t i { transform: rotate(90deg); }
.wb-fold[data-open="false"] .wb-fold__c { display: none; }
.wb-fold__c { margin: 4px 0 0 20px; font-size: var(--fs-13); color: var(--ink-2-deep); line-height: 1.65; }
.wb-fold__c--mono { font-family: var(--mono); font-size: var(--fs-mono); white-space: pre-wrap; overflow-wrap: anywhere; color: var(--ink-3); max-height: 190px; overflow-y: auto; }

.wb-search { font-size: var(--fs-13); color: var(--ink-2-deep); margin: 2px 0 5px; }
.wb-search__q {
  background: linear-gradient(90deg, var(--ink-3) 0%, var(--ink) 45%, var(--ink-3) 90%);
  background-size: 220% 100%; -webkit-background-clip: text; background-clip: text; color: transparent;
  animation: wb-shim 1.7s linear infinite;
}
@keyframes wb-shim { to { background-position: -220% 0; } }

/* diff 摘录块 & 代码块：时间线里唯一允许有边界的两种（DESIGN §5.2） */
.wb-fd { margin: var(--sp-2) 0 var(--sp-2) 20px; background: var(--surface); border-radius: var(--r-sm); box-shadow: var(--sh-ring); overflow: hidden; font-family: var(--mono); }
.wb-fd__h { display: flex; align-items: center; gap: 7px; padding: 7px 11px; border-bottom: 1px solid var(--border-soft); font-size: var(--fs-mono); }
.wb-fd__f { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 摘录标签：diff 卡展示的是**单次 Edit 的 excerpt**，不是整文件 Git 统计。
   增删数按 excerpt 实际行数算；没有 hunk header 就不补行号（补了就是编）。 */
.wb-fd__tag {
  flex: none; margin-left: auto;
  font-family: var(--sans); font-size: 11px; color: var(--ink-3);
}
.wb-fd__add { flex: none; margin-left: 8px; color: var(--diff-add); font-size: 12px; }
.wb-fd__del { flex: none; color: var(--diff-del); font-size: 12px; }
.wb-fd__r { position: relative; display: grid; grid-template-columns: 30px 30px 16px minmax(0, 1fr); font-size: var(--fs-mono); line-height: 20px; }
.wb-fd__r:first-of-type { margin-top: 3px; }
.wb-fd__r:last-child { margin-bottom: 3px; }
.wb-fd__ln, .wb-fd__s { user-select: none; color: var(--ink-3); font-size: 11px; }
.wb-fd__ln { text-align: right; padding: 0 6px; }
.wb-fd__s { text-align: center; }
.wb-fd__r code { white-space: pre; overflow-x: auto; padding: 0 10px 0 6px; color: var(--ink-2-deep); }
.wb-fd__r--a { background: var(--diff-add-bg); }
.wb-fd__r--d { background: var(--diff-del-bg); }
.wb-fd__r--a code, .wb-fd__r--d code { color: var(--ink); }
.wb-fd__r--a .wb-fd__s { color: var(--diff-add); }
.wb-fd__r--d .wb-fd__s { color: var(--diff-del); }
.wb-fd__r--a::before, .wb-fd__r--d::before { content: ""; position: absolute; inset: 0 auto 0 0; width: 3px; }
.wb-fd__r--a::before { background: var(--diff-add); }
.wb-fd__r--d::before { background: repeating-linear-gradient(45deg, var(--diff-del) 0 1.5px, transparent 1.5px 3px); }

.wb-code { margin: var(--sp-2) 0; background: var(--code-bg); color: var(--code-ink); border-radius: var(--r-sm); padding: 10px 12px; font-family: var(--mono); font-size: var(--fs-mono); line-height: var(--lh-mono); overflow-x: auto; }
.wb-code pre { margin: 0; white-space: pre; }

/* --------------------------------------------------------------------- */
/* B6. 回答卡                                                             */
/* --------------------------------------------------------------------- */
.wb-ans {
  background: var(--surface); border: 1px solid var(--border-soft);
  border-radius: var(--r); box-shadow: var(--sh-1);
  padding: var(--sp-4) var(--sp-5); margin-bottom: var(--sp-5);
}
.wb-ans p { margin: 0 0 10px; line-height: var(--lh-body); }
.wb-ans > *:last-child { margin-bottom: 0; }
.wb-ans h3 { margin: var(--sp-4) 0 var(--sp-2); font-size: var(--fs-15); font-weight: var(--fw-title); }
.wb-ans h3:first-child { margin-top: 0; }
.wb-ans ul, .wb-ans ol { margin: 0 0 10px; padding-left: 20px; }
.wb-ans li { margin-bottom: 3px; line-height: var(--lh-body); }
.wb-ans a { color: var(--brand-ink); text-underline-offset: 2px; }
.wb-ans code { font-family: var(--mono); font-size: var(--fs-mono); background: var(--hover); padding: 1px 5px; border-radius: var(--r-xs); }
.wb-ans blockquote { margin: 0 0 10px; padding: 2px 0 2px 12px; border-left: 2px solid var(--border); color: var(--ink-2-deep); }
.wb-ans hr { border: 0; border-top: 1px solid var(--border-soft); margin: var(--sp-4) 0; }
/* 表格必须能横滚：375px 下三列表格会撑破卡片 */
.wb-tablewrap { overflow-x: auto; margin: 0 0 10px; }
.wb-ans table { width: 100%; border-collapse: collapse; font-size: var(--fs-13); }
.wb-ans th, .wb-ans td { text-align: left; padding: 6px 9px; border-bottom: 1px solid var(--border-soft); white-space: nowrap; }
.wb-ans th { font-weight: var(--fw-label); font-size: var(--fs-12); color: var(--ink-2-deep); background: var(--hover); }
.wb-ans .tasklist { list-style: none; padding-left: 2px; }
.wb-ans .tasklist li { display: flex; gap: 8px; align-items: baseline; }
.wb-ans .tasklist .box { flex: none; font-family: var(--mono); color: var(--ink-3); }
.wb-ans .tasklist .done { color: var(--diff-add); }
.wb-ans .tasklist li.is-done { color: var(--ink-2-deep); }

.wb-stream::after {
  content: ""; display: inline-block; width: 7px; height: 15px; margin-left: 2px;
  vertical-align: text-bottom; background: var(--ink-3); animation: wb-caret 1s steps(1) infinite;
}
@keyframes wb-caret { 50% { opacity: 0; } }

/* 结果面板 */
.wb-res { margin-top: var(--sp-4); padding-top: var(--sp-4); border-top: 1px solid var(--border-soft); }
.wb-res + .wb-res { margin-top: var(--sp-3); padding-top: var(--sp-3); }
.wb-res__l { font-size: var(--fs-10); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--ink-3); font-weight: var(--fw-label); margin-bottom: var(--sp-2); }
.wb-res__none { font-size: var(--fs-13); color: var(--ink-3); }
.wb-file { display: flex; align-items: center; gap: 9px; min-height: 24px; }
.wb-file__m { width: 17px; height: 17px; flex: none; border-radius: var(--r-xs); font-size: 10px; font-weight: var(--fw-label); display: grid; place-items: center; font-family: var(--mono); }
/* porcelain 的状态域不止 M/A/D：还有 R(重命名) C(复制) U(冲突) ?(未跟踪) !(忽略)
   以及双列组合（AM、MM…）。只给最常见的几种上语义色，其余一律中性降级，
   不硬塞进三选一——塞了就是替 git 下结论。 */
.wb-file__m--M { background: var(--brand-soft); color: var(--brand-ink); }
.wb-file__m--A { background: var(--ok-soft); color: var(--diff-add); }
.wb-file__m--D { background: var(--danger-soft); color: var(--danger); }
.wb-file__m--R { background: var(--hover); color: var(--ink-2-deep); }
.wb-file__m--U { background: var(--warn-soft); color: var(--ink); }
.wb-file__m--Q,
.wb-file__m--X { background: var(--hover); color: var(--ink-2-deep); font-size: 9px; }
.wb-file__p { min-width: 0; font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-2-deep); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-file__s { margin-left: auto; flex: none; font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); }
.wb-file__s .a { color: var(--diff-add); }
.wb-file__s .d { color: var(--diff-del); }

.wb-art { display: flex; align-items: center; gap: 9px; min-height: 26px; font-size: var(--fs-13); }
.wb-art__i { flex: none; color: var(--ink-3); font-size: 11px; width: 14px; text-align: center; }
.wb-art a { color: var(--brand-ink); }
.wb-art__path { min-width: 0; font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-2-deep); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-art__tag { margin-left: auto; flex: none; }

/* 子 run：保留内联行 + 一条聚合。不做自动弹出最终结果。 */
.wb-subs { margin: 0 0 var(--sp-5); }
.wb-subs__sum { font-size: var(--fs-13); color: var(--ink-2-deep); margin-bottom: 6px; }
.wb-subs__sum b { color: var(--ink); font-weight: var(--fw-ui); }
.wb-subrun {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; min-height: 34px; margin: 0 0 var(--sp-2); padding: 6px 8px 6px 10px;
  border: 0; border-radius: var(--r-sm); background: var(--hover);
  font: inherit; font-size: var(--fs-13); color: var(--ink); text-align: left; cursor: pointer;
}
.wb-subrun:hover { background: var(--border-soft); }
.wb-subrun__who { font-weight: var(--fw-ui); flex: none; }
.wb-subrun__what { min-width: 0; flex: 1; color: var(--ink-2-deep); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 终态的派发记录用文字徽章不用点：绿点/红点在会话行是「未读」，
   搬到这里会变成第二个意思。转圈可以复用——它两边都表示「还没结束」。 */
.wb-subrun__st { flex: none; margin-left: auto; }
.wb-subrun--stale { opacity: .72; }

/* --------------------------------------------------------------------- */
/* B7. 按钮 / 徽章                                                        */
/* --------------------------------------------------------------------- */
.wb-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 30px; padding: 6px 14px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); color: var(--ink-2-deep);
  font: inherit; font-size: var(--fs-13); font-weight: var(--fw-ui); cursor: pointer; white-space: nowrap;
}
.wb-btn:hover { background: var(--hover); color: var(--ink); }
.wb-btn--pri { background: var(--ink); border-color: var(--ink); color: var(--on-brand); }
.wb-btn--pri:hover { background: var(--ink-2-deep); border-color: var(--ink-2-deep); color: var(--on-brand); }
.wb-btn--pri:active { box-shadow: var(--sh-press); }
.wb-btn--ghost { border-color: transparent; background: transparent; }
.wb-btn--sm { min-height: 26px; padding: 4px 10px; font-size: var(--fs-12); }
.wb-btn[disabled] { opacity: .5; cursor: default; }

.wb-badge {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: var(--r-full);
  font-size: var(--fs-12); font-weight: var(--fw-label); line-height: 1.35;
  background: var(--hover); color: var(--ink-2-deep); white-space: nowrap;
}
.wb-badge--ok { background: var(--ok-soft); color: var(--diff-add); }
.wb-badge--err { background: var(--danger-soft); color: var(--danger); }
.wb-badge--info { background: var(--info-soft); color: var(--info); }

/* --------------------------------------------------------------------- */
/* B8. 全局条                                                             */
/* --------------------------------------------------------------------- */
.wb-bar { flex: none; display: flex; align-items: center; gap: var(--sp-2); padding: 8px var(--sp-5); font-size: var(--fs-13); border-bottom: 1px solid var(--border-soft); }
.wb-bar .act { margin-left: auto; flex: none; }
.wb-bar--err { background: var(--danger-soft); color: var(--ink); }
.wb-bar--warn { background: var(--warn-soft); color: var(--ink); }
.wb-bar--quiet { background: var(--hover); color: var(--ink-2-deep); }

.wb-fresh { display: flex; align-items: center; gap: var(--sp-2); padding: 7px var(--sp-5); font-size: var(--fs-12); border-bottom: 1px solid var(--border-soft); background: var(--hover); color: var(--ink-2-deep); }
.wb-fresh .act { margin-left: auto; flex: none; }
.wb-fresh--stale { background: var(--warn-soft); color: var(--ink); }
.wb-fresh--err { background: var(--danger-soft); color: var(--ink); }

/* 掉线条贴 composer 上方 */
.wb-preline { display: flex; align-items: center; gap: var(--sp-2); max-width: 860px; margin: 0 auto var(--sp-2); padding: 8px 12px; border-radius: var(--r-sm); font-size: var(--fs-13); }
.wb-preline--warn { background: var(--warn-soft); color: var(--ink); }
.wb-preline--err { background: var(--danger-soft); color: var(--ink); }
.wb-preline--quiet { background: var(--hover); color: var(--ink-2-deep); }

/* --------------------------------------------------------------------- */
/* B9. Composer —— 实体容器                                               */
/*     控件全部在容器内底边一行；容器上方没有分隔线，容器自身的边界就是分隔。 */
/*     发送与停止共用同一个圆形按钮位。                                     */
/* --------------------------------------------------------------------- */
.wb-comp__wrap {
  flex: none; background: var(--canvas);
  padding: var(--sp-3) var(--sp-5) var(--sp-4);
  padding-bottom: max(var(--sp-4), env(safe-area-inset-bottom));
}
/* 「立体」按 A-3 的答复做：不引入深色孤例，改用 --surface 实底（比画布 --canvas 白一档）
   + 1px --border + 二档阴影。二档阴影在 §5.1 里本来归浮层，这里是显式豁免：
   composer 是常驻的输入容器，用户明确要求它读起来比画布更"实"。已记进 DESIGN §15.6。 */
.wb-comp {
  max-width: 860px; margin: 0 auto; position: relative;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  box-shadow: var(--sh-2), var(--sh-ring);
  padding: var(--sp-3) var(--sp-3) var(--sp-2);
}
.wb-comp--focus { box-shadow: var(--sh-2), var(--focus-ring); }
.wb-comp--drop { border-style: dashed; border-color: var(--brand); background: var(--brand-soft); }
.wb-comp__att { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: var(--sp-2); }
.wb-comp__field { font-size: var(--fs-14); line-height: var(--lh-body); min-height: 46px; padding: 2px 4px; color: var(--ink); overflow-wrap: anywhere; }
.wb-comp__field:empty::before { content: attr(data-ph); color: var(--ink-3); }
.wb-comp__ime { border-bottom: 2px dotted var(--brand); }
/* 底边控件行：与输入区同处一个容器，不加分隔线 */
.wb-comp__foot { display: flex; align-items: center; gap: 6px; margin-top: var(--sp-2); }
.wb-comp__hint { font-size: var(--fs-12); color: var(--ink-3); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-comp__err { margin-top: 6px; padding: 0 4px; font-size: var(--fs-12); color: var(--danger); }

.wb-ic {
  width: 30px; height: 30px; flex: none;
  border: 0; border-radius: var(--r-full); background: transparent;
  color: var(--ink-2-deep); font: inherit; font-size: 16px; line-height: 1;
  display: grid; place-items: center; cursor: pointer;
}
.wb-ic:hover { background: var(--hover); color: var(--ink); }

/* 发送 / 停止：同一个位置、同一个按钮，只换形态 */
.wb-send {
  margin-left: auto; flex: none;
  width: 32px; height: 32px;
  border: 0; border-radius: var(--r-full);
  background: var(--ink); color: var(--on-brand);
  display: grid; place-items: center; cursor: pointer;
}
.wb-send[disabled] { background: var(--hover); color: var(--ink-3); cursor: default; }
.wb-send[data-mode="stop"] { background: var(--danger-soft); color: var(--danger); }
.wb-send svg { width: 14px; height: 14px; }
.wb-send__stop { width: 10px; height: 10px; border-radius: 2px; background: currentColor; display: block; }

/* 附件 chip */
.wb-att { display: inline-flex; align-items: center; gap: 6px; max-width: 220px; min-height: 26px; padding: 3px 8px; border-radius: var(--r-full); background: var(--hover); font-size: var(--fs-12); color: var(--ink-2-deep); }
.wb-att__n { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-att__x { border: 0; background: transparent; color: var(--ink-3); cursor: pointer; font: inherit; padding: 0 2px; }
.wb-att--up { background: var(--brand-soft); color: var(--brand-ink); }
.wb-att--err { background: var(--danger-soft); color: var(--danger); }
.wb-att--ready { background: var(--ok-soft); color: var(--diff-add); }
.wb-att--sent { background: transparent; box-shadow: var(--sh-ring); color: var(--ink-2-deep); }
/* 上传中：接口不返回百分比，所以是不定量的往复条，不是进度条 */
.wb-att__ind { width: 30px; height: 3px; border-radius: var(--r-full); background: var(--border); overflow: hidden; flex: none; position: relative; }
.wb-att__ind::after { content: ""; position: absolute; top: 0; bottom: 0; width: 40%; border-radius: var(--r-full); background: var(--brand); animation: wb-indet 1.1s var(--ease-standard) infinite; }
@keyframes wb-indet { 0% { left: -40%; } 100% { left: 100%; } }

/* 命令面板 */
.wb-cmd {
  position: absolute; left: 0; right: 0; bottom: calc(100% + 6px);
  background: var(--raised); border: 1px solid var(--border-soft); border-radius: var(--r);
  box-shadow: var(--sh-2); padding: 5px; z-index: var(--z-popover); max-height: 216px; overflow-y: auto;
}
.wb-cmd__i { display: flex; align-items: baseline; gap: var(--sp-2); width: 100%; min-height: 30px; padding: 5px 9px; border: 0; background: transparent; border-radius: var(--r-sm); font: inherit; font-size: var(--fs-13); color: var(--ink); text-align: left; cursor: pointer; }
.wb-cmd__i:hover, .wb-cmd__i[aria-selected="true"] { background: var(--hover); }
.wb-cmd__k { font-family: var(--mono); font-size: var(--fs-mono); font-weight: var(--fw-ui); flex: none; width: 62px; }
.wb-cmd__d { color: var(--ink-2-deep); font-size: var(--fs-12); }

/* --------------------------------------------------------------------- */
/* B10. 浮层                                                              */
/* --------------------------------------------------------------------- */
.wb-scrim { position: absolute; inset: 0; background: var(--scrim); z-index: var(--z-scrim); animation: wb-fade var(--dur-3) var(--ease-standard); }
@keyframes wb-fade { from { opacity: 0; } }

.wb-pop {
  position: absolute; z-index: var(--z-drawer);
  width: 340px; max-height: calc(100% - 96px); overflow-y: auto;
  background: var(--raised); border: 1px solid var(--border-soft); border-radius: var(--r);
  box-shadow: var(--sh-2); padding: var(--sp-4);
}
/* 详情浮层贴着触发它的那枚感叹号 —— 现在在身份头左侧，浮层也跟着靠左 */
.wb-pop--id { top: 54px; left: var(--sp-5); }
.wb-pop--hb { bottom: 44px; left: 12px; width: 300px; }

/* 三点菜单：小浮层，位置由 JS 按触发行算 */
.wb-menu {
  position: absolute; z-index: var(--z-drawer);
  min-width: 168px; padding: 5px;
  background: var(--raised); border: 1px solid var(--border-soft); border-radius: var(--r-sm);
  box-shadow: var(--sh-2);
}
.wb-menu button {
  display: flex; align-items: center; gap: var(--sp-2);
  width: 100%; min-height: 32px; padding: 6px 10px;
  border: 0; background: transparent; border-radius: var(--r-xs);
  font: inherit; font-size: var(--fs-13); color: var(--ink); text-align: left; cursor: pointer;
}
.wb-menu button:hover { background: var(--hover); }
.wb-menu button.danger { color: var(--danger); }
.wb-menu button[disabled] { color: var(--ink-3); cursor: default; }
.wb-menu button[disabled]:hover { background: transparent; }
.wb-menu__note { margin-left: auto; font-size: 11px; color: var(--ink-3); }

/* 移动端左抽屉直接复用 .wb-rail（加 .is-drawer），不另起一个 .wb-drawer--left 组件 */
@keyframes wb-slide-l { from { transform: translateX(-24px); opacity: 0; } }

.wb-x { width: 30px; height: 30px; flex: none; border: 0; border-radius: var(--r-sm); background: transparent; color: var(--ink-2-deep); font: inherit; font-size: 15px; cursor: pointer; display: grid; place-items: center; }
.wb-x:hover { background: var(--hover); color: var(--ink); }

.wb-modal {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: var(--z-drawer); width: min(440px, 88cqw);
  background: var(--raised); border-radius: var(--r-lg); box-shadow: var(--sh-3); padding: var(--sp-5);
}
/* R-2 方案 B：H5 长按被截断的元素 → 弹出完整值。
   桌面靠 hover 出 title，触屏没有 hover，而完整值又没有别的入口，
   所以必须给触屏一条路。值自身要能换行，不能撑破屏幕。 */
.wb-full {
  position: absolute; left: var(--sp-3); right: var(--sp-3); bottom: var(--sp-4);
  z-index: var(--z-drawer);
  background: var(--raised); border: 1px solid var(--border-soft);
  border-radius: var(--r); box-shadow: var(--sh-3); padding: var(--sp-4);
}
.wb-full__v {
  font-family: var(--mono); font-size: var(--fs-mono); line-height: var(--lh-mono);
  color: var(--ink); word-break: break-all; overflow-wrap: anywhere;
  max-height: 40cqh; overflow-y: auto;
  background: var(--hover); border-radius: var(--r-sm); padding: var(--sp-3);
}
.wb-full__f { display: flex; gap: var(--sp-2); justify-content: flex-end; margin-top: var(--sp-3); }

/* 文档级回退载体：图鉴样张的 .wb 里没有浮层载体，长按要落到这里。
   用 fixed 而不是 absolute —— 它不在任何 .wb 的定位上下文里。 */
.wb-full--doc {
  position: fixed;
  left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: min(520px, calc(100vw - 32px));
  z-index: 2147482000;      /* 在批注层（2147483000）之下，其余之上 */
}
.wb-full--doc .wb-full__v { max-height: 40vh; }
.wb-full__scrim {
  position: fixed; inset: 0;
  background: var(--scrim);
  z-index: 2147481999;
}

.wb-modal h3 { margin: 0 0 var(--sp-2); font-size: var(--fs-15); font-weight: var(--fw-title); }
.wb-modal p { margin: 0 0 var(--sp-3); font-size: var(--fs-13); color: var(--ink-2-deep); line-height: 1.6; }
.wb-modal__f { display: flex; justify-content: flex-end; gap: var(--sp-2); margin-top: var(--sp-4); }

/* 身份详情：二层直给，三层再折一次。runner / 引擎锁本轮移进这里。 */
.wb-id__who { display: flex; align-items: center; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.wb-id__duty { font-size: var(--fs-13); line-height: 1.65; margin: 0 0 var(--sp-4); }
.wb-id__sec { margin-bottom: var(--sp-4); }
.wb-id__l { font-size: var(--fs-10); letter-spacing: var(--ls-caps); text-transform: uppercase; color: var(--ink-3); font-weight: var(--fw-label); margin-bottom: 6px; }
.wb-id__perms { display: flex; flex-wrap: wrap; gap: 5px; }
.wb-perm { display: inline-flex; align-items: center; gap: 4px; padding: 3px 9px; border-radius: var(--r-full); font-size: var(--fs-12); font-weight: var(--fw-label); }
.wb-perm--y { background: var(--ok-soft); color: var(--diff-add); }
.wb-perm--n { background: var(--danger-soft); color: var(--danger); }
/* 有些权限既不是「能」也不是「不能」，而是 contract_gated：
   registry 里写的是「按轮次契约放行」。硬塞成 ✕ 就是编。 */
.wb-perm--gate { background: var(--warn-soft); color: var(--ink); }
.wb-kv { display: grid; grid-template-columns: 68px minmax(0, 1fr); gap: 5px var(--sp-2); font-size: var(--fs-13); }
.wb-kv dt { color: var(--ink-3); font-size: var(--fs-12); }
.wb-kv dd { margin: 0; min-width: 0; font-family: var(--mono); font-size: var(--fs-mono); color: var(--ink-2-deep); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wb-kv dd.wrap { white-space: normal; overflow-wrap: anywhere; }

/* --------------------------------------------------------------------- */
/* B11. 空态 / 骨架 / 其他面板                                            */
/* --------------------------------------------------------------------- */
.wb-empty { max-width: 480px; margin: 0 auto; padding: var(--sp-8) var(--sp-3); text-align: center; }
.wb-empty h3 { margin: 0 0 6px; font-size: var(--fs-15); font-weight: var(--fw-title); }
.wb-empty p { margin: 0 0 var(--sp-4); font-size: var(--fs-13); color: var(--ink-2-deep); line-height: 1.65; }
.wb-empty__acts { display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center; }

.wb-skel { background: var(--hover); border-radius: var(--r-xs); animation: wb-breathe 1.4s ease-in-out infinite; }
@keyframes wb-breathe { 0%, 100% { opacity: 1; } 50% { opacity: .55; } }
.wb-skel--line { height: 12px; margin-bottom: 8px; }
.wb-skel--card { height: 96px; border-radius: var(--r); margin-bottom: var(--sp-5); }

.wb-conn { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3); background: var(--surface); border: 1px solid var(--border-soft); border-radius: var(--r); margin-bottom: var(--sp-2); }
.wb-conn__t { min-width: 0; }
.wb-conn__n { font-size: var(--fs-13); font-weight: var(--fw-ui); }
.wb-conn__d { font-size: var(--fs-12); color: var(--ink-2-deep); }
.wb-conn__a { margin-left: auto; flex: none; }

.wb-field { margin-bottom: var(--sp-4); }
.wb-field label { display: block; font-size: var(--fs-12); color: var(--ink-2-deep); margin-bottom: 5px; }
.wb-input { width: 100%; padding: 9px 12px; border: 1px solid var(--border); border-radius: var(--r-sm); background: var(--surface); font: inherit; font-size: var(--fs-14); color: var(--ink); }
.wb-input::placeholder { color: var(--ink-3); }
.wb-input:focus-visible { outline: none; box-shadow: var(--focus-ring); }

/* --------------------------------------------------------------------- */
/* B12. ≤640px                                                            */
/* --------------------------------------------------------------------- */
@container app (max-width: 640px) {
  .wb-rail { display: none; }
  .wb-rail.is-drawer {
    display: flex; position: absolute; inset: 0 auto 0 0; z-index: var(--z-drawer);
    width: min(86cqw, 320px); box-shadow: var(--sh-3);
    animation: wb-slide-l var(--dur-3) var(--ease-standard);
  }
  .wb-x.wb-burger { display: grid; }

  .wb-idbar { padding: 6px var(--sp-3); min-height: 52px; }
  .wb-conv { padding: var(--sp-4) var(--sp-3) var(--sp-2); }
  .wb-comp__wrap { padding: var(--sp-2) var(--sp-3) var(--sp-3); padding-bottom: max(var(--sp-3), env(safe-area-inset-bottom)); }
  .wb-bar, .wb-fresh { padding-left: var(--sp-3); padding-right: var(--sp-3); }

  /* 移动正文 / 输入 15px */
  .wb-user__b, .wb-ans p, .wb-ans li, .wb-comp__field { font-size: var(--fs-15); }
  .wb-user__b { max-width: 88%; }

  /* 触控 ≥44px */
  .wb-btn, .wb-x, .wb-ic, .wb-hb, .wb-att { min-height: var(--tap-min); }
  .wb-send { width: var(--tap-min); height: var(--tap-min); }
  .wb-ic { width: var(--tap-min); }
  .wb-sess, .wb-agent__row, .wb-sess__hit, .wb-agent__hit,
  .wb-dir, .wb-proc__sum, .wb-subrun, .wb-fold__t, .wb-menu button { min-height: var(--tap-min); }
  .wb-btn--sm { min-height: 36px; }

  /* 触屏没有 hover：状态与三点改成两格并列常显。
     槽位必须同时加宽到「状态 20 + 间隙 4 + 三点 32 = 56」，
     否则静态布局的三点会顶破 20px 的槽（这是静态核宽度时抓到的一处溢出）。 */
  /* 固定两格栅格：状态永远在第 1 格、三点永远在第 2 格。
     用显式 grid-column 而不是自动排布——否则「只有三点没有状态」的行
     会把三点填进第 1 格，状态列就断了。 */
  .wb-slot {
    width: 56px; height: 32px;
    display: grid; grid-template-columns: 20px 32px; gap: 4px; align-items: center; justify-items: center;
  }
  .wb-slot > .wb-st { position: static; grid-column: 1; }
  .wb-slot > .wb-agent__n { position: static; grid-column: 1; }
  .wb-slot > .wb-more { position: static; display: grid; grid-column: 2; width: 32px; height: 32px; }
  /* 触屏没有 hover，所以计数与状态点都不让位——两格并列常显 */
  .wb-sess:hover .wb-slot > .wb-st,
  .wb-sess:focus-within .wb-slot > .wb-st,
  .wb-agent__row:hover .wb-slot > .wb-agent__n,
  .wb-agent__row:focus-within .wb-slot > .wb-agent__n { visibility: visible; }

  /* popover → 底部 sheet，同一段 DOM */
  .wb-pop {
    top: auto; left: 0; right: 0; bottom: 0; width: auto; max-height: 78%;
    border-radius: var(--r-lg) var(--r-lg) 0 0; box-shadow: var(--sh-3);
    padding: var(--sp-4) var(--sp-4) max(var(--sp-4), env(safe-area-inset-bottom));
    animation: wb-slide-up var(--dur-3) var(--ease-standard);
  }
  @keyframes wb-slide-up { from { transform: translateY(16px); opacity: 0; } }

  .wb-kv { grid-template-columns: 62px minmax(0, 1fr); }

  /* 破坏性动作不放拇指落点：确认键移到左侧 */
  .wb-modal { width: calc(100cqw - 32px); }
  .wb-modal__f { flex-direction: row-reverse; justify-content: flex-start; }

  /* 键盘弹起：对话区被压缩，composer 吸在键盘上沿 */
  .wb.is-kbd .wb-kbd { display: block; }
}

.wb-kbd {
  display: none; flex: none; height: 258px;
  border-top: 1px solid var(--border); background: var(--hover);
  color: var(--ink-3); font-size: var(--fs-12); text-align: center; padding-top: var(--sp-4);
}
.wb-safe { height: env(safe-area-inset-bottom, 0px); min-height: 0; }
