/* ============================================================
   Agent 管理页 · 样式
   本文件分两段，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__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__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 */

/* ---- .why：交互式 PRD 的灵魂 ----
   每个界面区块旁边一段「为什么这样设计」。写的是取舍与口径，不是复述界面。
   形态照参照物 wb-redesign（.spec > header .why）：小字、次要色、限宽 46ch。
   prototype-verify 会数正文里的 .why —— 少于场景数报红：有界面没解释不是 PRD。 */
.why {
  display: block; font-size: var(--fs-12); line-height: 1.65;
  color: var(--ink-2); max-width: 46ch; margin-top: 4px;
}
.why b, .why code { color: var(--ink); }

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

.app-root { padding: 20px; padding-bottom: calc(20px + var(--kb-inset)); }

/* ---- 头部 ---- */
.app-head { margin-bottom: 18px; }
.app-h1 { font: var(--fw-title) var(--fs-18)/1.2 var(--sans); margin: 0 0 4px; }
.app-sum { color: var(--ink-2); font-size: var(--fs-13); }
.app-sum b { color: var(--ink); font-weight: var(--fw-label); }
.app-sum--bad { color: var(--danger); }
.app-sum--bad b { color: var(--danger); }

/* ---- 花名册 ---- */
.app-list { display: grid; gap: 10px; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.app-list--dim { opacity: .45; }

.app-card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r); padding: 14px 16px;
}
/* 在跑的卡用左侧色条标记，不改底色 —— 底色变了会让人以为这张卡是另一类东西 */
.app-card--busy { box-shadow: inset 3px 0 0 var(--brand); }
.app-card--open { grid-column: 1 / -1; max-width: 520px; }

.app-card__top { display: flex; align-items: baseline; gap: 10px; margin-bottom: 6px; }
/* 名字不截断、允许折行：截断会把两个相似的 agent 名显示成同一个 */
.app-name { font: var(--fw-ui) var(--fs-14)/1.35 var(--sans); overflow-wrap: anywhere; }
.app-state {
  margin-left: auto; flex: none; font-size: var(--fs-12); color: var(--ink-2);
}
.app-state--busy { color: var(--brand); font-weight: var(--fw-label); }

.app-desc { margin: 0 0 10px; color: var(--ink-2); font-size: var(--fs-13); line-height: 1.5; }
.app-desc--missing { color: var(--warn); }

.app-meta { display: flex; flex-wrap: wrap; gap: 6px; }
.app-tag {
  font-size: var(--fs-12); color: var(--ink-2);
  background: var(--hover); border-radius: var(--r-sm); padding: 2px 8px;
}
/* 两种工作区模式的权限边界完全不同，所以不跟引擎标签同色 */
.app-tag--wt { background: var(--brand-soft); color: var(--brand-ink); }
.app-tag--home { background: var(--hover); color: var(--ink-3); }

/* ---- 在跑的 run ---- */
.app-run {
  margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--border);
  display: grid; gap: 4px;
}
.app-run__row { display: grid; grid-template-columns: 56px minmax(0, 1fr); gap: 10px; font-size: var(--fs-12); }
.app-run__k { color: var(--ink-3); }
.app-run__v { color: var(--ink-2); overflow-wrap: anywhere; }
/* run id 要能被整段选中贴进终端 —— 这是卡片上唯一会被复制的东西 */
code.app-run__v { font-family: var(--mono); user-select: all; }

/* ---- worker 全离线 ---- */
.app-alert {
  background: var(--danger-soft); border: 1px solid var(--danger);
  border-radius: var(--r); padding: 14px 16px; margin-bottom: 16px;
}
.app-alert__t { font: var(--fw-label) var(--fs-14)/1.4 var(--sans); margin-bottom: 6px; }
.app-alert__d { margin: 0 0 10px; font-size: var(--fs-13); color: var(--ink-2); line-height: 1.55; }
.app-alert__cmd {
  display: inline-block; font-family: var(--mono); font-size: var(--fs-12);
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--r-sm); padding: 4px 10px; user-select: all;
}

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