/* ============================================================================
   统一 AI 会话控制台 — INSTRUMENT 仪表台样式（DESIGN_UI v1）
   零外部资源：字体用系统栈，图标是 index.html 里的内联 SVG sprite。
   深色为默认，浅色为"蓝图纸"主题（随系统 prefers-color-scheme）。
   ---------------------------------------------------------------------------
    with four token values lifted/darkened for contrast (every text pair below
   clears 4.5:1 on --bg / --surface — measured, see the report):
     dark  --text-3  #5f7085 → #748699   (3.8:1 → 5.1:1 on --bg)
     light --text-3  #7a8798 → #626e7b   (3.4:1 → 4.9:1 on --bg)
     light --ok      #178a4c → #15803d   (4.1:1 → 4.7:1 on --bg)
     light --warn    #9a6a12 → #8a5c0e   (4.4:1 → 5.5:1 on --bg)
   Two extra ink tokens (--warn-ink / --bad-ink) keep filled signal chips
   readable in both themes; no new hue is introduced.
   ========================================================================== */

:root {
  /* ---- 调色（信号色，不做装饰） */
  --bg: #0b1017;
  --surface: #111823;
  --surface-2: #16202d;
  --surface-3: #1d2836;
  --line: #202c3a;
  --line-strong: #2e3d50;
  --text: #e3eaf3;
  --text-2: #9aa8ba;
  --text-3: #748699;
  --accent: #5aa2ff;
  --ok: #3ecf8e;
  --warn: #e8b158;
  --bad: #f0716f;
  --violet: #a78bfa;
  --accent-ink: #06121f;
  --warn-ink: #22160a;
  --bad-ink: #1f0605;
  /* hover 只挪明度：暗色主题提亮，浅色主题压暗，字始终压得住底 */
  --accent-hover: color-mix(in srgb, var(--accent) 86%, #ffffff);
  --bad-hover: color-mix(in srgb, var(--bad) 86%, #ffffff);

  /* ---- 形状 / 空间 */
  --r-ctl: 6px;
  --r-card: 10px;
  --r-sheet: 14px;
  --r-pill: 999px;
  --pad: 14px;
  --col: 780px;
  --hdr: 45px;

  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", "DejaVu Sans Mono", monospace;
  --sans: -apple-system, BlinkMacSystemFont, "Segoe UI", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "Songti SC", "Noto Sans CJK SC", sans-serif;

  --shadow: 0 12px 32px rgba(0, 0, 0, .55), 0 2px 6px rgba(0, 0, 0, .4);
  --ring: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
  --blueprint: transparent;
}

/* ── 浅色"蓝图纸"值：全仓唯一一处（U1，避免两处复制漂移）─────────────── */
:root {
  --l-bg: #f6f8fb;
  --l-surface: #ffffff;
  --l-surface-2: #eef2f7;
  --l-surface-3: #e3e9f1;
  --l-line: #e1e7ef;
  --l-line-strong: #c9d4e0;
  --l-text: #0f1720;
  --l-text-2: #4b5a6e;
  --l-text-3: #626e7b;
  --l-accent: #2b6fd4;
  --l-ok: #15803d;
  --l-warn: #8a5c0e;
  --l-bad: #c23f3a;
  --l-violet: #6d4fc0;
  --l-accent-ink: #ffffff;
  --l-warn-ink: #ffffff;
  --l-bad-ink: #ffffff;
  --l-shadow: 0 10px 26px rgba(23, 40, 66, .16), 0 2px 6px rgba(23, 40, 66, .1);
}

/*
 * 浅色映射：同一份"令牌 → 主题变量"映射，两个入口共用
 *   · 显式浅色（data-theme="light"）——不受系统影响
 *   · 自动（无 data-theme）且系统为浅色——由媒体查询接管
 * 深色 = :root 默认值（data-theme="dark" 与"自动+系统深色"都落在这里）。
 */
:root[data-theme="light"] {
  --bg: var(--l-bg);
  --surface: var(--l-surface);
  --surface-2: var(--l-surface-2);
  --surface-3: var(--l-surface-3);
  --line: var(--l-line);
  --line-strong: var(--l-line-strong);
  --text: var(--l-text);
  --text-2: var(--l-text-2);
  --text-3: var(--l-text-3);
  --accent: var(--l-accent);
  --ok: var(--l-ok);
  --warn: var(--l-warn);
  --bad: var(--l-bad);
  --violet: var(--l-violet);
  --accent-ink: var(--l-accent-ink);
  --warn-ink: var(--l-warn-ink);
  --bad-ink: var(--l-bad-ink);
  --accent-hover: color-mix(in srgb, var(--l-accent) 88%, #000000);
  --bad-hover: color-mix(in srgb, var(--l-bad) 88%, #000000);
  --shadow: var(--l-shadow);
  --blueprint: color-mix(in srgb, var(--l-line-strong) 34%, transparent);
  color-scheme: light;
}

@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) {
    --bg: var(--l-bg);
    --surface: var(--l-surface);
    --surface-2: var(--l-surface-2);
    --surface-3: var(--l-surface-3);
    --line: var(--l-line);
    --line-strong: var(--l-line-strong);
    --text: var(--l-text);
    --text-2: var(--l-text-2);
    --text-3: var(--l-text-3);
    --accent: var(--l-accent);
    --ok: var(--l-ok);
    --warn: var(--l-warn);
    --bad: var(--l-bad);
    --violet: var(--l-violet);
    --accent-ink: var(--l-accent-ink);
    --warn-ink: var(--l-warn-ink);
    --bad-ink: var(--l-bad-ink);
    --accent-hover: color-mix(in srgb, var(--l-accent) 88%, #000000);
    --bad-hover: color-mix(in srgb, var(--l-bad) 88%, #000000);
    --shadow: var(--l-shadow);
    /* "蓝图纸"：浅色主题下留白处铺一层极淡的坐标格 */
    --blueprint: color-mix(in srgb, var(--l-line-strong) 34%, transparent);
    color-scheme: light;
  }
}

/* 显式深色：即使系统偏好浅色也压住（并让原生控件/滚动条跟着深色） */
:root[data-theme="dark"] { color-scheme: dark; }

/* ------------------------------------------------------------------- base */

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
[hidden] { display: none !important; }
/* 横滚防线（U23）：整页永远不可横向移动，横向滑动只准发生在内层容器里。
   1) overscroll-behavior 两个方向都 contain：内层横滑容器滑到边缘后残余的
      横向位移不再链到页面/浏览器，否则会被当成"整页横拖"（或后退手势）。
   2) overflow-x: hidden（老浏览器兜底）→ clip（不建立滚动容器，sticky 照旧）：
      将来某个元素意外变宽时，页面本身也不出现横向滚动条。
   3) 视口按规范把 clip 当 hidden 用；纵向滚动、position: sticky/fixed 都不受影响。 */
html, body { overscroll-behavior: contain; }
/* 禁缩放（U21-2）：viewport meta 管住多数浏览器，CSS 再兜一层——
   交互元素去掉双击缩放（touch-action: manipulation = 允许平移 + 去掉
   double-tap zoom）。内层滚动容器不受影响：手势的 touch-action 判定到"该手势
   的滚动容器"为止，所以 chip 行/代码块的内部横滑不受 html 的 pan-y 影响。 */
html {
  background: var(--bg);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* U23：页面只接受纵向平移。pan-x 一开，横向手势就能拖动整页（哪怕只多 1px
     溢出也会被拖走），所以这里必须是 pan-y 而不是 pan-x pan-y。 */
  touch-action: pan-y;
  overflow-x: hidden;
  overflow-x: clip;
}
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font: 15px/1.55 var(--sans);
  overflow-wrap: break-word;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* U23：同 html —— 整页只纵向平移；横滑只归内层容器（它们本身是滚动容器，
     见下方"合法横滑容器"段） */
  touch-action: pan-y;
}
a { color: var(--accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }
button, input, textarea, select, label { touch-action: manipulation; }
/* 合法横滑容器（U23）：附件 chip 行 / 代码块 / 表格 / 工具详情 /
   折叠列表 / key 块。这些地方该横滑，但只准在自己里面滑到边缘为止。
   · 这里**刻意不写** touch-action：这些元素自己就是该手势的滚动容器，默认值
     auto 已经允许内部横滑（html/body 的 pan-y 判定不到它们）；反而一旦同时声明
     touch-action + overscroll-behavior，Chrome 会把手势完全扣在这个容器上，
     使得"在 chip 行/代码块上起手的竖拖"再也滚不动整页（实测 dy 290 → 0）。
   · overscroll-behavior-x（只锁横轴）：滑到边缘后残余的横拖不再链给页面/浏览器
     （否则会变成整页横移或 iOS 的边缘返回手势）。
   每条都必须自带 overflow-x/overflow: auto，否则就变成"能拖但没得拖"的假横滑。
   U24：卷进来的横滑单位从"计划体整块"降到"计划体里的代码块/表格"——
   .m-ask .planbody 现在是纵向容器（overflow-x: clip），它整块横滑会让审批卡底部
   永远挂着一条滚动条；改由 .mdbody pre / .mdbody table 在卡片内部横滑。 */
.attrow,
.m-bot pre,
.m-bot table,
.mdbody pre,
.mdbody table,
.code,
.m-tool .tdetail,
.m-generic .rawjson,
.m-generic.fold .foldlist,
.keyblock .kval {
  overscroll-behavior-x: contain;
}
button, input, textarea, select { font-family: inherit; }
:where(button, a, input, textarea, select, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
::selection { background: color-mix(in srgb, var(--accent) 34%, transparent); }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-thumb { background: var(--line-strong); border: 3px solid transparent; background-clip: padding-box; border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-3); background-clip: padding-box; }
::-webkit-scrollbar-track { background: transparent; }

.num, .cnt, .gcount, #newMsgCnt { font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------------ icons */

.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
.i {
  width: 18px; height: 18px; flex: none;
  fill: none; stroke: currentColor;
  stroke-width: 1.75; stroke-linecap: round; stroke-linejoin: round;
}
.i.sm { width: 15px; height: 15px; }
.i.tiny { width: 13px; height: 13px; }
.i.lg { width: 22px; height: 22px; }
.i.xl { width: 26px; height: 26px; }
.i.mono { stroke-width: 1.6; }

/* ---------------------------------------------------------------- controls */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  min-height: 40px; padding: 0 13px;
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  background: var(--surface-2); color: var(--text);
  font: 600 13px/1 var(--sans); cursor: pointer;
  transition: background .12s, border-color .12s, color .12s, opacity .12s;
}
.btn:hover { background: var(--surface-3); }
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: .42; cursor: not-allowed; transform: none; }
.btn.pri { background: var(--accent); border-color: var(--accent); color: var(--accent-ink); }
.btn.pri:hover { background: var(--accent-hover); }
.btn.pri.danger { background: var(--bad); border-color: var(--bad); color: var(--bad-ink); }
.btn.pri.danger:hover { background: var(--bad-hover); }
.btn.ghost { background: transparent; border-color: var(--line-strong); color: var(--text-2); }
.btn.ghost:hover { background: var(--surface-2); color: var(--text); }
.btn.danger, .btn.ghost.danger { background: transparent; border-color: color-mix(in srgb, var(--bad) 45%, transparent); color: var(--bad); }
.btn.danger:hover, .btn.ghost.danger:hover { background: color-mix(in srgb, var(--bad) 12%, transparent); }
.btn.small { min-height: 40px; padding: 0 10px; font-size: 12.5px; }
.btn.wide { width: 100%; }

/* 行内 quiet 文字钮：不用方框按钮海（DESIGN_UI §3.2） */
.tbtn {
  display: inline-flex; align-items: center; gap: 5px;
  min-height: 40px; padding: 0 8px; border: 0; border-radius: var(--r-ctl);
  background: none; color: var(--text-2);
  font: 500 12.5px/1 var(--sans); white-space: nowrap; cursor: pointer;
  transition: color .12s, background .12s;
}
.tbtn:hover { color: var(--text); background: var(--surface-2); }
.tbtn:active { transform: translateY(1px); }
.tbtn.pri { color: var(--accent); }
.tbtn.danger { color: var(--bad); }
.tbtn.danger:hover { background: color-mix(in srgb, var(--bad) 12%, transparent); }

.iconbtn {
  position: relative; display: inline-grid; place-items: center;
  width: 40px; height: 40px; flex: none;
  border: 1px solid transparent; border-radius: var(--r-ctl);
  background: none; color: var(--text-2); cursor: pointer;
  transition: color .12s, background .12s, border-color .12s;
}
.iconbtn:hover { color: var(--text); background: var(--surface-2); }
.iconbtn:active { transform: translateY(1px); }
.iconbtn.quiet { width: 40px; height: 40px; color: var(--text-3); }
.iconbtn.quiet:hover { color: var(--text-2); }
.iconbtn.on { color: var(--ok); }
.iconbtn.has { color: var(--warn); }
.apbar { display: flex; align-items: center; gap: 2px; }
.apbar .iconbtn { margin-left: auto; }
.cnt {
  position: absolute; top: 3px; right: 2px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: var(--r-pill); background: var(--warn); color: var(--warn-ink);
  font: 700 10px/16px var(--mono); text-align: center;
}

input, textarea, select {
  background: var(--bg); color: var(--text);
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  padding: 9px 11px; font-size: 16px; width: 100%; min-height: 40px;
}
input:focus, textarea:focus, select:focus { border-color: var(--accent); outline: none; box-shadow: var(--ring); }
input::placeholder, textarea::placeholder { color: var(--text-3); opacity: 1; }
textarea { resize: vertical; line-height: 1.5; }
label { display: block; margin: 12px 0 5px; font: 500 11px var(--mono); letter-spacing: .02em; color: var(--text-3); }

/* ----------------------------------------------------------------- header */

header {
  position: sticky; top: 0; z-index: 5;
  display: flex; align-items: center; gap: 2px;
  height: calc(44px + env(safe-area-inset-top));
  padding: env(safe-area-inset-top) 6px 0 8px;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(14px) saturate(1.3);
  border-bottom: 1px solid var(--line);
}
#dot {
  width: 7px; height: 7px; flex: none; margin: 0 7px 0 3px;
  border-radius: var(--r-pill); background: var(--bad);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--bad) 15%, transparent);
  transition: background .25s, box-shadow .25s;
}
#dot.on { background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 14%, transparent); }
.brand {
  display: flex; align-items: center; gap: 5px;
  min-height: 40px; padding: 0 4px; border: 0; background: none;
  color: var(--text); font: 600 13.5px var(--mono);
  max-width: 46vw; overflow: hidden; white-space: nowrap; text-overflow: ellipsis;
  cursor: pointer;
}
.brand::before { content: "❯"; color: var(--accent); font-weight: 700; }
.brand:hover { color: var(--accent); }
#state {
  display: none; align-items: center; height: 19px; padding: 0 8px; margin-left: 6px;
  border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent); border-radius: var(--r-pill);
  color: var(--warn); font: 500 10.5px var(--mono); white-space: nowrap;
}
#state.show { display: inline-flex; }
.hspacer { flex: 1; }

/* ---------------------------------------------------------------- banners */

#connBanner, #notifyBanner, #updateBanner {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  padding: 8px var(--pad);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  font-size: 13px; color: var(--text-2);
}
#connBanner { color: var(--warn); }
#updateBanner { color: var(--accent); }
#connBanner .i, #notifyBanner .i { color: inherit; }
#connBanner .retry, #notifyBanner .btn, #updateBanner .retry { margin-left: auto; }
.link { color: var(--accent); cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }

/* ----------------------------------------------------------------- layout */

main { padding: 0 0 96px; }
#pageView { padding: 10px var(--pad) 110px; }
#deskHint {
  display: none; position: fixed; left: 340px; right: 0; top: 0; bottom: 0;
  align-items: center; justify-content: center; flex-direction: column; gap: 12px;
  padding: 0 var(--pad) 60px; text-align: center; color: var(--text-3); font-size: 13px;
  background-image:
    linear-gradient(to right, var(--blueprint) 1px, transparent 1px),
    linear-gradient(to bottom, var(--blueprint) 1px, transparent 1px);
  background-size: 26px 26px;
  pointer-events: none;
}
#deskHint .i { width: 30px; height: 30px; color: var(--line-strong); }
body.desk #deskHint:not([hidden]) { display: flex; }

/* ------------------------------------------------------------- 列表：工具 */
/* 手机端顶部留白压缩：工具区 padding 6/4、搜索与新建同一行、分组头 margin 6。 */

#listTools { display: flex; flex-direction: column; gap: 6px; padding: 6px var(--pad) 4px; }
.searchrow { display: flex; align-items: stretch; gap: 8px; }
.searchrow .searchwrap { flex: 1; min-width: 0; }
.searchwrap { position: relative; display: flex; align-items: center; }
.searchwrap .i { position: absolute; left: 11px; color: var(--text-3); pointer-events: none; }
#searchBox {
  width: 100%; min-height: 40px; padding: 0 12px 0 35px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  color: var(--text); font-size: 15px;
}
#searchBox:focus { border-color: var(--accent); outline: none; box-shadow: var(--ring); }
#searchBox::-webkit-search-cancel-button { -webkit-appearance: none; }

#chips { display: flex; gap: 2px; flex-wrap: wrap; }
.chipbtn {
  min-height: 40px; padding: 0 10px;
  background: none; border: 0; border-bottom: 2px solid transparent; margin-bottom: -1px;
  color: var(--text-3); font: 500 13px/38px var(--sans);
  cursor: pointer; transition: color .12s, border-color .12s;
}
.chipbtn:hover { color: var(--text-2); }
.chipbtn.on { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }

.pad { padding: 6px var(--pad); }
/* 新建会话：跟搜索框同一行的虚线钮；.off = 无可建目标（置灰，点击 toast 说明） */
.newbtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px; flex: none;
  min-height: 40px; padding: 0 12px;
  background: none; border: 1px dashed var(--line-strong); border-radius: var(--r-ctl);
  color: var(--text-2); font: 500 13px var(--sans); white-space: nowrap; cursor: pointer;
  transition: color .12s, border-color .12s, background .12s, opacity .12s;
}
.newbtn:hover { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 45%, transparent); background: color-mix(in srgb, var(--accent) 6%, transparent); }
.newbtn:active { transform: translateY(1px); }
.newbtn.off { color: var(--text-3); border-color: var(--line); cursor: default; opacity: .55; }
.newbtn.off:hover { color: var(--text-3); border-color: var(--line); background: none; }
.newbtn.off:active { transform: none; }
.tbtn.wide { width: calc(100% - 28px); justify-content: center; }

/* ------------------------------------------------------------ 列表：分组头 */

.sec, .sec2 {
  display: flex; align-items: center; gap: 8px;
  margin: 0; padding: 0 var(--pad); height: 34px;
  font-family: var(--mono); font-weight: 600; color: var(--text-2);
}
.sec { font-size: 11.5px; letter-spacing: .02em; margin-top: 6px; }
.sec2 { font-size: 11px; letter-spacing: .02em; color: var(--text-3); height: 30px; padding-left: 30px; }
.sec2.sub { height: 26px; padding-left: 44px; gap: 7px; color: var(--text-3); }
.sec2.sub .lead { opacity: .7; }
.sec .lead, .sec2 .lead { flex: 1; height: 1px; background: var(--line); }
.gname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 58%; }
.gcount { color: var(--text-3); font-size: 11px; font-weight: 500; }
.clickable { cursor: pointer; user-select: none; }
.clickable:hover { color: var(--text); }
.chev { color: var(--text-3); transition: transform .15s ease; }
.chev.closed { transform: rotate(-90deg); }

.st { width: 7px; height: 7px; flex: none; border-radius: var(--r-pill); background: var(--text-3); }
.st.online { background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 13%, transparent); }
.st.waiting { background: var(--warn); animation: breathe 2.4s ease-in-out infinite; }
.st.running { background: var(--ok); box-shadow: 0 0 0 3px color-mix(in srgb, var(--ok) 13%, transparent); }

/* ------------------------------------------- 机器页：启动配置（U30）/ 接入面板 */

/* 机器页的启动配置区：一行一个（备注名 + 路径 + 删除），下面是添加表单 */
.setrow {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 0; border-bottom: 1px solid var(--line);
}
.setrow:last-of-type { border-bottom: 0; }
.setrow .sinfo { min-width: 0; flex: 1; }
.setrow .sname { font-size: 14px; color: var(--text); }
.setrow .spath {
  font: 11.5px var(--mono); color: var(--text-3);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.wform-actions { display: flex; gap: 8px; margin-top: 10px; }

/* 说明性小字（面板上的后果提示、机器页的提示） */
.note { color: var(--text-3); font-size: 12.5px; line-height: 1.6; margin-top: 6px; }

/* 只读字段（接入面板的工作目录）：长得像输入框但不可改，一眼看出是"给定的" */
.readonlyfield { margin-top: 10px; }
.readonlyfield .rlabel { font-size: 12.5px; color: var(--text-3); }
.readonlyfield .rvalue {
  margin-top: 4px; padding: 9px 11px; border-radius: var(--r-ctl);
  background: var(--surface-2); border: 1px dashed var(--line-strong);
  font: 12.5px var(--mono); color: var(--text-2); word-break: break-all;
}

/* ------------------------------------------------- 列表：面包屑 / 层级入口 */

/* 面包屑（08 §4.1）：滚动时吸顶 —— 175 行滑到第三屏也知道自己在哪一层。
   高度对齐 .sec 的 34px，免得和分类标题打架。 */
.crumbs {
  position: sticky; top: var(--hdr); z-index: 4;
  display: flex; align-items: center; gap: 4px;
  height: 34px; padding: 0 var(--pad); margin-bottom: 2px;
  background: var(--bg); border-bottom: 1px solid var(--line);
  font-family: var(--mono); font-size: 11.5px; color: var(--text-3);
  overflow-x: auto; scrollbar-width: none;
}
.crumbs::-webkit-scrollbar { display: none; }
.crumbs .i { color: var(--text-3); opacity: .7; flex: none; }
.crumbs .clink {
  flex: none; padding: 2px 5px; margin: 0 -2px; border: 0; border-radius: 5px;
  background: none; color: var(--accent); font: inherit; cursor: pointer;
  white-space: nowrap;
}
.crumbs .clink:hover { background: var(--accent-soft); }
.crumbs .cnow {
  flex: none; padding: 2px 5px; margin: 0 -2px; color: var(--text-2); font-weight: 600;
  white-space: nowrap; max-width: 46vw; overflow: hidden; text-overflow: ellipsis;
}

/* 机器入口行 / 待应答行 / AI 行：整行可点的层级入口，右侧统一 chevron */
.machrow, .airow, .wrow {
  display: flex; align-items: center; gap: 8px;
  width: 100%; min-height: 44px; padding: 0 var(--pad);
  border: 0; background: none; color: var(--text); font: inherit; text-align: left;
  border-bottom: 1px solid var(--line);
}
.machrow { cursor: pointer; }
.machrow:hover, .wrow:hover, .airow.link:hover { background: var(--surface); }
.machrow .mname, .airow .aname { font-weight: 600; font-size: 14.5px; }
.machrow .mmeta, .airow .ameta, .airow .aver {
  color: var(--text-3); font: 11.5px var(--mono);
}
.machrow .mmeta, .airow .ameta { margin-left: auto; text-align: right; }
.machrow .i, .airow .i, .wrow .i { color: var(--text-3); flex: none; }
.wrow { cursor: pointer; color: var(--warn); }
.wrow .wtext { font-weight: 600; font-size: 14px; }
.wrow .i:last-child { margin-left: auto; }
.airow { cursor: default; }
.airow.link { cursor: pointer; }
.airow.off .aname, .airow.off .ameta { color: var(--text-3); font-weight: 500; }
.airow .aver { padding: 1px 6px; border-radius: var(--r-pill); background: var(--surface-2); }
.airow .ameta { margin-left: auto; }
@media (hover: none) {
  .machrow:active, .wrow:active, .airow.link:active { background: var(--surface-2); }
}

/* ------------------------------------------------------------- 列表：会话行 */

.row {
  position: relative;
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: "top stat" "meta stat" "acts acts";
  align-items: center; column-gap: 6px; row-gap: 3px;
  padding: 9px var(--pad) 9px 16px;
  cursor: pointer; user-select: none;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent);
  transition: background .12s;
}
.row::before {
  content: ""; position: absolute; left: 0; top: 8px; bottom: 8px; width: 2px;
  border-radius: 0 2px 2px 0; background: var(--line-strong); opacity: .55;
  transition: background .2s, opacity .2s, box-shadow .2s;
}
.row:hover { background: var(--surface-2); }
.row:hover::before { opacity: 1; }
.row:active { background: var(--surface-3); }
.row[data-st="online"]::before { background: var(--ok); opacity: 1; }
.row[data-st="running"]::before { background: var(--ok); opacity: 1; }
.row[data-st="working"]::before { background: var(--accent); opacity: 1; }
.row[data-st="waiting"]::before { background: var(--warn); opacity: 1; box-shadow: 0 0 10px color-mix(in srgb, var(--warn) 55%, transparent); animation: breathe 2.4s ease-in-out infinite; }
.row[data-st="background"]::before { background: var(--violet); opacity: 1; }
.row[data-st="bad"]::before { background: var(--bad); opacity: 1; }
.row.waiting { background: color-mix(in srgb, var(--warn) 6%, var(--bg)); }
.row.waiting:hover { background: color-mix(in srgb, var(--warn) 12%, var(--surface-2)); }

.rtop { grid-area: top; display: flex; align-items: center; gap: 7px; min-width: 0; }
.title2 {
  flex: 1; min-width: 0;
  font: 600 14.5px/1.35 var(--sans); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row.waiting .title2 { color: var(--warn); }
.rmeta {
  grid-area: meta; display: flex; align-items: center; gap: 6px; min-width: 0;
  font: 11.5px var(--mono); color: var(--text-3);
}
.rmeta .mtxt { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rmeta .mtxt.cwd { flex: 0 1 auto; max-width: 46%; }
.rmeta .mtxt.time { flex: none; }
.rmeta .mtxt.model { flex: 0 1 auto; min-width: 0; }
.rmeta .sep { color: color-mix(in srgb, var(--text-3) 65%, transparent); flex: none; }
.racts {
  grid-column: 2; grid-row: 1 / span 2;
  display: flex; align-items: center; gap: 2px; justify-self: end;
}
.racts .tbtn { padding: 0 7px; }

.udot {
  width: 7px; height: 7px; flex: none; border-radius: var(--r-pill); background: var(--warn);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 15%, transparent);
  animation: breathe 1.8s ease-in-out infinite;
}
.unum { font: 600 11px var(--mono); color: var(--warn); }

.tag {
  display: inline-flex; align-items: center; gap: 4px; height: 17px; padding: 0 5px;
  border: 1px solid var(--line); border-radius: 3px;
  font: 500 10.5px var(--mono); color: var(--text-3); white-space: nowrap;
}
.b-waiting { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 45%, transparent); }
.b-working { color: var(--accent); border-color: color-mix(in srgb, var(--accent) 40%, transparent); }
.b-running { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 38%, transparent); }
.b-duplicate, .b-offline { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 40%, transparent); }
.b-background, .b-compacting { color: var(--violet); border-color: color-mix(in srgb, var(--violet) 40%, transparent); }
.b-online { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 38%, transparent); }
.b-migrated, .b-archived, .b-detached, .b-ended, .b-generic { color: var(--text-3); }
.b-unread { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 42%, transparent); }
.pulse { animation: breathe 1.6s ease-in-out infinite; }

@keyframes breathe { 0%, 100% { opacity: 1 } 50% { opacity: .38 } }

/* ------------------------------------------------------ 列表：空态 / 骨架 */

.empty {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  margin: 10px var(--pad); padding: 34px 18px;
  border: 1px solid var(--line); border-radius: var(--r-card);
  background-color: var(--surface);
  background-image:
    linear-gradient(to right, var(--blueprint) 1px, transparent 1px),
    linear-gradient(to bottom, var(--blueprint) 1px, transparent 1px);
  background-size: 22px 22px;
  color: var(--text-3); font-size: 12.5px; text-align: center;
}
.empty .i { color: var(--text-3); opacity: .7; }
.empty .etitle { font: 600 13.5px var(--sans); color: var(--text-2); }
.empty .ebody { max-width: 32ch; line-height: 1.6; }
.empty .btn { margin-top: 4px; }

.skel { display: flex; flex-direction: column; gap: 2px; padding: 6px 0; }
.skrow { display: flex; flex-direction: column; gap: 9px; padding: 12px 16px; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.skrow .bar {
  height: 11px; border-radius: 4px;
  background: linear-gradient(90deg, var(--surface-2) 0%, var(--surface-3) 40%, var(--surface-2) 80%);
  background-size: 220% 100%; animation: shimmer 1.5s linear infinite;
}
.skrow .bar.l1 { width: 58%; height: 13px; }
.skrow .bar.l2 { width: 38%; height: 10px; }
@keyframes shimmer { from { background-position: 120% 0 } to { background-position: -120% 0 } }

/* ------------------------------------------------------------------ chat */

/* 会话页外框也 clip（U24，与 #log 同理）：整页横向溢出的最后一道闸门。
   #chatMeta 是 sticky，clip 不建滚动容器，所以它照旧贴着视口吸顶。 */
#chatView { display: flex; flex-direction: column; min-width: 0; overflow-x: clip; }

#chatMeta {
  position: sticky; top: var(--hdr); z-index: 3;
  display: flex; flex-direction: column; gap: 2px;
  padding: 5px var(--pad) 6px;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(12px) saturate(1.2);
  border-bottom: 1px solid var(--line);
  transition: background .2s, border-color .2s;
}
#chatMeta .mhead { display: flex; align-items: center; gap: 8px; min-width: 0; }
#chatMeta .findbtn { width: 32px; height: 32px; }
#chatMeta .mtitle {
  flex: 1; min-width: 0;
  font: 600 14px/1.35 var(--sans); color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#chatMeta .mline { display: flex; align-items: center; gap: 7px; min-width: 0; font: 11px var(--mono); color: var(--text-3); }
#chatMeta .mident { display: flex; align-items: center; gap: 5px; min-width: 0; overflow: hidden; white-space: nowrap; }
#chatMeta .mident .mach { color: var(--text-2); flex: none; }
#chatMeta .mident .harness { flex: none; }
#chatMeta .mident .model { overflow: hidden; text-overflow: ellipsis; }
#chatMeta .mident .msep { color: color-mix(in srgb, var(--text-3) 65%, transparent); }
#chatMeta .mread {
  margin-left: auto; display: inline-flex; align-items: center; gap: 5px;
  white-space: nowrap; color: var(--text-2);
}
#chatMeta .mread .tot { font-variant-numeric: tabular-nums; color: var(--text); }
#chatMeta .mread .spin { color: var(--accent); animation: spin 1.1s linear infinite; }
#chatMeta.waiting { background: color-mix(in srgb, var(--warn) 10%, var(--bg)); border-bottom-color: color-mix(in srgb, var(--warn) 38%, transparent); }
#chatMeta.waiting .mread { color: var(--warn); }
#chatMeta.waiting .mtitle { color: var(--warn); }
.rdot { width: 6px; height: 6px; border-radius: var(--r-pill); background: var(--text-3); flex: none; }
.rdot.warn { background: var(--warn); box-shadow: 0 0 0 3px color-mix(in srgb, var(--warn) 16%, transparent); animation: breathe 1.6s ease-in-out infinite; }
.rdot.ok { background: var(--ok); }
.rdot.live { background: var(--accent); }

#offlineBar {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  margin: 8px var(--pad) 0; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-left: 2px solid var(--bad);
  border-radius: var(--r-ctl); background: var(--surface);
  color: var(--text-2); font-size: 13px;
}
#offlineBar .i { color: var(--bad); }
#offlineBar .btn { margin-left: auto; }

/* overflow-x: clip（U24）：消息列自己不外扩。它不是滚动容器（y 仍是 visible，
   clip + visible 是合法组合），所以不产生横滑、不影响 sticky/fixed 子孙；
   但任何"意外更宽"的内容从此到此为止，不会再走 #log → #chatView → 整页。 */
#log { display: flex; flex-direction: column; gap: 11px; padding: 10px var(--pad) 8px; overflow-x: clip; }
.mrow { display: flex; flex-direction: column; }
.mrow.right { align-items: flex-end; }
.mtime { font: 10.5px var(--mono); color: var(--text-3); margin-bottom: -6px; }
.m-user {
  max-width: 82%; padding: 9px 12px;
  background: var(--accent); color: var(--accent-ink);
  border-radius: var(--r-card) var(--r-card) 2px var(--r-card);
  font-size: 15px; line-height: 1.55;
  white-space: pre-wrap; overflow-wrap: anywhere;
}
.dstate { display: flex; align-items: center; gap: 5px; margin-top: 5px; font: 10.5px var(--mono); color: var(--text-3); }
.dstate.failed { color: var(--bad); }
.dstate .i { width: 12px; height: 12px; }
.dstate.queued { color: var(--warn); }

.m-bot {
  border-left: 1px solid var(--line-strong); padding-left: 12px;
  font-size: 15px; line-height: 1.62; overflow-wrap: anywhere;
}
.m-bot.streaming { white-space: pre-wrap; }
.caret { display: inline-block; width: 7px; height: 15px; margin-left: 2px; vertical-align: -2px; background: var(--accent); animation: breathe 1s steps(2, start) infinite; }
.m-bot > :first-child { margin-top: 0; }
.m-bot > :last-child { margin-bottom: 0; }
.m-bot h1, .m-bot h2, .m-bot h3, .m-bot h4 { margin: 16px 0 6px; line-height: 1.35; font-weight: 650; }
.m-bot h1 { font-size: 17px; }
.m-bot h2 { font-size: 15.5px; }
.m-bot h3 { font-size: 15px; }
.m-bot h4 { font-size: 13.5px; color: var(--text-2); font-family: var(--mono); letter-spacing: .01em; }
.m-bot p { margin: 8px 0; }
/* ---------- U10 会话内搜索 ---------- */
#searchBar { padding: 6px 14px; border-bottom: 1px solid var(--line); background: var(--surface-2); }
.searchbar-in { display: flex; align-items: center; gap: 8px; max-width: var(--col); margin: 0 auto; }
/* min-width: 0（U23）：flex: 1 的输入框默认 min-width: auto = 固有宽度，窄屏
   上会和计数/按钮一起把行撑破（iOS 上输入框固有宽度还与字号有关）。 */
.searchbar-in input { flex: 1; min-width: 0; min-height: 36px; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-ctl); color: var(--text); padding: 6px 10px; font: 16px var(--sans); }
.searchbar-in .shcount { font: 11.5px var(--mono); color: var(--text-3); min-width: 44px; text-align: right; }
.findbtn { margin-left: 8px; }
mark.shl { background: color-mix(in srgb, var(--warn) 38%, transparent); color: inherit; border-radius: 2px; }
mark.shl.current { background: var(--accent); color: var(--accent-ink); }

/* ---------- T1 未完成工具卡（陈旧残卡不转圈） ---------- */
.m-tool[data-status="unfinished"] { border-style: dashed; color: var(--text-3); }
.m-tool[data-status="unfinished"] .tstate { color: var(--text-3); }
.m-tool .tflag { font: 11px var(--mono); color: var(--text-3); border: 1px solid var(--line-strong); border-radius: var(--r-pill); padding: 0 6px; white-space: nowrap; flex: none; }
.m-bot.md-degraded { border-left-color: var(--line-strong); }

/* ---------- T4 后台任务读数 ---------- */
.rdot.bg { background: var(--violet); }
.rdot.sched { background: color-mix(in srgb, var(--accent) 70%, var(--violet)); }
.b-scheduled { color: var(--violet); border-color: color-mix(in srgb, var(--violet) 38%, transparent); }

/* ---------- U3 审批卡过期倒计时 ---------- */
.cdown { display: flex; align-items: center; gap: 10px; margin: 10px 0 2px; }
.cdowntrack { flex: 1; height: 3px; border-radius: var(--r-pill); background: var(--surface-3); overflow: hidden; }
.cdownbar {
  display: block; height: 100%; width: 100%; transform-origin: left center;
  background: var(--accent); transition: transform .95s linear, background .3s linear;
}
.cdownbar.urgent { background: var(--warn); }
.cdownbar.expired { background: var(--bad); transition: none; }
.cdownleft { font: 11.5px var(--mono); color: var(--text-2); min-width: 62px; text-align: right; }
.m-ask.expired { opacity: .62; }
.m-ask.expired .cdownleft { color: var(--bad); }

/* ---------- U7 复制 ---------- */
.codewrap { position: relative; }
.copybtn {
  display: inline-flex; align-items: center; justify-content: center; gap: 5px;
  min-height: 40px; min-width: 40px; padding: 0 8px;
  border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  background: color-mix(in srgb, var(--surface) 88%, transparent);
  color: var(--text-2); font: 11.5px var(--mono); cursor: pointer;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
.copybtn:hover { color: var(--text); border-color: var(--accent); }
.copybtn.code { position: absolute; top: 6px; right: 6px; opacity: 1; }
.copybtn.msg { position: absolute; left: 0; bottom: -6px; opacity: 0; transition: opacity .15s; }
.m-bot { position: relative; }
@media (hover: hover) and (pointer: fine) {
  .copybtn.code { opacity: 0; transition: opacity .15s; }
  .codewrap:hover .copybtn.code { opacity: 1; }
  .copybtn.code:focus-visible { opacity: 1; }
  .m-bot:hover .copybtn.msg { opacity: 1; }
}
/* 触屏：代码块复制常显；整段复制不出现（也不留隐形点击区） */
@media (hover: none), (pointer: coarse) {
  .copybtn.code { opacity: 1; }
  .copybtn.msg { display: none; }
}
.codewrap pre { margin-top: 0; }

/* .mdbody = 会话里所有 markdown 正文的根（.m-bot 助手气泡 + .m-plan / .m-ask 的
   计划体）。三处必须共用同一套内容块规则：早先只有 .m-bot 有，plan 体里的一条长
   代码行没有滚动容器也不换行，直接把 #log → #chatView → 整页撑宽
   （实测 1280 下 documentElement.scrollWidth 1566 > 1280，手机 390 下 1146 > 390）。 */
.m-bot pre, .mdbody pre {
  margin: 10px 0; padding: 10px 12px; overflow-x: auto;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-ctl);
  font: 12.5px/1.6 var(--mono); white-space: pre;
}
.m-bot code, .mdbody code { background: var(--surface-2); border-radius: 3px; padding: 1px 4px; font: 0.88em/1.5 var(--mono); }
.m-bot pre code, .mdbody pre code { background: none; padding: 0; font-size: 12.5px; }
.m-bot ul, .m-bot ol, .mdbody ul, .mdbody ol { margin: 8px 0; padding-left: 22px; }
.m-bot li, .mdbody li { margin: 4px 0; }
.m-bot blockquote, .mdbody blockquote { margin: 10px 0; padding: 2px 12px; border-left: 2px solid var(--line-strong); color: var(--text-2); }
.m-bot table, .mdbody table { display: block; max-width: 100%; overflow-x: auto; border-collapse: collapse; margin: 10px 0; font: 12.5px var(--mono); }
.m-bot th, .m-bot td, .mdbody th, .mdbody td { border: 1px solid var(--line); padding: 5px 9px; text-align: left; }
.m-bot th, .mdbody th { background: var(--surface-2); font-weight: 600; }
.m-bot hr, .mdbody hr { border: 0; border-top: 1px solid var(--line); margin: 14px 0; }

.m-sys { align-self: center; max-width: 92%; text-align: center; font: 11px var(--mono); color: var(--text-3); }
.m-sys.ended { color: var(--bad); }
.m-sys.task { display: inline-flex; align-items: center; gap: 6px; text-align: left; }
.m-sys.task .i { color: var(--text-3); }
.m-sys .sep, .dstate .sep, .apstats .sep { color: color-mix(in srgb, var(--text-3) 65%, transparent); }

.chatempty {
  align-self: center; display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 46px 20px; text-align: center; color: var(--text-3); font-size: 12.5px;
}
.chatempty .i { color: var(--line-strong); }
.chatempty .etitle { font: 600 13.5px var(--sans); color: var(--text-2); }
.chatempty .ebody { max-width: 30ch; line-height: 1.6; }
.chatempty.err .i { color: var(--bad); }
.chatempty .btn { margin-top: 6px; }

.m-tool, .m-plan, .m-generic {
  align-self: stretch; padding: 8px 10px;
  border: 1px solid var(--line); border-radius: var(--r-card); background: var(--surface);
  font: 12.5px var(--mono); color: var(--text-2); cursor: pointer;
  transition: border-color .12s, background .12s;
}
.m-tool:hover, .m-generic:hover { border-color: var(--line-strong); background: var(--surface-2); }
.tline { display: flex; align-items: center; gap: 7px; min-width: 0; }
.tline .i { color: var(--text-3); }
.tname { color: var(--text); font-weight: 600; flex: none; }
.tsum { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text-3); }
.m-tool .chev { margin-left: auto; transition: transform .15s ease; }
.m-tool.open .chev { transform: rotate(180deg); }
.m-tool[data-status="running"] .tstate { color: var(--accent); animation: spin 1.1s linear infinite; }
.m-tool[data-status="error"] { border-color: color-mix(in srgb, var(--bad) 42%, transparent); }
.m-tool[data-status="error"] .tstate, .m-tool[data-status="error"] .tname { color: var(--bad); }
.m-tool .tdetail, .m-generic .rawjson {
  display: none; margin-top: 8px; padding: 9px 11px;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-ctl);
  max-height: 45vh; overflow: auto;
  white-space: pre-wrap; overflow-wrap: anywhere; color: var(--text-2); font: 12px/1.6 var(--mono);
}
.m-tool.open .tdetail { display: block; }
.m-plan { cursor: default; }
/* 计划体只滚纵向：宽内容（代码块/表格）由上面的 .mdbody 规则各自横滑，正文里的
   长串靠 anywhere 换行。overflow-x: clip 不建滚动容器 —— 既不会冒出横向滚动条，
   也把"意外更宽"钉死在这里不外溢（sticky/fixed 子孙不受影响）。 */
.m-plan .planbody {
  font-family: var(--sans); font-size: 14px; line-height: 1.6;
  min-width: 0; overflow-wrap: anywhere; overflow-x: clip;
}
.m-generic { cursor: default; }
.m-generic .asktitle { display: flex; align-items: center; gap: 8px; }
.m-generic .kindname { color: var(--text); font-weight: 600; }
.m-generic .askq { margin: 7px 0 0; font-family: var(--sans); font-size: 14px; color: var(--text-2); }
.payloadfold { margin-top: 9px; }
.payloadfold > summary { cursor: pointer; color: var(--text-3); font: 11px var(--mono); list-style: none; display: inline-flex; align-items: center; gap: 5px; }
.payloadfold > summary::-webkit-details-marker { display: none; }
.payloadfold > summary::before { content: ""; width: 0; height: 0; border: 4px solid transparent; border-left-color: currentColor; transform: translateX(1px); }
.payloadfold[open] > summary::before { transform: rotate(90deg) translateX(1px); }
.payloadfold > summary:hover { color: var(--text-2); }
.payloadfold .rawjson { display: block; }

/* 高频未知 kind 折叠卡（[kind] ×N） */
.m-generic.fold { border-style: dashed; cursor: pointer; }
.m-generic.fold .foldcount {
  font: 600 11px var(--mono); color: var(--warn);
  border: 1px solid color-mix(in srgb, var(--warn) 42%, transparent); border-radius: var(--r-pill);
  padding: 0 7px; height: 17px; display: inline-flex; align-items: center;
}
.m-generic.fold .foldtoggle { margin-left: auto; font-size: 11px; color: var(--accent); }
.m-generic.fold .foldlatest { color: var(--text-3); }
.m-generic.fold .foldlist { display: flex; flex-direction: column; gap: 7px; margin-top: 9px; max-height: 45vh; overflow: auto; }
.m-generic.fold .foldlist .m-generic { background: var(--surface-2); }

#statusRow { display: none; align-self: flex-start; padding-left: 13px; position: relative; font: 11.5px var(--mono); color: var(--ok); }
#statusRow::before { content: ""; position: absolute; left: 0; top: 7px; width: 5px; height: 5px; border-radius: 999px; background: currentColor; }
#statusRow.on { display: block; }

#newMsgBtn {
  position: fixed; left: 50%; transform: translateX(-50%);
  /* --att-h = 附件 chip 行的高度（没有附件时是 0，由 ui/chat.js 写） */
  bottom: calc(104px + var(--att-h, 0px) + env(safe-area-inset-bottom)); z-index: 20;
  display: inline-flex; align-items: center; gap: 6px; height: 34px; padding: 0 13px;
  border: 0; border-radius: var(--r-pill); background: var(--accent); color: var(--accent-ink);
  font: 600 12.5px var(--sans); box-shadow: var(--shadow); cursor: pointer;
}
#newMsgBtn .i { width: 15px; height: 15px; }

/* ------------------------------------------------------------- 输入条 */

#chatbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 30;
  padding: 8px 10px calc(8px + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: blur(14px) saturate(1.2);
  border-top: 1px solid var(--line);
}
.cwrap { display: flex; align-items: flex-end; gap: 7px; max-width: 812px; margin: 0 auto; }
.cbox {
  flex: 1; min-width: 0; display: flex; align-items: flex-end; gap: 6px;
  padding: 2px 2px 2px 10px;
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--r-ctl);
  transition: border-color .12s, box-shadow .12s;
}
.cbox:focus-within { border-color: var(--accent); box-shadow: var(--ring); }
#prompt { flex: none; padding-bottom: 10px; font: 600 15px var(--mono); color: var(--accent); }
#inp {
  flex: 1; min-width: 0; min-height: 40px; max-height: 132px;
  padding: 9px 0; border: 0; background: none; color: var(--text);
  /* 16px 是硬要求：iOS 上聚焦 <16px 的输入框会自动放大整页（U21-2） */
  font: 16px/1.5 var(--mono); resize: none; outline: none;
}
#inp:focus { box-shadow: none; }
#attachBtn, #expandBtn { margin-bottom: 0; }
/* 展开钮只在窄屏 / 粗指针出现（桌面有全宽输入框，不需要全屏层） */
#expandBtn { display: none; }
@media (hover: none), (max-width: 700px) {
  #expandBtn { display: inline-grid; }
  .cwrap .cbox .iconbtn.quiet, .cwrap .iconbtn.stop { width: 36px; }
}
/* 待发附件 chip 行：输入框上方一条，可横滑，不产生页面横向滚动 */
.attrow {
  display: flex; align-items: center; gap: 6px;
  max-width: 812px; margin: 0 auto 7px;
  overflow-x: auto; overflow-y: hidden;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.attrow::-webkit-scrollbar { display: none; }
.attchip {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  max-width: 64vw; height: 34px; padding: 0 2px 0 7px;
  background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--text-2); font: 500 12px var(--mono);
}
.attchip .aname { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; max-width: 42vw; }
.attchip .athumb { width: 24px; height: 24px; flex: none; border-radius: 5px; object-fit: cover; background: var(--surface-3); }
.attchip .i { color: var(--text-3); }
.attchip.uploading { color: var(--text-3); }
.attchip.failed { border-color: color-mix(in srgb, var(--bad) 55%, transparent); color: var(--bad); cursor: pointer; }
.attchip.failed .i { color: var(--bad); }
.attchip.failed .aflag { color: var(--bad); font-weight: 600; }
.attchip .arm {
  display: inline-grid; place-items: center; width: 26px; height: 26px; flex: none;
  border: 0; border-radius: var(--r-pill); background: none; color: var(--text-3); cursor: pointer;
}
.attchip .arm:hover { background: var(--surface-3); color: var(--text); }
.attchip .arm:active { transform: translateY(1px); }
.sendbtn {
  width: 40px; height: 40px; flex: none; display: grid; place-items: center;
  border: 0; border-radius: var(--r-pill); background: var(--accent); color: var(--accent-ink);
  cursor: pointer; transition: background .12s, opacity .12s;
}
.sendbtn:hover { background: var(--accent-hover); }
.sendbtn:disabled { opacity: .5; cursor: not-allowed; }
.sendbtn.busy .i { animation: spin 1.1s linear infinite; }
.iconbtn.stop {
  width: 40px; height: 40px; border-radius: var(--r-pill);
  border: 1px solid color-mix(in srgb, var(--bad) 50%, transparent); color: var(--bad);
}
.iconbtn.stop:hover { background: color-mix(in srgb, var(--bad) 12%, transparent); }

@keyframes spin { from { transform: rotate(0) } to { transform: rotate(360deg) } }

/* ------------------------------------------------------------ 命令菜单 */

#cmdMenu {
  position: fixed; left: 0; right: 0; bottom: calc(78px + var(--att-h, 0px)); z-index: 40;
  max-height: 52vh; overflow-y: auto;
  /* U24：同 #listView —— 只声明 overflow-y 会把 x 的计算值抬成 auto，菜单里
     冒出一条横向滚动条。菜单只纵向滚动，超宽的命令名/参数靠下面的 anywhere 换行。 */
  overflow-x: clip;
  background: var(--surface-3); border-top: 1px solid var(--line-strong);
  box-shadow: var(--shadow);
  padding: 6px 8px calc(8px + env(safe-area-inset-bottom));
}
.cmd-sec {
  display: flex; align-items: center; gap: 8px;
  padding: 10px 8px 4px; color: var(--text-3);
  font: 500 10.5px var(--mono); letter-spacing: .04em;
}
.cmd-sec::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.cmd-item {
  display: grid; grid-template-columns: auto auto auto 1fr; align-items: center; gap: 8px;
  padding: 7px 9px; border-radius: var(--r-ctl); cursor: pointer;
}
.cmd-item:hover { background: var(--surface); }
.cmd-item.disabled { opacity: .5; cursor: default; }
/* anywhere（U24）：/命令名与 --参数 都是没有空格的长串，不换行就会把菜单撑宽 */
.cmd-name { font: 600 13px var(--mono); color: var(--text); overflow-wrap: anywhere; }
.cmd-exec { font: 500 10.5px var(--mono); border: 1px solid var(--line-strong); border-radius: 3px; padding: 0 5px; height: 17px; display: inline-flex; align-items: center; color: var(--text-3); }
.cmd-exec.e-direct { color: var(--ok); border-color: color-mix(in srgb, var(--ok) 42%, transparent); }
.cmd-exec.e-passthrough { color: var(--warn); border-color: color-mix(in srgb, var(--warn) 42%, transparent); }
.cmd-exec.e-unsupported { color: var(--bad); border-color: color-mix(in srgb, var(--bad) 42%, transparent); }
.cmd-risk { font: 10.5px var(--mono); color: var(--text-3); }
.cmd-risk.r-high { color: var(--bad); }
.cmd-risk.r-medium { color: var(--warn); }
.cmd-desc { grid-column: 1 / -1; color: var(--text-3); font: 12.5px var(--sans); line-height: 1.5; }
.cmd-args { grid-column: 1 / -1; color: var(--text-3); font: 11.5px var(--mono); overflow-wrap: anywhere; }
.cmd-empty { padding: 18px 10px; text-align: center; color: var(--text-3); font: 12.5px var(--mono); }

/* --------------------------------------------------------------- 审批卡 */

.m-ask {
  position: relative; align-self: stretch;
  padding: 10px 12px 12px 14px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
}
.m-ask::before {
  content: ""; position: absolute; left: 0; top: 10px; bottom: 10px; width: 2px;
  border-radius: 0 2px 2px 0; background: var(--warn);
}
.m-ask.terminal::before, .m-ask.tui::before { background: var(--line-strong); }
.m-ask.terminal, .m-ask.tui { opacity: .72; }
.m-ask .askhead { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; min-width: 0; }
.m-ask .asktag { display: inline-flex; align-items: center; gap: 5px; color: var(--warn); font: 600 12.5px var(--sans); }
.m-ask.terminal .asktag, .m-ask.tui .asktag { color: var(--text-3); }
.m-ask .kindtag {
  display: inline-flex; align-items: center; height: 17px; padding: 0 5px;
  border: 1px solid var(--line); border-radius: 3px;
  font: 500 10.5px var(--mono); color: var(--text-3);
}
.m-ask .asktime { margin-left: auto; font: 10.5px var(--mono); color: var(--text-3); }
.m-ask .askq { margin: 8px 0; font-size: 15px; line-height: 1.55; color: var(--text); white-space: pre-wrap; }
.m-ask .askq.muted { color: var(--text-2); font-size: 13.5px; }
.m-ask .askbody { margin-top: 2px; }
.m-ask .askbtns { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
.m-ask .askstatus { margin-top: 9px; font: 11px var(--mono); color: var(--text-3); }
.m-ask .askstatus.answered { color: var(--ok); }
.m-ask .askstatus.expired, .m-ask .askstatus.fallback, .m-ask .askstatus.other { color: var(--text-3); }
.m-ask .wq { margin-top: 12px; }
.m-ask .wqh { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; font-size: 14px; color: var(--text); }
.m-ask .wtag {
  display: inline-flex; align-items: center; height: 17px; padding: 0 6px;
  border-radius: 3px; background: color-mix(in srgb, var(--warn) 16%, transparent); color: var(--warn);
  font: 600 10.5px var(--mono);
}
.m-ask .wopt { display: flex; flex-direction: column; align-items: flex-start; text-align: left; height: auto; padding: 8px 12px; min-height: 40px; }
.m-ask .wopt.sel { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 13%, transparent); outline: none; }
.m-ask .wdesc { margin-top: 2px; font-size: 11px; font-weight: 400; opacity: .8; }
.m-ask .wft, .wform .wft { margin-top: 8px; width: 100%; font-size: 14px; }
.m-ask .planbody {
  /* overflow-x: clip + overflow-y: auto（U24）：计划体自己纵向滚动就好，横向交给
     里层的代码块/表格（.mdbody 规则）。之前是 overflow: auto，宽代码行让整个审批
     卡出现一条横向滚动条 —— 用户看到的就是它。 */
  margin-top: 9px; padding: 10px 12px; max-height: 340px;
  overflow-y: auto; overflow-x: clip;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r-ctl);
  font-size: 13.5px; line-height: 1.6;
  min-width: 0; overflow-wrap: anywhere;
}
.m-ask .planbody > :first-child { margin-top: 0; }
.wform { display: flex; flex-direction: column; gap: 4px; }
.wform .wqh { font-size: 13.5px; color: var(--text-2); }
.wcheck { display: inline-flex; align-items: center; gap: 7px; margin: 8px 14px 0 0; font-size: 13.5px; color: var(--text-2); }
.wcheck input { width: 18px; height: 18px; min-height: 0; }

/* --------------------------------------------------------- 审批中心 */

.aphead { display: flex; flex-direction: column; gap: 4px; }
.apstats { display: flex; align-items: baseline; gap: 8px; font: 500 11.5px var(--mono); color: var(--text-3); }
.apstats .big { font: 600 20px var(--mono); color: var(--warn); font-variant-numeric: tabular-nums; }
.apgroup { margin-top: 12px; border-top: 1px solid var(--line); padding-top: 10px; }
.apgroup .sec { padding: 0; margin: 0 0 8px; height: 26px; }
.closedfold { margin-top: 20px; border-top: 1px solid var(--line); padding-top: 10px; }
.closedfold > summary { cursor: pointer; display: flex; align-items: center; gap: 8px; padding: 6px 0; color: var(--text-3); font: 11.5px var(--mono); list-style: none; }
.closedfold > summary::-webkit-details-marker { display: none; }
.closedfold > summary::before { content: ""; width: 0; height: 0; border: 4px solid transparent; border-left-color: currentColor; }
.closedfold[open] > summary::before { transform: rotate(90deg); }
.closedfold > summary:hover { color: var(--text-2); }
.closedfold > .m-ask { margin-top: 10px; }
.machinechips { margin-top: 2px; }
.apgrid { display: flex; flex-direction: column; gap: 10px; }

/* ------------------------------------------------------- 机器 / 设备页 */

.mgmt { margin-bottom: 26px; }
.mgmt > .sec { padding: 0; margin: 0 0 10px; }
.card {
  padding: 12px 14px; margin-bottom: 10px;
  background: var(--surface); border: 1px solid var(--line); border-radius: var(--r-card);
}
.card.revoked { opacity: .55; }
.chead { display: flex; align-items: center; gap: 8px; min-width: 0; }
.chead .name { font: 600 14.5px var(--sans); color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.chead .name.clickable:hover { color: var(--accent); }
.card .meta { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px; font: 11.5px var(--mono); color: var(--text-3); }
.card .meta .sep { color: color-mix(in srgb, var(--text-3) 65%, transparent); }
.card .meta .hlist { color: var(--text-2); }
.acts { display: flex; align-items: center; gap: 2px; flex-wrap: wrap; margin-top: 8px; margin-left: -8px; }
.hint { color: var(--text-2); font-size: 13px; line-height: 1.6; }
.hint b { color: var(--text); font-weight: 600; }
.hint ol { margin: 6px 0 0; padding-left: 20px; color: var(--text-2); }
.hint li { margin: 3px 0; }

.keyblock {
  display: flex; flex-direction: column; gap: 9px;
  padding: 12px; border: 1px solid color-mix(in srgb, var(--warn) 42%, transparent);
  border-radius: var(--r-card); background: color-mix(in srgb, var(--warn) 7%, var(--surface));
}
.keyblock .kh { display: flex; align-items: center; gap: 7px; color: var(--warn); font: 600 12.5px var(--sans); }
.keyblock .kval {
  font: 12px/1.6 var(--mono); color: var(--text); word-break: break-all;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 9px 10px;
  max-height: 180px; overflow: auto;
}
.keyblock .kfoot { display: flex; align-items: center; gap: 8px; }
.keyblock .kfoot .once { color: var(--text-3); font: 11px var(--mono); }
.keyblock .kfoot .once.warn { color: var(--warn); }

/* 自助配对（SE1）：页签 + 选项行 + 结果块 */
.minttabs { margin: 10px 0 2px; border-bottom: 1px solid var(--line); }
.mintpane { display: flex; flex-direction: column; gap: 12px; margin-top: 12px; }
.mintrow { display: flex; flex-direction: column; gap: 7px; }
.mintrow .mlbl { color: var(--text-3); font: 11.5px var(--mono); }
.mintrow .pills { display: flex; gap: 7px; flex-wrap: wrap; }
.pillbtn {
  min-height: 34px; padding: 0 13px;
  background: var(--surface-2); border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  color: var(--text-2); font: 500 13px/32px var(--sans); cursor: pointer;
  transition: color .12s, border-color .12s, background .12s;
}
.pillbtn:hover { color: var(--text); }
.pillbtn.on {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border-color: var(--accent); color: var(--accent); font-weight: 600;
}
.rolehint { margin-top: -4px; }
.mintgo { align-self: flex-start; margin-top: 2px; }
.minthelp { margin-top: 0; }
.mintresult .kval { max-height: none; }
.mintalt { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.mintalt .mlbl { color: var(--text-3); font: 11.5px var(--mono); }
.mintalt .mintcode { font: 12px var(--mono); color: var(--text); word-break: break-all; }
.mintacts { margin-top: 2px; }
.mintstatus { margin-left: auto; }

/* 复制兜底用的临时节点（execCommand 路径） */
.offscreen { position: fixed; top: -1000px; left: -1000px; opacity: 0; }
.pairbox .hint.ready { color: var(--accent); }

.code {
  padding: 10px 12px; overflow-x: auto;
  background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-ctl);
  font: 12px/1.65 var(--mono); color: var(--text-2); white-space: pre;
}

/* --------------------------------------------------------- sheet / toasts */

#toasts {
  position: fixed; left: 50%; transform: translateX(-50%);
  bottom: calc(96px + env(safe-area-inset-bottom)); z-index: 60;
  display: flex; flex-direction: column; gap: 8px; align-items: center;
  width: max-content; max-width: 92vw; pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 14px; border-radius: var(--r-pill);
  background: var(--surface-3); border: 1px solid var(--line-strong); color: var(--text);
  font-size: 13.5px; box-shadow: var(--shadow);
  opacity: 0; transform: translateY(6px); transition: opacity .18s, transform .18s;
}
.toast.show { opacity: 1; transform: none; }
.toast .i { color: var(--text-3); }
.toast.ok { border-color: color-mix(in srgb, var(--ok) 55%, transparent); }
.toast.ok .i { color: var(--ok); }
.toast.err { border-color: color-mix(in srgb, var(--bad) 55%, transparent); }
.toast.err .i { color: var(--bad); }

#sheetWrap {
  position: fixed; inset: 0; z-index: 70;
  display: flex; align-items: flex-end; justify-content: center;
  background: rgba(0, 0, 0, .5); backdrop-filter: blur(3px);
}
#sheet {
  width: 100%; max-width: 560px; max-height: 86vh; overflow-y: auto;
  overflow-x: clip; /* U24：同上，只滚纵向（x 的计算值不再被抬成 auto） */
  padding: 8px 18px calc(16px + env(safe-area-inset-bottom));
  background: var(--surface-3); border: 1px solid var(--line-strong); border-bottom: 0;
  border-radius: var(--r-sheet) var(--r-sheet) 0 0;
  box-shadow: var(--shadow);
  animation: sheetup .22s cubic-bezier(.22, .61, .36, 1);
}
@keyframes sheetup { from { transform: translateY(18px); opacity: .6 } to { transform: none; opacity: 1 } }
body.sheet-open { overflow: hidden; }
/* U6：软键盘（visualViewport）遮挡时把输入条抬起来，并给日志留出等量底部空间 */
#chatbar { bottom: var(--kb, 0px); }
#log { padding-bottom: calc(96px + var(--kb, 0px)); }
#sheetBody label .req { color: var(--bad); margin-left: 5px; font-size: 11px; }
#sheetBody details.adv { margin-top: 12px; }
#sheetBody details.adv summary { cursor: pointer; color: var(--text-3); font: 12px var(--mono); }
#sheet { max-height: min(86vh, calc(var(--vvh, 100vh) - 24px)); }
#sheet .grab { width: 36px; height: 4px; margin: 2px auto 10px; border-radius: var(--r-pill); background: var(--line-strong); }
#sheetTitle { font: 600 15px/1.4 var(--sans); color: var(--text); margin-bottom: 8px; }
#sheetBody { font-size: 13.5px; line-height: 1.6; color: var(--text-2); margin-bottom: 16px; }
#sheetBody .rawjson { margin-top: 8px; }
#sheetBody input, #sheetBody textarea, #sheetBody select { margin-top: 8px; }
#sheetBtns { display: flex; gap: 10px; justify-content: flex-end; flex-wrap: wrap; }
.sheetlist { display: flex; flex-direction: column; gap: 2px; margin: -4px 0 6px; }
.actrow {
  display: flex; align-items: center; gap: 8px; width: 100%; min-height: 46px; padding: 0 11px;
  border: 0; border-radius: var(--r-ctl); background: none;
  color: var(--text); font: 500 14px var(--sans); text-align: left; cursor: pointer;
  transition: background .12s, color .12s;
}
.actrow:hover { background: var(--surface-2); }
.actrow:active { background: var(--surface); }
.actrow.danger { color: var(--bad); }
.actrow.danger:hover { background: color-mix(in srgb, var(--bad) 12%, transparent); }

/* ---------------------------------------------------------- 全屏输入层（U22） */

#composeWrap {
  position: fixed; top: 0; left: 0; right: 0; z-index: 75;
  height: var(--vvh, 100dvh);
  display: flex; flex-direction: column;
  padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);
  background: var(--bg);
}
body.compose-open { overflow: hidden; }
#compose {
  display: flex; flex-direction: column; flex: 1; min-height: 0;
  width: 100%; max-width: 812px; margin: 0 auto; padding: 0 12px;
}
#compose .cchead { display: flex; align-items: center; gap: 8px; min-height: 54px; flex: none; }
#composeTitle { font: 600 12.5px var(--mono); color: var(--text-3); letter-spacing: .02em; }
#composeTitle::before { content: "❯ "; color: var(--accent); font-weight: 700; }
#composeChips { max-width: none; margin: 0 0 8px; flex: none; }
.cchead .iconbtn { margin-left: auto; }
#composeInput {
  flex: 1; min-height: 0; width: 100%; margin: 0; padding: 12px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-card);
  font: 16px/1.6 var(--mono); resize: none;
}
#composeInput:focus { border-color: var(--accent); box-shadow: var(--ring); }
.ccfoot { display: flex; align-items: center; gap: 8px; flex: none; padding: 10px 0 6px; }
.ccfoot #composeSend { margin-left: auto; min-height: 44px; padding: 0 24px; }
.ccfoot #composeAttach { width: 44px; height: 44px; }

/* ---------------------------------------------------------- 配对 / 门 */

.pairwrap { display: flex; justify-content: center; padding-top: 4vh; }
.pairbox {
  width: 100%; max-width: 420px;
  padding: 20px; background: var(--surface);
  border: 1px solid var(--line); border-radius: var(--r-card);
}
.pairbox .pbrand { display: flex; align-items: center; gap: 6px; font: 600 12.5px var(--mono); color: var(--accent); }
.pairbox h2 { margin: 12px 0 6px; font: 600 19px/1.3 var(--sans); color: var(--text); }
.pairbox .hint { margin: 0 0 4px; }
.pairbox .codeinput { margin-top: 8px; font: 16px var(--mono); letter-spacing: .06em; }
.pairbox .btn.wide { margin-top: 14px; }
.pairbox .iosblock { margin-top: 18px; padding-top: 14px; border-top: 1px solid var(--line); }
.pairbox .iosblock .bt { display: flex; align-items: center; gap: 6px; font: 600 12px var(--sans); color: var(--text-2); }
.pairbox .iosblock ol { margin: 8px 0 0; padding-left: 20px; color: var(--text-2); font-size: 13px; }
.pairbox .iosblock li { margin: 4px 0; }
.rawjson { background: var(--bg); border: 1px solid var(--line); border-radius: var(--r-ctl); padding: 10px; font: 12px/1.6 var(--mono); white-space: pre-wrap; word-break: break-all; color: var(--text-2); }

/* -------------------------------------------------------------- 桌面双栏 */

@media (min-width: 1100px) {
  body { padding-left: 340px; }
  #listView {
    position: fixed; top: 0; left: 0; bottom: 0; width: 340px; z-index: 4;
    margin: 0; max-width: none; overflow-y: auto; padding-bottom: 40px;
    /* U24：只写 overflow-y: auto 时，overflow-x 的计算值会变成 auto —— 侧栏因此
       是个横向滚动容器，行一宽就冒出一条经典横向滚动条（桌面能直接看到）。
       这里只滚纵向。 */
    overflow-x: clip;
    background: var(--surface); border-right: 1px solid var(--line);
  }
  #listView[hidden] { display: block !important; }
  #listTools { padding-top: 2px; }
  #listView .row { padding-right: 12px; }
  #listView .row:hover { background: var(--surface-2); }
  #listView .row:active { background: var(--surface-3); }
  /* 读数的 sticky 条铺满右栏，正文列 780 居中（两者左缘对齐） */
  #chatView { max-width: none; }
  #chatMeta {
    padding-left: calc((100% - var(--col)) / 2 + var(--pad));
    padding-right: calc((100% - var(--col)) / 2 + var(--pad));
  }
  #log { max-width: var(--col); margin: 0 auto; }
  #offlineBar { max-width: var(--col); margin: 10px auto 0; }
  #pageView { max-width: var(--col); margin: 0 auto; padding-top: 20px; }
  #deskHint { top: var(--hdr); }
  #chatbar { left: 340px; }
  #cmdMenu { left: 340px; right: 0; bottom: calc(74px + var(--att-h, 0px)); max-width: 812px; margin: 0 auto; border: 1px solid var(--line-strong); border-radius: var(--r-card); }
  #newMsgBtn { bottom: calc(100px + var(--att-h, 0px)); }
  #toasts { bottom: 88px; }
  .mgmt { max-width: var(--col); margin-inline: auto; }
}

/* 默认（可悬停的指针）：行动作浮在行尾，悬停/聚焦才现身，不占位不改行高 */
.racts {
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  padding-left: 16px; border-radius: var(--r-ctl); background: inherit;
}
/* 左缘羽化：浮层压住 meta 文本时不出现硬边 */
.racts::before {
  content: ""; position: absolute; left: -14px; top: 0; bottom: 0; width: 14px;
  background: inherit;
  -webkit-mask-image: linear-gradient(to right, transparent, #000);
  mask-image: linear-gradient(to right, transparent, #000);
}
.racts .tbtn { opacity: 0; pointer-events: none; }
.row:hover .racts .tbtn, .row:focus-within .racts .tbtn { opacity: 1; pointer-events: auto; }

/* 没有悬停能力的设备（触屏 / 无指针）：同一个行尾簇就地常显，
   JS 在这种设备上把操作收进一个 40px 的 ⋯（见 ui/list.js）。 */
@media (hover: none) {
  .racts {
    position: static; transform: none; padding-left: 0; background: none; justify-self: end;
  }
  .racts::before { display: none; }
}
@media (max-width: 560px) {
  .brand { max-width: 38vw; }
}

/* ------------------------------------------------------------- 动效收敛 */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
  .rdot.warn, .st.waiting, .row[data-st="waiting"]::before, .udot { opacity: 1; }
  .skrow .bar { background: var(--surface-2); }
  .sendbtn.busy .i, .spin { animation: none; }
}

@media print {
  #chatbar, header, #newMsgBtn, #composeWrap { display: none !important; }
  body { background: #fff; color: #000; }
}
