/* ============================================================
   __TITLE__ · 样式
   本文件分两段，prototype-verify 按下方的 @pv-section 哨兵注释切分并校验：
     外壳段   —— 类选择器一律 wb-shell / pv- 前缀
     内容侧段 —— 不许出现顶层裸标签选择器（button {} 会漏出去污染外壳）
   断点用 @container，不用 @media —— 这样桌面框与 H5 框能跑同一份 DOM
   和同一份 CSS，「两套共用同一套信息层级」是可以并排直接验的。

   哨兵注释不要删、不要改写、不要在别处重复 —— 它是分段的唯一依据。
   （早期版本靠找 "[A]"/"[B]" 字样，结果命中了这段说明文字本身，
     整个文件被当成内容侧段，把 html/body 误报成违规。）
   ============================================================ */

/* @pv-section: shell */
/* ============ [A] 稿子外壳 ============ */


/* border-box 必须全局生效：H5 框写 width:390px 加 1px 边框，在 content-box 下
   实测量到 392px —— 等于整份 H5 设计稿都在错误宽度上验证，属于"看着对其实不对"。 */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--canvas); color: var(--ink);
  font: var(--fw-body) var(--fs-14)/1.6 var(--sans);
  -webkit-font-smoothing: antialiased;
}

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

.wb-shell__rail {
  display: flex; flex-direction: column; gap: 4px;
  border-right: 1px solid var(--border); background: var(--surface);
  padding: 18px 14px; position: sticky; top: 0; height: 100vh; overflow-y: auto;
}
.wb-shell__brand { font: var(--fw-title) var(--fs-15)/1.3 var(--sans); margin-bottom: 12px; }

.wb-shell__tabs { display: flex; flex-direction: column; gap: 2px; }
.wb-shell__tabs button {
  text-align: left; border: 0; background: transparent; color: var(--ink-2);
  padding: 9px 12px; border-radius: var(--r-sm); cursor: pointer;
  font: var(--fw-label) var(--fs-13)/1 var(--sans);
}
.wb-shell__tabs button:hover { background: var(--hover); color: var(--ink); }
.wb-shell__tabs button[aria-selected="true"] { background: var(--brand); color: var(--on-brand); }

.wb-shell__scenes { margin-top: 14px; display: flex; flex-direction: column; gap: 2px; }
.wb-shell__railfoot {
  margin-top: auto; padding-top: 14px; border-top: 1px solid var(--border);
  color: var(--ink-2); font-size: var(--fs-12);
  overflow-wrap: anywhere;   /* 字段契约路径是长串，不断行会撑宽侧栏 */
}

.wb-shell__main { display: flex; flex-direction: column; min-width: 0; }

.wb-shell__bar {
  display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
  padding: 12px 20px; border-bottom: 1px solid var(--border);
  background: var(--surface); position: sticky; top: 0; z-index: 5;
}
.wb-shell__grp { display: inline-flex; background: var(--hover); border-radius: var(--r-sm); padding: 3px; }
.wb-shell__grp button {
  border: 0; background: transparent; color: var(--ink-2); cursor: pointer;
  padding: 7px 11px; border-radius: var(--r-sm); font: var(--fw-label) var(--fs-12)/1 var(--sans);
}
.wb-shell__grp button[aria-pressed="true"] { background: var(--surface); color: var(--ink); box-shadow: var(--sh-2); }
.wb-shell__grow { flex: 1; }
.wb-shell__now { color: var(--ink-2); font-size: var(--fs-12); }

.wb-shell__pane { padding: 20px; min-width: 0; }
.wb-shell__pane[hidden] { display: none; }
.wb-shell__panehead { max-width: 760px; margin-bottom: 16px; }
.wb-shell__panehead h2 { margin: 0 0 6px; font: var(--fw-title) var(--fs-18)/1.3 var(--sans); }
.wb-shell__panehead p { margin: 0; color: var(--ink-2); font-size: var(--fs-13); }

/* 宽内容必须在自己的容器里滚，不能撑破 document ——
   实测：窗口缩到 375（用户在手机上打开评审稿）时外壳横向溢出 613px。 */
.wb-shell__stage { display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap; overflow-x: auto; }
.wb-shell__device { margin: 0; }
.wb-shell__device figcaption { color: var(--ink-2); font-size: var(--fs-12); margin-bottom: 8px; }
/* caption 写「桌面 1440」而屏上只有 720 —— 必须标出缩放，否则评审者会以为
   自己看到的就是 1440 下的真实尺寸感。 */
/* 缩放百分比由 app.js 写进 .pv-scalenote 的文本。
   不要用 CSS 的 attr(data-scale) —— attr() 只能取伪元素所属元素自己的属性，
   data-scale 在祖先 .wb-shell__device 上，结果渲染成「· % 缩放」，数字丢了却不报错。 */
.pv-scalenote { color: var(--ink-3); }
:root[data-view="desktop"] .wb-shell__device[data-frame="h5"] { display: none; }
:root[data-view="h5"] .wb-shell__device[data-frame="desktop"] { display: none; }

/* 内容槽是容器查询的容器 —— 内容侧的断点全部相对它，不相对屏幕 */
.wb-shell__viewport {
  container-type: inline-size;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); overflow: hidden; box-shadow: var(--sh-2);
}
.wb-shell__viewport--desktop { width: min(1440px, 100%); height: 900px; overflow-y: auto; }

/* 并排对照：桌面框保持 1440 逻辑宽度后整体缩放，绝不能被挤压。
   实测（2026-08-17 端到端截图）：不缩放时 1440 框在 1440 视口里被 H5 框和侧栏
   挤到只剩 30px 宽，标题文字竖排 —— 并排对照这个核心功能等于不可用。
   注意 scale 后 getBoundingClientRect 返回的是视觉坐标，与截图坐标系一致，
   所以批注定位不受影响。 */
/* 并排对照：两框保持各自的逻辑尺寸，然后**用同一个比例**一起缩放。
   比例由 app.js 的 scaleFrames() 按可用宽度算（Math.min(1, avail/total)，只缩不放）。

   为什么不是「桌面框 scale(.5) + H5 框 100%」——那是本 skill 犯过的错：
   同屏两种比例，稿子上量出来的尺寸一个要除以 2 一个不用，
   「栅格宽度、对齐边、间距体系严格一致」这类需求在这种稿上根本没法验，
   批注坐标也跟着分裂。参照物 wb-redesign 是两框同一比例（实测 0.6047）。 */
.wb-shell__device[data-frame] { flex: 0 0 auto; overflow: hidden; }
.wb-shell__viewport { transform-origin: top left; }
:root[data-view="side-by-side"] .wb-shell__viewport--desktop { width: 1440px; height: 900px; }
.wb-shell__viewport--h5 { width: 375px; height: 812px; overflow-y: auto; }
:root[data-h5size="390x844"] .wb-shell__viewport--h5 { width: 390px; height: 844px; }

.wb-shell__logic {
  margin-top: 20px; max-width: 900px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--r); padding: 16px 18px;
}
.wb-shell__atlas { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 16px; }
.wb-shell__table { max-width: 1000px; display: flex; flex-direction: column; gap: 8px; }

/* 外壳内部件（pv- 前缀同属 [A] 段） */
.pv-slot { min-height: 100%; }
.pv-group { margin-bottom: 6px; }
.pv-group > summary {
  cursor: pointer; list-style: none; padding: 8px 12px; border-radius: var(--r-sm);
  color: var(--ink-2); font: var(--fw-label) var(--fs-12)/1 var(--sans);
}
.pv-group > summary::-webkit-details-marker { display: none; }
.pv-group > summary:hover { background: var(--hover); color: var(--ink); }
.pv-scene {
  display: block; width: 100%; text-align: left; border: 0; background: transparent;
  color: var(--ink-2); padding: 8px 12px 8px 22px; border-radius: var(--r-sm); cursor: pointer;
  font: var(--fw-ui) var(--fs-13)/1.3 var(--sans);
}
.pv-scene:hover { background: var(--hover); color: var(--ink); }
.pv-scene[aria-current="true"] { background: var(--hover); color: var(--brand); font-weight: var(--fw-title); }

.pv-logicgrid { display: grid; grid-template-columns: 120px minmax(0, 1fr); gap: 6px 14px; font-size: var(--fs-13); }
.pv-logickey { color: var(--ink-2); }
.pv-todo { color: var(--warn); font-weight: var(--fw-label); }

.pv-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.pv-cardhead { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; border-bottom: 1px solid var(--border); }
.pv-cardname { font: var(--fw-title) var(--fs-13)/1.4 var(--sans); }
.pv-cardwhy { margin-left: auto; max-width: 58%; color: var(--ink-2); font-size: var(--fs-12); text-align: right; }
.pv-static { display: inline-block; margin-top: 4px; color: var(--warn); font-size: 11px; font-weight: var(--fw-label); }
.pv-cardbody { padding: 14px; background: var(--hover); }

.pv-row { display: grid; grid-template-columns: 90px minmax(0, 1fr); gap: 12px; align-items: start;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--r); padding: 10px 14px; font-size: var(--fs-13); }
.pv-pill { font: var(--fw-label) 11px/1.6 var(--sans); padding: 1px 8px; border-radius: var(--r-full); text-align: center; }
.pv-pill--ok { background: var(--hover); color: var(--ink-2); }
.pv-pill--skip { background: var(--warn-soft); color: var(--warn); }
.pv-pill--absent { background: var(--brand-soft); color: var(--brand); }
.pv-empty { padding: 24px; color: var(--ink-2); font-size: var(--fs-13); }

/* 外壳自身的窄屏适配（外壳响应真实窗口，用 @media；
   内容侧响应内容槽宽度，用 @container —— 两者不是一回事，别混）。
   用户会在手机上打开评审稿，那时侧栏必须让位、设备框必须纵向堆叠。 */
@media (max-width: 900px) {
  .wb-shell { grid-template-columns: minmax(0, 1fr); }
  .wb-shell__rail {
    position: static; height: auto; overflow-y: visible;
    border-right: 0; border-bottom: 1px solid var(--border);
  }
  .wb-shell__tabs { flex-direction: row; flex-wrap: wrap; }
  .wb-shell__stage { flex-direction: column; }
  .wb-shell__pane { padding: 14px; }
  .wb-shell__viewport--desktop { width: 100%; }

  /* 窄屏下并排对照必须退化成「只看 H5」，不能硬塞两个框。
     2026-08-28 实测（新加的「内容被压窄」断言抓出来的）：
     375 视口里两框并排，可用宽 347 要分给 1440+375=1815 的逻辑宽，
     比例算成 0.19，H5 框只剩 71px、桌面框缩到 24% —— 两个都看不清。
     光把 stage 改成 column 也救不了：1440 的稿子在 347px 里怎么缩都读不了。
     想在窄屏看桌面稿，切到「桌面 1440」页签单独看（那时不隐藏）。 */
  :root[data-view="side-by-side"] .wb-shell__device[data-frame="desktop"] { display: none; }
}

/* 键盘弹起：H5 上输入法占掉近半屏，composer 不上移用户看不见自己打的字。
   真实实现由 visualViewport 驱动 --kb-inset，仅在 ≤640px 或 pointer:coarse 挂监听；
   这里是稿子里的模拟开关。 */
/* 默认值必须在这里给，不能靠每处引用写 var(--kb-inset, 0px)。
   2026-08-28 去掉全部硬编码 fallback 时踩到：--kb-inset 只在 [data-kb="on"]
   下定义，默认态下 calc(16px + var(--kb-inset)) 整条声明变 invalid，
   padding-bottom 直接失效 —— 不报错、不崩，只是稿子底部贴边了。 */
.wb-shell__viewport--h5 { --kb-inset: 0px; }
:root[data-kb="on"] .wb-shell__viewport--h5 { --kb-inset: 336px; }

/* ---- 空层声明条（本 skill 最不可替代的机制，必须醒目）---- */
.wb-shell__layers { padding: 0; }
.wb-shell__layers:empty { display: none; }
.wb-shell__layers.is-gap {
  background: var(--brand-soft); border-bottom: 2px solid var(--brand);
  padding: 12px 20px;
}
.wb-shell__layers.is-warn {
  background: var(--warn-soft); border-bottom: 2px solid var(--warn);
  padding: 12px 20px;
}
/* 「四层齐备」是常态，不该抢产品的注意力。
   2026-08-28 之前这里铺 --ok-soft 绿底，是整份稿子面积最大的一块彩色 ——
   评审时第一眼看到的是工具自己的绿横幅，不是产品长什么样。
   现在只留一条细线；缺层的 is-gap / is-warn 才保留强调色，那才是要人看见的。 */
.wb-shell__layers.is-ok {
  background: transparent; border-bottom: 1px solid var(--border);
  padding: 8px 20px; color: var(--ink-2);
}
.wb-shell__layers.is-ok .pv-layerhead { color: var(--ink-2); }
.pv-layerhead {
  font: var(--fw-display) var(--fs-12)/1.4 var(--sans); letter-spacing: .02em;
  color: var(--brand); margin-bottom: 4px;
}
.wb-shell__layers.is-warn .pv-layerhead { color: var(--warn); }
.pv-layerline { font-size: var(--fs-13); line-height: 1.65; }
.pv-layerline--gap b { color: var(--brand); }
.pv-layerline--warn b { color: var(--warn); }

/* ---- 侧栏四层指示器：位置固定、走法自由 ---- */
.wb-shell__stack {
  display: flex; flex-direction: column; gap: 2px;
  margin-bottom: 14px; padding-bottom: 12px; border-bottom: 1px solid var(--border);
}
.pv-stackrow {
  display: grid; grid-template-columns: 16px 1fr auto; gap: 6px; align-items: center;
  padding: 4px 6px; border-radius: var(--r-sm); font-size: var(--fs-12);
}
.pv-stackno { color: var(--ink-2); font-variant-numeric: tabular-nums; }
.pv-stackname { color: var(--ink); font-weight: var(--fw-label); }
.pv-stackstate { font-size: 11px; }
.pv-stackrow--ok { background: transparent; box-shadow: inset 2px 0 0 var(--border); }
.pv-stackrow--ok .pv-stackstate { color: var(--ink-2); }
.pv-stackrow--warn { background: var(--warn-soft); }
.pv-stackrow--warn .pv-stackstate { color: var(--warn); }
.pv-stackrow--gap { background: var(--brand-soft); }
.pv-stackrow--gap .pv-stackstate { color: var(--brand); font-weight: var(--fw-display); }

/* ---- 层间对照矩阵 ---- */
.wb-shell__matrix { max-width: 1100px; overflow-x: auto; }
.pv-msum { color: var(--ink-2); font-size: var(--fs-12); margin-bottom: 8px; }
.pv-mrow {
  display: grid; grid-template-columns: 1.3fr 1.5fr 1fr .8fr 1fr;
  gap: 12px; padding: 10px 14px; font-size: var(--fs-13); align-items: start;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); margin-bottom: 6px; min-width: 720px;
}
.pv-mrow--head {
  background: var(--hover); font-weight: var(--fw-title); font-size: var(--fs-12);
  color: var(--ink-2); border: 0;
}
.pv-bad { color: var(--brand); font-weight: var(--fw-label); }
.pv-okmark { color: var(--ink-2); font-size: 11px; font-weight: var(--fw-label); }
.pv-note { color: var(--ink-2); font-size: var(--fs-12); }
.pv-pill--full { background: var(--hover); color: var(--ink-2); }
.pv-pill--nofact { background: var(--brand-soft); color: var(--brand); }
.pv-pill--nodesign { background: var(--brand-soft); color: var(--brand); }
.pv-pill--reverse { background: var(--warn-soft); color: var(--warn); }
.pv-pill--unknownfact { background: var(--warn-soft); color: var(--warn); }
.pv-pill--skip { background: var(--hover); color: var(--ink-2); }

/* @pv-section: content */
/* ============ [B] 内容侧 ============ */
/* 规则：不许出现裸标签选择器。类名用产品自己的前缀（示例用 app-）。
   断点一律 @container，相对内容槽宽度，不相对屏幕。 */

.app-root { padding: 16px; padding-bottom: calc(16px + var(--kb-inset)); }
.app-title { font: var(--fw-title) var(--fs-16)/1.3 var(--sans); margin: 0 0 8px; }
.app-hint { color: var(--ink-2); font-size: var(--fs-13); margin: 0; }
.app-grid { display: grid; gap: 12px; grid-template-columns: repeat(2, minmax(0, 1fr)); margin-top: 14px; }
.app-cell { background: var(--hover); border: 1px solid var(--border); border-radius: var(--r); padding: 12px; }

@container (max-width: 640px) {
  .app-grid { grid-template-columns: minmax(0, 1fr); }
  .app-root { padding: 12px; padding-bottom: calc(12px + var(--kb-inset)); }
}

/* ============ Workbench 产品 UI（本轮设计对象）============
   命名以 .app- 前缀，与外壳段 .wb-shell__ / .pv- 前缀严格分开。
   视觉语言逐字对齐 design/mockups/wb-redesign 的产品侧 (.wb-rail/.wb-dir/.wb-agent)
   —— 加平级 SKILLS 栏目要用同一套折叠头/monogram/槽位样式，任何走样都是「新东西」
   的错觉。断点用 @container 相对内容槽宽度，不相对屏幕。
   ============================================================ */

/* 与 .app-root 双类命中：覆盖脚手架 .app-root 的 padding:16px（我要的是无内边距的
   grid 布局），只保留 padding-bottom 响应键盘弹起。特异性 (0,2,0) 高于 .app-root
   单类的 (0,1,0)，所以覆盖成立。 */
.app-wb.app-root {
  display: grid; grid-template-columns: 264px minmax(0, 1fr);
  min-height: 100%; background: var(--canvas); color: var(--ink);
  font-family: var(--sans);
  padding: 0; padding-bottom: var(--kb-inset);
}

/* ---- 左栏（.wb-rail 的镜像）---- */
.app-rail {
  display: flex; flex-direction: column; min-height: 0;
  background: var(--shell); border-right: 1px solid var(--border-soft);
}
.app-rail__head { padding: 18px 14px 6px; }
.app-wordmark { margin: 0; font-size: var(--fs-17); font-weight: var(--fw-title); letter-spacing: var(--ls-title); line-height: 1.2; }
.app-wordmark i { color: var(--brand-ink); font-style: normal; }

/* ---- 折叠头 .app-dir（AGENTS / SKILLS 两个头**完全同构**）----
   Notion 侧栏做法：标题弱化小字、caret 承担折叠语义、整行可点、hover 才给底色。
   SKILLS 头不加特殊色/图标——加了就暗示它是「新东西」，与「日常抽屉里的东西」的
   定位不符。 */
.app-dir {
  display: flex; align-items: center; gap: 6px;
  width: calc(100% - 16px); min-height: 28px;
  margin: 12px 8px 2px; 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;
}
.app-dir:hover { background: var(--hover); color: var(--ink-2-deep); }
.app-dir__caret {
  flex: none; width: 12px; text-align: center;
  color: var(--ink-3); font-size: 9px; letter-spacing: 0;
}
.app-dir[data-open="true"] .app-dir__caret { transform: rotate(90deg); }
.app-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);
}
/* SKILLS 头下面第一条与 AGENTS 头之间需要一段更明显的呼吸——
   两栏之间靠留白分区（不加边框、不加背景色），沿用 Notion 做法。 */
.app-dir--skills { margin-top: 14px; }

/* ---- 滚动容器 ----
   两栏都可展开时，两个都拿到自己的 min-content 高度，超出再滚。
   R17 刚把 AGENTS 改成真可滚动（去掉截断和「还有 N 条」浮层）——SKILLS 加上
   不会破坏这个改造：AGENTS 依然 flex:1 拿到剩余空间，SKILLS 只占它需要的高度。 */
.app-rail__scroll { overflow-y: auto; padding: 4px 0 8px; min-height: 0; }
.app-rail__scroll--agents { flex: 1 1 auto; }
/* SKILLS 只有 7 条（叶子），天然短——**不让它抢**主要滚动带；只有极端小屏时才滚 */
.app-rail__scroll--skills { flex: 0 1 auto; max-height: 40vh; }

/* ---- Agent 行 ---- */
.app-agent { padding: 0 8px; }
.app-agent__row {
  display: flex; align-items: center; gap: 8px;
  width: 100%; min-height: 32px; padding-right: 6px;
  border-radius: var(--r-sm); position: relative;
}
.app-agent__row:hover { background: var(--hover); }
.app-agent__hit,
.app-sess__hit,
.app-skill__hit {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  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;
}
.app-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;
}
.app-agent__name { font-size: var(--fs-13); font-weight: var(--fw-ui); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-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;
}
.app-agent[data-open="false"] .app-agent__sessions { display: none; }

/* 角色 accent —— 从 wb-redesign 抄的调色板，加 techlead/research/qa/skill 四档 */
.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-techlead { background: var(--role-techlead-soft); color: var(--ink); }
.role-research { background: var(--role-research-soft); color: var(--ink); }
.role-qa       { background: var(--role-qa-soft);       color: var(--ink); }
.role-neutral  { background: var(--hover);              color: var(--ink-2-deep); }
/* skill 用中性色——不给它专属角色色。理由：skill 不是「谁」，是「工具」。
   角色色是身份语义，工具借用会破坏「彩色 = 有人格」的语义系统。 */
.role-skill    { background: var(--border-soft); color: var(--ink-2); font-family: var(--mono); }

/* ---- 会话行（agent 子项）---- */
.app-agent__sessions { padding-bottom: 2px; }
.app-sess {
  display: flex; align-items: center; gap: 8px;
  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;
}
.app-sess:hover { background: var(--hover); }
.app-sess__label { min-width: 0; flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-sess[aria-current="true"] { background: var(--surface); box-shadow: 0 0 0 1px var(--border), var(--sh-1); font-weight: var(--fw-ui); }
.app-sess[aria-current="true"]::before {
  content: ""; position: absolute; left: -10px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 16px; border-radius: 999px; background: var(--brand);
}

/* ---- Skill 行（叶子 · 无子会话）----
   与 .app-agent__row 结构对齐：mono + name + slot。差别：
   - 缩进比 agent 少一档（skill 在 SKILLS 头下直接列，不再包一层 .app-agent 容器）
   - 无 sessions 折叠区、无计数、无 hover 三点（本期不做启停/编辑/删除）
   选中态与 .app-sess[aria-current] 完全一致，让「点开一个 skill」和「点开一个会话」
   在感觉上是同一个动作。 */
.app-skill {
  display: flex; align-items: center; gap: 8px;
  margin: 0 8px; padding-right: 6px;
  min-height: 32px; border-radius: var(--r-sm);
  position: relative;
}
.app-skill:hover { background: var(--hover); }
.app-skill__name { font-size: var(--fs-13); font-weight: var(--fw-ui); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.app-skill[aria-current="true"] { background: var(--surface); box-shadow: 0 0 0 1px var(--border), var(--sh-1); }
.app-skill[aria-current="true"]::before {
  content: ""; position: absolute; left: -2px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 16px; border-radius: 999px; background: var(--brand);
}

/* ---- 状态槽（agent 计数 / session 未读点 / skill 无内容 · 变体的 toggle） ---- */
.app-slot { position: relative; width: 20px; height: 20px; flex: none; }
.app-slot > .app-agent__n,
.app-slot > .app-st { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; }
.app-st__dot {
  width: 8px; height: 8px; border-radius: 999px; background: var(--ink-3);
}
.app-st--run .app-st__dot { background: var(--brand); animation: appPulse 1.6s ease-in-out infinite; }
/* 会话完成态用 --ok（绿色 8px 圆点）—— 这是产品侧的**语义色**，与 wb-redesign 一致：
   彩色小圆点承担「已完成 / 在跑 / 失败」三态，尺寸 8px、语义清晰、不承担底色。
   与外壳 .pv-* 段已修好、把彩色留给 --warn/--brand 的判断互不冲突。 */
.app-st--done .app-st__dot { background: var(--ok); }
.app-st--fail .app-st__dot { background: var(--danger); }
@keyframes appPulse { 0%,100% { opacity: 1 } 50% { opacity: .35 } }
@media (prefers-reduced-motion: reduce) { .app-st--run .app-st__dot { animation: none; } }

/* ---- 变体：toggle（弱语义，本期不真绑 disabled 状态）---- */
.app-toggle {
  width: 26px; height: 14px; padding: 1px; border: 0; border-radius: 999px;
  background: var(--border); cursor: pointer;
  display: inline-flex; align-items: center;
}
.app-toggle[aria-checked="true"] { background: var(--brand); }
.app-toggle__dot {
  width: 10px; height: 10px; border-radius: 999px; background: var(--surface);
  transform: translateX(0); transition: transform .16s ease;
}
.app-toggle[aria-checked="true"] .app-toggle__dot { transform: translateX(12px); }
.app-toggle--lg { width: 40px; height: 22px; padding: 2px; }
.app-toggle--lg .app-toggle__dot { width: 16px; height: 16px; }
.app-toggle--lg[aria-checked="true"] .app-toggle__dot { transform: translateX(18px); }
.app-toggle__label { margin-left: 8px; color: var(--ink-2); font-size: var(--fs-13); }

/* ---- 左栏页脚 ---- */
.app-rail__foot {
  margin-top: auto; flex: none; border-top: 1px solid var(--border-soft);
  padding: 10px 14px; display: flex; align-items: center; gap: 8px;
  color: var(--ink-2); font-size: var(--fs-13);
}
.app-me__avatar {
  width: 22px; height: 22px; border-radius: 999px; background: var(--hover); color: var(--ink);
  font-size: 10px; font-weight: var(--fw-label); display: grid; place-items: center;
}
.app-me__name { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Mac Worker 心跳灯用 --ok（绿色 8px 圆点）—— 与 wb-redesign 同构；
   与 .app-st--done 是同一批语义色（在跑/完成/心跳），共占产品侧仅有的两处绿。 */
.app-heart { width: 8px; height: 8px; border-radius: 999px; background: var(--ok); }

/* ---- 主区 ---- */
.app-main { display: flex; flex-direction: column; min-width: 0; }
.app-topbar {
  padding: 14px 20px; border-bottom: 1px solid var(--border-soft);
  background: var(--canvas);
  display: flex; align-items: baseline; gap: 12px;
}
.app-topbar__title { font-size: var(--fs-15); font-weight: var(--fw-title); }
.app-topbar__meta { font-size: var(--fs-12); color: var(--ink-2); font-family: var(--mono); }

/* ---- 聊天体态（安静背景，只作对照）---- */
.app-chatbody { flex: 1; padding: 20px; display: flex; flex-direction: column; gap: 12px; overflow-y: auto; }
.app-msg { max-width: 720px; padding: 10px 14px; border-radius: 14px; font-size: var(--fs-14); line-height: 1.55; }
.app-msg--user { align-self: flex-end; background: var(--brand-soft); color: var(--ink); }
.app-msg--assistant { align-self: flex-start; background: var(--surface); border: 1px solid var(--border-soft); }
.app-msg--running { color: var(--ink-2); font-size: var(--fs-13); }
.app-run-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 999px;
  background: var(--brand); margin-right: 6px; vertical-align: middle;
  animation: appPulse 1.6s ease-in-out infinite;
}
.app-composer { border-top: 1px solid var(--border-soft); padding: 12px 20px; background: var(--surface); display: flex; gap: 10px; align-items: center; }
.app-composer textarea {
  flex: 1; height: 40px; padding: 10px 14px; border-radius: 12px;
  border: 1px solid var(--border); background: var(--surface); resize: none;
  font: inherit; font-size: var(--fs-14); color: var(--ink);
}
.app-composer textarea::placeholder { color: var(--ink-3); }
.app-send {
  border: 0; background: var(--ink); color: var(--on-brand);
  padding: 10px 18px; border-radius: 12px; cursor: pointer; font: inherit; font-weight: var(--fw-label);
}

/* ---- 详情体态：主区顶掉对话区，展示 SKILL.md 与元数据 ---- */
.app-detailbody { flex: 1; overflow-y: auto; }
.app-detail { max-width: 820px; margin: 0 auto; padding: 24px 28px 40px; }
.app-detail__breadcrumb { font-size: var(--fs-12); color: var(--ink-2); letter-spacing: 0.02em; }
.app-detail__breadcrumb span { margin: 0 6px; color: var(--ink-3); }
.app-detail__title {
  margin: 6px 0 12px; font-family: var(--mono); font-size: 22px;
  font-weight: var(--fw-title); letter-spacing: -0.01em; color: var(--ink);
}
.app-detail__desc {
  margin: 0 0 20px; font-size: var(--fs-14); line-height: 1.65; color: var(--ink-2-deep);
  max-width: 68ch;
}
.app-detail__meta {
  display: grid; grid-template-columns: 140px 1fr; gap: 6px 14px; margin: 0 0 24px;
  padding: 14px 16px; background: var(--surface);
  border: 1px solid var(--border-soft); border-radius: 12px;
  font-size: var(--fs-13);
}
.app-detail__meta dt { color: var(--ink-2); margin: 0; }
.app-detail__meta dd { margin: 0; color: var(--ink); }
.app-detail__meta code { font-family: var(--mono); font-size: 12.5px; padding: 1px 6px; background: var(--hover); border-radius: 4px; }

/* 资产段（bin/refs 列表）—— 只有真存在的 skill 才出现 */
.app-detail__assets { display: grid; gap: 12px; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); margin: 0 0 24px; }
.app-asset { padding: 14px 16px; border: 1px solid var(--border-soft); border-radius: 12px; background: var(--surface); font-size: var(--fs-13); }
.app-asset__head { font-weight: var(--fw-title); font-size: var(--fs-13); margin-bottom: 8px; }
.app-asset__list { list-style: none; padding: 0; margin: 0; display: grid; gap: 4px; }
.app-asset__list code { font-family: var(--mono); font-size: 12.5px; color: var(--ink-2-deep); }
.app-asset__hint { color: var(--ink-2); font-size: var(--fs-12); line-height: 1.55; }

/* Markdown 正文段（示意，只画头 + 一小段）*/
.app-detail__md { border: 1px solid var(--border-soft); border-radius: 12px; background: var(--surface); overflow: hidden; }
.app-md__head { padding: 10px 14px; background: var(--hover); font-size: var(--fs-12); color: var(--ink-2); border-bottom: 1px solid var(--border-soft); }
.app-md__body { padding: 16px 20px; }
.app-md__body h2 { margin: 0 0 8px; font-size: var(--fs-15); font-weight: var(--fw-title); font-family: var(--mono); color: var(--ink); }
.app-md__p { margin: 8px 0; font-size: var(--fs-14); line-height: 1.65; color: var(--ink-2-deep); }

/* ---- 变体：诚实警示条 ---- */
.app-honesty {
  margin: 0 0 16px; padding: 12px 14px;
  background: var(--warn-soft);
  border-left: 3px solid var(--warn);
  border-radius: 4px 8px 8px 4px;
  font-size: var(--fs-13); line-height: 1.65; color: var(--ink);
}
.app-honesty b { color: var(--ink); }
.app-detail__toggle {
  display: flex; align-items: center; gap: 10px; margin: 0 0 20px;
  padding: 12px 14px; background: var(--surface);
  border: 1px solid var(--border-soft); border-radius: 12px;
  font-size: var(--fs-13);
}
.app-detail__toggle > span:first-child { font-weight: var(--fw-title); }

/* ---- 加载/失败/空 ---- */
.app-loading { padding: 40px 28px; display: flex; flex-direction: column; gap: 12px; max-width: 640px; }
.app-skel { height: 14px; background: linear-gradient(90deg, var(--hover) 0%, var(--border-soft) 50%, var(--hover) 100%); border-radius: 6px; animation: appShimmer 1.4s ease-in-out infinite; }
.app-skel--title { height: 22px; width: 40%; }
.app-skel--w60 { width: 60%; }
@keyframes appShimmer { 0% { opacity: .6 } 50% { opacity: 1 } 100% { opacity: .6 } }
@media (prefers-reduced-motion: reduce) { .app-skel { animation: none; } }

.app-error {
  margin: 40px auto; max-width: 480px; padding: 28px;
  background: var(--surface); border: 1px solid var(--border-soft);
  border-radius: 14px; text-align: center;
}
.app-error__icon {
  width: 40px; height: 40px; margin: 0 auto 12px; border-radius: 999px;
  background: var(--warn-soft);
  color: var(--warn);
  display: grid; place-items: center; font-size: 22px; font-weight: 700;
}
.app-error h3 { margin: 0 0 8px; font-size: var(--fs-15); }
.app-error p { margin: 0 0 14px; color: var(--ink-2-deep); font-size: var(--fs-13); line-height: 1.6; }
.app-error code { font-family: var(--mono); background: var(--hover); padding: 1px 6px; border-radius: 4px; }
.app-btn {
  border: 1px solid var(--border); background: var(--surface);
  color: var(--ink); padding: 8px 18px; border-radius: 10px; cursor: pointer; font: inherit; font-weight: var(--fw-label);
}

.app-empty {
  margin: 40px auto; max-width: 520px; padding: 28px;
  background: var(--surface); border: 1px dashed var(--border);
  border-radius: 14px;
}
.app-empty h3 { margin: 0 0 10px; font-size: var(--fs-15); }
.app-empty p { margin: 0 0 10px; color: var(--ink-2-deep); font-size: var(--fs-13); line-height: 1.65; }
.app-empty code { font-family: var(--mono); background: var(--hover); padding: 1px 6px; border-radius: 4px; }
.app-empty__hint { color: var(--ink-2); font-size: var(--fs-12); border-top: 1px solid var(--border-soft); padding-top: 12px; margin-top: 14px; }

/* ---- 图鉴样张外框：atlas 卡的内部展示容器 ---- */
.atlas-frame {
  background: var(--canvas);
  border-radius: 8px;
  overflow: hidden;
}

/* ---- H5 断点：≤640 时左栏变抽屉；本稿并排看图为主，抽屉只画默认展开态 ----
   选择器**必须**与桌面规则同特异性：桌面写 .app-wb.app-root (0,2,0)，
   断点里若只写 .app-wb (0,1,0) 就被桌面压住，@container **不增加特异性** ——
   条件命中了声明也赢不过。响应式静静失效：横向溢出 0px、grid 行归属正确，
   两套闸门 147 项全过；但 H5 框里 .app-main 被压到 67px（288 字），
   人一眼看出坏了。skill 8-28 新增的「内容未被压窄」判据（e2e §checkSqueezed）
   正是接着这类问题，宽度 < 120px 且承载 ≥8 字的可视块就报红。 */
@container (max-width: 640px) {
  .app-wb.app-root { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto 1fr; }
  .app-rail {
    border-right: 0; border-bottom: 1px solid var(--border-soft);
    max-height: 60vh; overflow-y: auto;
  }
  .app-rail__scroll--skills { max-height: none; }
  .app-detail { padding: 16px; }
  .app-detail__meta { grid-template-columns: 1fr; gap: 2px 0; }
  .app-detail__meta dt { margin-top: 8px; }
  .app-detail__meta dt:first-of-type { margin-top: 0; }
}
