/* Hallmark · pre-emit critique: P5 H5 E4 S5 R4 V5 */
/* Hallmark · genre: modern-minimal · macrostructure: Index-First · theme: Cobalt
 * nav: N9 edge-aligned minimal · footer: Ft2 inline single line · enrichment: none (typography only)
 * audience: one operator, on a phone, away from the desk, interrupted
 * use case: notice Claude stopped → see what it is asking → answer it
 * tone: utilitarian (instrument panel)
 * axes — paper: cool light (L 98.5 h 254) / display: mono-structural / accent: electric cobalt (h 256)
 * declared deviations from the Cobalt spec, and why:
 *   1. no Google Fonts — contract §8 forbids CDN (proxied machines fail silently). Space Grotesk /
 *      Inter / JetBrains Mono are replaced by a two-role SYSTEM pairing split by content type:
 *      prose (CJK-heavy session titles + summaries) in --font-ui, machine text (paths, status,
 *      timestamps, tool names, terminal) in --font-mono. Zero bytes over the wire.
 *   2. no ⌘K palette — scope.md cut global shortcuts as useless on the primary (phone) surface.
 *   3. dark mode shipped — this panel is opened at 2 a.m. on a phone. Same anchor hue; only
 *      lightness and chroma move (color.md dark recipe).
 *   4. no window-chrome dots on the terminal card — gate 47 (re-drawn UI chrome) outranks the
 *      theme's code-card hint. A typographic label rule frames it instead.
 * project memory: .hallmark/log.json NOT written — the task forbids touching files outside
 * v2/web/. This stamp is the durable record.
 */

/* ═══════════════════════ tokens ═══════════════════════ */

:root {
  /* colour · light — cool engineered paper, one cobalt signal, amber only for staleness */
  --color-paper:        oklch(98.5% 0.004 252);
  --color-paper-2:      oklch(96.4% 0.006 253);
  --color-paper-3:      oklch(93.6% 0.008 254);
  --color-rule:         oklch(89.5% 0.009 254);   /* 分隔线：结构性、克制 */
  --color-rule-2:       oklch(71.0% 0.016 256);   /* 控件边框：必须 ≥3:1，按钮边界要看得见 */
  --color-neutral:      oklch(50.0% 0.016 257);
  --color-muted:        oklch(44.0% 0.017 257);
  --color-ink-2:        oklch(34.0% 0.018 257);
  --color-ink:          oklch(24.0% 0.020 258);

  --color-accent:       oklch(52.0% 0.190 256);
  --color-accent-ink:   oklch(99.0% 0.005 256);
  --color-accent-dim:   oklch(62.0% 0.140 256);
  --color-accent-wash:  oklch(96.2% 0.030 256);

  --color-warn:         oklch(50.0% 0.130 66);
  --color-warn-wash:    oklch(96.0% 0.036 76);
  --color-danger:       oklch(50.0% 0.190 25);

  --color-graphite:     oklch(21.5% 0.016 260);
  --color-graphite-2:   oklch(28.0% 0.016 260);
  --color-graphite-ink: oklch(89.0% 0.012 250);
  --color-graphite-dim: oklch(58.0% 0.014 256);
  --color-graphite-rule:oklch(38.0% 0.016 258);
  --color-term-box:     oklch(48.0% 0.018 258);   /* 框线要压暗，但 1px 笔画得比正文更亮才看得见 */

  --color-focus:        oklch(52.0% 0.190 256);
  --color-scrim:        oklch(24% 0.02 258 / 0.42);

  /* type · two roles. Prose is system-ui (CJK-safe); machine text is mono. */
  --font-ui: system-ui, -apple-system, "Segoe UI Variable Text", "Segoe UI", Roboto,
             "Helvetica Neue", "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", "JetBrains Mono", "Cascadia Mono",
               Menlo, Consolas, "Liberation Mono", monospace;
  --font-display: var(--font-mono);

  --text-2xs:   0.6875rem;  /* 11px — key caps */
  --text-xs:    0.75rem;    /* 12px — status labels, meta */
  --text-sm:    0.8125rem;  /* 13px — mono body, tool rows */
  --text-base:  0.9375rem;  /* 15px — summaries, prose */
  --text-md:    1rem;       /* 16px — titles AND every input (below 16 iOS zooms) */
  --text-lg:    1.125rem;   /* 18px — detail title */
  --text-xl:    1.375rem;   /* 22px — the one display moment */

  /* space · 4pt */
  --space-3xs: 0.125rem;
  --space-2xs: 0.25rem;
  --space-xs:  0.5rem;
  --space-sm:  0.75rem;
  --space-md:  1rem;
  --space-lg:  1.5rem;
  --space-xl:  2.5rem;
  --space-2xl: 4rem;

  /* geometry — drawn with a ruler, never a pill */
  --radius-sm: 4px;
  --radius:    6px;
  --radius-lg: 10px;
  --tap:       44px;

  /* motion */
  --ease-out:    cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in:     cubic-bezier(0.7, 0, 0.84, 0);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-micro: 120ms;
  --dur-short: 220ms;
  --dur-long:  420ms;

  /* z */
  --z-base: 1;
  --z-raised: 10;
  --z-dropdown: 100;
  --z-sticky: 200;
  --z-modal: 400;
  --z-toast: 500;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-paper:        oklch(16.0% 0.012 258);
    --color-paper-2:      oklch(19.5% 0.014 258);
    --color-paper-3:      oklch(23.0% 0.015 258);
    --color-rule:         oklch(28.5% 0.014 258);
    --color-rule-2:       oklch(45.0% 0.018 258);
    --color-neutral:      oklch(62.0% 0.014 256);
    --color-muted:        oklch(72.0% 0.012 256);
    --color-ink-2:        oklch(86.0% 0.010 254);
    --color-ink:          oklch(94.0% 0.008 252);

    --color-accent:       oklch(72.0% 0.155 256);
    --color-accent-ink:   oklch(16.0% 0.020 258);
    --color-accent-dim:   oklch(56.0% 0.120 256);
    --color-accent-wash:  oklch(26.0% 0.048 256);

    --color-warn:         oklch(80.0% 0.115 78);
    --color-warn-wash:    oklch(27.0% 0.040 74);
    --color-danger:       oklch(70.0% 0.160 25);

    --color-graphite:     oklch(12.5% 0.014 260);
    --color-graphite-2:   oklch(18.0% 0.014 260);
    --color-graphite-ink: oklch(88.0% 0.012 250);
    --color-graphite-dim: oklch(60.0% 0.014 256);
    --color-graphite-rule:oklch(30.0% 0.014 258);
    --color-term-box:     oklch(44.0% 0.016 258);

    --color-focus:        oklch(72.0% 0.155 256);
    --color-scrim:        oklch(8% 0.01 258 / 0.62);
  }
}

/* ═══════════════════════ base ═══════════════════════ */

*, *::before, *::after { box-sizing: border-box; }

/* 面板用 display:flex/grid，会盖掉 UA 的 [hidden]{display:none}。这条必须在最前面。 */
[hidden] { display: none !important; }

html, body {
  overflow-x: clip;              /* clip, not hidden — keeps position:sticky alive */
  margin: 0;
  height: 100%;
}

html { -webkit-text-size-adjust: 100%; }

body {
  background: var(--color-paper);
  color: var(--color-ink-2);
  font-family: var(--font-ui);
  font-size: var(--text-base);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}

h1, h2, h3, p, figure { margin: 0; }
button, input, textarea, select { font: inherit; color: inherit; }

:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

.sr {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}
.skip {
  position: absolute; left: var(--space-xs); top: -100%;
  z-index: var(--z-toast);
  background: var(--color-accent); color: var(--color-accent-ink);
  padding: var(--space-xs) var(--space-sm); border-radius: var(--radius);
  font: 500 var(--text-xs)/1 var(--font-mono); text-decoration: none;
}
.skip:focus-visible { top: var(--space-xs); }

.ico { width: 20px; height: 20px; display: block; }
.ico--sm { width: 16px; height: 16px; }

/* ═══════════════════════ controls — all 8 states ═══════════════════════ */

.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: var(--space-xs);
  min-height: var(--tap);
  padding-inline: var(--space-md);
  background: var(--color-paper);
  color: var(--color-ink);
  border: 1px solid var(--color-rule-2);
  border-radius: var(--radius);
  font: 500 var(--text-md)/1 var(--font-ui);
  white-space: nowrap;                    /* gate 49 — affordances never wrap */
  cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease-out),
              border-color var(--dur-micro) var(--ease-out),
              transform var(--dur-micro) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .btn:hover:not([disabled]) { background: var(--color-paper-2); border-color: var(--color-ink-2); }
}
.btn:active:not([disabled]) { transform: translateY(1px); background: var(--color-paper-3); }
.btn[disabled], .btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; transform: none; }

.btn--primary { background: var(--color-accent); color: var(--color-accent-ink); border-color: var(--color-accent); }
@media (hover: hover) and (pointer: fine) {
  .btn--primary:hover:not([disabled]) { background: var(--color-accent-dim); border-color: var(--color-accent-dim); }
}
.btn--danger { color: var(--color-danger); border-color: var(--color-rule-2); }
.btn--block { width: 100%; }
.btn--icon { padding-inline: 0; width: var(--tap); flex: 0 0 auto; }


/* loading / error / success — driven by data-state, label stays readable */
.btn[data-state="loading"] { color: transparent; position: relative; pointer-events: none; }
.btn[data-state="loading"] > * { visibility: hidden; }
.btn[data-state="loading"]::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--color-accent-ink); border-top-color: transparent;
  animation: spin 640ms linear infinite;
}
.btn:not(.btn--primary)[data-state="loading"]::after { border-color: var(--color-ink-2); border-top-color: transparent; }
.btn[data-state="error"] { border-color: var(--color-danger); color: var(--color-danger); }
.btn[data-state="success"] { border-color: var(--color-accent); }
@keyframes spin { to { transform: rotate(360deg); } }

.ibtn {
  display: inline-flex; align-items: center; justify-content: center;
  width: var(--tap); height: var(--tap);
  flex: 0 0 auto;
  background: none; border: 1px solid transparent; border-radius: var(--radius);
  color: var(--color-muted); cursor: pointer;
  transition: color var(--dur-micro) var(--ease-out), background-color var(--dur-micro) var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .ibtn:hover:not([disabled]) { background: var(--color-paper-3); color: var(--color-ink); }
}
.ibtn:active:not([disabled]) { background: var(--color-paper-3); }
.ibtn[aria-pressed="true"] { color: var(--color-accent); }
/* 按键条开着时，输入行里的 ⌨ 要能看出来是「按下」的状态 */
.ibtn.is-on { color: var(--color-accent); background: var(--color-paper-3); }
.ibtn[disabled] { opacity: 0.45; cursor: not-allowed; }

.key {
  min-height: 40px; min-width: 44px;
  background: var(--color-paper); color: var(--color-ink);
  border: 1px solid var(--color-rule-2); border-radius: var(--radius);
  font: 500 var(--text-sm)/1 var(--font-mono);
  cursor: pointer; white-space: nowrap;
  transition: background-color var(--dur-micro) var(--ease-out), transform var(--dur-micro) var(--ease-out);
}
.key:active:not([disabled]) { transform: translateY(1px); background: var(--color-paper-3); }
.key[disabled] { opacity: 0.45; cursor: not-allowed; }
@media (hover: hover) and (pointer: fine) { .key:hover:not([disabled]) { background: var(--color-paper-2); } }

/* inputs — border-width constant across every state (no layout shift) */
.input {
  width: 100%;
  min-height: var(--tap);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-paper);
  color: var(--color-ink);
  border: 1px solid var(--color-rule-2);
  border-radius: var(--radius);
  outline: 2px solid transparent;         /* reserved slot — ring never shifts geometry */
  outline-offset: 1px;
  font-size: var(--text-md);              /* 16px floor: stops iOS zoom-on-focus */
  transition: background-color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out);
}
.input--mono { font-family: var(--font-mono); }
.input::placeholder { color: var(--color-neutral); }
@media (hover: hover) and (pointer: fine) { .input:hover:not([disabled]) { background: var(--color-paper-2); } }
.input:focus-visible { outline-color: var(--color-focus); border-color: var(--color-ink-2); }
.input[disabled] { opacity: 0.55; cursor: not-allowed; }
.input[aria-invalid="true"] { border-color: var(--color-danger); }

.field { margin-bottom: var(--space-md); }
.field__label {
  display: block; margin-bottom: var(--space-2xs);
  font: 500 var(--text-xs)/1.4 var(--font-mono);
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--color-muted);
}
.field__help {
  min-height: 1.4em;                      /* reserved — errors never push the page */
  margin-top: var(--space-2xs);
  font-size: var(--text-xs); color: var(--color-neutral);
}
.field__help[data-state="error"] { color: var(--color-danger); }

/* ═══════════════════════ shell ═══════════════════════ */

/* 精确视口高：列表和对话各自内部滚动，页面本身永远不滚 */
.app { display: flex; flex-direction: column; height: 100dvh; }

/* nav · N9 edge-aligned minimal — flush bar, one hairline, no marketing links */
.bar {
  position: sticky; top: 0; z-index: var(--z-sticky);
  display: flex; align-items: center; gap: var(--space-xs);
  padding-inline: var(--space-sm);
  padding-top: env(safe-area-inset-top);
  background: color-mix(in oklab, var(--color-paper) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--color-rule);
}
.bar__mark {
  display: flex; align-items: center; gap: var(--space-2xs);
  font: 500 var(--text-sm)/1 var(--font-display);
  letter-spacing: -0.01em; color: var(--color-ink);
}
.mark__glyph { color: var(--color-accent); font-size: 1.1em; }
.mark__name { display: none; }
.bar__acts { display: flex; align-items: center; margin-left: auto; }

.live {
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  min-height: 32px; padding-inline: var(--space-xs);
  margin-left: var(--space-xs);
  background: none; border: 1px solid var(--color-rule); border-radius: var(--radius);
  font: 500 var(--text-2xs)/1 var(--font-mono);
  letter-spacing: 0.04em; color: var(--color-muted);
  cursor: pointer; white-space: nowrap;
}
.live__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--color-neutral); flex: 0 0 auto; }
.live[data-s="live"] { color: var(--color-ink-2); }
.live[data-s="live"] .live__dot { background: var(--color-accent); }
.live[data-s="stale"] { color: var(--color-warn); border-color: var(--color-warn); }
.live[data-s="stale"] .live__dot { background: var(--color-warn); }
.live[data-s="down"] { color: var(--color-warn); border-color: var(--color-warn); }
.live[data-s="down"] .live__dot { background: none; box-shadow: inset 0 0 0 1.5px var(--color-warn); }
.live[data-s="mock"] .live__dot { background: var(--color-rule-2); }

.menu {
  position: absolute; top: calc(100% + 4px); right: var(--space-sm);
  z-index: var(--z-dropdown);
  min-width: 12rem; padding: var(--space-2xs);
  background: var(--color-paper); border: 1px solid var(--color-rule-2);
  border-radius: var(--radius-lg);
  box-shadow: 0 1px 2px oklch(24% 0.02 258 / 0.06);
}
.menu__it {
  display: block; width: 100%; min-height: 40px; padding-inline: var(--space-sm);
  text-align: left; background: none; border: 0; border-radius: var(--radius);
  color: var(--color-ink-2); font-size: var(--text-base); cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .menu__it:hover { background: var(--color-paper-3); } }

/* freshness alarm — the only place amber ever appears at page scale */
.stale-bar {
  display: flex; align-items: center; gap: var(--space-xs);
  padding: var(--space-xs) var(--space-md);
  background: var(--color-warn-wash); color: var(--color-warn);
  border-bottom: 1px solid var(--color-warn);
  font: 500 var(--text-xs)/1.4 var(--font-mono);
}

.panes { flex: 1; display: flex; min-height: 0; }
.pane { min-width: 0; min-height: 0; }
.pane--list { flex: 1; display: flex; flex-direction: column; min-width: 0; }

/* ═══════════════════════ 视图 1 · 列表 (Index-First) ═══════════════════════ */

.filters {
  display: flex; gap: var(--space-2xs);
  padding: var(--space-xs) var(--space-sm);
  overflow-x: auto; scrollbar-width: none;
  border-bottom: 1px solid var(--color-rule);
  background: var(--color-paper);
}
.filters::-webkit-scrollbar { display: none; }
.fchip {
  display: inline-flex; align-items: baseline; gap: var(--space-2xs);
  min-height: 34px; padding-inline: var(--space-sm);
  background: none; color: var(--color-muted);
  border: 1px solid var(--color-rule); border-radius: var(--radius);
  font: 500 var(--text-xs)/1 var(--font-mono);
  letter-spacing: 0.06em; text-transform: uppercase;
  white-space: nowrap; cursor: pointer;
  transition: color var(--dur-micro) var(--ease-out), border-color var(--dur-micro) var(--ease-out);
}
.fchip__n { font-variant-numeric: tabular-nums; opacity: 0.75; }
.fchip[aria-selected="true"] {
  background: var(--color-accent); color: var(--color-accent-ink); border-color: var(--color-accent);
}
.fchip[aria-selected="true"] .fchip__n { opacity: 0.85; }
.fchip[data-empty="1"]:not([aria-selected="true"]) { opacity: 0.45; }

.list { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; }

.grp {
  position: sticky; top: 0; z-index: var(--z-raised);
  display: flex; align-items: baseline; gap: var(--space-xs);
  padding: var(--space-sm) var(--space-md) var(--space-2xs);
  background: color-mix(in oklab, var(--color-paper) 92%, transparent);
  backdrop-filter: blur(8px);
  font: 500 var(--text-xs)/1.2 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--color-neutral);
}
.grp__n { font-variant-numeric: tabular-nums; }
.grp__hint { margin-left: auto; letter-spacing: 0.02em; text-transform: none; opacity: 0.8; }

/* the row IS the button — Index-First divider language, hairline rules, no boxed cards */
/* 卡片外壳：★ 是 .row 的**兄弟**而不是子元素（<button> 不能套 <button>）。
   用 relative + absolute 让 .row 保持整块可点，★ 浮在右上角。 */
.rowwrap { position: relative; border-bottom: 1px solid var(--color-rule); }

.star {
  position: absolute; top: 6px; right: 6px;
  width: 34px; height: 34px;
  display: flex; align-items: center; justify-content: center;
  background: none; border: 0; border-radius: var(--radius);
  color: var(--color-neutral); cursor: pointer;
  font: 400 15px/1 var(--font-ui);
  transition: color var(--dur-micro) var(--ease-out), background-color var(--dur-micro) var(--ease-out);
}
.star.is-on { color: var(--color-accent); }
.star:active { background: var(--color-paper-3); }
@media (hover: hover) and (pointer: fine) { .star:hover { background: var(--color-paper-3); color: var(--color-ink); } }
/* 顶行给 ★ 让出位置；只让这一行，标题和摘要仍占满宽 */
.rowwrap .row__top { padding-right: 34px; }
.rowwrap--mini { --row-mini: 1; }

.row {
  display: block; width: 100%; text-align: left;
  padding: var(--space-sm) var(--space-md);
  background: none; border: 0;
  color: inherit; cursor: pointer;
  transition: background-color var(--dur-micro) var(--ease-out);
}
/* 紧凑行：一行放下「状态 · 标题 · 路径 · 年龄」，实测约 45px（完整卡平均 118px） */
.row--mini .row__top { margin-bottom: 0; }
.row--mini .row__mt {
  font: 500 var(--text-sm)/1.3 var(--font-ui); color: var(--color-ink);
  letter-spacing: -0.005em;
}
.row--mini .row__mw { color: var(--color-neutral); }
.row--mini .row__where { display: flex; gap: var(--space-xs); align-items: baseline; }
.row--mini .row__mt, .row--mini .row__mw { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 标题吃掉所有剩余宽度；机器名按内容定宽、永不被截 —— 截一半的机器名没有信息量 */
.row--mini .row__mt { flex: 1 1 auto; min-width: 0; }
.row--mini .row__mw { flex: 0 0 auto; font-size: var(--text-2xs); }

/* 折叠条：一行顶掉一整层 */
.fold {
  display: flex; align-items: center; gap: var(--space-xs);
  width: 100%; text-align: left;
  padding: var(--space-xs) var(--space-md);
  min-height: 40px;
  background: var(--color-paper-2); border: 0;
  border-bottom: 1px solid var(--color-rule);
  color: var(--color-muted); cursor: pointer;
  font: 500 var(--text-xs)/1.3 var(--font-mono);
  letter-spacing: 0.06em;
}
@media (hover: hover) and (pointer: fine) { .fold:hover { background: var(--color-paper-3); color: var(--color-ink); } }
.fold__cx { display: inline-block; transition: transform var(--dur-micro) var(--ease-out); color: var(--color-neutral); }
.fold.is-open .fold__cx { transform: rotate(90deg); }
.fold__l { text-transform: uppercase; }
.fold__n {
  color: var(--color-ink); font-variant-numeric: tabular-nums;
  background: var(--color-paper-3); border-radius: var(--radius-sm); padding: 1px 6px;
}
.fold__s { margin-left: auto; color: var(--color-neutral); font-size: var(--text-2xs); letter-spacing: 0.04em; }

.empty--tip { padding: var(--space-md); border-bottom: 1px solid var(--color-rule); }
@media (hover: hover) and (pointer: fine) { .row:hover { background: var(--color-paper-2); } }
.row:active { background: var(--color-paper-3); }
.row:focus-visible { outline-offset: -2px; }
.row.is-on { background: var(--color-paper-3); }

/* pending_question: same hue, escalated by FILL + WASH + LABEL + rank. Never a second colour,
   never the banned left side-stripe. */
.row--ask { background: var(--color-accent-wash); }
@media (hover: hover) and (pointer: fine) {
  .row--ask:hover { background: color-mix(in oklab, var(--color-accent-wash) 80%, var(--color-accent)); }
}
.row--exited { color: var(--color-neutral); }
.row--snoozed { opacity: 0.72; }

.row__top { display: flex; align-items: center; gap: var(--space-xs); margin-bottom: var(--space-3xs); }

.st {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 3px var(--space-xs);
  border: 1px solid currentColor; border-radius: var(--radius-sm);
  font: 500 var(--text-2xs)/1.2 var(--font-mono);
  letter-spacing: 0.08em; text-transform: uppercase;
  white-space: nowrap; flex: 0 0 auto;
}
.st--waiting { color: var(--color-accent); }
.st--ask     { color: var(--color-accent-ink); background: var(--color-accent); border-color: var(--color-accent); }
.st--working { color: var(--color-muted); }
.st--exited  { color: var(--color-neutral); }
.st__dot { width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: 0 0 auto; }
.st--working .st__dot { animation: breathe 1.9s var(--ease-in-out) infinite; }
@keyframes breathe { 0%, 100% { opacity: 1; } 50% { opacity: 0.25; } }
.st--exited .st__dot { background: none; box-shadow: inset 0 0 0 1.5px currentColor; }

.row__where {
  min-width: 0; flex: 1;
  font: 400 var(--text-xs)/1.3 var(--font-mono);
  color: var(--color-neutral);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.row__age {
  font: 400 var(--text-xs)/1.3 var(--font-mono);
  color: var(--color-neutral); font-variant-numeric: tabular-nums;
  white-space: nowrap; flex: 0 0 auto;
}

.row__title {
  font: 500 var(--text-md)/1.35 var(--font-ui);
  color: var(--color-ink);
  letter-spacing: -0.005em;
  overflow-wrap: anywhere; min-width: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.row__title--fallback { font-family: var(--font-mono); font-size: var(--text-base); color: var(--color-muted); }
.row__title--fallback::after {
  content: "未命名";
  margin-left: var(--space-xs);
  font-size: var(--text-2xs); letter-spacing: 0.06em;
  color: var(--color-neutral); border: 1px solid var(--color-rule-2);
  border-radius: var(--radius-sm); padding: 1px 4px; vertical-align: 1px;
}

/* summary: markdown marks are stripped in JS, then clamped to 2 rendered lines here */
.row__sum {
  margin-top: var(--space-3xs);
  font-size: var(--text-base); line-height: 1.5;
  color: var(--color-muted);
  overflow-wrap: anywhere;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.row__sum--none { color: var(--color-neutral); font-style: italic; }

.row__tags { display: flex; flex-wrap: wrap; gap: var(--space-2xs); margin-top: var(--space-xs); }
.tag {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px var(--space-xs);
  border: 1px solid var(--color-rule-2); border-radius: var(--radius-sm);
  font: 400 var(--text-2xs)/1.4 var(--font-mono);
  letter-spacing: 0.03em; color: var(--color-neutral);
}
.tag--stale { color: var(--color-warn); border-color: var(--color-warn); background: var(--color-warn-wash); }
.tag--ro    { color: var(--color-muted); }
.tag--snz   { color: var(--color-muted); }

.empty {
  padding: var(--space-xl) var(--space-md);
  text-align: left; color: var(--color-neutral);
}
.empty__h { font: 500 var(--text-md)/1.4 var(--font-ui); color: var(--color-ink-2); margin-bottom: var(--space-2xs); }
.empty__p { font-size: var(--text-base); max-width: 34ch; }

/* footer · Ft2 inline single line */
.foot {
  padding: var(--space-sm) var(--space-md);
  padding-bottom: max(var(--space-sm), env(safe-area-inset-bottom));
  border-top: 1px solid var(--color-rule);
  font: 400 var(--text-xs)/1.5 var(--font-mono);
  color: var(--color-neutral);
  overflow-wrap: anywhere;
}

/* ═══════════════════════ 视图 2/3 · 详情 ═══════════════════════ */

.pane--detail {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; flex-direction: column;
  background: var(--color-paper);
  animation: rise var(--dur-short) var(--ease-out);
}
/* 只位移不淡入 —— 淡入会让底下的列表透出来，看着像还没画完 */
@keyframes rise { from { transform: translateY(10px); } }

/* 标题行与元信息行分开：返回键始终和标题水平对齐，不会被两行 meta 顶歪 */
.dhead {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; column-gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-xs) var(--space-xs);
  padding-top: max(var(--space-2xs), env(safe-area-inset-top));
  border-bottom: 1px solid var(--color-rule);
}
.ibtn--back { grid-column: 1; }
.dhead__title {
  grid-column: 2;
  font: 500 var(--text-lg)/1.25 var(--font-ui);
  letter-spacing: -0.012em; color: var(--color-ink);
  overflow-wrap: anywhere; min-width: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.dhead__meta {
  grid-column: 1 / -1;
  margin-top: var(--space-2xs); padding-inline: var(--space-2xs);
  font: 400 var(--text-xs)/1.5 var(--font-mono);
  color: var(--color-neutral);
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2xs) var(--space-xs);
}
.dhead__acts { grid-column: 3; display: flex; }

.tabs {
  display: flex; align-items: center; gap: var(--space-2xs);
  padding: var(--space-2xs) var(--space-xs);
  border-bottom: 1px solid var(--color-rule);
}
.tab {
  min-height: 38px; padding-inline: var(--space-md);
  background: none; border: 1px solid transparent; border-radius: var(--radius);
  color: var(--color-muted);
  font: 500 var(--text-sm)/1 var(--font-mono);
  letter-spacing: 0.06em; cursor: pointer; white-space: nowrap;
}
.tab.is-on { background: var(--color-paper-3); color: var(--color-ink); border-color: var(--color-rule); }
.tab[disabled] { opacity: 0.42; cursor: not-allowed; }
.tabs__note {
  margin-left: auto; padding-right: var(--space-xs);
  font: 400 var(--text-2xs)/1.3 var(--font-mono); color: var(--color-neutral);
  text-align: right;
}

.dbody { flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch; min-height: 0; }

/* ── 对话 · kind 是结构化字段，这里一条正则都没有 ── */
.convo { padding: var(--space-sm) var(--space-md) var(--space-lg); }

.blk { margin-bottom: var(--space-md); }
.blk__who {
  font: 500 var(--text-2xs)/1.4 var(--font-mono);
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--color-neutral); margin-bottom: var(--space-3xs);
}

.say { font-size: var(--text-base); line-height: 1.62; color: var(--color-ink-2); overflow-wrap: anywhere; }
.say strong { font-weight: 600; color: var(--color-ink); }
.say code {
  font: 400 0.9em/1.4 var(--font-mono);
  background: var(--color-paper-3); border-radius: var(--radius-sm);
  padding: 1px 4px;
}
.say a { color: var(--color-accent); text-decoration-thickness: 1px; text-underline-offset: 2px; }

.blk--user .say {
  background: var(--color-paper-3);
  border-radius: var(--radius-lg);
  padding: var(--space-sm) var(--space-md);
  color: var(--color-ink);
}
.blk--sys .say {
  border-left: 1px solid var(--color-rule-2);
  padding-left: var(--space-sm);
  color: var(--color-muted); font-size: var(--text-sm);
}

/* tool_use + tool_result pair as one instrument block */
.tool {
  border: 1px solid var(--color-rule);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--color-paper-2);
}
.tool__head {
  display: flex; align-items: baseline; gap: var(--space-xs);
  width: 100%; text-align: left;
  padding: var(--space-xs) var(--space-sm);
  background: none; border: 0; cursor: pointer;
  font-family: var(--font-mono);
}
.tool__name {
  font: 500 var(--text-sm)/1.3 var(--font-mono);
  color: var(--color-ink); flex: 0 0 auto;
}
.tool__brief {
  font: 400 var(--text-sm)/1.4 var(--font-mono);
  color: var(--color-neutral); min-width: 0; flex: 1;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.tool__caret { color: var(--color-neutral); font-size: var(--text-2xs); flex: 0 0 auto; }
.tool__body {
  padding: 0 var(--space-sm) var(--space-xs);
  font: 400 var(--text-sm)/1.5 var(--font-mono);
  color: var(--color-muted);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 9lh; overflow: hidden;
}
.tool.is-open .tool__body { max-height: none; }
.tool.is-open .tool__brief { white-space: normal; overflow: visible; }
.tool__out {
  border-top: 1px solid var(--color-rule);
  padding: var(--space-xs) var(--space-sm);
  font: 400 var(--text-sm)/1.5 var(--font-mono);
  color: var(--color-muted);
  white-space: pre-wrap; overflow-wrap: anywhere;
  max-height: 7.5lh; overflow: hidden; position: relative;
}
.tool.is-open .tool__out { max-height: none; }
.tool__out::before { content: "└ "; color: var(--color-neutral); }
.tool__more {
  display: block; width: 100%; text-align: left;
  padding: var(--space-2xs) var(--space-sm) var(--space-xs);
  background: none; border: 0; cursor: pointer;
  font: 500 var(--text-2xs)/1.4 var(--font-mono);
  letter-spacing: 0.06em; color: var(--color-accent);
}

.turn {
  display: flex; align-items: center; gap: var(--space-sm);
  margin: var(--space-lg) 0;
  font: 400 var(--text-2xs)/1 var(--font-mono);
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--color-neutral);
}
.turn::before, .turn::after { content: ""; height: 1px; background: var(--color-rule); flex: 1; }

.gap {
  margin: var(--space-md) 0; padding: var(--space-sm);
  border: 1px dashed var(--color-warn); border-radius: var(--radius);
  background: var(--color-warn-wash); color: var(--color-warn);
  font: 400 var(--text-xs)/1.5 var(--font-mono);
}
.gap .btn { margin-top: var(--space-xs); min-height: 36px; font-size: var(--text-sm); }

.trunc { color: var(--color-warn); font-size: var(--text-2xs); letter-spacing: 0.06em; }

/* skeleton beats a spinner when the shape is known */
.skel { padding: var(--space-md); }
.skel__l {
  height: 1lh; margin-bottom: var(--space-xs); border-radius: var(--radius-sm);
  background: var(--color-paper-3);
  animation: pulse 1.4s var(--ease-in-out) infinite;
}
.skel__l:nth-child(2) { width: 76%; } .skel__l:nth-child(3) { width: 54%; }
.skel__l:nth-child(4) { width: 88%; } .skel__l:nth-child(5) { width: 41%; }
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }

/* ── 终端 · 副通道，只在需要操作 TUI 时 ── */
.term { padding: var(--space-sm) var(--space-sm) var(--space-lg); }
.term__label {
  font: 400 var(--text-2xs)/1.4 var(--font-mono);
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--color-neutral);
  padding-bottom: var(--space-2xs);
  border-bottom: 1px solid var(--color-rule);
  margin-bottom: var(--space-xs);
}
.term__screen {
  margin: 0; padding: var(--space-sm);
  background: var(--color-graphite); color: var(--color-graphite-ink);
  border: 1px solid var(--color-graphite-rule); border-radius: var(--radius-lg);
  font: 400 var(--text-sm)/1.45 var(--font-mono);
  white-space: pre; overflow-x: auto; -webkit-overflow-scrolling: touch;
  tab-size: 2;
}
/* 语义配色 · 只剩 3 条（契约裁决） */
.tl--prompt { color: var(--color-accent); }              /* #2  ❯ 提示符 — 等你输入的信号 */
.tl--busy   { color: var(--color-graphite-dim); }        /* #4  ✢ · ✶ 干活中 */
.tl--box    { color: var(--color-term-box); }            /* #15 方框线 — 压暗让内容突出 */

/* ── 动作条 · 7 种指令共用同一条通道 ── */
.acts {
  border-top: 1px solid var(--color-rule);
  background: var(--color-paper);
  padding: var(--space-xs) var(--space-sm);
  padding-bottom: max(var(--space-xs), env(safe-area-inset-bottom));
  display: flex; flex-direction: column; gap: var(--space-xs);
}
.acts__why {
  display: flex; align-items: flex-start; gap: var(--space-xs);
  padding: var(--space-xs) var(--space-sm);
  background: var(--color-paper-3); border-radius: var(--radius);
  font: 400 var(--text-xs)/1.5 var(--font-ui);
  color: var(--color-muted);
}
/* 按键条 · 一行横滑，和 .filters 同一个手势语汇（滑，不换行）。
   横滑胜过网格换行：键保持 44px 触控宽，窄屏也只占一行，以后加键也不长高。 */
.keypad {
  display: flex; gap: var(--space-2xs);
  overflow-x: auto; scrollbar-width: none;
  overscroll-behavior-x: contain;
}
.keypad::-webkit-scrollbar { display: none; }
.keypad .key { flex: 0 0 auto; }
.key--w { font-size: var(--text-2xs); }

.composer { display: flex; align-items: flex-end; gap: var(--space-2xs); }
.composer__ta {
  resize: none; min-height: var(--tap); max-height: 8lh;
  line-height: 1.45; padding-top: 11px; padding-bottom: 11px;
}
.composer__help {
  min-height: 1.35em;
  font: 400 var(--text-2xs)/1.35 var(--font-mono); color: var(--color-neutral);
  overflow-wrap: anywhere;
}
.composer__help[data-state="error"] { color: var(--color-danger); }
.composer__help[data-state="ok"] { color: var(--color-accent); }
.ibtn--file { position: relative; cursor: pointer; }
/* 详情页的 ★ 是字形不是图标，字号要单独给 —— .ibtn 本来只装 24px 的 svg */
.ibtn--star { font: 400 17px/1 var(--font-ui); }
.ibtn--star.is-on { color: var(--color-accent); }

/* ═══════════════════════ docs 面板 ═══════════════════════ */

.sheet {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: flex; flex-direction: column;
  background: var(--color-paper);
  animation: rise var(--dur-short) var(--ease-out);
}
.sheet__head {
  display: flex; align-items: center; gap: var(--space-xs);
  padding: var(--space-2xs) var(--space-xs);
  padding-top: max(var(--space-2xs), env(safe-area-inset-top));
  border-bottom: 1px solid var(--color-rule);
}
.sheet__h {
  flex: 1; padding-left: var(--space-xs);
  font: 500 var(--text-md)/1.3 var(--font-mono); letter-spacing: 0.04em; color: var(--color-ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sheet__bar { display: flex; gap: var(--space-xs); padding: var(--space-xs) var(--space-sm); }
.sheet__bar .btn { flex: 0 0 auto; }
.sheet__body { flex: 1; overflow-y: auto; padding-bottom: max(var(--space-lg), env(safe-area-inset-bottom)); }

.frow {
  display: flex; align-items: baseline; gap: var(--space-xs);
  width: 100%; text-align: left;
  padding: var(--space-sm) var(--space-md);
  background: none; border: 0; border-bottom: 1px solid var(--color-rule);
  cursor: pointer;
}
@media (hover: hover) and (pointer: fine) { .frow:hover { background: var(--color-paper-2); } }
.frow__p {
  flex: 1; min-width: 0;
  font: 400 var(--text-sm)/1.4 var(--font-mono); color: var(--color-ink-2);
  overflow-wrap: anywhere;
}
.frow__p b { font-weight: 600; color: var(--color-ink); }
.frow__m {
  font: 400 var(--text-2xs)/1.4 var(--font-mono); color: var(--color-neutral);
  font-variant-numeric: tabular-nums; white-space: nowrap; flex: 0 0 auto;
}

/* markdown — purpose-built renderer, ~130 lines of JS, no library, no CDN
   Docs 面板（.md）与对话气泡（.say）共用这套块级样式：两边渲染器是同一个，
   样式再分家就会出现「文档里好看、对话里裸奔」。
   .md 的容器内边距不共用 —— 对话气泡有自己的一套（见 .blk--user .say）。 */
.md { padding: var(--space-md); font-size: var(--text-base); line-height: 1.62; color: var(--color-ink-2); }
.md h1, .md h2, .md h3,
.say h1, .say h2, .say h3 {
  font-family: var(--font-ui); font-weight: 600; color: var(--color-ink);
  letter-spacing: -0.012em; line-height: 1.25;
  margin: var(--space-lg) 0 var(--space-xs);
}
.md h1, .say h1 { font-size: var(--text-xl); }
.md h2, .say h2 { font-size: var(--text-lg); }
.md h3, .say h3 { font-size: var(--text-md); }
.md > :first-child, .say > :first-child { margin-top: 0; }
/* 气泡里最后一段不留下边距，否则底部会多出一块空白 */
.say > :last-child { margin-bottom: 0; }
.md p, .md ul, .md ol, .md blockquote,
.say p, .say ul, .say ol, .say blockquote { margin: 0 0 var(--space-sm); }
.md ul, .md ol, .say ul, .say ol { padding-left: 1.35em; }
.md li, .say li { margin-bottom: var(--space-3xs); }
.md code { font: 400 0.9em/1.4 var(--font-mono); background: var(--color-paper-3); border-radius: var(--radius-sm); padding: 1px 4px; }
.md pre, .say pre {
  margin: 0 0 var(--space-sm); padding: var(--space-sm);
  background: var(--color-graphite); color: var(--color-graphite-ink);
  border-radius: var(--radius-lg); overflow-x: auto;
  font: 400 var(--text-sm)/1.5 var(--font-mono);
}
.md pre code, .say pre code { background: none; padding: 0; color: inherit; }
.md blockquote, .say blockquote { border-left: 2px solid var(--color-rule-2); padding-left: var(--space-sm); color: var(--color-muted); }
.md hr, .say hr { border: 0; border-top: 1px solid var(--color-rule); margin: var(--space-lg) 0; }
.md a { color: var(--color-accent); }
/* wide tables scroll inside their own box, the page never does */
.md__tw { overflow-x: auto; margin-bottom: var(--space-sm); max-width: 100%; }
.md table, .say table { border-collapse: collapse; font-size: var(--text-sm); }
.md th, .md td, .say th, .say td { border: 1px solid var(--color-rule); padding: var(--space-2xs) var(--space-xs); text-align: left; }
.md th, .say th { background: var(--color-paper-2); font-weight: 600; color: var(--color-ink); }

/* ═══════════════════════ dialogs & toasts ═══════════════════════ */

.dlg {
  position: fixed; inset: 0; margin: auto;
  width: min(92vw, 26rem); height: fit-content; max-height: min(84dvh, 40rem);
  padding: var(--space-lg);
  background: var(--color-paper); color: var(--color-ink-2);
  border: 1px solid var(--color-rule-2); border-radius: var(--radius-lg);
  overflow-y: auto;
}
.dlg::backdrop { background: var(--color-scrim); }
.dlg__h { font: 500 var(--text-lg)/1.3 var(--font-ui); color: var(--color-ink); margin-bottom: var(--space-xs); letter-spacing: -0.012em; }
.dlg__p { font-size: var(--text-base); color: var(--color-muted); margin-bottom: var(--space-md); }
.dlg__acts { display: flex; gap: var(--space-xs); justify-content: flex-end; margin-top: var(--space-md); }
.snz { display: flex; gap: var(--space-xs); }
.snz .btn { flex: 1; padding-inline: var(--space-xs); }

.toasts {
  position: fixed; z-index: var(--z-toast);
  left: var(--space-sm); right: var(--space-sm);
  bottom: max(var(--space-sm), env(safe-area-inset-bottom));
  display: flex; flex-direction: column-reverse; gap: var(--space-xs);
  pointer-events: none;
}
.toast {
  display: flex; align-items: center; gap: var(--space-xs);
  padding: var(--space-sm) var(--space-md);
  background: var(--color-ink); color: var(--color-paper);
  border-radius: var(--radius-lg);
  font-size: var(--text-base);
  pointer-events: auto;
  animation: toast-in var(--dur-short) var(--ease-out);
  overflow-wrap: anywhere;
}
.toast--err { background: var(--color-danger); color: var(--color-accent-ink); }
.toast__x { margin-left: auto; background: none; border: 0; color: inherit; cursor: pointer; font-size: var(--text-sm); flex: 0 0 auto; }
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } }

.gate {
  position: fixed; inset: 0; z-index: var(--z-modal);
  display: grid; place-items: center;
  padding: var(--space-md); background: var(--color-paper);
}
.gate__form { width: min(100%, 22rem); }
.gate__mark { font: 500 var(--text-sm)/1 var(--font-display); color: var(--color-muted); margin-bottom: var(--space-md); }
.gate__h {
  font: 500 var(--text-xl)/1.25 var(--font-ui); color: var(--color-ink);
  letter-spacing: -0.018em; margin-bottom: var(--space-lg);
  overflow-wrap: anywhere;
}

/* ═══════════════════════ ≥ 640px — the phone layout, more room ═══════════════════════ */

@media (min-width: 40rem) {
  .mark__name { display: inline; }
  .filters { padding-inline: var(--space-md); }
  .row, .grp, .foot, .frow { padding-inline: var(--space-lg); }
  .convo, .term { padding-inline: var(--space-lg); }
  .acts { padding-inline: var(--space-lg); }
  .toasts { left: auto; right: var(--space-lg); width: min(24rem, calc(100vw - 2 * var(--space-lg))); }
}

/* ═══════════════════════ ≥ 960px — two panes, desktop is the phone enlarged ═══════════════════════ */

@media (min-width: 60rem) {
  .panes {
    display: grid;
    grid-template-columns: minmax(0, 24rem) minmax(0, 1fr);
    grid-template-rows: minmax(0, 1fr);       /* 行高钉死，否则详情的动作条会被顶到屏幕外 */
  }
  .pane--list { border-right: 1px solid var(--color-rule); overflow: hidden; }
  .filters { flex-wrap: wrap; overflow-x: visible; }   /* 桌面有竖向余量，换行胜过横向滚 */
  .row, .grp, .foot { padding-inline: var(--space-md); }

  .pane--detail {
    position: static; z-index: var(--z-base);
    animation: none;
    border: 0;
  }
  .ibtn--back { display: none; }
  .dhead, .tabs, .acts { padding-inline: var(--space-md); }
  .convo, .term, .frow { padding-inline: var(--space-xl); }
  .convo { max-width: 62rem; }
  /* 桌面不是「把手机按钮拉宽」：动作条按内容定宽，靠左，读起来还是一条工具栏 */
  .acts > * { max-width: 62rem; }
  .composer__ta { max-width: 44rem; }

  /* nothing selected: the right pane says so, it doesn't sit blank */
  .pane--detail[hidden] { display: none; }
  .nosel {
    display: grid; place-content: center start;
    padding: var(--space-xl);
    color: var(--color-neutral);
  }
  .nosel__h { font: 500 var(--text-md)/1.4 var(--font-ui); color: var(--color-muted); margin-bottom: var(--space-2xs); }
  .nosel__p { font-size: var(--text-base); max-width: 40ch; }

  .sheet { left: auto; width: min(46rem, 60vw); border-left: 1px solid var(--color-rule-2); }
}
@media (max-width: 59.999rem) { .nosel { display: none; } }

@media (min-width: 90rem) {
  .panes { grid-template-columns: minmax(0, 27rem) minmax(0, 1fr); }
}

/* ═══════════════════════ reduced motion ═══════════════════════ */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 150ms !important;
    transition-duration: 150ms !important;
  }
  .pane--detail, .sheet, .toast { animation: none; }
  /* functional loaders keep running — just slower */
  .btn[data-state="loading"]::after { animation-duration: 1200ms !important; animation-iteration-count: infinite !important; }
  .st--working .st__dot { animation-duration: 3s !important; animation-iteration-count: infinite !important; }
  .skel__l { animation-duration: 2s !important; animation-iteration-count: infinite !important; }
}
