/* The board's visual language is Zed's — the tokens below are lifted verbatim from
   zed-industries/zed · assets/themes/one/one.json (One Dark + One Light), with Zed's
   own semantics kept: background vs surface vs elevated_surface, border vs
   border.variant, text vs text.muted, and status colors used sparingly.

   The traits matter as much as the palette: flat dense panels, 1px borders, no
   shadows, no gradients, quiet monochrome with color reserved for status, crisp
   small type, mono for ids and paths, minimal chrome.

   THE FULL DESIGN GUIDE lives at docs/design.md — tokens, the chip family, nav
   grammar, answer-first ordering, status displays, the sidebar, words, process.
   Read it before building UI; this header keeps only the load-bearing rules.

   ONE CHIP FAMILY, ONE METRIC (decision of record, 2026-08-17): every inline
   status indicator in a header row — passive chips (status, version, tier) and
   CLICKABLE pills alike — shares one size: ~10.5px/600 type on a 999px-radius
   pill, padding 1.5px 7-8px, 1px var(--border), var(--element) ground, so the
   row reads as one line of equals in harmony with the text beside it. The
   canonical pair is the plan header's `v1` version chip sitting flush beside
   the stage pill. Clickability is signaled ONLY by affordance — a chevron ▾
   plus hover lift (accent border, element-hover ground) — never by making the
   clickable pill larger than its passive siblings. The pinned metric lives at
   `.adm .chip` (admin.css); reuse it rather than re-deriving. */

:root,
:root[data-theme="dark"] {
  --background: #3b414d;
  --surface: #2f343e;
  --elevated: #2f343e;
  --editor: #282c33;
  --editor-fg: #acb2be;
  --border: #464b57;
  --border-variant: #363c46;
  --text: #dce0e5;
  --text-muted: #a9afbc;
  --text-placeholder: #878a98;
  --text-accent: #74ade8;
  --element: #2e343e;
  --element-hover: #363c46;
  --element-selected: #454a56;
  --tab-active: #282c33;
  --title-bar: #3b414d;
  --line-number: #4e5a5f;
  --active-line: #2f343ebf;
  --scrollbar: #c8ccd44c;

  --success: #a1c181;
  --error: #d07277;
  --warning: #dec184;
  --info: #74ade8;
  --hint: #788ca6;
  --created: #a1c181;
  --modified: #dec184;
  --deleted: #d07277;
}

:root[data-theme="light"] {
  --background: #dcdcdd;
  --surface: #ebebec;
  --elevated: #ebebec;
  --editor: #fafafa;
  --editor-fg: #242529;
  --border: #c9c9ca;
  --border-variant: #dfdfe0;
  --text: #242529;
  --text-muted: #58585a;
  --text-placeholder: #7e8086;
  --text-accent: #5c78e2;
  --element: #ebebec;
  --element-hover: #dfdfe0;
  --element-selected: #cacaca;
  --tab-active: #fafafa;
  --title-bar: #dcdcdd;
  --line-number: #b4b4bb;
  --active-line: #ebebecbf;
  --scrollbar: #383a414c;

  --success: #669f59;
  --error: #d36151;
  --warning: #a48819;
  --info: #5c78e2;
  --hint: #7274a7;
  --created: #669f59;
  --modified: #a48819;
  --deleted: #d36151;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

body {
  background: var(--background);
  color: var(--text);
  font: 13px/1.5 ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.mono, code, .id, .path {
  font-family: "Zed Mono", ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace;
  font-size: 12px;
}

/* ── title bar ─────────────────────────────────────────────────────────── */

.titlebar {
  display: flex;
  align-items: center;
  gap: 2px;
  height: 32px;
  padding: 0 8px;
  background: var(--title-bar);
  border-bottom: 1px solid var(--border);
}

.brand {
  font-weight: 600;
  font-size: 12px;
  padding: 0 10px 0 4px;
  color: var(--text);
  letter-spacing: 0.2px;
}

.tab {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 12px;
  border: 1px solid transparent;
  border-bottom: none;
}

.tab:hover { background: var(--element-hover); color: var(--text); }

.tab[aria-current] {
  background: var(--tab-active);
  color: var(--text);
  border-color: var(--border);
}

.tab .count {
  font-size: 10px;
  padding: 1px 5px;
  border-radius: 6px;
  background: var(--element-selected);
  color: var(--text-muted);
}

.tab .count.hot { background: var(--warning); color: var(--editor); }

/* work: Board | Runs as two views of one nav item — a small segmented control
   that rides beside the lit "work" tab, only while on a work surface. */
.workviews { display: flex; align-items: center; gap: 3px; padding: 0 8px 0 2px; }
.workviews .wv {
  font-size: 11px;
  padding: 2px 9px;
  color: var(--text-muted);
  text-decoration: none;
  border: 1px solid var(--border);
  border-radius: 5px;
  background: var(--element);
}
.workviews .wv:hover { background: var(--element-hover); color: var(--text); }
.workviews .wv.on { border-color: var(--text-accent); color: var(--text-accent); }

.spacer { flex: 1; }

/* ── inline SVG icons — vendored from Zed's set (priv/static/icons), always
   stroke/fill currentColor so they follow the text color in either theme ── */
.icon { display: inline-flex; flex: none; vertical-align: -0.18em; }
.icon svg { width: 1.15em; height: 1.15em; display: block; }
.brand .icon svg { width: 14px; height: 14px; }
.icon-btn .icon { vertical-align: middle; }

.icon-btn {
  height: 22px;
  min-width: 22px;
  padding: 0 6px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--text-muted);
  cursor: pointer;
  font-size: 12px;
}

.icon-btn:hover { background: var(--element-hover); color: var(--text); }

/* ── project switcher (M13) — scope, not navigation ────────────────────── */

.switcher { position: relative; display: flex; align-items: center; margin-right: 8px; }

.swbtn {
  display: flex;
  align-items: center;
  gap: 7px;
  height: 22px;
  padding: 0 9px;
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-size: 12px;
  cursor: pointer;
  min-width: 0;
}

.swbtn:hover { border-color: var(--text-accent); }

/* Fixed-width project name: the pill is a constant size whatever the project is
   called, so the brand + switcher block's right edge always lands within the
   232px sidebar edge and the tabs after it never shift. width is tuned to that
   edge; longer names (e.g. "Data capture") ellipsize, shorter ones left-align in
   the same slot. flex: none pins the width inside the .swbtn flex row. */
.swname {
  flex: none;
  min-width: 0;
  width: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-align: left;
}

.swdot { width: 7px; height: 7px; border-radius: 50%; flex: none; }

.swcaret { color: var(--text-muted); font-size: 10px; }

.kbd {
  font-size: 9.5px;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0 4px;
}

.swpop {
  position: absolute;
  top: 28px;
  left: 0;
  width: 300px;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: 6px;
  z-index: 40;
  overflow: hidden;
}

.swsearch {
  width: 100%;
  background: var(--editor);
  border: none;
  border-bottom: 1px solid var(--border);
  color: var(--text);
  padding: 7px 10px;
  font-size: 12px;
  outline: none;
  font-family: inherit;
}

.swsearch::placeholder { color: var(--text-placeholder); }

.swrow {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 10px;
  cursor: pointer;
  font-size: 12px;
  color: var(--text);
  text-decoration: none;
}

.swrow:hover, .swrow.sel { background: var(--element-hover); }

.swrow-name { flex: 1; color: var(--text); }

.swrow-meta { font-size: 10px; color: var(--text-muted); }

.swrow.swnew { border-top: 1px solid var(--border-variant); color: var(--text-accent); }

.swrow.swnew .swrow-name { color: var(--text-accent); }

/* ── the identity menu (org switcher + new organization) ──────────────────────
   Introduced in the titlebar alongside settings/logout. Mirrors the project
   switcher's vocabulary (.swrow/.swrow-name/.swrow-meta) but anchors its popover
   to the RIGHT edge, since it lives on the far side of the titlebar. */
.identity { position: relative; display: flex; align-items: center; margin-left: 4px; }

.idbtn {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 8px;
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text);
  font-size: 12px;
  cursor: pointer;
  min-width: 0;
}

.idbtn:hover { border-color: var(--text-accent); }

.idname {
  flex: none;
  max-width: 120px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.idpop {
  position: absolute;
  top: 28px;
  right: 0;
  width: 260px;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: 6px;
  z-index: 40;
  overflow: hidden;
}

.idpop[hidden] { display: none; }

.idhead { padding: 8px 10px; border-bottom: 1px solid var(--border-variant); }

.idemail { font-size: 11px; color: var(--text-muted); word-break: break-all; }

.idsect {
  padding: 7px 10px 4px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
}

.idrow.active { background: var(--element-hover); }

.idcheck { width: 12px; flex: none; color: var(--text-accent); font-size: 11px; }

.idnew {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 7px 10px;
  border-top: 1px solid var(--border-variant);
}

.idplus { color: var(--text-accent); flex: none; }

.idnew-input {
  flex: 1;
  min-width: 0;
  background: var(--editor);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  padding: 4px 7px;
  font-size: 12px;
  outline: none;
  font-family: inherit;
}

.idnew-input::placeholder { color: var(--text-placeholder); }

.idnew-btn {
  flex: none;
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text-accent);
  padding: 4px 8px;
  font-size: 11px;
  cursor: pointer;
}

.idnew-btn:hover { border-color: var(--text-accent); }

/* ── ⌘K command palette ─────────────────────────────────────────────────
   The switcher's vocabulary (swpop/swsearch/swrow) scaled up to a centered,
   body-level overlay. Zed traits held: 1px borders, flat elevated panel, no
   shadow, no gradient — a plain translucent scrim, color only on status dots. */

.cmdk-open {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 22px;
  padding: 0 8px;
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 5px;
  color: var(--text-muted);
  cursor: pointer;
  margin-right: 6px;
}

.cmdk-open:hover { border-color: var(--text-accent); color: var(--text); }

.cmdk-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding-top: 12vh;
  background: color-mix(in srgb, var(--editor) 55%, transparent);
}

.cmdk {
  width: 560px;
  max-width: 92vw;
  background: var(--elevated);
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
}

.cmdk-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: var(--editor);
  border-bottom: 1px solid var(--border);
}

.cmdk-glass { color: var(--text-placeholder); flex: none; }

.cmdk-scope { flex: none; }

.cmdk-search {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  color: var(--text);
  font-size: 13px;
  outline: none;
  font-family: inherit;
}

.cmdk-search::placeholder { color: var(--text-placeholder); }

.cmdk-list { max-height: 46vh; overflow-y: auto; }

.cmdk-row .cmdk-id { flex: none; color: var(--text-muted); }

.cmdk-row .cmdk-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.cmdk-foot {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  border-top: 1px solid var(--border-variant);
  background: var(--surface);
  font-size: 10px;
  color: var(--text-placeholder);
}

.cmdk-foot .mono {
  font-size: 10px;
  color: var(--text-muted);
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0 4px;
}

.statusbar .dim { color: var(--text-placeholder); }

/* ── layout ────────────────────────────────────────────────────────────── */

.workspace { display: flex; height: 100%; }

.panel {
  background: var(--surface);
  border-right: 1px solid var(--border);
  width: 300px;
  min-width: 300px;
  overflow-y: auto;
}

.panel.right { border-right: none; border-left: 1px solid var(--border); width: 340px; min-width: 340px; }

.pane {
  flex: 1;
  background: var(--editor);
  overflow-y: auto;
  min-width: 0;
}

/* inbox: a single centered content column (no middle/right panes) */
.workspace.inbox-single { justify-content: center; }
.workspace.inbox-single > .panel {
  flex: 0 1 760px;
  max-width: 760px;
  min-width: 0;
  border-right: none;
}

.panel-header {
  position: sticky;
  top: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: var(--surface);
  border-bottom: 1px solid var(--border-variant);
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-muted);
}

.pane-header {
  position: sticky;
  top: 0;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  background: var(--editor);
  border-bottom: 1px solid var(--border-variant);
}

.pane-title { font-weight: 600; font-size: 13px; }
.pane-sub { color: var(--text-muted); font-size: 12px; }

/* ── lists ─────────────────────────────────────────────────────────────── */

.row {
  display: block;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border-variant);
  color: var(--text);
  text-decoration: none;
  cursor: pointer;
}

.row:hover { background: var(--element-hover); }
.row[aria-selected="true"] { background: var(--element-selected); }
.row-top { display: flex; align-items: center; gap: 6px; }
.row-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-meta { color: var(--text-muted); font-size: 11px; margin-top: 2px; display: flex; gap: 8px; }

.empty { padding: 14px 10px; color: var(--text-placeholder); font-size: 12px; }

.section {
  padding: 5px 10px;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-placeholder);
  background: var(--surface);
  border-bottom: 1px solid var(--border-variant);
}

/* ── status: the only place color is allowed ───────────────────────────── */

.dot { width: 6px; height: 6px; border-radius: 50%; flex: none; background: var(--text-muted); }
.dot.running { background: var(--info); }
.dot.needs_input { background: var(--warning); }
.dot.done { background: var(--success); }
.dot.failed { background: var(--error); }
.dot.interrupted { background: var(--modified); }
.dot.created { background: var(--hint); }

.status { font-size: 11px; color: var(--text-muted); }
.status.green, .status.done { color: var(--success); }
.status.red, .status.failed { color: var(--error); }
.status.hold, .status.needs_input { color: var(--warning); }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10px;
  padding: 1px 6px;
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--text-muted);
  background: var(--element);
  white-space: nowrap;
}

.chip.work { border-color: var(--info); color: var(--info); }
.chip.process { border-color: var(--warning); color: var(--warning); }
.chip.template { border-color: var(--hint); color: var(--hint); }
.chip.ready { border-color: var(--success); color: var(--success); }
.chip.stale { border-color: var(--error); color: var(--error); }
/* a chip standing for a CHOSEN value (the rule editor's per-repo scope pairs and
   its param presets) or a good outcome — lit, so "which one is on" is legible */
.chip.ok { border-color: var(--success); color: var(--success); }
.chip.err { border-color: var(--error); color: var(--error); }

/* ── thread ────────────────────────────────────────────────────────────── */

.thread { padding: 12px 14px 150px; }

.run-block {
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  margin-bottom: 10px;
}

.run-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-bottom: 1px solid var(--border-variant);
}

.verdict {
  padding: 6px 10px;
  font-size: 12px;
  color: var(--editor-fg);
  border-bottom: 1px solid var(--border-variant);
  word-break: break-word;
}

/* the verdict banner — the run's call in plain words, leading its page. The left
   border reads the tone at a glance; the kernel's raw line demotes to a quiet foot. */
.vbanner {
  border: 1px solid var(--border);
  border-left-width: 3px;
  border-radius: 6px;
  padding: 8px 11px;
  margin-bottom: 12px;
  background: var(--surface);
}
.vbanner.ok { border-left-color: var(--success); }
.vbanner.run { border-left-color: var(--info); }
.vbanner.warn { border-left-color: var(--warning); }
.vbanner.err { border-left-color: var(--error); }
.vbanner .vb-line { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.vbanner .vb-head { font-size: 13px; font-weight: 500; color: var(--text); }
.vbanner.ok .vb-head { color: var(--success); }
.vbanner.err .vb-head { color: var(--error); }
.vbanner.warn .vb-head { color: var(--warning); }
.vbanner .vb-detail { font-size: 11.5px; color: var(--text-muted); margin-top: 4px; }
.vbanner .vb-detail > :first-child { margin-top: 0; }
.vbanner .vb-call { font-size: 11.5px; color: var(--text); margin-top: 5px; }
.vbanner .vb-raw {
  font-size: 10.5px;
  color: var(--text-placeholder);
  margin-top: 6px;
  padding-top: 5px;
  border-top: 1px solid var(--border-variant);
  word-break: break-word;
}

/* run detail tabs — Summary · Turns · Log · Report */
.rtabs {
  display: flex;
  gap: 3px;
  padding: 0 0 8px;
  border-bottom: 1px solid var(--border-variant);
  margin-bottom: 10px;
}
.rtab {
  font-size: 11.5px;
  padding: 3px 11px;
  color: var(--text-muted);
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 5px;
  cursor: pointer;
}
.rtab:hover { background: var(--element-hover); color: var(--text); }
.rtab.on { border-color: var(--text-accent); color: var(--text-accent); }
.rtab-body { display: none; }
.rtab-body.show { display: block; }

.turn {
  display: flex;
  gap: 8px;
  padding: 7px 10px;
  border-bottom: 1px solid var(--border-variant);
}

.turn:last-child { border-bottom: none; }
.turn .who { width: 48px; flex: none; color: var(--text-muted); font-size: 11px; padding-top: 1px; }
.turn.human .who { color: var(--text-accent); }
.turn .body { flex: 1; white-space: pre-wrap; word-break: break-word; font-size: 12px; }
.turn .body .chip { margin-right: 6px; }

/* ── .md — the one SafeMarkdown surface treatment ──────────────────────────
   Every place that renders agent/brief prose through FoundryWeb.SafeMarkdown
   (chat bubbles, queue cards, run turns, the playbook doc, the order proof)
   carries `md`, so the heading/list/code subset lands at ONE crisp small-type
   ladder (design.md §1) instead of the browser's huge defaults. Prose still
   flows on pre-wrap where the container sets it; these rules only tame the
   block tags this module introduces. */
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6 {
  margin: 6px 0 3px; font-weight: 700; line-height: 1.3; color: var(--text);
}
.md h1 { font-size: 14px; }
.md h2 { font-size: 13px; }
.md h3 { font-size: 12.5px; }
.md h4, .md h5, .md h6 {
  font-size: 11px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.08em;
}
.md ul, .md ol { margin: 3px 0; padding-left: 18px; }
.md li { margin: 1px 0; }
.md ul { list-style: disc; }
.md ol { list-style: decimal; }
.md code {
  font-family: "Zed Mono", ui-monospace, Menlo, monospace;
  font-size: 0.92em; background: var(--element);
  padding: 0 3px; border-radius: 3px;
}
.md pre {
  background: var(--element); border: 1px solid var(--border);
  border-radius: 4px; padding: 6px 8px; margin: 4px 0;
  overflow-x: auto; white-space: pre;
}
.md pre code { background: none; padding: 0; font-size: 11px; }
.md > :first-child { margin-top: 0; }
.md > :last-child { margin-bottom: 0; }

/* in flow, never fixed — the composer docks at the bottom of the place's main
   column (order AND source places) instead of floating over the log/right rail */
.composer {
  background: var(--surface);
  border-top: 1px solid var(--border);
  padding: 8px 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.composer textarea {
  width: 100%;
  min-height: 48px;
  resize: vertical;
  background: var(--editor);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 6px 8px;
  font: inherit;
  font-size: 12px;
}

.composer textarea:focus { outline: none; border-color: var(--text-accent); }
.composer-row { display: flex; align-items: center; gap: 6px; }

/* Stage 7 — the "saved exactly as written" receipt, shown when a draft-order button
   mints a verbatim Source from the originating turn. Carries Capture's retired copy. */
.saved-receipt {
  display: flex; align-items: center; gap: 8px;
  margin: 8px 0; padding: 8px 10px;
  border: 1px solid color-mix(in srgb, var(--success) 45%, var(--border));
  border-left: 3px solid var(--success);
  border-radius: 6px; font-size: 12px; line-height: 1.5;
}
.saved-receipt .rtext { color: var(--text-muted); }
.saved-receipt .rlink { color: var(--text-accent); text-decoration: none; }
.saved-receipt .rdismiss {
  margin-left: auto; background: none; border: none; cursor: pointer;
  color: var(--text-muted); font-size: 13px;
}

/* Stage 7 — automation legibility: the on/off switch and the overflow menu. */
.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.rule-switch {
  position: relative; width: 34px; height: 18px; flex: none; padding: 0; cursor: pointer;
  border: 1px solid var(--border); border-radius: 999px; background: var(--surface);
  transition: background .15s, border-color .15s;
}
.rule-switch .knob {
  position: absolute; top: 1px; left: 1px; width: 14px; height: 14px; border-radius: 50%;
  background: var(--text-muted); transition: transform .15s, background .15s;
}
.rule-switch.on { background: color-mix(in srgb, var(--success) 55%, var(--surface)); border-color: var(--success); }
.rule-switch.on .knob { transform: translateX(16px); background: #fff; }
.rule-switch-label { font-size: 11px; color: var(--text-muted); min-width: 18px; }

.overflow { display: inline-flex; }
.overflow .overflow-btn { padding: 2px 9px; line-height: 1; font-size: 14px; }
.overflow-menu {
  position: absolute; right: 0; top: calc(100% + 4px); z-index: 40; min-width: 130px;
  background: var(--elevated); border: 1px solid var(--border); border-radius: 6px;
  box-shadow: 0 4px 16px rgba(0, 0, 0, .28); padding: 4px; overflow: hidden;
}
.overflow-menu[hidden] { display: none; }
.overflow-menu .omenu-item {
  display: block; width: 100%; text-align: left; background: none; border: none;
  color: var(--text); font: inherit; font-size: 12px; padding: 5px 8px; border-radius: 4px; cursor: pointer;
}
.overflow-menu .omenu-item:hover { background: var(--element-hover); }
.overflow-menu .omenu-item.danger { color: var(--error); }

.tagpick {
  display: inline-flex;
  border: 1px solid var(--border);
  border-radius: 4px;
  overflow: hidden;
}

.tagpick button {
  white-space: nowrap;
  background: var(--element);
  border: none;
  border-right: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 11px;
  padding: 3px 8px;
  cursor: pointer;
}

.tagpick button:last-child { border-right: none; }
.tagpick button:hover { background: var(--element-hover); color: var(--text); }
.tagpick button[aria-pressed="true"] { background: var(--element-selected); color: var(--text); }

.btn {
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 11px;
  padding: 3px 10px;
  cursor: pointer;
}

.btn:hover { background: var(--element-hover); }
.btn:disabled { color: var(--text-placeholder); cursor: not-allowed; }
.btn.primary { border-color: var(--text-accent); color: var(--text-accent); }
/* .btn.primary is declared after .btn:disabled, so it won the cascade and a
   disabled primary kept its accent border and colour — reading as clickable-
   but-broken rather than not-yet. Muted here explicitly. */
.btn.primary:disabled { border-color: var(--border); color: var(--text-placeholder); }
.btn.danger:hover { border-color: var(--error); color: var(--error); }

.warn {
  color: var(--warning);
  font-size: 11px;
}

/* Each blocking run in the delete banner: its id + a small kill button, kept
   together and comfortably spaced so several read as a list, not a run-on. */
.delete-liverun {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-right: 12px;
}
.delete-liverun .btn { padding: 1px 8px; font-size: 11px; }

/* ── run detail ────────────────────────────────────────────────────────── */

.kv { display: grid; grid-template-columns: 116px 1fr; gap: 2px 10px; padding: 8px 14px; font-size: 12px; }
.kv dt { color: var(--text-muted); }
.kv dd { color: var(--text); word-break: break-all; }

.journal {
  margin: 0 14px 14px;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--editor);
  max-height: 340px;
  overflow: auto;
}

/* ── run log as a chat with the agent ─────────────────────────────────────
   The journal is the agent's own side of the conversation carried above it, so
   each event is a turn — a speech bubble for what it says, an action line for
   what it does, a quiet meta line for bookkeeping — left-aligned into the same
   who-gutter the human/agent turns use, not a monospaced event table. */
.jturn {
  display: flex;
  gap: 8px;
  padding: 3px 10px;
}

/* the gutter matches .turn's who column so the log stays in the conversation's
   left rail; the label reads only on speech, and actions cascade beneath it */
.jturn .who { width: 46px; flex: none; color: var(--text-muted); font-size: 10.5px; padding-top: 4px; }
.jturn .bubble { min-width: 0; display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px; }

/* speech — the agent talking: a soft bubble with a chat tail at top-left, sized
   to its content like a chat message (pre-wrap lives on the text, not the box,
   so HEEx's inter-tag whitespace doesn't leak in as a stray first-line indent) */
.jturn.say .bubble {
  display: block;
  width: fit-content;
  max-width: 78%;
  padding: 5px 9px;
  background: var(--element);
  border: 1px solid var(--border-variant);
  border-radius: 3px 10px 10px 10px;
  color: var(--editor-fg);
  font-size: 12px;
  line-height: 1.5;
}
.jturn.say .say { white-space: pre-wrap; word-break: break-word; }

/* action — a tool the agent reached for: verb · target · duration */
.jturn.act { padding: 0; }
.jturn.act .bubble { padding-top: 0; align-items: baseline; flex-wrap: nowrap; }
.jturn.act .verb { color: var(--hint); font-size: 10.5px; flex: none; min-width: 34px; }
.jturn.act .targ { color: var(--text-muted); font-size: 11px; word-break: break-all; }
.jturn.act .took { color: var(--hint); font-size: 10.5px; margin-left: 4px; white-space: nowrap; }

/* profile — the run's slowest commands, one line each: duration · tool · target */
.profile-row { display: flex; align-items: baseline; gap: 8px; padding: 3px 12px; font-size: 11px; }
.profile-row .took { color: var(--hint); min-width: 52px; text-align: right; white-space: nowrap; }
.profile-row .targ { color: var(--text-muted); word-break: break-all; }

/* meta — the system's voice: a glyph and a sentence, never raw JSON (the
   payload survives on the row's title hover) */
.jturn.meta .bubble { padding-top: 3px; align-items: baseline; }
.jturn.meta .glyph { flex: none; width: 14px; text-align: center; font-size: 11px; color: var(--hint); }
.jturn.meta .glyph.good { color: var(--success); }
.jturn.meta .glyph.warn { color: var(--warning); }
.jturn.meta .stext { color: var(--text-muted); font-size: 11.5px; }
.jturn.meta .sdetail { color: var(--hint); font-size: 10.5px; word-break: break-all; }

.artifact {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border-variant);
  font-size: 12px;
}

.artifact img {
  max-width: 100%;
  border: 1px solid var(--border);
  border-radius: 3px;
  display: block;
  margin: 6px 0;
}

/* a screenshot artifact in the place's artifacts card: the image shows inline,
   click to open it full-size in its own tab, the filename reads underneath. */
.card .shot { display: block; text-decoration: none; cursor: zoom-in; margin: 6px 0; }
.card .shot img { max-width: 100%; display: block; border: 1px solid var(--border); border-radius: 3px; }
.card .shot .cap { display: block; font-size: 10.5px; color: var(--text-muted); margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.filters { display: flex; gap: 4px; padding: 6px 10px; border-bottom: 1px solid var(--border-variant); flex-wrap: wrap; }

/* ── status bar ────────────────────────────────────────────────────────── */

.statusbar {
  display: flex;
  align-items: center;
  gap: 14px;
  height: 24px;
  padding: 0 10px;
  background: var(--title-bar);
  border-top: 1px solid var(--border);
  font-size: 11px;
  color: var(--text-muted);
}

.statusbar .live { color: var(--success); }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 5px; }

/* ── onboarding wizard (M10) ───────────────────────────────────────────── */

.wizard-pane { max-width: 640px; padding: 18px 22px; }

.wizard-title { font-size: 16px; font-weight: 600; margin-bottom: 6px; }

.wizard-caption { color: var(--text-muted); font-size: 12px; margin: 6px 0 12px; }
.wizard-caption code { color: var(--editor-fg); }

.card {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 14px;
  margin: 10px 0;
}

.card-actions { display: flex; justify-content: flex-end; margin-top: 10px; }

.field-label {
  display: block;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-placeholder);
  margin: 10px 0 4px;
}

.field {
  width: 100%;
  background: var(--editor);
  border: 1px solid var(--border);
  border-radius: 3px;
  color: var(--text);
  font: inherit;
  padding: 5px 8px;
}

.field:focus { outline: none; border-color: var(--text-accent); }

.segmented { display: inline-flex; border: 1px solid var(--border); border-radius: 4px; overflow: hidden; }

.segmented button {
  background: transparent;
  border: none;
  border-right: 1px solid var(--border);
  color: var(--text-muted);
  font: inherit;
  font-size: 12px;
  padding: 4px 14px;
  cursor: pointer;
}

.segmented button:last-child { border-right: none; }
.segmented button[aria-pressed="true"] { background: var(--element-selected); color: var(--text); font-weight: 600; }
.segmented button:disabled { color: var(--text-placeholder); cursor: not-allowed; }

.btn.fill { background: var(--info); border-color: var(--info); color: var(--editor); font-weight: 600; text-decoration: none; }
.btn.fill:hover { filter: brightness(1.08); background: var(--info); }
.btn.fill:disabled { background: var(--element); border-color: var(--border); color: var(--text-placeholder); filter: none; }

.step-dot {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--border);
  color: var(--text-muted);
  font-size: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.step-dot.current { border-color: var(--info); color: var(--info); }
.step-dot.done { border-color: var(--success); color: var(--success); }

.repo-line {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 2px;
  border-bottom: 1px solid var(--border-variant);
  font-size: 12px;
}

.repo-line .probe { color: var(--success); }

.repo-empty {
  color: var(--text-placeholder);
  font-size: 12px;
  line-height: 1.5;
  padding: 4px 2px 10px;
}
.repo-empty strong { color: var(--text-muted); }

.repo-count {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--success);
  padding: 2px 2px 8px;
  margin-bottom: 4px;
  border-bottom: 1px solid var(--border-variant);
}

.repo-add { display: flex; gap: 6px; margin-top: 10px; }
.repo-add .handle { width: 130px; flex: none; }

.tree {
  white-space: pre-wrap;
  background: var(--editor);
  color: var(--editor-fg);
  font-size: 12px;
  line-height: 1.6;
}

.toast {
  position: fixed;
  right: 16px;
  bottom: 36px;
  background: var(--elevated);
  border: 1px solid var(--success);
  color: var(--text);
  border-radius: 4px;
  padding: 8px 14px;
  font-size: 12px;
}

/* ── work-order queue (M12) ────────────────────────────────────────────── */

.queue { display: flex; flex-direction: column; height: 100%; background: var(--editor); }

.qhead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border-variant);
  background: var(--editor);
}

.qcols { display: flex; flex: 1; min-height: 0; }

.qcol { flex: 1; min-width: 0; border-right: 1px solid var(--border-variant); display: flex; flex-direction: column; }
.qcol:last-child { border-right: none; }

.qcolhead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border-variant);
}

.qbadge {
  font-size: 10px;
  padding: 0 6px;
  border-radius: 7px;
  background: var(--element-selected);
  color: var(--text-muted);
}

.qcolbody { flex: 1; overflow-y: auto; padding: 8px; }

.qempty {
  border: 1px dashed var(--border);
  border-radius: 4px;
  padding: 14px 10px;
  text-align: center;
  color: var(--text-placeholder);
  font-size: 12px;
}

.qcard {
  display: block;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 10px;
  margin-bottom: 8px;
  color: var(--text);
  text-decoration: none;
}

.qcard:hover { border-color: var(--text-accent); }

.qid { font-size: 10.5px; color: var(--text-accent); }
.qwhat { font-weight: 600; font-size: 12.5px; margin: 3px 0; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; }
.qmeta { color: var(--text-muted); font-size: 11px; display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.qrun { color: var(--text-muted); }

/* The bar holds the persistent controls (.qbar-main) — operational only, no
   transient notes. Kept as a column so the controls row lays out predictably. */
.qbar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 14px;
  border-top: 1px solid var(--border-variant);
  background: var(--surface);
}

/* controls (left, allowed to wrap internally) + spacer + capture button. The
   button is pinned to the top-right and never wraps under the controls, so it
   stays put as the primary action; align-items:flex-start keeps it at the top
   when the .tickbox beside it grows to two rows. */
.qbar-main {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}

/* ── the visible tick (M14) — countdown, slots, doorbell ───────────────── */

/* the controls themselves; at a normal width they sit on one line, and wrap
   gracefully only as a last resort on a very narrow window */
.tickbox { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; row-gap: 8px; min-width: 0; }

.tickbox .cd { font-size: 11.5px; color: var(--text-muted); }

.tickbox .cd b { color: var(--text); font-weight: 600; }

.btn.tick { border-color: var(--text-accent); color: var(--text-accent); }

/* the run-slot limit — the one form left on this bar. It sizes to its content
   instead of stretching across the row the 👁 watch form used to share. */
.slotlim { display: inline-flex; align-items: center; gap: 6px; }
.slotlim-input {
  width: 62px;
  background: var(--editor);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 11.5px;
  padding: 2px 6px;
}

.slots { display: flex; gap: 3px; align-items: center; }

/* scoped under .slots — the playbook's .layer.slot / .lg.slot are unrelated */
.slots .slot { width: 9px; height: 9px; border-radius: 2px; border: 1px solid var(--border); }

.slots .slot.busy { background: var(--warning); border-color: var(--warning); }

/* ── parked tray + honest evidence (M15) ───────────────────────────────── */

.qlink { display: block; color: var(--text); text-decoration: none; }

.evbadge {
  display: inline-block;
  margin-top: 5px;
  font-size: 10.5px;
  padding: 1px 7px;
  border-radius: 3px;
  border: 1px solid var(--border);
  background: var(--elevated);
  font: inherit;
  font-size: 10.5px;
  cursor: default;
}

.evbadge.ok { border-color: var(--success); color: var(--success); }
.evbadge.bad { border-color: var(--error); color: var(--error); cursor: pointer; }

/* the verbatim error is folded until the badge is clicked (JS.toggle_class) */
.errline {
  display: none;
  margin-top: 4px;
  padding: 3px 6px;
  font-size: 10px;
  color: var(--text-muted);
  background: var(--editor);
  border: 1px solid var(--border-variant);
  border-radius: 3px;
  white-space: pre-wrap;
}

.qcard.showerr .errline { display: block; }

.evacts { display: flex; align-items: center; gap: 6px; margin-top: 5px; }

.evacts .btn { font-size: 11px; padding: 2px 8px; }

/* The queue card's inline approve control: the Source page's segmented model
   picker, wrapped to fit the narrow column (the labels are long). */
.qcard .klabel { margin: 8px 0 4px; }
.qapprove-models { display: flex; flex-wrap: wrap; border: none; border-radius: 0; gap: 4px; }
.qapprove-models button { border: 1px solid var(--border); border-radius: 4px; font-size: 11px; padding: 2px 8px; }
.qapprove-models button[aria-pressed="true"] { border-color: var(--info); }
.qsrclink { margin-left: auto; font-size: 11px; color: var(--text-muted); text-decoration: underline dotted; }
.qsrclink:hover { color: var(--text); }

.tray { flex: none; border-top: 1px solid var(--border); background: var(--surface); }

.trayhead {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 14px;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-muted);
}

/* only the toggle half is a click-to-open target — the delete-all button is its own act */
.traytoggle { display: flex; align-items: center; gap: 8px; flex: 1; cursor: pointer; }

.traytoggle:hover { color: var(--text); }

.trayhead .btn { font-size: 11px; padding: 2px 8px; text-transform: none; letter-spacing: 0; }

.trayhead .pane-sub { text-transform: none; letter-spacing: 0; }

.trayhead .car { transition: transform 0.15s; display: inline-block; }

.tray.open .trayhead .car { transform: rotate(90deg); }

.traybody { display: none; flex-wrap: wrap; gap: 8px; padding: 4px 14px 10px; }

.tray.open .traybody { display: flex; }

.pk {
  width: 330px;
  padding: 7px 10px;
  background: var(--editor);
  border: 1px solid var(--border);
  border-radius: 5px;
}

/* layered parked card: title · 2-line summary · why · disclosed verbatim brief */
.pktitle { font-weight: 600; font-size: 12.5px; margin: 3px 0; color: var(--text); }

.pksum {
  font-size: 11px;
  color: var(--text-muted);
  margin: 2px 0;
  overflow: hidden;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}

.pkwhy { font-size: 10.5px; color: var(--modified); margin: 3px 0; }

/* the verbatim brief + park reason, one disclosure away — never lost, only folded */
.pkbrief { margin: 4px 0 2px; }
.pkbrief > summary { list-style: none; cursor: pointer; font-size: 11px; color: var(--text-accent); }
.pkbrief > summary::-webkit-details-marker { display: none; }
.pkbrief > summary:hover { text-decoration: underline; }
.pkbrief .klabel { margin: 8px 0 3px; }
.pkbrief .pkwhat { font-size: 11.5px; color: var(--text); margin: 2px 0; }
.pkreason { font-size: 11px; color: var(--text-muted); white-space: pre-wrap; }

/* Done's "all N →" fold: a quiet text-link that sits under the capped cards. */
.qmore { display: block; margin: 6px 2px 2px; font-size: 11px; }

/* the demoted delete-all: quiet and muted until hovered, then it reddens — a
   whisper with a confirm behind it, not a standing hazard. */
.traydelall { color: var(--text-muted); font-size: 11px; text-transform: none; letter-spacing: 0; }
.traydelall:hover { color: var(--error); text-decoration: underline; }

/* the WHY beside "0 claim(s) possible" — same muted register as the count. */
.claimwhy { color: var(--text-muted); }

/* ── capture composer (M12) ────────────────────────────────────────────── */

.capture { display: flex; align-items: center; justify-content: center; height: 100%; background: var(--editor); }

.reqcard { width: 560px; max-width: 92%; }

.capture textarea.field { resize: vertical; min-height: 110px; }

/* ── drafts beside the thread (M12) ────────────────────────────────────── */

.panel.drafts { width: 380px; min-width: 380px; }

.draft-card {
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
  margin: 8px;
  padding-bottom: 2px;
}

.dll {
  border-left: 2px solid var(--success);
  margin: 4px 10px;
  padding: 2px 8px;
  color: var(--text-muted);
  font-size: 11.5px;
}

/* ── the spaces shell (M16) — sidebar + place ──────────────────────────── */

.shell { display: flex; height: calc(100vh - 32px - 24px); min-height: 0; }
.shell-main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }

/* The automation surfaces size their grid rows to CONTENT (a definite height —
   even a max-height — makes the grid distribute rows instead, and the panels
   overlap). So the shell scrolls for them, which keeps the tall page above the
   status bar instead of painting over it. Scoped: no other page overflows. */
.shell-main:has(> #automation),
.shell-main:has(> #automation-rule) { overflow-y: auto; }

.sidebar {
  width: 232px;
  flex: none;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.sb-top { flex: 1; overflow-y: auto; padding: 10px; min-height: 0; }
.sb-bottom { height: 46%; flex: none; border-top: 1px solid var(--border); display: flex; flex-direction: column; min-height: 0; }
.sb-bottom .rows { flex: 1; overflow-y: auto; padding: 6px 10px 10px; }
.sb-empty { padding: 4px 8px; }
.sb-empty.nested { padding-left: 23px; }

/* ── shell-2: chat-first sidebar — new-chat button, one scroll, needs-you footer ── */
.newchat {
  display: flex; align-items: center; gap: 7px; flex: none;
  margin: 10px 10px 2px; padding: 4px 8px;
  border: 1px solid var(--border); border-radius: 4px; background: var(--element);
  font-size: 12px; color: var(--text); text-decoration: none;
}
.newchat:hover { background: var(--element-hover); border-color: var(--text-accent); color: var(--text-accent); }
.newchat .plus { color: var(--text-accent); }
.sb-scroll { flex: 1; overflow-y: auto; min-height: 0; padding: 0 6px 10px; }

/* rail-3: TWO half-height panes — work & plans above, chats below (decision of record,
   2026-08-17). Each pane pins its section title and scrolls only its rows, so a long
   work list can never push chats off-screen and both titles stay reachable. */
.sb-pane { flex: 1 1 50%; min-height: 0; display: flex; flex-direction: column; padding: 0 6px; }
.sb-pane + .sb-pane { border-top: 1px solid var(--border); }
.sb-pane > .sb-sect { flex: none; }
.sb-pane .sb-rows { flex: 1; min-height: 0; overflow-y: auto; padding-bottom: 8px; }

/* actionable empty state: a dashed block that says what the thing is and offers the
   one next action — not inherited body text. */
.sb-empty-block {
  border: 1px dashed var(--border); border-radius: 6px; padding: 10px; margin: 2px 0 4px;
  font-size: 11.5px; color: var(--text-muted);
}
.sb-empty-block .cta { display: inline-block; margin-top: 5px; color: var(--text-accent);
  text-decoration: none; font-weight: 600; }
.sb-empty-block .cta:hover { text-decoration: underline; }

/* the plan glyph: a roadmap (lines + milestone dot), inline currentColor SVG */
.planrow .picon { flex: none; width: 12px; height: 12px; color: var(--hint); }
.planrow .ttl { font-weight: 600; }
/* children hang off a guide line, titles muted — group vs child reads at a glance */
.worow.nested { margin-left: 13px; padding-left: 14px; border-left: 1px solid var(--border-variant);
  border-radius: 0 5px 5px 0; }

/* selection gets the accent bar, not just a background tint — "where am I" is unambiguous */
.worow, .sessrow { position: relative; }
.worow.on::before, .sessrow.on::before {
  content: ""; position: absolute; left: -4px; top: 5px; bottom: 5px;
  width: 2px; border-radius: 2px; background: var(--text-accent);
}
/* a plan and its nested stage orders — one group, the orders indented under the plan row */
.sidebar .plangroup { margin-bottom: 2px; }
.sidebar .planrow {
  display: flex; align-items: center; gap: 6px;
  padding: 5px 8px; border-radius: 5px; margin-bottom: 1px;
  font-size: 12px; color: var(--text); text-decoration: none;
}
.sidebar .planrow:hover { background: var(--element-hover); }
.sidebar .planrow .tri { color: var(--text-placeholder); }
.sidebar .planrow .tri svg { width: 11px; height: 11px; }
.sidebar .planrow .ttl { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar .planrow .pill { flex: none; margin-left: auto; }
.sidebar .worow.nested { padding-left: 23px; }
.sidebar .worow.nested .t .ttl { color: var(--text-muted); }
/* the flat one-off bucket's quiet sub-label */
.sb-sub { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-placeholder); margin: 8px 2px 4px; }
/* the needs-you footer: pinned below the scroll, the retired rail's attention as one count */
.navrow.needs-you { flex: none; border-top: 1px solid var(--border); margin: 0; }

.sb-sect {
  display: flex; align-items: center; gap: 6px;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); font-weight: 600; margin: 12px 0 6px; padding: 0 2px;
}
.sb-bottom .sb-sect { margin: 10px 10px 0; flex: none; }
.sb-sect .n { background: var(--element-selected); border-radius: 7px; padding: 0 6px; font-size: 10px; }
.sb-sect .all { color: var(--text-accent); text-decoration: none; font-weight: 400; text-transform: none; letter-spacing: 0; visibility: hidden; }
.sb-sect:hover .all { visibility: visible; }

.navrow {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 8px; border-radius: 5px; font-size: 12px;
  color: var(--text); text-decoration: none;
}
.navrow:hover { background: var(--element-hover); }
.navrow .n { margin-left: auto; background: var(--element-selected); border: 1px solid var(--border); border-radius: 7px; padding: 0 6px; font-size: 10px; color: var(--text-muted); }
.navrow .n.hot { background: var(--warning); border-color: var(--warning); color: var(--editor); }

.worow { display: block; padding: 5px 8px; border-radius: 5px; margin-bottom: 1px; color: var(--text); text-decoration: none; }
.worow:hover { background: var(--element-hover); }
.worow.on { background: var(--element-selected); }
/* Words only: the `what` sentence is the row — no id, the label carries identity. */
.worow .t { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.worow .t .ttl { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.worow .t .pill { flex: none; margin-left: auto; }

.sdot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.sdot.hold { background: var(--info); }
.sdot.in_progress { background: var(--warning); }
.sdot.approved { background: var(--info); }
.sdot.draft { background: var(--text-muted); }
.sdot.done { background: var(--success); }
.sdot.parked { background: var(--text-placeholder); }

.sessrow { display: block; padding: 5px 8px; border-radius: 5px; margin-bottom: 1px; color: var(--text); text-decoration: none; }
.sessrow:hover { background: var(--element-hover); }
.sessrow.on { background: var(--element-selected); }
/* The /sessions list row reads title-first: the stored title grows, the short id demotes to
   small muted mono metadata beside it (design-legibility rule — no raw id as the primary label). */
.sesslist-row { display: flex; align-items: center; gap: 8px; }
.sesslist-row .sess-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sesslist-row .sid { flex: none; color: var(--text-muted); font-size: 10.5px; }
.sesslist-row .pill { flex: none; }
/* Words lead: the readable title is the primary line, the type · status label below — no ids. */
.sessrow .t { display: flex; align-items: center; gap: 6px; font-size: 12px; }
.sessrow .t .ttl { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--text); }
.sessrow .sub { font-size: 10px; color: var(--text-muted); margin-top: 1px; padding-left: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sessrow.working .t .ttl { animation: shimmer 1.6s infinite; }
@keyframes shimmer { 50% { opacity: 0.45; } }
/* Working-now: a running/awake row whose journal has FLATLINED reads as stalled — the shimmer
   stops and the pulsing dot freezes to a static muted one, so a silently-dead run no longer looks
   identical to one actively writing. Purely visual (journal mtime); it triggers no cluster act. */
.sessrow.wn-stalled .t .ttl { animation: none; opacity: 1; }
.sessrow.wn-stalled .rdot.running { animation: none; background: var(--text-muted); box-shadow: 0 0 0 2px color-mix(in srgb, var(--warning) 30%, transparent); }
.bell { font-size: 10px; }
.bell.soft { opacity: 0.6; }

.rdot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
.rdot.done { background: var(--success); }
.rdot.running { background: var(--warning); animation: pulse 1.2s infinite; }
.rdot.needs_input { background: var(--error); animation: pulse 1.2s infinite; }
.rdot.failed { background: var(--error); }
.rdot.interrupted { background: var(--text-muted); }
.rdot.created { background: var(--text-muted); }
/* shell-2: a chat's folded attention — a waiting report rings amber, an asleep chat dims. */
.rdot.attention { background: var(--warning); animation: pulse 1.2s infinite; }
.rdot.idle { background: var(--text-placeholder); }
@keyframes pulse { 50% { opacity: 0.3; } }

/* The working-now chip (order live feed + session header). `.on` writes live (a soft shimmer);
   `.stalled` freezes to a muted-amber outline that does not animate — flatline reads as flatline. */
.worknow { font-size: 10px; letter-spacing: .02em; padding: 0 5px; border-radius: 4px; flex: none; }
.worknow.on { color: var(--success); animation: shimmer 1.6s infinite; }
.worknow.stalled { color: var(--warning); border: 1px solid var(--warning); }
.pill.wn-stalled { border-color: var(--warning); color: var(--warning); }
/* rail-3: a held loose order's status pill lights warning — the band-1 treatment */
.pill.hot { border-color: var(--warning); color: var(--warning); }

/* ── the place ─────────────────────────────────────────────────────────── */

.place { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; background: var(--editor); }
.pagehead { display: flex; align-items: center; gap: 10px; padding: 9px 14px; border-bottom: 1px solid var(--border); flex: none; flex-wrap: wrap; }
.pagehead h2 { font-size: 13px; }
.place-what { color: var(--text); font-weight: 500; }
.place-title { color: var(--text); font-weight: 500; min-width: 0; max-width: 52ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* An id is metadata, never the primary label: small, muted, mono, beside the title it annotates
   (design-legibility rule — "mono for ids and paths"). Used in header rows and the run pane. */
.metatag { color: var(--text-muted); font-size: 11px; font-weight: 400; }
.crumb { font-size: 11px; color: var(--text-muted); display: flex; align-items: center; gap: 6px; }
.lin { color: var(--text-accent); text-decoration: none; cursor: pointer; background: none; border: none; font: inherit; padding: 0; }
.lin:hover { text-decoration: underline; }
/* copy-path sits on the pagehead baseline at the from-crumb's size — a text
   control in the head, not a button of its own (colour comes from .lin, so it
   follows the accent in both themes). */
.pagehead .copypath { font-size: 11px; white-space: nowrap; }

.cols { flex: 1; display: flex; min-height: 0; }
.wsrail { width: 220px; flex: none; border-right: 1px solid var(--border-variant); overflow-y: auto; padding: 10px; }
.rrail { width: 262px; flex: none; border-left: 1px solid var(--border-variant); overflow-y: auto; padding: 10px; background: var(--surface); }
.main { flex: 1; min-width: 0; display: flex; flex-direction: column; min-height: 0; }

.klabel { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); margin: 12px 0 5px; font-weight: 600; }
.wsrail .klabel:first-child { margin-top: 0; }

.srccard { border: 1px solid var(--border); border-radius: 5px; padding: 8px 9px; background: var(--surface); font-size: 11px; }
.srcbody { margin-top: 5px; white-space: pre-wrap; color: var(--text); }
.srctoggle { display: block; margin-top: 4px; font-size: 10.5px; }

.runrow { border: 1px solid var(--border); border-radius: 5px; padding: 6px 9px; margin-bottom: 6px; cursor: pointer; background: var(--surface); }
.runrow:hover { border-color: var(--text-accent); }
.runrow.on { border-color: var(--text-accent); background: var(--element-hover); }
.runrow .t { display: flex; align-items: center; gap: 6px; min-width: 0; }
/* the run id is the row's handle — it never wraps or shrinks; longer siblings give way */
.runrow .t .rid { flex: none; white-space: nowrap; }
.runrow .sub { font-size: 10.5px; color: var(--text-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the model reads last and quiet — free to wrap, since nothing sits beside it */
.runrow .runmodel { font-size: 10px; color: var(--text-placeholder); margin-top: 3px; overflow-wrap: anywhere; }

/* the human's note on a run — annotation, quiet and italic wherever it reads:
   the place rail row, the sidebar session row, the runs-page list row */
.runrow .note, .sessrow .note, .row-note { font-size: 10.5px; font-style: italic; color: var(--text-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-note { margin-top: 3px; }
.notebtn { flex: none; background: none; border: none; padding: 0 2px; border-radius: 3px; cursor: pointer; font-size: 11px; line-height: 1; color: var(--text-muted); }
.notebtn:hover { color: var(--text-accent); }
.noteform { display: flex; align-items: center; gap: 4px; margin-top: 5px; }
.noteform input[type="text"] { flex: 1; min-width: 0; background: var(--background); border: 1px solid var(--border); border-radius: 4px; color: var(--text); font: inherit; font-size: 11px; padding: 3px 6px; outline: none; }
.noteform input[type="text"]:focus { border-color: var(--text-accent); }
.noteform .btn { flex: none; }

/* the conversation's opening line — the old mainhead bar, demoted into the
   chat: same facts (dot · id · type · echo · elapsed · kill), no header box */
.convo-open { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-muted); min-width: 0; }
.convo-open .rid { white-space: nowrap; flex: none; }
.convo-open .hint { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.convo-open .lapse { color: var(--text-muted); white-space: nowrap; font-size: 11px; }
.turns { flex: 1; overflow-y: auto; padding: 12px 14px; min-height: 0; }
/* The who-label sits ON TOP of the message, not in a fixed left column — the body
   gets the full width, which matters in the narrow thread rail. */
.turn { display: flex; flex-direction: column; gap: 3px; padding: 8px 12px; border-bottom: 1px solid var(--border-variant); font-size: 12px; }
.turn .who { width: auto; flex: none; color: var(--text-muted); font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; padding-top: 0; }
.turn .body { flex: none; min-width: 0; }

/* ── the thread as a CHAT (.turns.chat — the place's thread pane) ────────
   One chronological stream, newest at the bottom (ScrollToEnd keeps it
   pinned): you on the right in the accent, the agent on the left, the
   system's bookkeeping as quiet glyph lines between them. Nothing folds. */
.turns.chat { display: flex; flex-direction: column; gap: 10px; }
.turns.chat .turn { padding: 0; border-bottom: none; max-width: 88%; }
.turns.chat .turn .who { display: flex; gap: 6px; align-items: baseline; }
.turns.chat .turn .who .when { font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--hint); font-size: 10px; }
.turns.chat .turn .body {
  width: fit-content;
  background: var(--surface); border: 1px solid var(--border-variant);
  border-radius: 3px 10px 10px 10px;
  padding: 7px 11px; line-height: 1.55;
  /* pre-wrap lives on .btext, not the box — see the .jturn.say note */
  white-space: normal;
}
.turns.chat .turn .body .btext { white-space: pre-wrap; word-break: break-word; }

/* you: right-aligned, tinted by the accent — the chat side-switch */
.turns.chat .turn.human { align-self: flex-end; align-items: flex-end; }
.turns.chat .turn.human .who { color: var(--text-accent); }
.turns.chat .turn.human .body {
  background: color-mix(in srgb, var(--text-accent) 10%, var(--editor));
  border-color: color-mix(in srgb, var(--text-accent) 30%, var(--border-variant));
  border-radius: 10px 3px 10px 10px;
}

/* ── the SLACK provenance chips ───────────────────────────────────────────
   A Slack session's turns carry two facts a reader needs at a glance: an inbound
   turn ARRIVED from a channel (and from whom), an outbound one was POSTED to it.
   They used to be bare text inheriting `.who` — uppercase, muted, no box — so a
   link read as a label, and "→ slack failed" read the same as "→ slack". Chips
   now, and coloured by direction and outcome: neutral inbound, success for a
   delivered post, error for one that never reached the channel. */
.turns.chat .turn .who .via,
.turns.chat .turn .who .who-ext {
  font-size: 9.5px; font-weight: 600; letter-spacing: 0.02em; text-transform: none;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  padding: 1px 6px; border-radius: 3px; border: 1px solid transparent;
  text-decoration: none; white-space: nowrap; flex: none;
}
.turns.chat .turn .who .via.in {
  color: var(--text-muted); background: var(--element); border-color: var(--border-variant);
}
.turns.chat .turn .who a.via.in:hover { color: var(--text-accent); border-color: var(--text-accent); }
.turns.chat .turn .who .via.out {
  color: var(--success);
  background: color-mix(in srgb, var(--success) 12%, transparent);
  border-color: color-mix(in srgb, var(--success) 40%, transparent);
}
.turns.chat .turn .who a.via.out:hover { background: color-mix(in srgb, var(--success) 22%, transparent); }
.turns.chat .turn .who .via.failed {
  color: var(--error);
  background: color-mix(in srgb, var(--error) 12%, transparent);
  border-color: color-mix(in srgb, var(--error) 45%, transparent);
}
/* the SENDER, when Slack gave us only a `U…` id: a link that resolves the person in
   the reader's own Slack, since Foundry holds no `users:read` to name them here. */
.turns.chat .turn .who a.who-ext { color: var(--text-accent); padding: 0; }
.turns.chat .turn .who a.who-ext:hover { text-decoration: underline; }

/* shell-3 — the machine's voice IN the chat: delivery notices and kernel/external
   lines demote to a quiet glyph sentence between the bubbles, never a chat box. */
.turns.chat .jmeta { align-self: stretch; max-width: 100%; display: flex; gap: 8px; align-items: baseline; padding: 0 2px; }
.turns.chat .jmeta .glyph { flex: none; width: 14px; text-align: center; font-size: 11px; color: var(--hint); }
.turns.chat .jmeta .glyph.warn { color: var(--warning); }
.turns.chat .jmeta .stext { color: var(--text-muted); font-size: 11.5px; }
.turns.chat .jmeta .when { color: var(--hint); font-size: 10px; margin-left: auto; }

/* shell-3 — the creation receipt: a compact card in the stream at the moment a plan,
   order or artifact was minted; clicking opens it. The app's own card idiom. */
.turns.chat .made { align-self: flex-start; display: flex; align-items: center; gap: 8px; width: fit-content; max-width: 88%; text-decoration: none;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface); padding: 6px 9px; }
.turns.chat a.made:hover { border-color: var(--text-accent); }
.turns.chat .made .ttl { font-size: 12px; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.turns.chat .made .sub { font-size: 10.5px; color: var(--text-muted); flex: none; }
.turns.chat .made .go { color: var(--text-placeholder); font-size: 11px; flex: none; }
.turns.chat a.made:hover .go { color: var(--text-accent); }

/* shell-3 — the "from this chat" rail: one card per minted object, live status on the
   sub line. Reuses the 262px .rrail slot; a plain div card for a placeless run. */
.rrail .railcard { display: block; width: 100%; text-align: left; text-decoration: none;
  border: 1px solid var(--border); border-radius: 5px; padding: 6px 9px; margin-bottom: 6px; background: var(--surface); }
.rrail a.railcard:hover { border-color: var(--text-accent); }
.rrail .railcard .t { display: flex; align-items: center; gap: 6px; font-size: 12px; min-width: 0; }
.rrail .railcard .t .ttl { flex: 1; min-width: 0; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rrail .railcard .sub { display: block; font-size: 10.5px; color: var(--text-muted); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rrail .rail-empty { border: 1px dashed var(--border); border-radius: 5px; padding: 12px 10px; font-size: 11px; color: var(--text-placeholder); text-align: center; }

/* ── the rail's ORIGIN card: WHERE THIS SESSION CAME FROM ──────────────────
   For a Slack thread this is the fact that makes the session different from every
   other chat, and the rail carried none of it. The accent edge marks it as
   provenance rather than something this chat minted. */
.rrail .origin { margin-bottom: 14px; }
.rrail .origin-card {
  border: 1px solid var(--border); border-left: 2px solid var(--info);
  border-radius: 5px; padding: 7px 9px; background: var(--surface);
}
.rrail .origin-card .t { display: flex; align-items: center; gap: 6px; margin-bottom: 4px; min-width: 0; }
.rrail .origin-card .t .ws { font-size: 10.5px; color: var(--text-muted); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rrail .origin-card .k { font-size: 10.5px; color: var(--text-muted); line-height: 1.55; }
.rrail .origin-card .k b { color: var(--text); font-weight: 600; }
.rrail .origin-card .fail { color: var(--error); }
.rrail .origin-card .fail.none { color: var(--text-muted); }
.rrail .origin-card .origin-open { display: inline-block; margin-top: 6px; font-size: 11px; color: var(--text-accent); text-decoration: none; }
.rrail .origin-card .origin-open:hover { text-decoration: underline; }

/* the channel chip — the same word in the origin card and on the sidebar's chat row,
   so "this chat is #social" reads identically wherever you meet it */
.chip.slack {
  border-color: var(--info); color: var(--info);
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
}
.sessrow .t .chip.slack { flex: none; max-width: 46%; overflow: hidden; text-overflow: ellipsis; }

/* shell-3b — the tool-call audit affordance: a quiet rail link, not a card and not a
   header button (a machine surface demotes onto the rail). */
.rrail .rail-audit { display: flex; align-items: center; gap: 6px; margin-top: 10px; padding: 6px 9px;
  border: 1px dashed var(--border); border-radius: 5px; font-size: 11px; color: var(--text-muted);
  text-decoration: none; }
.rrail a.rail-audit:hover { border-color: var(--text-accent); color: var(--text); }
.rrail .rail-audit .glyph { color: var(--text-placeholder); }
.rrail .rail-audit .go { margin-left: auto; color: var(--text-placeholder); }

/* shell-3b — the tool-call audit surface: read-only, most-recent-first table. */
.audit-log { width: 100%; border-collapse: collapse; font-size: 12px; }
.audit-log th { text-align: left; font-weight: 500; color: var(--text-muted); font-size: 10.5px;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 6px 10px; border-bottom: 1px solid var(--border); }
.audit-log td { padding: 6px 10px; border-bottom: 1px solid var(--border-variant); vertical-align: top; }
.audit-log tr.tc.error td { background: color-mix(in srgb, var(--danger, #b00) 6%, transparent); }
.audit-log .when { color: var(--text-muted); white-space: nowrap; }
.audit-log .ctx { color: var(--text-muted); white-space: nowrap; }
.audit-log .ctx .dim { color: var(--text-placeholder); }
.audit-log .summary { color: var(--text); max-width: 360px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.audit-log .pill.ok { color: var(--text-muted); }
.audit-log .pill.err { color: var(--danger, #b00); }

/* art-3 — the artifact panel: the agent-authored page beside the stream. A middle
   column between the chat and the "from this chat" rail; present only when the chat
   has minted a page. Preview frames the served (sandboxed) file; source shows bytes;
   version chips walk the lineage. */
.apanel { width: 420px; flex: none; border-left: 1px solid var(--border-variant); background: var(--surface);
  display: flex; flex-direction: column; min-height: 0; }
.apanel-head { display: flex; align-items: center; gap: 7px; padding: 9px 10px; border-bottom: 1px solid var(--border-variant); flex: none; }
.apanel-title { font-size: 12px; font-weight: 500; color: var(--text); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.apanel-pages { display: flex; flex-wrap: wrap; gap: 5px; padding: 8px 10px 0; flex: none; }
.apanel-pages .pagechip { max-width: 15ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.apanel-versions { display: flex; flex-wrap: wrap; gap: 5px; padding: 8px 10px; flex: none; }
.pagechip, .vchip { font: inherit; font-size: 11px; padding: 2px 9px; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border); background: var(--element); color: var(--text-muted); }
.pagechip:hover, .vchip:hover { border-color: var(--text-accent); }
.pagechip.on, .vchip.on { border-color: var(--text-accent); color: var(--text-accent); background: var(--element-hover); }
.apanel-toggle { display: flex; gap: 0; padding: 0 10px 8px; flex: none; }
.apanel-toggle .seg { font: inherit; font-size: 11px; padding: 4px 12px; cursor: pointer; border: 1px solid var(--border); background: var(--element); color: var(--text-muted); }
.apanel-toggle .seg:first-child { border-radius: 5px 0 0 5px; }
.apanel-toggle .seg:last-child { border-radius: 0 5px 5px 0; border-left: none; }
.apanel-toggle .seg.on { background: var(--element-hover); color: var(--text-accent); border-color: var(--text-accent); }
.apanel-body { flex: 1; min-height: 0; padding: 10px; display: flex; }
/* the preview fills the WHOLE body — flex-grow on the main axis, 100% on the cross axis so an
   iframe (which won't stretch on its own like a text block does) takes all the height too. */
.apanel-frame { flex: 1; width: 100%; height: 100%; border: 1px solid var(--border); border-radius: 5px; background: #fff; }
.apanel-source { flex: 1; margin: 0; overflow: auto; border: 1px solid var(--border); border-radius: 5px;
  padding: 9px 10px; font-size: 11.5px; line-height: 1.5; color: var(--text); background: var(--editor); white-space: pre-wrap; word-break: break-word; }

/* art-3 push-panel — the session view is a THREE-track grid (chat | rail | panel) whose column
   widths ANIMATE, so opening the panel PUSHES the layout aside (Cursor-style) rather than
   floating over it. Closed = two columns (chat + the 262px rail), the panel track 0 and empty —
   the old permanently-docked artifact column is gone. Open = the rail collapses to 0 and the chat
   narrows to give the panel a real column. Full = chat and rail both collapse and the panel takes
   the whole width. No scrim, no overlay: the chat stays visible and interactive throughout. This
   overrides the flex `.cols` base for the session view only. */
.cols.session {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 262px 0px;
  transition: grid-template-columns .26s cubic-bezier(.32, .72, 0, 1);
}
.cols.session.open { grid-template-columns: minmax(0, 1fr) 0px clamp(440px, 48%, 760px); }
.cols.session.open.full { grid-template-columns: 0px 0px minmax(0, 1fr); }
/* the tracks govern width — the children give up their fixed widths and clip when their track
   collapses to 0, so the push reads as one smooth motion with nothing spilling out. */
.cols.session > .main { width: auto; min-width: 0; overflow: hidden; }
.cols.session > .rrail { width: auto; min-width: 0; }
.cols.session > .apanel { width: auto; min-width: 0; overflow: hidden; }
@media (prefers-reduced-motion: reduce) {
  .cols.session { transition: none; }
}

/* the panel header's icon controls — download · expand-to-full · close — pushed to the right
   edge. Real SVG icons (not glyphs), sized to the header type; the expand icon swaps to a
   collapse icon while full. */
.apanel-ctl { display: inline-flex; align-items: center; justify-content: center; padding: 4px;
  cursor: pointer; background: none; border: 1px solid transparent; border-radius: 5px;
  color: var(--text-muted); text-decoration: none; }
.apanel-ctl:hover { color: var(--text-accent); border-color: var(--border); background: var(--element); }
.apanel-ctl svg { width: 15px; height: 15px; stroke-width: 1.8; display: block; }

/* the rail's artifact PAGE items — rail cards that OPEN the push panel (a button, not a link),
   the open one accented so the rail marks which page the panel is showing. */
.rrail .rail-artifacts { margin-bottom: 4px; }
.rrail button.railcard { font: inherit; cursor: pointer; color: inherit; }
.rrail button.railcard:hover { border-color: var(--text-accent); }
.rrail .railcard.art.on { border-color: var(--text-accent); background: var(--element-hover); }
.rrail .railcard.art .sub { text-transform: none; }

/* art-3 — the composer's iterate hint, beside attach-image: names that the next
   reply supersedes the panel's current version. Quiet, non-interactive. */
.iterate-hint { font-size: 11px; color: var(--text-accent); display: inline-flex; align-items: center; gap: 4px; white-space: nowrap; }

/* a run boundary: a divider in the one conversation, not a new pane */
.runmark { display: flex; align-items: center; gap: 10px; color: var(--hint); font-size: 10.5px; margin: 4px 0 0; }
.runmark::before, .runmark::after { content: ""; flex: 1; border-top: 1px solid var(--border-variant); }
.runmark .mono { color: var(--text-muted); }

/* the agent's actions — clustered under a thin rail, every line visible */
.acts { align-self: flex-start; max-width: 88%; display: flex; flex-direction: column; gap: 2px; border-left: 2px solid var(--border-variant); padding-left: 10px; margin-left: 2px; }
.acts .actlabel { font-size: 10px; color: var(--hint); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; margin-bottom: 1px; }

.composer { flex: none; position: sticky; bottom: 0; border-top: 1px solid var(--border); padding: 9px 14px; background: var(--surface); }
.composer textarea { width: 100%; background: var(--input-bg, var(--editor)); border: 1px solid var(--border); border-radius: 4px; color: var(--text); font: 12px/1.4 inherit; padding: 7px 9px; resize: none; height: 48px; }
.tagrow { display: flex; align-items: center; gap: 6px; margin-top: 6px; }
.tagpick { display: inline-flex; gap: 6px; }
.tagpick button { font-size: 10.5px; border: 1px solid var(--border); border-radius: 3px; padding: 1px 8px; cursor: pointer; color: var(--text-muted); background: none; }
.tagpick button[aria-pressed="true"] { border-color: var(--modified); color: var(--modified); }
.warn { color: var(--warning); font-size: 11px; }

.card { border: 1px solid var(--border); border-radius: 6px; padding: 9px 11px; margin-bottom: 10px; background: var(--surface); }
/* Long content (the work order's what, a source verbatim) caps here and scrolls
   inside the card rather than pushing the rail's other cards off-screen. */
.card.scrollcap { max-height: 340px; overflow-y: auto; }
.card h3 { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-weight: 600; margin-bottom: 6px; }
.card-what { font-size: 12px; color: var(--text); }
.card .t { display: flex; align-items: center; gap: 6px; }
.sha { display: flex; justify-content: space-between; align-items: center; font-size: 11px; padding: 2px 0; gap: 8px; }
.evrow { display: flex; gap: 8px; margin-top: 7px; }
.hold-card { border-color: var(--info); }
.hold-card h3 { color: var(--info); }

/* Data-heavy orders must not widen the page. .card.scrollcap only caps VERTICAL
   height; on the order place (the .rrail cards) long unbroken content — a cite
   path, a URL in the what/done-looks-like, a long branch name in a .sha row —
   otherwise stays one wide token and pushes the fixed 262px rail open sideways.
   Wrap/contain it inside the card, and clip the rail's horizontal overflow as a
   backstop. Wrapping only engages when a token is actually wider than the card,
   so short-data orders look unchanged. */
.rrail { overflow-x: hidden; }
.rrail .card-what { overflow-wrap: anywhere; word-break: break-word; }
.rrail .chip.mono { max-width: 100%; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
.rrail .sha { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.rrail .sha > * { min-width: 0; }

/* The left rail needs the same containment: on a source place the SOURCE
   (VERBATIM) card lives in the fixed 220px .wsrail, so anything wider than the
   card — an attached screenshot, most visibly — crossed the card's right border
   and put a horizontal scrollbar under the whole rail. Wrap what can wrap, then
   clip as a backstop; the .turn-atts rule below is what makes the image itself
   fit. The run row's model pill is nowrap by design, so it ellipsizes rather
   than pushing the row's ✎ button out past the clip. */
.wsrail { overflow-x: hidden; }
.wsrail .card-what { overflow-wrap: anywhere; word-break: break-word; }
.wsrail .chip.mono { max-width: 100%; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
.wsrail .sha { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.wsrail .sha > * { min-width: 0; }
.wsrail .runrow .t { min-width: 0; }
.wsrail .runrow .pill.model { min-width: 0; overflow: hidden; text-overflow: ellipsis; display: block; }

/* ── source place → a REVIEW SPACE ─────────────────────────────────────────
   Work-order-local IA: on a source's own place the drafted work orders and the
   intake run's open questions ARE the subject, so they get a wide, comfortable
   review column (the .rrail, promoted out of its 262px cramp), while the intake
   run's transcript is demoted to a narrower supporting pane (.main). Reordered
   with flex `order` so no DOM moves — scoped to .cols.source so the order place
   is untouched. */
.cols.source .wsrail { order: 1; }
.cols.source .rrail {
  order: 2;
  flex: 1;
  width: auto;
  min-width: 0;
  border-left: none;
  border-right: 1px solid var(--border-variant);
  background: var(--editor);
  padding: 16px 20px;
}
.cols.source .main {
  order: 3;
  flex: none;
  width: 360px;
  min-width: 300px;
  background: var(--surface);
}

/* the demoted transcript names itself — support, not the thing under review */

/* the review column reads as cards, not a rail: generous spacing, clear order */
.review-label { font-size: 11px; color: var(--text); margin: 0 0 12px; }
.card.draft { padding: 13px 15px; margin-bottom: 13px; }
.card.draft .t { margin-bottom: 2px; }
.card.draft .card-what { font-size: 13.5px; line-height: 1.45; font-weight: 500; }
.card.draft .klabel { margin: 11px 0 4px; }
.card.draft .dll { font-style: normal; color: var(--text); }
.card.draft .chip { display: inline-block; margin: 0 4px 4px 0; }
.card.draft .evrow { margin-top: 13px; }

/* ── overview (M16) ────────────────────────────────────────────────────── */

.overview { flex: 1; overflow-y: auto; padding: 16px 20px; background: var(--editor); }
.ov-title { font-size: 14px; color: var(--text); margin-bottom: 12px; }
.ovgrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; max-width: 1100px; }
.ovrow { display: flex; justify-content: space-between; align-items: center; gap: 8px; font-size: 11.5px; padding: 3px 0; color: var(--text); text-decoration: none; }
.ovrow:hover .lin { text-decoration: underline; }
/* Title leads the overview row; the id stays a small mono tag pinned to the right. */
.ovtitle { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.card .big { font-size: 26px; font-weight: 600; color: var(--text); margin: 2px 0 4px; }
.ov-foot { margin-top: 12px; }

/* ── the playbook (M17) — read the doc you keep voting on ───────────────── */

.playbook { flex: 1; display: flex; min-height: 0; background: var(--editor); }

.pb-files { width: 250px; flex: none; background: var(--surface); border-right: 1px solid var(--border); overflow-y: auto; }
.pb-files .klabel { padding: 10px 12px 2px; margin: 0; }
.pb-group { border-top: 1px solid var(--border-variant); }
.pb-group:first-child { border-top: none; }
.ksub { padding: 0 12px 6px; font-size: 10.5px; line-height: 1.4; color: var(--text-muted); }

.frow { display: flex; align-items: center; gap: 8px; padding: 7px 12px; font-size: 12px; cursor: pointer; color: var(--text); }
.frow:hover { background: var(--element-hover); }
.frow.on { background: var(--element-selected); color: var(--text); }
.frow .der { margin-left: auto; font-size: 9px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--modified); border: 1px solid var(--border); border-radius: 3px; padding: 0 4px; }

.commit { padding: 6px 12px; border-bottom: 1px solid var(--border-variant); cursor: pointer; font-size: 11px; }
.commit:hover { background: var(--element-hover); }
.commit.on { background: var(--element-selected); }
.commit .chead { display: flex; align-items: center; gap: 4px; }
.commit .sha { color: var(--text-accent); font-size: 10px; }
.commit .csub { color: var(--text-muted); margin-top: 1px; }
.commit .k { font-size: 9.5px; text-transform: uppercase; border: 1px solid var(--border); border-radius: 3px; padding: 0 4px; }
.commit .k.process { color: var(--info); border-color: var(--info); }
.commit .k.config { color: var(--success); border-color: var(--success); }
.commit .k.template { color: var(--modified); border-color: var(--modified); }
.commit .k.onboard { color: var(--text-muted); }

.pb-doc { flex: 1; overflow-y: auto; padding: 16px 22px; min-width: 0; }

/* the proposals sidebar — pending proposals live here now, out of the doc column */
.pb-proposals { width: 300px; flex: none; background: var(--surface); border-left: 1px solid var(--border); overflow-y: auto; padding-bottom: 16px; }
.pb-proposals .klabel { padding: 10px 12px 2px; margin: 0; }
.pb-proposals .pending { margin: 10px 12px; }
.pb-proposals .phead { display: flex; align-items: center; gap: 6px; margin-bottom: 5px; }
.pb-proposals .phead .pfile { margin-left: auto; font-size: 10px; color: var(--text-muted); }
.pb-empty { margin: 14px 12px; font-size: 11.5px; color: var(--text-muted); font-style: italic; }

/* the version switcher — a subtle disclosure, only when a source doc is picked */
.pb-versions { margin-bottom: 12px; border: 1px solid var(--border-variant); border-radius: 6px; background: var(--surface); }
.pb-versions > summary { list-style: none; cursor: pointer; display: flex; align-items: center; gap: 6px; padding: 6px 12px; font-size: 11px; color: var(--text-muted); user-select: none; }
.pb-versions > summary::-webkit-details-marker { display: none; }
.pb-versions > summary:hover { color: var(--text); }
.pb-versions > summary .icon svg { width: 12px; height: 12px; }
.pb-versions > summary .vcount { margin-left: auto; font-size: 9.5px; border: 1px solid var(--border); border-radius: 8px; padding: 0 6px; }
.pb-versions[open] > summary { border-bottom: 1px solid var(--border-variant); color: var(--text); }
.pb-versions .ver-note { padding: 6px 12px 2px; font-size: 10.5px; color: var(--text-muted); }
.pb-versions .commit .cago { margin-left: auto; font-size: 9.5px; color: var(--text-muted); }
.pb-versions .commit:last-child { border-bottom: none; }

.robar { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); padding: 8px 12px; font-size: 11.5px; margin-bottom: 12px; display: flex; align-items: center; gap: 8px; }
.robar.der { border-color: var(--modified); }

/* the project's own watch settings — the one hand-edited panel on this page,
   so it is visibly a form and not a doc */
.pb-watch { max-width: 760px; }
.pb-watch .klabel { display: flex; align-items: center; gap: 8px; }
.pb-watch .wrefresh { font-size: 10px; padding: 1px 7px; text-transform: none; letter-spacing: 0; }
.pb-watch .wrow { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pb-watch .pane-sub { font-size: 11.5px; }
.pb-watch input { background: var(--editor); border: 1px solid var(--border); border-radius: 4px; color: var(--text); font-size: 11.5px; padding: 3px 7px; }
.pb-watch input[type="number"] { width: 80px; }
.pb-watch .wtext { width: 320px; }

/* F8: the runtime picker's <select> — styled to match the poll-interval input
   rather than the browser's raw control. `appearance: none` drops the native
   chevron so a custom one can carry the theme; the chevron is a background SVG
   whose stroke follows --text-muted, overridden for the light theme below. */
.runtime-select {
  appearance: none;
  -webkit-appearance: none;
  background-color: var(--editor);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23a9afbc' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 9px center;
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 11.5px;
  padding: 3px 26px 3px 8px;
  cursor: pointer;
  line-height: 1.5;
  transition: border-color 0.12s ease;
}
:root[data-theme="light"] .runtime-select {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%2358585a' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
.runtime-select:hover { border-color: var(--text-muted); }
.runtime-select:focus-visible {
  outline: none;
  border-color: var(--text-accent);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--text-accent) 28%, transparent);
}
/* the popup list itself is the OS's; at least keep its own colors on-theme */
.runtime-select option { background: var(--editor); color: var(--text); }

.wrepo { border: 1px solid var(--border-variant); border-radius: 6px; padding: 8px 10px; margin-bottom: 8px; background: var(--surface); }
.wrepo-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.wrepo-name { font-size: 12px; font-weight: 600; color: var(--text); }
.wchecks { flex-wrap: wrap; row-gap: 5px; }
.wchecks button { display: inline-flex; align-items: baseline; gap: 5px; padding: 2px 8px; }
.wchecks button[aria-pressed="true"] { border-color: var(--success); color: var(--success); background: var(--element-selected); }
.wchecks .worigin { font-size: 9px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); }
.wsave { margin-top: 14px; }
.watch-legacy { display: block; margin-top: 10px; color: var(--warning); }

.pending { border: 1px solid var(--info); border-radius: 6px; padding: 10px 12px; margin-bottom: 12px; font-size: 12px; }
.pending-pill { color: var(--info); border-color: var(--info); }
.pending-body { margin-top: 6px; font-family: "Zed Mono", ui-monospace, Menlo, monospace; background: var(--editor); border: 1px solid var(--border); border-left: 2px solid var(--warning); border-radius: 3px; padding: 4px 8px; white-space: pre-wrap; color: var(--text); }
.pending-acts { display: flex; gap: 8px; margin-top: 8px; align-items: center; }
.btn.ok:hover { border-color: var(--success); color: var(--success); }
.btn.no:hover { border-color: var(--error); color: var(--error); }

/* Stage 7 — the document/source toggle and the rendered-document view. */
.pb-settings-back { display: block; padding: 8px 12px 2px; font-size: 11px; color: var(--text-muted); text-decoration: none; }
.pb-settings-back:hover { color: var(--text); }
.pb-viewtoggle { display: inline-flex; gap: 0; margin: 0 0 10px; border: 1px solid var(--border); border-radius: 6px; overflow: hidden; }
.pb-viewtoggle .vt { background: var(--surface); border: none; color: var(--text-muted); font: inherit; font-size: 12px; padding: 4px 12px; cursor: pointer; }
.pb-viewtoggle .vt.on { background: var(--element-hover); color: var(--text); }
.pb-document { max-width: 760px; line-height: 1.65; color: var(--text); }
.pb-document h1, .pb-document h2, .pb-document h3 { margin: 1em 0 0.4em; line-height: 1.3; }
.pb-document p { margin: 0.6em 0; }
.pb-document code { font-family: "Zed Mono", ui-monospace, Menlo, monospace; font-size: 0.92em; }
.pb-document pre { background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 10px 12px; overflow-x: auto; }

.pb-file { font: 11.5px/1.7 "Zed Mono", ui-monospace, Menlo, monospace; color: var(--text); white-space: pre-wrap; margin: 0; }
.pb-file .pline { display: block; }
.pb-file .prov { color: var(--text-muted); font-size: 10px; padding-left: 8px; }
/* a line that carries provenance is a graduated rule — mark it green */
.pb-file .pline:has(.prov) { background: color-mix(in srgb, var(--success) 10%, transparent); border-left: 2px solid var(--success); display: block; padding-left: 8px; margin-left: -10px; }
.pb-file .pline:has(.prov) .prov { display: block; }

.diffbox { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); padding: 6px 12px 10px; margin-bottom: 12px; }
.diffbox pre { font: 10.5px/1.6 "Zed Mono", ui-monospace, Menlo, monospace; color: var(--text-muted); white-space: pre-wrap; margin: 0; }

/* the derived-prompt explainer: the recipe, then a legend of the four layer kinds */
.pb-explain { margin-bottom: 14px; }
.robar.der > div { font-size: 11.5px; line-height: 1.45; }
.pb-legend { display: flex; flex-wrap: wrap; gap: 6px 16px; padding: 8px 2px 0; font-size: 10.5px; color: var(--text-muted); }
.pb-legend .lg { display: inline-flex; align-items: center; gap: 5px; }
.pb-legend .lg i { width: 8px; height: 8px; border-radius: 2px; flex: none; }
.pb-legend .lg.slot i { background: var(--text-accent); }
.pb-legend .lg.doc i { background: var(--success); }
.pb-legend .lg.meas i { background: var(--info); }
.pb-legend .lg.kernel i { background: var(--modified); }

.pb-layers { display: flex; flex-direction: column; }
.layer { border-left: 2px solid var(--border); border-radius: 0 4px 4px 0; padding: 8px 11px; margin: 0 0 12px; }
.layer .lt { display: flex; align-items: center; gap: 6px; font: 600 9.5px/1.5 ui-sans-serif, -apple-system, sans-serif; text-transform: uppercase; letter-spacing: 0.07em; }
.layer .lt .ln { font-size: 12px; }
/* the category badge — the whole point of the redesign: WHY this layer says what it says */
.layer .lbadge { margin-left: auto; font: 600 9px/1.4 ui-sans-serif, -apple-system, sans-serif; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-muted); border: 1px solid var(--border); border-radius: 3px; padding: 1px 5px; background: var(--surface); }
.layer .lbadge.jump { display: inline-flex; align-items: center; gap: 4px; cursor: pointer; }
.layer .lbadge.jump:hover { color: var(--text); border-color: var(--text-accent); }
.layer .lbadge .icon svg { width: 11px; height: 11px; }
.layer .lnote { font-size: 11px; line-height: 1.4; color: var(--text-muted); text-transform: none; letter-spacing: 0; font-weight: 400; margin: 4px 0 6px; }
.layer .lexample { font: 10.5px/1.4 "Zed Mono", ui-monospace, Menlo, monospace; color: var(--text-accent); margin: 0 0 6px; }
.layer pre { font: 11.5px/1.6 "Zed Mono", ui-monospace, Menlo, monospace; color: var(--text); white-space: pre-wrap; margin: 0; }
.layer.slot { border-color: var(--text-accent); background: color-mix(in srgb, var(--text-accent) 6%, transparent); }
.layer.slot .lt { color: var(--text-accent); }
.layer.doc { border-color: var(--success); background: color-mix(in srgb, var(--success) 6%, transparent); }
.layer.doc .lt { color: var(--success); }
.layer.doc .lbadge.jump { color: var(--success); border-color: color-mix(in srgb, var(--success) 45%, var(--border)); }
.layer.doc .lbadge.jump:hover { border-color: var(--success); }
.layer.meas { border-color: var(--info); background: color-mix(in srgb, var(--info) 6%, transparent); }
.layer.meas .lt { color: var(--info); }
.layer.kernel { border-color: var(--modified); background: color-mix(in srgb, var(--modified) 7%, transparent); }
.layer.kernel .lt { color: var(--modified); }

/* the run's journal inside the chat: the say-bubble's label moves ON TOP of
   the bubble (the row gutter is the runs page's layout, kept there) */
.turns.chat .jturn { padding: 0; }
.turns.chat .jturn.say { flex-direction: column; gap: 3px; max-width: 88%; align-self: flex-start; }
.turns.chat .jturn.say .who { width: auto; font-size: 10px; text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; padding-top: 0; }
.turns.chat .jturn.say .bubble { max-width: 100%; }

/* An action reads as ONE column here, not three: `verb · took` as a heading
   line with the target full-width under it. The nowrap three-column row is
   the runs page's layout, where the pane is wide; in the chat (a phone, or
   the desktop's 262px rail) the middle column collapsed to a ravine of
   letter-broken text. break-word/anywhere instead of break-all: paths still
   break when they must, words stop breaking mid-letter when they don't. */
.turns.chat .jturn.act .bubble { flex-wrap: wrap; row-gap: 1px; }
.turns.chat .jturn.act .verb { min-width: 0; }
.turns.chat .jturn.act .targ {
  flex-basis: 100%; order: 1;
  word-break: normal; overflow-wrap: anywhere;
}
.turns.chat .jturn.act .took { margin-left: 0; }

/* ── annotate-before-attach modal (AnnotateAttach hook, layouts.ex) ─────── */

.an-backdrop {
  position: fixed; inset: 0; z-index: 9999;
  background: rgba(0, 0, 0, .5);
  display: flex; align-items: center; justify-content: center; padding: 16px;
}

.an-modal {
  /* fill the viewport so the image preview gets as much room as possible */
  width: min(1200px, 100%); height: 90vh; max-height: 90vh;
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
  display: flex; flex-direction: column; overflow: hidden; min-height: 0;
  color: var(--text);
}

.an-head {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 12px; border-bottom: 1px solid var(--border);
}

.an-head h3 { margin: 0; font-size: 12px; font-weight: 600; }

.an-file-pill {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--element); color: var(--text-muted); padding: 2px 8px;
  border: 1px solid var(--border-variant); border-radius: 3px; font-size: 10px;
}

.an-spacer { flex: 1; }

.an-body { display: grid; grid-template-columns: 1fr 300px; min-height: 0; min-width: 0; flex: 1; }
.an-body > * { min-width: 0; min-height: 0; }

.an-canvas-wrap {
  position: relative; background: var(--editor);
  display: flex; align-items: center; justify-content: center; padding: 14px;
  overflow: auto; min-height: 240px;
}

.an-canvas {
  position: relative; max-width: 100%; max-height: calc(90vh - 120px);
  border-radius: 4px; overflow: hidden; border: 1px solid var(--border-variant);
  background: #111; cursor: crosshair; user-select: none;
}

.an-canvas img {
  display: block; max-width: 100%; max-height: calc(90vh - 120px);
  -webkit-user-drag: none; pointer-events: none;
}

.an-pin-layer { position: absolute; inset: 0; pointer-events: none; }

.an-pin {
  position: absolute; transform: translate(-50%, -50%);
  width: 26px; height: 26px; border-radius: 999px;
  background: var(--c, #ec4899); color: #fff; font-weight: 700; font-size: 12px;
  display: flex; align-items: center; justify-content: center;
  border: 2px solid rgba(255, 255, 255, .9);
  pointer-events: auto; cursor: pointer;
}

.an-pin.sel { transform: translate(-50%, -50%) scale(1.1); }

.an-side {
  border-left: 1px solid var(--border); background: var(--surface);
  display: flex; flex-direction: column; min-width: 0; min-height: 0;
}

.an-side-head {
  padding: 8px 10px; border-bottom: 1px solid var(--border-variant);
  display: flex; align-items: center; justify-content: space-between;
}

.an-side-title { font-weight: 600; font-size: 11px; }
.an-count { color: var(--text-muted); font-size: 10px; }

.an-side-list { flex: 1; overflow-y: auto; padding: 8px; display: flex; flex-direction: column; gap: 8px; }

.an-empty {
  padding: 12px; border: 1px dashed var(--border); border-radius: 4px;
  color: var(--text-muted); font-size: 11px; text-align: center; line-height: 1.6;
}

.an-ann {
  background: var(--element); border: 1px solid var(--border); border-radius: 4px;
  padding: 8px 10px; display: flex; flex-direction: column; gap: 8px; cursor: pointer;
}

.an-ann.sel { border-color: var(--text-accent); cursor: default; }
.an-ann-head { display: flex; align-items: center; gap: 8px; }

.an-num {
  width: 20px; height: 20px; border-radius: 999px; flex: 0 0 20px;
  background: var(--c, #ec4899); color: #fff; font-weight: 700; font-size: 11px;
  display: inline-flex; align-items: center; justify-content: center;
}

.an-ann-tag { flex: 1; font-size: 11px; font-weight: 600; color: var(--text); }

.an-del {
  background: transparent; border: 0; color: var(--text-muted); cursor: pointer;
  font-size: 11px; width: 20px; height: 20px; border-radius: 3px;
}

.an-del:hover { background: var(--element-hover); color: var(--text); }
.an-ann-note { font-size: 11px; color: var(--text-muted); }

.an-picker { display: flex; flex-direction: column; gap: 6px; border-top: 1px dashed var(--border-variant); padding-top: 8px; }
.an-group-label { color: var(--text-muted); font-size: 9px; letter-spacing: .04em; text-transform: uppercase; }
.an-tag-row { display: flex; flex-wrap: wrap; gap: 4px; }

.an-tag {
  display: inline-flex; align-items: center; font: inherit; font-size: 10px;
  border: 1px solid var(--border); background: var(--element); color: var(--text-muted);
  padding: 2px 8px; border-radius: 999px; cursor: pointer;
}

.an-tag:hover { background: var(--element-hover); color: var(--text); }
.an-tag.sel { border-color: var(--text-accent); color: var(--text-accent); font-weight: 600; }
.an-tag.add { border-style: dashed; }

.an-note {
  border: 1px solid var(--border); border-radius: 4px; padding: 6px 8px;
  font: inherit; font-size: 11px; resize: vertical; min-height: 44px;
  background: var(--editor); color: var(--editor-fg); width: 100%;
}

.an-foot {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; border-top: 1px solid var(--border);
}

.an-info { flex: 0 1 auto; color: var(--text-muted); font-size: 11px; }

.an-btn {
  font: inherit; font-size: 11px; cursor: pointer; border-radius: 4px; padding: 4px 12px;
  border: 1px solid var(--border); background: var(--element); color: var(--text);
}

.an-btn:hover { background: var(--element-hover); }
.an-btn.primary { border-color: var(--text-accent); color: var(--text-accent); font-weight: 600; }
.an-btn.ghost { border-color: transparent; color: var(--text-muted); }
.an-btn.ghost:hover { background: var(--element-hover); color: var(--text); }

/* ── attachment chips in the composers + images on the place ────────────── */

.att-row { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 8px; }

.att-chip {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--border); border-radius: 4px; background: var(--element);
  padding: 4px 8px 4px 4px; font-size: 10px; color: var(--text-muted);
}

.att-chip img { display: block; width: 44px; height: 44px; object-fit: cover; border-radius: 3px; }

.att-chip .x {
  background: transparent; border: 0; color: var(--text-muted);
  cursor: pointer; font-size: 11px; border-radius: 3px; width: 18px; height: 18px;
}

.att-chip .x:hover { background: var(--element-hover); color: var(--text); }

.turn-atts { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px; min-width: 0; }

/* The gallery's links are flex items, and a flex item will not shrink below its
   content while min-width is auto — so the percentage cap below only bites once
   the item is allowed to give. */
.turn-atts > a { display: block; min-width: 0; max-width: 100%; }

/* The 320px ceiling had no percentage companion, so a screenshot attached to a
   source burst out of the SOURCE (VERBATIM) card inside the 220px .wsrail.
   min() keeps 320px wherever there is room and only falls back to the
   container's width when the container is the narrower of the two, so an image
   that already fits is left exactly as it was. */
.turn-atts img {
  display: block; max-width: min(320px, 100%); max-height: 240px; height: auto;
  border: 1px solid var(--border); border-radius: 4px;
}

.turn-atts .cap { white-space: pre-wrap; font-size: 10px; color: var(--text-muted); }

/* A NON-image attachment — a .txt, a .pdf, whatever someone drops in Slack. It used to be rendered
   through the <img> rule above, which is how a text file became a broken-image icon with a link
   glued to it. A named chip instead: it says what the file IS, and clicking still opens it. */
.turn-atts > a.att-file {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 4px 9px; border: 1px solid var(--border); border-radius: 4px;
  background: var(--bg-soft, transparent); color: var(--text); text-decoration: none;
  font-size: 12px; line-height: 1.4;
}
.turn-atts > a.att-file:hover { border-color: var(--accent, var(--border)); }
.turn-atts > a.att-file .glyph { color: var(--text-muted); flex: none; }
.turn-atts > a.att-file .fname {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* a failed run's ending — the step that raised and what it said */
.place-fail { margin-top: 10px; padding: 8px 10px; border: 1px solid var(--error); border-radius: 4px; color: var(--error); }


/* ═══════════════════════════════════════════════════════════════════════════
   M19 · order-place v2 — the proof-first surface (prototypes/order-place-v2.html)
   Tokens verbatim from :root above; classes below are additive.
   ═══════════════════════════════════════════════════════════════════════════ */

/* status pills had no base rule — give them one (pagehead status, rail type/model) */
.pill {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 10px; padding: 1px 6px;
  border: 1px solid var(--border); border-radius: 9px;
  color: var(--text-muted); background: var(--element); white-space: nowrap;
}
.pill.hold, .pill.in_progress { border-color: var(--warning); color: var(--warning); }
.pill.done { border-color: var(--success); color: var(--success); }

/* The compact worked/waited split meter (.wsplit) that rode beside an order row's
   status pill is gone with the 2026-08-15 UI declutter — the numeric durations stay
   on the rows that had them; the bar does not. */

.order-proof { display: flex; flex-direction: column; }

/* ── the order place: the RAIL SWAP ──
   The thread (turns + reply box) lives in the RIGHT rail, always in view beside
   the proof; the reference cards (watch, source verbatim, work order, workspace)
   live in the LEFT rail under the runs. The proof owns the wide middle alone.
   (②) the proof keeps the 12/16 gutter any content section has.
   (③) the proof fills the middle column and scrolls on its own — and because the
       thread now has its OWN column, a data-heavy proof can never push it off. */
.cols.order .order-proof { flex: 1; min-height: 0; overflow-y: auto; padding: 12px 16px; }

/* (the 264px reference column is gone from ORDER places — its cards live in the activity
   rail's drawers now, styled with the drawer above; `.wsrail` survives on source places) */
/* the workspace card names its folder: one selectable mono line under the
   heading, wrapped by the drawer's long-string rules rather than clipped. */
.refdrawer .wspath { display: block; color: var(--text-muted); font-size: 10.5px; user-select: text; padding-bottom: 4px; }

/* right rail: the thread column — a fixed caption header, the turns scrolling,
   and the composer pinned at the bottom. Wider than a reference rail, and it
   reads on the editor surface like the thread always did. */
.cols.order .rrail { width: 400px; padding: 0; background: var(--editor); display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
/* the runs list sits at the top of the thread rail — a fixed band (its own scroll
   if there are many chains), divided from the thread it selects below it */
/* the run picker, demoted INTO the chat: it opens the conversation as a quiet
   element — no section box, no card chrome, no own scroll. Rows stay clickable
   (they pick the chain); the sub-echo and model hide here because the runmark
   dividers and the turns themselves already carry both. */
.cols.order .rrail .turns .runrail { flex: none; max-height: none; overflow: visible; padding: 0; border-bottom: none; }
.cols.order .rrail .turns .runrail .klabel { margin-top: 0; }
.cols.order .rrail .turns .runrow { border: none; background: none; border-radius: 0; padding: 0; margin: 0 0 4px; }
.cols.order .rrail .turns .runrow .sub, .cols.order .rrail .turns .runrow .runmodel { display: none; }
.cols.order .rrail .turns .runrow.on .rid { color: var(--text-accent); }
.cols.order .rrail .turns .runrow:hover .rid { color: var(--text-accent); }
.cols.order .rrail .thread-cap { flex: none; padding: 10px 14px 0; margin: 0; }

/* ── the call strip — compact, decision only ── */
.callstrip { border: 1px solid var(--info); border-radius: 6px; background: var(--surface); margin-bottom: 12px; }
.cs-top { display: flex; align-items: center; gap: 10px; padding: 7px 12px; flex-wrap: wrap; }
.cs-top h3 { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--info); font-weight: 600; }
/* one line, always — the verdict is an echo here, and it shrinks before the ci glance
   and bundle label do. Its full text is on the title, and reads under "does it work". */
.cs-verdict { font-size: 12px; color: var(--success); flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* the call in plain words — leads the strip, the sentence that names the decision */
.cs-call { font-size: 12.5px; color: var(--text); flex: 1 1 auto; min-width: 0; }
/* the kernel's raw verdict, demoted to a quiet line under the plain-words call */
.cs-echo { font-size: 10.5px; color: var(--text-placeholder); padding: 0 12px 7px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cs-acts { display: flex; align-items: center; gap: 8px; padding: 7px 12px; border-top: 1px solid var(--border-variant); flex-wrap: wrap; }
.next { display: flex; align-items: center; gap: 8px; }
.next .nlabel { font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); font-weight: 600; }
/* the git landing status — a glyph + "merged into main", the key fact on the card */
.git-landed { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--success); }
.git-landed .gicon svg { width: 13px; height: 13px; display: block; }
/* the suggested act + the ⋯ menu, gathered as one group on the right */
.act-group { display: inline-flex; align-items: center; gap: 8px; }
.act-group .menu { margin-left: 0; }
.menu { position: relative; margin-left: auto; }
.menu-pop { position: absolute; right: 0; top: calc(100% + 4px); background: var(--surface);
  border: 1px solid var(--border); border-radius: 6px; min-width: 250px; z-index: 20; padding: 4px; display: none; }
.menu-pop.show { display: block; }
.mi { display: flex; flex-direction: column; gap: 1px; padding: 6px 9px; border-radius: 4px; cursor: pointer;
  text-align: left; background: none; border: none; color: var(--text); width: 100%; text-decoration: none; }
.mi:hover { background: var(--element-hover); }
.mi .ml { font-size: 11.5px; }
.mi .mh { font-size: 10px; color: var(--text-placeholder); }

/* the handed-back callout — the call strip's slot when the order is red: the
   reason the machine stopped, the declared runbook, and the failing-checks link */
.callstrip.handedback { border-color: var(--error); }
.callstrip.handedback .cs-top h3 { color: var(--error); }
.hb-reason { padding: 2px 12px 8px; font-size: 12.5px; line-height: 1.45; }
/* the handback chronology — run/ci outcomes oldest → newest, same-colored
   repeats collapsed to ×N, so "red, then recovered" reads as a sequence */
.hb-timeline { display: flex; align-items: center; gap: 7px; flex-wrap: wrap;
  padding: 0 12px 8px; font-family: "Zed Mono", ui-monospace, "SF Mono", "JetBrains Mono", Menlo, monospace; font-size: 11px; }
.hb-tl { display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; }
.hb-sep { color: var(--text-placeholder); }
.hb-when { color: var(--text-muted); font-size: 10px; }
.hb-runbook { margin: 0 12px 8px; padding: 8px 10px; background: var(--element); border-radius: 4px;
  font-size: 11px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; }
.hb-summary { padding: 0 12px 8px; }
.hb-summary summary { cursor: pointer; font-size: 10.5px; color: var(--text-muted);
  text-transform: uppercase; letter-spacing: 0.06em; }
.hb-summary p { margin: 6px 0 0; font-size: 12px; line-height: 1.5; white-space: pre-wrap; }

/* ── THE PROOF — the page's main body ── */
.proof { border: 1px solid var(--border); border-radius: 6px; background: var(--surface); margin-bottom: 12px; }
.proof.archived { opacity: 0.82; }
.proof.archived .pf-head h3 { color: var(--text-muted); }
.pf-head { display: flex; align-items: center; gap: 8px; padding: 8px 12px; border-bottom: 1px solid var(--border-variant); flex-wrap: wrap; }
.pf-head h3 { font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); font-weight: 600; }
.vtabs { display: flex; gap: 4px; margin-left: 6px; flex-wrap: wrap; }
.vtab { font-size: 10.5px; padding: 1px 8px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--element); color: var(--text-muted); cursor: pointer; text-decoration: none;
  font-family: "Zed Mono", ui-monospace, Menlo, monospace; }
.vtab:hover { border-color: var(--text-accent); }
.vtab.on { border-color: var(--success); color: var(--success); }
.vtab.old { opacity: 0.75; }
.superseded { margin: 10px 12px 0; padding: 6px 10px; border: 1px solid var(--warning); border-radius: 4px;
  font-size: 11px; color: var(--warning); }

/* the run's headline — the first thing read on the place */
.pf-summary { margin: 10px 12px 0; padding: 8px 10px; border-left: 2px solid var(--text-accent);
  background: var(--element); border-radius: 0 4px 4px 0; font-size: 12px; line-height: 1.5;
  color: var(--text); }

/* the three questions */
.q3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; padding: 10px 12px; }
.qcard { border: 1px solid var(--border); border-radius: 6px; background: var(--editor); padding: 8px 11px; cursor: pointer; min-width: 0; }
.qcard:hover, .qcard.on { border-color: var(--text-accent); }
.qcard .ql { font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em; color: var(--text-muted); font-weight: 600; }
.qcard .qv { font-size: 12.5px; margin-top: 3px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qcard .qs { font-size: 10.5px; color: var(--text-placeholder); margin-top: 2px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.qbody { border-top: 1px solid var(--border-variant); padding: 10px 12px; display: none; }
.qbody.show { display: block; }

/* what changed */
.filelist { display: flex; flex-direction: column; gap: 4px; }
.file { display: flex; align-items: center; gap: 8px; font-size: 11.5px; }
.file .stat { margin-left: auto; font-family: "Zed Mono", ui-monospace, Menlo, monospace; font-size: 10.5px; }
.add { color: var(--success); }
.del { color: var(--error); }

/* does it work */
.cmdrow { display: flex; align-items: baseline; gap: 8px; font-size: 11.5px; padding: 3px 0; border-bottom: 1px solid var(--border-variant); }
.cmdrow:last-child { border-bottom: none; }
.cmdrow .ic { flex: none; width: 12px; }
.cmdrow .ic.ok { color: var(--success); }
.cmdrow .ic.err { color: var(--error); }
.cmdrow .cmd { min-width: 0; font-family: "Zed Mono", ui-monospace, Menlo, monospace; font-size: 11px; }
.cmdrow .took { margin-left: auto; flex: none; color: var(--text-placeholder); font-size: 10.5px; }

/* how it looks — a CAPPED gallery, not an unbounded wrap. Twelve shots used to
   become four rows that pushed the bundle footer off screen; the strip is held
   to ~two rows and scrolls inside itself instead. */
.shots { display: flex; gap: 10px; flex-wrap: wrap; align-content: flex-start; max-height: 322px; overflow-y: auto; overscroll-behavior: contain; padding-right: 4px; }
.shot { position: relative; width: 180px; cursor: zoom-in; }
/* top-anchored, never a centre crop: the centre of a wide desktop capture is
   empty page, so every tile looked alike. The page header is at the top. */
.shot img { width: 100%; aspect-ratio: 16/10; object-fit: cover; object-position: top center; border: 1px solid var(--border); border-radius: 5px; background: var(--element); }
/* the position badge — "3/12", so a reviewer can name the tile they mean */
.shot .shot-n { position: absolute; top: 5px; right: 5px; z-index: 1; padding: 1px 5px; border-radius: 3px; font-size: 10px; line-height: 1.5; color: #fff; background: rgba(0, 0, 0, 0.66); pointer-events: none; }
/* two lines, wrapped; the HEAD is truncated server-side (shot_caption_short/1),
   because the tail is what identifies the shot. Full text in the title tooltip. */
.shot .cap { font-size: 10.5px; color: var(--text-muted); margin-top: 4px; overflow: hidden; white-space: normal; overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; }
.lightbox { position: fixed; inset: 0; background: rgba(0, 0, 0, 0.72); display: none; align-items: center; justify-content: center; z-index: 50; }
.lightbox.show { display: flex; }
/* the frame runs to the viewport now: a 2560px capture squeezed into 880px made
   the very UI text the shot was taken to prove unreadable. */
.lightbox .frame { display: flex; flex-direction: column; gap: 8px; width: min(2600px, 96vw); max-height: 94vh; background: var(--surface); border: 1px solid var(--border); border-radius: 6px; padding: 12px; }
.lightbox .lbbar { display: flex; align-items: center; gap: 8px; flex: none; }
.lightbox .lbcount { font-size: 11px; color: var(--text-muted); min-width: 64px; text-align: center; }
.lightbox .lbnav { padding: 1px 9px 3px; font-size: 15px; line-height: 1.3; color: var(--text); background: var(--element); border: 1px solid var(--border); border-radius: 4px; cursor: pointer; }
.lightbox .lbnav:hover:not(:disabled) { background: var(--surface-variant, var(--element)); border-color: var(--text-muted); }
.lightbox .lbnav:disabled { opacity: 0.35; cursor: default; }
.lightbox .lbclose { margin-left: auto; font-size: 12px; }
.lightbox .lbscroll { flex: 1; min-height: 0; overflow: auto; border: 1px solid var(--border); border-radius: 5px; background: var(--element); }
.lightbox .lbscroll img { display: block; max-width: 100%; height: auto; margin: 0 auto; cursor: zoom-in; }
/* click-to-zoom: 1:1, the capture's natural size, and the frame scrolls */
.lightbox .lbscroll.zoom img { max-width: none; width: auto; margin: 0; cursor: zoom-out; }
.lightbox .lbcap { display: flex; align-items: baseline; gap: 10px; flex: none; font-size: 10.5px; color: var(--text-muted); }
.lightbox .lbcap [data-lb-caption] { min-width: 0; overflow-wrap: anywhere; }
.lightbox .lbcap .lin { margin-left: auto; flex: none; }

.pf-foot { display: flex; align-items: center; gap: 10px; padding: 7px 12px; border-top: 1px solid var(--border-variant); font-size: 11px; color: var(--text-muted); flex-wrap: wrap; }

/* landings + demoted thread */
.roundline { display: flex; align-items: center; gap: 10px; font-size: 11px; padding: 6px 0 12px; color: var(--text-muted); flex-wrap: wrap; }
.roundline .klabel { margin: 0; }
.landing { display: flex; align-items: center; gap: 6px; font-size: 11px; padding: 3px 0; flex-wrap: wrap; }

/* landings lead the proof column — carded, so the terminal fact reads before the bundle */
.landcard { border-color: var(--success); margin-bottom: 12px; }
.landcard h3 { color: var(--success); display: flex; align-items: center; gap: 6px; }
.landcard .hint { font-size: 11px; }
.thread-cap { display: flex; align-items: center; gap: 8px; margin: 6px 0 8px; }
.thread-cap .klabel { margin: 0; }

/* in_progress — proof accumulating live */
.livefeed { border: 1px dashed var(--border); border-radius: 6px; padding: 8px 12px; margin-bottom: 12px; font-size: 11.5px; color: var(--text-muted); }
.livefeed .row { display: flex; gap: 8px; align-items: center; }
.livefeed .row b { color: var(--text); }
/* A live run whose journal has flatlined: the feed's border warms to amber, marking that the run
   still says "running" but nothing has been written for over a minute (see `.worknow.stalled`). */
.livefeed.wn-stalled { border-color: var(--warning); }

/* ═══ M21 · Place × watcher — watch card, ci glance, :external turns ═══ */

.watchcard { border-color: var(--info); }
.watchcard h3 { color: var(--info); display: flex; align-items: center; gap: 6px; }
.watchcard .wrow { display: flex; align-items: center; gap: 6px; font-size: 11px; padding: 2px 0; }
.watchcard .wrow .k { color: var(--text-muted); width: 60px; flex: none; }
.watchcard .wfoot { display: flex; gap: 10px; margin-top: 6px; align-items: center; }

/* the ci glance in the call strip */
.cs-ci { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--text-muted); }

/* dot verdict colours used by the watch card + glance (prototype set) */
.dot.ok { background: var(--success); }
.dot.err { background: var(--error); }
.dot.warn { background: var(--warning); }
.dot.run { background: var(--info); animation: watchpulse 1.2s infinite; }
@keyframes watchpulse { 50% { opacity: 0.3; } }

/* chip variants for the watch status */
.chip.watch { border-color: var(--info); color: var(--info); }
.chip.watch.paused { border-color: var(--warning); color: var(--warning); }

/* an :external turn — the watcher speaking for the human, coloured like the watch */
.turn.external .who { color: var(--info); }
/* :kernel — Foundry itself, speaking to the session about the contract (the nudge). Its own
   colour because it is its own voice: not the forge (:external), not you, not the agent. */
.turn.kernel .who { color: var(--text-accent); }
.turn.kernel { border-left: 2px solid var(--border-variant); }

/* ═══ M22 · The plan — intake reports scope a human can glance at ═══
   The failure this replaces was a single prose field that swallowed scope,
   sequence and grounding. Everything here exists to make scope *scannable*:
   grouped by the repo it lands in, one row per change, questions rendered on
   the change they block. */

.planpanel { border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
  padding: 13px 15px; margin-bottom: 16px; }
.plan-head { display: flex; align-items: center; gap: 8px; margin-bottom: 8px; }
.plan-label { margin: 0; }
.plan-headline { font-size: 15px; line-height: 1.35; font-weight: 600; margin: 0 0 6px; }
.plan-summary { font-size: 12.5px; line-height: 1.5; color: var(--text-muted); margin: 0 0 9px; }
.plan-facts { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 12px; }
.chip.warn { border-color: var(--warning); color: var(--warning); }

/* one card per repo — the "which repo does what" answer */
.repocard { border: 1px solid var(--border); border-radius: 5px; background: var(--editor);
  margin-bottom: 10px; overflow: hidden; }
.repohead { display: flex; align-items: baseline; gap: 8px; padding: 6px 10px;
  border-bottom: 1px solid var(--border-variant); background: var(--element); }
.repohead .rname { font-weight: 600; font-size: 12px; }

.pchange { padding: 9px 11px; border-bottom: 1px solid var(--border-variant); }
.pchange:last-child { border-bottom: none; }
.ptop { display: flex; align-items: flex-start; gap: 7px; flex-wrap: wrap; }
.ptop .ptitle { font-weight: 600; font-size: 12.5px; min-width: 0; flex: 1; }
.scopebox { background: none; border: none; color: var(--text-accent); cursor: pointer;
  font-size: 13px; line-height: 1.2; padding: 0; flex: none; }
.scopebox:disabled { color: var(--text-placeholder); cursor: default; }
.pbody { font-size: 12px; line-height: 1.5; color: var(--text-muted); margin-top: 4px; }
.pfiles { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 7px; }
.fchip { font-size: 10px; padding: 1px 5px; border: 1px solid var(--border-variant);
  border-radius: 3px; color: var(--text-muted); background: var(--element);
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fchip.new { border-style: dashed; }
.pacc { margin-top: 7px; }
.pacc .klabel { margin: 0 0 3px; }
.paccline { font-size: 11.5px; color: var(--text-muted); padding: 1px 0 1px 16px; text-indent: -16px; }
.paccline::before { content: "☐ "; color: var(--text-placeholder); }
.pchange.out { opacity: 0.5; }
.pchange.out .ptitle { text-decoration: line-through; }
.phint { font-size: 11px; color: var(--text-placeholder); margin-top: 5px; }

/* a question, asked as a choice — rendered ON the change it blocks */
.pquestion { border: 1px solid var(--warning); border-radius: 4px; padding: 7px 9px; margin-top: 8px; }
.pquestion.loose { margin: 0 0 10px; }
.pquestion.answered { border-color: var(--border); border-left: 2px solid var(--text-accent); }
.pquestion .qhead { display: flex; align-items: center; gap: 6px; }
.pquestion .qlabel { margin: 0; color: var(--warning); }
.pquestion .qtext { font-size: 12px; line-height: 1.5; color: var(--text); margin: 4px 0 6px; }
.qopt { display: flex; gap: 7px; align-items: flex-start; font-size: 11.5px;
  color: var(--text-muted); padding: 2px 0; cursor: pointer; }
.qopt input { accent-color: var(--warning); margin-top: 3px; flex: none; }
.qopt:hover { color: var(--text); }
.qfree { display: flex; gap: 6px; margin-top: 6px; }
.qfree input[type="text"] { flex: 1; min-width: 0; background: var(--element);
  border: 1px solid var(--border); border-radius: 4px; color: var(--text);
  font-size: 11.5px; padding: 4px 8px; }
.qfree input::placeholder { color: var(--text-placeholder); }
.qanswered .qtext-small { font-size: 11.5px; color: var(--text-muted); margin: 2px 0; }
.qanswered .qans { font-size: 12px; color: var(--text); }
.qanswered .klabel { margin: 0; }

/* assumptions + out-of-scope */
.plan-margins { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 10px; margin: 12px 0; align-items: start; }
.plan-margins .margin { border: 1px solid var(--border-variant); border-radius: 5px; padding: 8px 10px; }
.plan-margins .klabel { margin: 0 0 5px; }
.arow { font-size: 11.5px; color: var(--text-muted); padding: 2px 0 2px 14px; text-indent: -14px; }
.arow::before { content: "≈ "; color: var(--text-placeholder); }
.arow .flip { color: var(--text-placeholder); }
.orow { font-size: 11.5px; color: var(--text-placeholder); padding: 2px 0 2px 14px; text-indent: -14px; }
.orow::before { content: "⊘ "; }

/* the cut decision — one order is the default AND the recommendation */
.agreebar { border-top: 1px solid var(--border-variant); padding-top: 10px; margin-top: 12px; }
.cutchoice .klabel { margin: 0 0 5px; }
.copt { display: flex; gap: 7px; align-items: flex-start; font-size: 11.5px;
  color: var(--text-muted); padding: 3px 0; cursor: pointer; }
.copt input { accent-color: var(--text-accent); margin-top: 3px; flex: none; }
.copt b { color: var(--text); }
.agreerow { display: flex; align-items: center; gap: 10px; margin-top: 10px; flex-wrap: wrap; }
.agreed-note { margin-top: 10px; }

/* the cut order, rendered from its plan's rows rather than its agent-facing text */
.cutsum { margin: 8px 0 4px; }
.cutsum > .klabel { margin: 0 0 6px; }
.cutrepo { border: 1px solid var(--border-variant); border-radius: 5px; margin-bottom: 7px; overflow: hidden; }
.cutrepo-head { padding: 4px 9px; background: var(--element); border-bottom: 1px solid var(--border-variant);
  font-size: 11px; font-weight: 600; }
.cutchange { padding: 6px 9px; border-bottom: 1px solid var(--border-variant); }
.cutchange:last-child { border-bottom: none; }
.cuttitle { font-size: 12px; font-weight: 600; display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.whatraw { margin-top: 6px; }
.whatraw summary { font-size: 11px; color: var(--text-muted); cursor: pointer; }
.whatraw summary:hover { color: var(--text); }
.whatraw pre { margin-top: 6px; padding: 8px 10px; background: var(--editor);
  border: 1px solid var(--border-variant); border-radius: 4px; white-space: pre-wrap;
  font-size: 11px; color: var(--text-muted); max-height: 320px; overflow-y: auto; }

/* the sticky action footer — one bar, one next act, never scrolled away.
   A five-change plan runs past 3,000px; an action parked at its bottom is an
   action you have to go looking for. */
/* No shadow: the board's visual language is flat — 1px borders, no shadows, no
   gradients (see the header of this file, and board_test asserts it). A sticky
   bar separates itself from the content scrolling under it with an opaque
   surface and a 2px accent top border instead. */
.planfoot { position: sticky; bottom: 0; z-index: 4; display: flex; align-items: center;
  gap: 10px; flex-wrap: wrap; margin-top: 14px; padding: 10px 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-top: 2px solid var(--text-accent); border-radius: 0 0 6px 6px; }
.planfoot .btn { font-size: 12px; padding: 5px 12px; }

/* an answered question keeps its controls live until the batch is sent */
.pquestion.answered { border-color: var(--success); }
.pquestion.answered .qlabel { color: var(--success); }
.pquestion .qmark.ok { color: var(--success); }
.pquestion.sent { border-color: var(--border); border-left: 2px solid var(--text-accent); }
.pquestion.sent .qlabel { color: var(--text-muted); }

/* ── terminal session place (M-term) ──────────────────────────────────────
   The pty fills the main column; xterm owns everything inside .term-host
   (its own theme paints the background). The right rail is the Artifacts
   tray — what the agent delivered for review. */
.cols.term .main { min-height: 0; }
.term-host { flex: 1; min-height: 0; background: #0d1117; padding: 6px 2px 6px 8px; }
.term-host .xterm { height: 100%; }
.cols.term .rrail { width: 300px; }

.pill.running { border-color: var(--warning); color: var(--warning); }
.pill.exited { border-color: var(--text-muted); color: var(--text-muted); }
.rdot.exited { background: var(--text-muted); }

.term-retitle input {
  background: var(--element);
  border: 1px solid var(--border);
  border-radius: 4px;
  color: var(--text);
  font-size: 12px;
  padding: 3px 8px;
  min-width: 24ch;
}

.tray-item { border-bottom: 1px solid var(--border-variant); padding: 7px 0; }
.tray-item:last-child { border-bottom: none; }
.tray-row { display: flex; gap: 8px; align-items: center; text-decoration: none; color: var(--text); font-size: 12px; min-width: 0; }
.tray-row:hover .tray-name { color: var(--text-accent); }
.tray-row .badge { flex: none; font-size: 9.5px; border: 1px solid var(--border); border-radius: 3px; padding: 1px 4px; color: var(--text-muted); }
.tray-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tray-sub { display: flex; gap: 8px; font-size: 10.5px; color: var(--text-muted); margin-top: 3px; min-width: 0; }
.tray-file { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.tray-age { margin-left: auto; flex: none; white-space: nowrap; }
.tray-item .shot { display: block; text-decoration: none; cursor: zoom-in; }
.tray-item .shot img { max-width: 100%; display: block; border: 1px solid var(--border); border-radius: 3px; }
.tray-item .shot .cap { display: block; font-size: 10.5px; color: var(--text-muted); margin-top: 4px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* P2 — the preview place (/p/:project/orders/:id/preview).

   The frame fills the VIEWPORT, and the unit matters: `height: 100%` was the first cut and it
   letterboxed the app into ~200px with most of the page empty below it, because a percentage
   height resolves against the parent's height and nothing in this layout's chain declares one —
   so it fell back to the iframe's intrinsic size. `100vh` needs no cooperation from any ancestor.
   An app in a 200px box is a thumbnail, and this route exists to be used rather than glanced at.
   `min-height: 0` on the wrapper is what then lets the flex child actually shrink instead of
   pushing the page taller than the screen. */
.preview-place { display: flex; flex-direction: column; min-height: calc(100vh - 24px); gap: 10px; padding: 12px; }
.pv-bar { display: flex; gap: 8px; align-items: center; flex: none; flex-wrap: wrap; }
.pv-bar .spacer { flex: 1; }
.pv-title { font-size: 12px; color: var(--text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 40ch; }

.pv-tabs { display: inline-flex; border: 1px solid var(--border); border-radius: 4px; overflow: hidden; }
.pv-tab {
  background: var(--element);
  border: none;
  border-right: 1px solid var(--border);
  color: var(--text-muted);
  cursor: pointer;
  font-size: 11px;
  padding: 3px 10px;
}
.pv-tab:last-child { border-right: none; }
.pv-tab:hover { background: var(--element-hover); color: var(--text); }
/* The declared service, marked on the control itself — not only in the meta line below the frame,
   because the tab strip is where a person looks to know what they are seeing. */
.pv-tab.on { background: var(--element-selected); color: var(--text-accent); }

.pv-frame-wrap { display: flex; flex-direction: column; gap: 6px; flex: 1; min-height: 0; }
.pv-frame {
  flex: 1;
  /* A floor as well as a flex share: on a short window the flex round-down can leave the frame a
     few pixels tall, which reads as a broken preview rather than a small one. */
  min-height: 60vh;
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
}
.pv-meta { flex: none; font-size: 10.5px; color: var(--text-muted); }
.pv-meta code { font-size: 10.5px; }

.pv-ask, .pv-empty { border: 1px solid var(--border); border-radius: 4px; padding: 14px 16px; font-size: 12px; max-width: 70ch; }
.pv-ask p, .pv-empty p { margin: 0 0 8px; }
.pv-sub { color: var(--text-muted); }
.pv-bad { color: var(--error); font-size: 12px; }
.pv-cands { list-style: none; padding: 0; margin: 10px 0 0; display: flex; flex-direction: column; gap: 6px; }
.pv-cands li { display: flex; gap: 10px; align-items: center; }
.pv-cands code { font-size: 10.5px; color: var(--text-muted); }

/* F-125 — the wake control the reclaim refusal offers, in the order rail's workspace card.

   NOT `.cmdrow`: that is the proof panel's row (a bottom border sized for a wide column, no
   wrapping), and reusing it put a stray divider under this button and let a long failure reason
   overflow the rail. Same trap `.wsslots` records one card over. `overflow-wrap: anywhere` because
   the reason is `inspect(term)` — an unbroken tuple with no spaces in it. */
.wswake { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.wswake .warn { overflow-wrap: anywhere; min-width: 0; }
/* The sleep account uses `.warn` inside `.wswake` for the overflow rule above; `.hint` there would
   not wrap an unbreakable `{:tuple, "wo-<uuid>"}`. This makes the account read as information rather
   than as an alarm — a successful sleep is not a warning. */
.wswake .warn.hint, .wswake span.warn { color: var(--text-muted); }

/* P5/P7 — notes inside the preview panel (`.pvpanel`, below). These stay as P5 wrote them because the
   notes were promoted with the panel, including the F-66 lap attribution: a `.warn` among hints, and it
   has to wrap because it carries two run ids in a column that narrows. */
.ap-note { font-size: 11px; margin: 8px 0 0; max-width: 80ch; }
.ap-note.warn { overflow-wrap: anywhere; }

/* P7 — the preview PANEL. It renders only inside `.order-proof.previewing` now (the surface
   swap below), which supplies its box: full column, no border of its own. What survives of P5/P7
   unchanged is everything inside — the switcher, the notes, the frame, the state footer. The
   `pvp-` prefix is *preview panel*; an earlier cut of this block said `pvs-`, for the sidebar
   S-14 withdrew. The tab row (`pvp-tabs`) is gone WITH its markup: the lone "Preview" tab's job
   — naming the surface — is the activity rail's now (`#surface-preview`), where a second surface
   actually exists to switch to. */
.pvpanel { background: var(--editor); }

/* The switcher row: the service tabs on the left, `open the room` pinned right — ONE row,
   never wrapped. The tab strip is the thing that yields (it shrinks and scrolls; that is what
   a tab strip is — the first live review's finding), so the row's buttons cannot be pushed
   onto an orphan line below it, which is exactly what `flex-wrap: wrap` here did the moment
   eleven services filled the strip. */
.pvp-bar { display: flex; align-items: center; gap: 6px; flex-wrap: nowrap; min-width: 0; }
.pvp-bar .pv-tabs { flex: 1 1 auto; min-width: 0; }
.pvp-bar .btn { flex: none; white-space: nowrap; }
.pvp-bar a.btn { text-decoration: none; }

.pvp-frame-wrap { display: flex; flex-direction: column; gap: 6px; margin-top: 8px; }
.pvp-frame {
  width: 100%;
  border: 1px solid var(--border);
  border-radius: 4px;
  background: var(--surface);
}

/* ══ the order column SURFACES — the activity rail swaps what the middle column carries.
   The docked SPLIT this replaces put proof and app side by side and paid for it in width:
   five fixed columns whose minimums (1516px) clipped a 14″ laptop, with the proof — the
   decision surface — the only band allowed to shrink. `.previewing` exists only while the
   preview surface is up; closed, `.op-content` is an unstyled block and every rule below is
   inert. The conversation rail is untouched either way (S-14). ══ */

/* the rail itself: two surface tabs, flat, 1px-bordered, no fill until chosen — Zed's traits */
/* rail-4 (2026-08-17): the order rail gets WORDS — its two jobs finally named. The
   surface group (order/preview, radio) and the reference group (workspace/watching/
   automation/source, drawers) share the settings-nav grammar: labels, accent bar,
   hover. The glyphs stay as 13px leading icons. */
.cols.order .actrail {
  width: 148px; flex: none;
  border-right: 1px solid var(--border-variant);
  background: var(--surface);
  display: flex; flex-direction: column; align-items: stretch;
  padding: 10px 8px; gap: 1px;
}
.actrail .rl {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-placeholder); font-weight: 600; margin: 2px 2px 6px;
}
.actrail .surf {
  position: relative;
  display: flex; align-items: center; gap: 7px;
  border: none; border-radius: 5px;
  background: none; color: var(--text);
  font: inherit; font-size: 12px; text-align: left;
  line-height: 1.4; cursor: pointer; padding: 5px 8px 5px 12px;
}
.actrail .surf .g { flex: none; width: 16px; text-align: center; font-size: 13px; color: var(--hint); }
.actrail .surf:hover { background: var(--element-hover); }
.actrail .surf.on { background: var(--element-selected); }
.actrail .surf.on::before, .actrail .surf[aria-expanded="true"]::before {
  content: ""; position: absolute; left: 3px; top: 5px; bottom: 5px;
  width: 2px; border-radius: 2px; background: var(--text-accent);
}
.actrail .surf[aria-expanded="true"] { background: var(--element-selected); }
.actrail .surf:focus-visible { outline: 2px solid var(--text-accent); outline-offset: 1px; }
.actrail .actsurfs { display: flex; flex-direction: column; align-items: stretch; gap: 1px; }
.actrail .actdiv { border-top: 1px solid var(--border-variant); margin: 8px 2px; }

/* the reference drawer — one at a time, over the surface, anchored at the rail. The cards
   inside are the reference column's own, so its long-string containment rules come along:
   a cite chip or an unbroken namespace would otherwise push the fixed width open sideways. */
.cols.order { position: relative; }
.refdrawer {
  position: absolute; left: 148px; top: 0; bottom: 0; width: 288px; z-index: 6;
  background: var(--surface); border-right: 1px solid var(--border);
  overflow-y: auto; overflow-x: hidden; padding: 8px 10px;
}
.drawerhead { display: flex; align-items: center; gap: 6px; margin-bottom: 6px; }
.drawerhead .klabel { padding: 0; }
.refdrawer .card-what { overflow-wrap: anywhere; word-break: break-word; }
.refdrawer .chip.mono { max-width: 100%; white-space: normal; overflow-wrap: anywhere; word-break: break-word; }
.refdrawer .sha { min-width: 0; overflow-wrap: anywhere; word-break: break-word; }
.refdrawer .sha > * { min-width: 0; }

/* the work order at the head of its surface — pinned above the scrolling proof, so the text
   the work is judged against stays in view. Capped, and the cap SCROLLS (never clips): the
   264px rail clipping this text mid-sentence is a live-review finding. */
.cols.order .order-brief { flex: none; padding: 12px 16px 0; }
.cols.order .order-brief .card { max-height: 34vh; overflow-y: auto; }
.cols.order .order-brief .card-what { overflow-wrap: anywhere; }

/* the preview surface: the whole middle column, its own scroll, the frame taking the slack */
.cols.order .order-proof.previewing { display: flex; flex-direction: column; padding: 0; overflow: hidden; }
.order-proof.previewing > .pvpanel {
  flex: 1 1 auto; min-height: 0; min-width: 0;
  margin: 0; border: none; border-radius: 0;
  display: flex; flex-direction: column;
  overflow-y: auto; padding: 7px 12px 10px;
}
.order-proof.previewing .pvp-frame-wrap { flex: 1 1 auto; min-height: 0; }
.order-proof.previewing .pvp-frame { height: 100%; min-height: 40vh; }

/* service-tab status dots — rendered only from a real read, grey until someone asks */
.pv-dot { display: inline-block; width: 7px; height: 7px; border-radius: 50%; margin-right: 6px;
  background: var(--text-placeholder); vertical-align: 1px; }
.pv-dot.on { background: var(--success); }
.pv-dot.off { background: var(--warning); }
/* started, still binding its port — its own colour, because it 502s like `off` but the instruction is WAIT. */
.pv-dot.starting { background: var(--info); }
.pv-dot.unknown { background: var(--text-placeholder); opacity: .55; }

/* the URL bar — the framed service's address above the frame, browser-shaped: the URL in its
   own bordered box (selectable), the read stamp, then reload and open. Replaces the pv-meta
   caption that sat under the frame. */
.pv-urlbar { display: flex; align-items: center; gap: 8px; margin-top: 8px; min-width: 0; }
.pv-url {
  flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--mono, ui-monospace, monospace); font-size: 11px; color: var(--text-muted);
  background: var(--surface); border: 1px solid var(--border); border-radius: 4px;
  padding: 3px 9px; user-select: all;
}
.pv-read { flex: none; font-size: 10.5px; color: var(--text-muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
/* the bar's controls hold their line: flex was shrinking them and "open ↗" broke into a
   two-line pill taller than the bar it sits in */
.pv-urlbar .btn { flex: none; white-space: nowrap; }
.pv-urlbar a.btn { text-decoration: none; }

/* the state card — the surface when nothing is framed: one centred card carrying the state
   line, the verdict whole, the acts, and the kept URLs. A serving preview renders none of this;
   the tab dots are its answer. */
.pv-state {
  max-width: 520px; margin: 9vh auto 0; padding: 16px 18px;
  border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
  display: flex; flex-direction: column; gap: 10px;
}
.pv-state-line { font-size: 12px; color: var(--text-muted); margin: 0; }
.pv-state-verdict h4 { font-size: 13px; margin: 0 0 4px; }
.pv-state-verdict p { font-size: 12px; line-height: 1.55; color: var(--text-muted); margin: 0; }
.pv-state-verdict p.hint { margin-top: 4px; font-size: 10.5px; font-variant-numeric: tabular-nums; }
.pv-state-acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pv-state-acts .btn { white-space: nowrap; }
.pv-state-acts a.btn { text-decoration: none; }
.pv-state .warn { font-size: 11.5px; overflow-wrap: anywhere; }
.pv-state .pvp-links { border-top: 1px solid var(--border-variant); padding-top: 10px; margin-top: 2px; }

/* the kept-URL chips (and any lite control): a quiet bordered chip, never a bare blue link —
   unstyled anchors were the sleeping screen's link soup */
.btn-lite {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 11px; color: var(--text-muted); text-decoration: none;
  background: var(--editor); border: 1px solid var(--border); border-radius: 4px;
  padding: 2px 8px; cursor: pointer; white-space: nowrap;
}
.btn-lite:hover { color: var(--text); background: var(--element-hover); }
.pvp-links { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-top: 6px; }
.pvp-links .klabel { padding: 0; }

/* ══ the staging rail — the minutes between "claimed" and the agent's first words, named ══ */
.brail { border: 1px solid var(--border); border-radius: 6px; background: var(--surface);
  margin-bottom: 12px; overflow: hidden; }
.brail-head { display: flex; align-items: baseline; gap: 10px; padding: 8px 12px 6px; }
.brail-when { margin-left: auto; font-size: 10.5px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
.brail-bar { height: 3px; background: var(--editor); }
.brail-bar i { display: block; height: 100%; transform-origin: left; transform: scaleX(0);
  background: var(--text-accent);
  transition: transform .5s ease; }
.brail-stages { list-style: none; margin: 0; padding: 6px 8px 8px; }
.bstage { display: grid; grid-template-columns: 20px 1fr auto; gap: 8px; padding: 5px 6px;
  border-radius: 5px; font-size: 12px; align-items: baseline; }
/* each stage's own duration, right-aligned — done stages read as a total, the active one
   ticks ("14s…") with the rail's poll */
.bstage .bdur { font-size: 11px; color: var(--text-muted); white-space: nowrap;
  font-variant-numeric: tabular-nums; }
.bstage .bmark { text-align: center; font-family: var(--mono, ui-monospace, monospace); }
.bstage.done .bmark { color: var(--success); }
.bstage.active { background: var(--element-hover); }
.bstage.active .bmark { color: var(--warning); animation: brail-pulse 1.6s ease-in-out infinite; }
.bstage.todo { opacity: .45; }
.bstage .bwhat small { display: block; font-size: 10.5px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }
@keyframes brail-pulse { 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) {
  .bstage.active .bmark { animation: none; }
  .brail-bar i { transition: none; }
}

/* ══ the phase bar — where the ORDER's wall clock went (pagehead) ══
   Sibling to the staging `.brail` above: the boot rail tells the before-the-agent
   story live and retires itself; this tells the whole-life story after the fact —
   the five phases as one horizontal budget, colored per phase, with the worked-vs-
   waited split named beside it and the WORKING segment folding open to per-tool
   detail. It wraps to its own full-width line under the pagehead's title row. */
/* rail-4 polish: the time chip sits IN the header row beside the status pill, at the
   chip metric; the breakdown opens as a popover instead of growing the header. */
.phasebar { position: relative; display: inline-flex; }
/* per-phase hue — queued idles grey, working is the worked green, waiting-on-you
   is the same warning the pill and boot rail use, landing blends toward the merge */
.phasebar .queued  { --ph: var(--text-muted); }
.phasebar .booting { --ph: var(--info); }
.phasebar .working { --ph: var(--success); }
.phasebar .waiting_on_human { --ph: var(--warning); }
.phasebar .landing { --ph: color-mix(in srgb, var(--success), var(--info)); }

.pbar { display: flex; gap: 2px; height: 4px; border-radius: 3px; overflow: hidden;
  background: var(--editor); }
.pbar .pseg { display: block; height: 100%; min-width: 3px; background: var(--ph);
  transition: flex-grow .5s ease; }
/* an absent phase took no derivable time — a faint, empty sliver, NOT a zero-width
   claim it was skipped; the present-but-unbounded one reads the same faint way */
.pbar .pseg.absent, .pbar .pseg.present { background: var(--border); opacity: .5;
  flex-grow: 0; flex-basis: 6px; }
.pbar .pseg.active { animation: brail-pulse 1.6s ease-in-out infinite; }

.pbar-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; margin-top: 5px; }
.pleg { display: inline-flex; align-items: baseline; gap: 5px; font-size: 11px; }
.pleg em { font-style: normal; color: var(--text-muted); display: inline-flex;
  align-items: baseline; gap: 5px; }
/* the phase's own dot, its hue */
.pleg em::before { content: ""; width: 7px; height: 7px; border-radius: 2px;
  background: var(--ph); align-self: center; }
.pleg b { color: var(--text); font-variant-numeric: tabular-nums; font-weight: 500; }
.pleg .approx { color: var(--text-muted); }
.pleg.absent em, .pleg.present em { opacity: .5; }
.pleg.active b { color: var(--warning); }

/* The chip is the toggle: a <summary> styled as the pill, collapsed by default,
   opening to the .pbar + .pbar-legend below. The ▸/▾ disclosure marker rides IN
   the pill (the same idiom the retired per-tool drill-down used) so the chip
   reads as clickable. The phase bar and breakdown are hidden until then. */
.pbar-chip { font: 600 10.5px/1.4 ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  color: var(--text-muted); font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
  padding: 1.5px 8px; border: 1px solid var(--border); border-radius: 999px; background: var(--element); }
.pbar-chip:hover { border-color: var(--text-accent); background: var(--element-hover); }
.pbar-chip b { color: var(--text); font-weight: 650; }
.pbar-disclosure > summary.pbar-chip { cursor: pointer; list-style: none;
  display: inline-flex; align-items: baseline; gap: 6px; width: fit-content; }
.pbar-disclosure > summary.pbar-chip::-webkit-details-marker { display: none; }
.pbar-disclosure > summary.pbar-chip::after { content: "▸"; color: var(--text-muted);
  font-size: 10px; }
.pbar-disclosure[open] > summary.pbar-chip::after { content: "▾"; }
.pbar-pop { position: absolute; top: calc(100% + 6px); left: 0; z-index: 8; min-width: 340px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface); padding: 10px 12px; }
@media (prefers-reduced-motion: reduce) {
  .pbar .pseg.active { animation: none; }
  .pbar .pseg { transition: none; }
}

/* ══ the PLAN's time story — where a whole plan's clock went ══
   The order phase-bar above tells one RUN's story; these three tell the plan's,
   summed across its stage orders' run timelines (Foundry.Engine.Timeline, folded
   in FoundryWeb.PlanSurface.branch/1). Same visual family as the phase bar — thin
   proportional bars, a compact rollup line — sized for the plan pagehead and rail. */

/* the pagehead rollup: "N stages · ~Xh worked · ~Yh waited · M human min" */
.plan-rollup { font-size: 12px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; white-space: nowrap; }

/* the branch-rail time axis (.plan-axis) — the segmented per-stage bar under the
   plan rail's switches — is gone with the 2026-08-15 UI declutter. The plan-rollup
   line above still names where the plan's clock went in words. */

/* the stage card's cut→landed duration; the worked/waited split meter that used to
   sit beside it retired with the same declutter, the duration number stays */
.branch-dur { font-size: 11px; color: var(--text-muted);
  font-variant-numeric: tabular-nums; }

/* pane polish from the first live review (wo-…66f5e7): fourteen services wrapped the switcher
   into a tall block that ate the frame's height — the row stays one line and scrolls, which is
   what a tab strip is. (The lone "Preview" TAB that review also flagged is gone entirely with
   the surface swap; the activity rail names the surface now.) */
.pv-tabs { display: flex; flex-wrap: nowrap; overflow-x: auto; max-width: 100%;
  scrollbar-width: thin; }
.pv-tabs .pv-tab { white-space: nowrap; flex: none; }


/* ═══════════════════════════════════════════════════════════════════════════
   A PHONE ON A DESKTOP ROUTE — the survival layer

   /m is the phone surface, and a narrow viewport is REDIRECTED there for every
   place that has a twin (see the root layout's script). What is left over is
   the dozen routes /m deliberately does not cover — a source place, the
   terminal, the playbook, the automation composer, the delete confirmations —
   reached on a phone by following a link.

   This layer exists so those pages are READABLE, not so they are good. It does
   one thing: stop fixed-width columns from running off the screen. It does not
   re-compose anything, which is what the previous version of this section did
   for the queue, the inbox, the runs page and the order place — 388 lines of
   overrides fighting rules written for a wider screen, and the source of every
   phone bug this project has had (a review column's flex:1 collapsing a band to
   33px; a horizontal centring becoming vertical and hiding the top of a list; a
   `flex: none` for one mode stopping another mode's surface scrolling at all).
   Those pages have compositions of their own now, so their overrides are gone.

   The rule for anything added here: if it RE-ARRANGES, it belongs in
   FoundryWeb.Mobile as a real composition. If it only prevents an overflow, it
   belongs here.
   ═══════════════════════════════════════════════════════════════════════════ */

:root { --tabh: 0px; }

@media (max-width: 820px) {
  /* dvh, not vh: mobile Safari's vh is the URL-bar-collapsed height. */
  .shell {
    height: calc(100dvh - 32px - env(safe-area-inset-top, 0px));
    margin-top: env(safe-area-inset-top, 0px);
  }
  .sidebar { display: none; }
  .statusbar { display: none; }

  /* the title bar keeps identity and the two controls; the place tabs go —
     they are a row of six on a 390px screen */
  .titlebar { padding: 0 4px 0 8px; gap: 4px; }
  .titlebar > .tab { display: none; }
  .titlebar > .workviews { display: none; }
  .titlebar .brand { padding-right: 4px; }
  .cmdk-open .kbd, .switcher .kbd, .titlebar .kbd { display: none; }

  /* ── stacking: a fixed-width column is the only thing that truly breaks ──
     Each mode restates `flex: none` at its own specificity — `.cols.source`
     carries flex:1 for the desktop review column, and a flex:1 band inside a
     scrolling column collapses to the free space while its content spills out
     over whatever is below it. */
  .cols { flex-direction: column; overflow-y: auto; }
  .cols > .wsrail, .cols > .rrail, .cols > .main {
    width: auto; min-width: 0; flex: none;
    border-left: none; border-right: none; border-bottom: 1px solid var(--border-variant);
  }
  .cols.source > .wsrail, .cols.source > .rrail, .cols.source > .main {
    width: auto; min-width: 0; flex: none; padding: 10px 12px;
  }
  .cols.term > .rrail, .cols.term > .main { width: auto; min-width: 0; flex: none; }

  /* art-3 push-panel — the desktop three-track grid stacks like every other `.cols` mode on
     the phone: drop back to the flex column the base mobile rule expects, and let the panel
     (when open) be a full-width stacked band rather than a grid track. */
  .cols.session { display: flex; grid-template-columns: none; }
  .cols.session > .apanel {
    width: auto; min-width: 0; flex: none; overflow: visible;
    border-left: none; border-bottom: 1px solid var(--border-variant);
  }

  /* `height: 100%` (the base rule) is what makes overflow-y: auto bite; with
     height:auto the box grows to its content and the DOCUMENT scrolls instead,
     taking the shell with it. */
  .workspace { flex-direction: column; overflow-y: auto; }
  .workspace > .panel, .workspace > .panel.right, .workspace > .pane {
    width: auto; min-width: 0; max-width: none; flex: none;
    border-right: none; border-left: none; border-bottom: 1px solid var(--border);
    overflow-y: visible;
  }
  /* horizontal centring becomes VERTICAL centring in a column, and a centred
     item taller than its container overflows at BOTH ends, where no scrollbar
     reaches */
  .workspace.inbox-single { justify-content: flex-start; }
  .workspace.inbox-single > .panel { flex: none; }

  .playbook { flex-direction: column; overflow-y: auto; }
  .playbook > .pb-files, .playbook > .pb-doc, .playbook > .pb-proposals {
    width: auto; flex: none; min-width: 0; overflow-y: visible;
    border-left: none; border-right: none; border-bottom: 1px solid var(--border);
  }
  .playbook > .pb-doc { padding: 14px 14px 18px; }

  .ovgrid { grid-template-columns: minmax(0, 1fr); }
  .overview { padding: 12px 12px 16px; }
  .capture { align-items: flex-start; padding: 10px 10px 0; }
  .reqcard { width: auto; max-width: none; }

  /* ── overflow hygiene ──────────────────────────────────────────────────── */
  .pagehead { padding: 8px 12px; gap: 7px; row-gap: 5px; }
  .pagehead .crumb {
    display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
    overflow: hidden; font-size: 11px;
  }
  /* copy that names a column has nothing to point at here */
  .desk-only, .pagehead .desk-only { display: none; }
  .pane-header, .panel-header { flex-wrap: wrap; row-gap: 4px; }
  .pane-header > .btn, .panel-header > .btn { flex: none; }
  .plan-head { flex-wrap: wrap; row-gap: 4px; }
  .plan-head .chip, .plan-head .btn { flex: none; white-space: nowrap; }
  .segmented { display: flex; flex-wrap: wrap; gap: 4px; border: none; border-radius: 0; }
  .segmented button { border: 1px solid var(--border); border-radius: 4px; flex: 0 1 auto; white-space: nowrap; }
  /* stacked: the plan rail is a horizontal tab row above the surface, not a side strip.
     `nav.plan-rail` on purpose: the desktop base rules live LATER in this file at equal
     specificity, so without the type selector they win and phones keep the side strip
     (the 2026-08-14 mobile finding). */
  .cols.plan > nav.plan-rail {
    width: auto; flex-direction: row; flex-wrap: wrap; align-self: auto;
    border-right: none; border-bottom: 1px solid var(--border-variant);
  }
  .cols.plan > nav.plan-rail button { flex: 0 1 auto; }
  .cols.plan .main .turns.chat .turn { max-width: 88%; }
  .filters .btn { padding: 6px 11px; }
  table { display: block; overflow-x: auto; max-width: 100%; }
  pre, .diff, .logbox { overflow-x: auto; }
  .card, .qcard, .runrow { max-width: 100%; }
  img, video, canvas, iframe { max-width: 100%; }
  .btn { padding: 7px 12px; font-size: 12px; }
  .navrow, .worow, .sessrow, .qcard { padding: 9px 10px; }
  /* Any focused control under 16px makes iOS zoom the page — a UA behavior
     keyed to the computed size, so EVERY text entry must clear the bar, not
     just the composer (the capture field, notes, the palette, settings all
     zoomed). The board styles these at 11-12px through classed selectors;
     the !important is what lets one statement clear the bar for all of them
     — and any control added later — without re-fighting each here. This is
     a UA-behavior threshold, not a styling preference; pinch-zoom stays. */
  input, textarea, select { font-size: 16px !important; }
  .palette { width: auto; left: 8px; right: 8px; max-width: none; top: 8px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   THE PHONE SURFACE — /m  (prototypes/mobile-columns.html)

   Written MOBILE-FIRST and scoped under `.msurface`: nothing here overrides a
   desktop rule, and no desktop rule reaches in. That is the lesson of the
   responsive layer above, taken as architecture — every bug it produced was a
   rule written for a wider screen being fought by a narrower one, resolved by
   specificity. This section has no fight to win: the phone composition is its
   own tree (FoundryWeb.Mobile), so its CSS can simply state what it wants.

   Everything visual below the shell — .card, .kv, .pill, .chip, .btn, .klabel,
   the proof panel, the call strip, the chat — is the board's own vocabulary,
   reused. Only the SHELL is new, because only the shell differs.
   ═══════════════════════════════════════════════════════════════════════════ */

.msurface {
  position: fixed; inset: 0; z-index: 2;
  display: flex; flex-direction: column;
  background: var(--editor);
  padding-top: env(safe-area-inset-top, 0px);
  transition: transform 0.22s ease;
}
/* Slack-style push: opening the drawer slides the pane right, leaving a ~52px
   sliver of it visible over the drawer beneath. The drawer's width is the same
   translation, so pane and panel move as one. */
html[data-drawer="open"] .msurface { transform: translateX(calc(100vw - 52px)); }

/* ── the top bar: the one persistent project control, on every /m screen ──── */
.mtopbar {
  flex: none; display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 9px 12px; background: var(--title-bar);
  border: none; border-bottom: 1px solid var(--border);
  color: var(--text); font: inherit; text-align: left; cursor: pointer;
}
.mtopbar:active { background: var(--element-hover); }
.mtopbar .pav {
  flex: none; width: 26px; height: 26px; border-radius: 7px;
  display: flex; align-items: center; justify-content: center;
  color: var(--editor); font-size: 12px; font-weight: 700;
}
.mtopbar .ptitle {
  min-width: 0; font-size: 14px; font-weight: 600;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.mtopbar .nbadge {
  flex: none; background: var(--warning); color: var(--editor);
  font-size: 10px; font-weight: 700; line-height: 1.6; border-radius: 8px; padding: 0 6px;
}
.mtopbar .spacer { flex: 1; }
.mtopbar .mgrip { flex: none; color: var(--text-muted); font-size: 14px; }

/* ── the project drawer: a left panel under the sliding pane ──────────────── */
.mdrawer {
  position: fixed; left: 0; top: 0; bottom: 0; z-index: 1;
  width: calc(100vw - 52px);
  display: flex; flex-direction: column;
  background: var(--title-bar); border-right: 1px solid var(--border);
  padding-top: env(safe-area-inset-top, 0px);
  overflow-y: auto; -webkit-overflow-scrolling: touch;
}
.mdrawer-head {
  flex: none; padding: 14px 16px 8px;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); font-weight: 600;
}
.mdrow {
  display: flex; align-items: center; gap: 10px; padding: 10px 14px;
  color: var(--text-muted); text-decoration: none; font-size: 13.5px;
  border-left: 2px solid transparent;
}
.mdrow.on { color: var(--text); background: var(--element-selected); border-left-color: var(--text-accent); }
.mdrow:active { background: var(--element-hover); }
.mdrow .pav {
  flex: none; width: 24px; height: 24px; border-radius: 6px;
  display: flex; align-items: center; justify-content: center;
  color: var(--editor); font-size: 11px; font-weight: 700;
}
.mdrow .pname { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.mdrow .land { flex: none; font-size: 10.5px; color: var(--text-placeholder); }
.mdrow .n {
  flex: none; font-size: 10px; font-weight: 700; border-radius: 8px; padding: 0 5px;
  background: var(--element-selected); color: var(--text-muted);
}
.mdrow .n.hot { background: var(--warning); color: var(--editor); }

/* the scrim over the pushed-aside pane: it covers the visible sliver so any tap
   there closes the drawer. Scoped to the pane (absolute inside .msurface), so it
   never covers the drawer itself. */
.mdrawer-scrim { display: none; }
html[data-drawer="open"] .mdrawer-scrim {
  display: block; position: absolute; inset: 0; z-index: 30;
}

.mstreamhead {
  flex: none; display: flex; align-items: center; gap: 8px; padding: 10px 12px 6px;
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); font-weight: 600;
}
.mstreamhead .maside {
  font-weight: 400; text-transform: none; letter-spacing: 0; font-size: 11px;
  color: var(--text-placeholder);
}

/* ── the scrolling stream ─────────────────────────────────────────────────── */
.mbody { flex: 1; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch; }
.mpad { padding: 10px 12px 16px; }

.mrow {
  display: block; padding: 10px 12px; border-bottom: 1px solid var(--border-variant);
  color: var(--text); text-decoration: none;
}
.mrow:active { background: var(--element-hover); }
.mrow .t { display: flex; align-items: flex-start; gap: 8px; font-size: 12.5px; }
.mrow .t .ttl {
  flex: 1; min-width: 0; line-height: 1.4;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.mrow .t .pill { flex: none; margin-top: 1px; }
.mrow .sub {
  display: flex; align-items: center; gap: 5px; flex-wrap: wrap;
  font-size: 10.5px; color: var(--text-muted); margin-top: 3px; padding-left: 15px;
}
.mdot { width: 7px; height: 7px; border-radius: 50%; flex: none; margin-top: 5px; }
.mdot.needs, .mdot.red, .mdot.failed { background: var(--error); }
.mdot.hold { background: var(--info); }
.mdot.in_progress, .mdot.running { background: var(--warning); animation: pulse 1.2s infinite; }
.mdot.needs { animation: pulse 1.2s infinite; }
.mdot.done { background: var(--success); }
.mdot.draft, .mdot.created, .mdot.interrupted { background: var(--text-muted); }
.mdot.approved { background: var(--info); }
.mdot.parked { background: var(--text-placeholder); }

.mempty { padding: 20px 14px; color: var(--text-placeholder); font-size: 12px; }

/* ── the tab bar ──────────────────────────────────────────────────────────── */
.mtabs {
  flex: none; display: flex; background: var(--title-bar); border-top: 1px solid var(--border);
  padding: 5px 2px calc(4px + env(safe-area-inset-bottom, 0px));
}
.mtab {
  flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 4px 2px 2px; position: relative;
  background: none; border: none; cursor: pointer; font: inherit;
  color: var(--text-placeholder); text-decoration: none;
}
.mtab .l { font-size: 9.5px; }
.mtab .icon svg { width: 17px; height: 17px; }
.mtab.on { color: var(--text-accent); }
.mtab:active { background: var(--element-hover); }
.mtab .n {
  position: absolute; top: 2px; left: 50%; margin-left: 5px;
  background: var(--warning); color: var(--editor);
  font-size: 9px; font-weight: 700; line-height: 1.5; border-radius: 7px; padding: 0 4px;
}

/* ── the `more` and `account` bottom sheets ───────────────────────────────── */
/* The two sheets share the .msheet shape; the modifier `data-` attribute keys
   which one is open, and `.account` scopes the scrim/sheet pair so opening one
   never reveals the other (both carry the .msheet-scrim/.msheet classes). */
.msheet-scrim, .msheet { display: none; }
html[data-more="open"] .msheet-scrim:not(.account),
html[data-account="open"] .msheet-scrim.account {
  display: block; position: fixed; inset: 0; z-index: 41; background: #0006;
}
html[data-more="open"] .msheet:not(.account),
html[data-account="open"] .msheet.account {
  display: flex; flex-direction: column;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 42; max-height: 80dvh; overflow-y: auto;
  background: var(--surface); border-top: 1px solid var(--border); border-radius: 12px 12px 0 0;
  padding: 6px 0 calc(10px + env(safe-area-inset-bottom, 0px));
}
.msheet .grab {
  width: 36px; height: 4px; border-radius: 2px; background: var(--border);
  margin: 2px auto 6px; flex: none;
}
.msheet .mslabel {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-muted); font-weight: 600; padding: 10px 16px 4px;
}
.msheet .msrow {
  display: flex; align-items: center; gap: 10px; padding: 11px 16px;
  font-size: 13px; color: var(--text); text-decoration: none;
  background: none; border: none; width: 100%; text-align: left; cursor: pointer; font-family: inherit;
}
.msheet .msrow:active { background: var(--element-hover); }
.msheet .msrow .val { margin-left: auto; color: var(--text-muted); font-size: 12px; }
.msheet .msrow.out .val { color: var(--text-placeholder); font-size: 11px; }

/* the account sheet's identity header — name · email · role, read-only here. */
.msheet.account .macct-id {
  display: flex; align-items: center; gap: 11px; padding: 6px 16px 10px;
  border-bottom: 1px solid var(--border-variant); margin-bottom: 2px;
}
.msheet.account .macct-id .who { display: flex; flex-direction: column; min-width: 0; }
.msheet.account .macct-id .nm {
  font-size: 14px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.msheet.account .macct-id .sub { font-size: 11.5px; color: var(--text-muted); }
.msheet.account .macct-out { display: block; margin-top: 6px; border-top: 1px solid var(--border-variant); }
.msheet.account .msrow.signout { color: var(--error); }

/* the round identity avatar, shared by the drawer footer and the account sheet. */
.uav {
  flex: none; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--element-selected); color: var(--text);
  font-size: 12px; font-weight: 700;
}

/* ── the drawer footer — who is signed in ─────────────────────────────────── */
.macctbtn {
  flex: none; margin-top: auto; display: flex; align-items: center; gap: 10px;
  padding: 12px 14px calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--title-bar); border: none; border-top: 1px solid var(--border);
  width: 100%; text-align: left; cursor: pointer; font-family: inherit; color: var(--text);
  position: sticky; bottom: 0;
}
.macctbtn:active { background: var(--element-hover); }
.macctbtn .who { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.macctbtn .nm {
  font-size: 13px; font-weight: 600; color: var(--text);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.macctbtn .sub {
  font-size: 10.5px; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.macctbtn .mgrip { flex: none; color: var(--text-placeholder); font-size: 12px; }

/* ── a detail push (the order, the preview) ───────────────────────────────── */
.mdetail .mdhead {
  flex: none; padding: 8px 12px 0; background: var(--editor); border-bottom: 1px solid var(--border);
}
.mdhead .idline { display: flex; align-items: center; gap: 8px; font-size: 11px; color: var(--text-muted); }
.mdhead .idline .dim { color: var(--text-placeholder); }
/* the primary navigation on a detail push: a thumb target, not a glyph */
.mback {
  color: var(--text-accent); font-size: 17px; line-height: 1; text-decoration: none;
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 34px; height: 34px; margin-left: -8px;
}

/* the order's own words: two lines, expanded in place. <details> so the open
   state belongs to the browser and survives a LiveView patch. */
.mwhat { margin: 6px 0 4px; }
.mwhat > summary { list-style: none; cursor: pointer; }
.mwhat > summary::-webkit-details-marker { display: none; }
.mwhat .wtext {
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
  font-size: 12.5px; color: var(--text-muted); line-height: 1.4;
}
.mwhat .exp { display: inline-block; margin-top: 3px; font-size: 11.5px; color: var(--text-accent); }
.mwhat[open] > summary .wtext { display: none; }
.mwhat[open] > summary .exp::after { content: " ⌃"; }
.mwhat:not([open]) > summary .exp::after { content: " ⌄"; }
.mwhat .wfull {
  font-size: 12.5px; color: var(--text); white-space: pre-wrap; word-break: break-word;
  padding: 6px 0 8px; max-height: 46dvh; overflow-y: auto;
}

.mseg { display: flex; align-items: stretch; }
.mseg > button, .mseg > .pv {
  flex: 1; background: none; border: none; border-bottom: 2px solid transparent;
  color: var(--text-muted); font: inherit; font-size: 12.5px; padding: 9px 4px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: 6px; text-decoration: none;
}
.mseg > button.on { color: var(--text); border-bottom-color: var(--text-accent); }
.mseg .n { font-size: 10px; color: var(--text-placeholder); }
.mseg > .pv { flex: none; width: 48px; font-size: 14px; }

/* The verdict is an ECHO here, exactly as it is on the desktop strip: its full
   text reads under "does it work", and verdicts run to 1500 characters of
   ·-joined command log. Two lines, and the clamp needs MARGIN rather than
   padding — padding sits inside the clipped box, so a third line shows through
   it and the ellipsis lands mid-word. */
.mverdict {
  font-size: 12.5px; color: var(--success); margin: 2px 0 10px; padding: 0;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}

/* the proof panel and the call strip are the desktop's own components: they only
   need the phone's spacing, not a phone version */
.mdetail .order-proof, .mdetail .proof { padding: 0; }
.mdetail .q3 { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px; padding: 10px 0 0; }
.mdetail .qcard .qs { display: none; }
.mdetail .qcard .qv { font-size: 11.5px; }
.mdetail .callstrip { flex: none; margin: 0; border-radius: 0; border-left: none; border-right: none; border-bottom: none; }
.mdetail .callstrip .cs-acts { padding: 9px 12px calc(9px + env(safe-area-inset-bottom, 0px)); gap: 8px; }
.mdetail .callstrip .cs-acts > .spacer { display: none; }
.mdetail .callstrip .cs-acts .btn { padding: 9px 14px; font-size: 12.5px; white-space: nowrap; }
.mdetail .callstrip .act-group { flex: 1 1 auto; min-width: 0; display: flex; align-items: center; gap: 8px; }
.mdetail .callstrip .act-group .next { flex: 1; min-width: 0; display: flex; }
.mdetail .callstrip .act-group .next .btn { flex: 1; justify-content: center; text-align: center; }
.mdetail .callstrip .act-group .nlabel { display: none; }
/* docked at the bottom, so its menu opens UPWARD or it opens off-screen */
.mdetail .callstrip .menu-pop {
  top: auto; bottom: calc(100% + 6px); right: 0; left: auto;
  min-width: 0; width: max-content; max-width: calc(100vw - 24px); max-height: 60dvh; overflow-y: auto;
}
.mdetail .callstrip .mi { padding: 9px 11px; }

/* the thread pane: the chat, with its composer docked */
.mthread { display: flex; flex-direction: column; padding: 0; }
.mthread .turns { flex: 1; min-height: 0; overflow-y: auto; padding: 12px; }
.mthread .composer { flex: none; padding: 8px 10px calc(8px + env(safe-area-inset-bottom, 0px)); }
/* The 820px block above already clears iOS's 16px focus-zoom threshold, but
   the phone tree can render wider than that (a tablet on /m) — so the same
   statement again, scoped to this surface. Same reasoning as there. */
.msurface input, .msurface textarea, .msurface select { font-size: 16px !important; }

/* the preview push */
.mpvacts { display: flex; gap: 8px; margin: 10px 0 4px; }
.mpvacts .btn { flex: 1; text-align: center; padding: 10px 12px; }
/* the bundle-version tabs and inline text controls carry a thumb's worth of
   height inside the phone surface — 22px is a mouse target, not a finger's */
.msurface .vtab { padding: 7px 10px; }
.msurface .lin { padding: 9px 0; display: inline-block; }
.msurface .proof .pf-head { flex-wrap: wrap; row-gap: 4px; }

.mpvframe {
  width: 100%; height: 210px; border: 1px solid var(--border); border-radius: 5px;
  background: var(--editor);
}

/* ── session place (WO-C): the state pill + asleep dim ──────────────────── */
/* Reuses .place / .pagehead / .cols / .main / .turns.chat / .composer wholesale;
   only the session's own lifecycle pill and a dim on an asleep thread are new. */
.pill.sess-awake { border-color: var(--success); color: var(--success); }
.pill.sess-asleep { border-color: var(--text-muted); color: var(--text-muted); }
.pill.sess-closed { border-color: var(--border); color: var(--text-placeholder); }
.cols.session .main .turns.chat { min-height: 0; }

/* ── plan place (step 3 slice 3): the compact surface rail + the projected chat ───────────
   Slice 3 shipped the plan page with NO layout CSS of its own, so the surface rail fell back to
   the horizontal `.segmented` control stretched down the `.cols` row — three full-height strips,
   labels floating mid-height, eating the page's left third — and the thread inherited the full
   page measure (a long human bubble spanning ~1760px at desk width). This block gives the plan
   place the shape its doctrine names:

     * the RAIL as ONE compact strip, modelled on the order place's `.actrail` (the rail
       doctrine's origin): the three switches grouped at its top, the active surface owning the
       rest of the width. A slim tab COLUMN rather than a 44px glyph rail, because the switches
       carry words (thread · preview · branch), not icons.
     * the THREAD as a chat at a READABLE MEASURE — the session place's `.turns.chat` reused
       wholesale, capped and centred so a bubble pins to the edge of the column, never the far
       side of a 2000px page. The composer follows the same centred measure, pinned bottom the
       way the session place pins it — no third pattern. */
/* rail-4 (2026-08-17): the plan rail wears the labeled settings-nav grammar — words,
   an accent bar for the active surface, quiet counts. One rail idiom across the app. */
.cols.plan .plan-rail {
  flex: none;
  width: 148px;
  align-self: stretch;
  border-right: 1px solid var(--border-variant);
  background: var(--surface);
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 1px;
  padding: 10px 8px;
}
.cols.plan .plan-rail .rl {
  font-size: 10px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-placeholder); font-weight: 600; margin: 2px 2px 6px;
}
.cols.plan .plan-rail button {
  position: relative;
  display: flex; align-items: center; gap: 7px;
  border: none; border-radius: 5px;
  background: none;
  color: var(--text);
  font: inherit;
  font-size: 12px;
  text-align: left;
  padding: 5px 8px 5px 12px;
  cursor: pointer;
}
.cols.plan .plan-rail button svg { width: 13px; height: 13px; flex: none; color: var(--hint); }
.cols.plan .plan-rail button .n {
  margin-left: auto; font-size: 10px; color: var(--text-muted);
  background: var(--element-selected); border: 1px solid var(--border);
  border-radius: 7px; padding: 0 6px;
}
.cols.plan .plan-rail button:hover { background: var(--element-hover); }
.cols.plan .plan-rail button:focus-visible { outline: 2px solid var(--text-accent); outline-offset: 1px; }
.cols.plan .plan-rail button[aria-pressed="true"] { background: var(--element-selected); }
.cols.plan .plan-rail button[aria-pressed="true"]::before {
  content: ""; position: absolute; left: 3px; top: 5px; bottom: 5px;
  width: 2px; border-radius: 2px; background: var(--text-accent);
}

/* the stream reads at a readable measure, centred in the wide surface */
.cols.plan .main .turns.chat { max-width: 900px; width: 100%; margin: 0 auto; min-height: 0; }
/* a bubble never spans the desk: cap it to the column, keep you-right / planner-left */
.cols.plan .main .turns.chat .turn { max-width: 78%; }

/* the composer follows the same centred measure — the bar spans full width (like the session's),
   its input aligns with the thread above it */
.cols.plan .main .composer { display: flex; flex-direction: column; }
.cols.plan .main .composer > * { max-width: 900px; width: 100%; margin-inline: auto; }

/* a lap boundary and a machine transition are UTTERANCES, not badges — quiet inline stream
   markers with the stream's own rhythm, not detached boxes with arbitrary gaps */
.cols.plan .main .turns.chat .plan-mark { font-size: 10.5px; color: var(--hint); }
.cols.plan .main .turns.chat .plan-mark.lap {
  align-self: stretch;
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-muted);
  margin: 2px 0;
}
.cols.plan .main .turns.chat .plan-mark.lap::before,
.cols.plan .main .turns.chat .plan-mark.lap::after {
  content: "";
  flex: 1;
  border-top: 1px solid var(--border-variant);
}
.cols.plan .main .turns.chat .plan-mark.move {
  align-self: center;
  display: flex;
  gap: 7px;
  align-items: baseline;
}
.cols.plan .main .turns.chat .plan-mark.move .when { color: var(--hint); }

/* the inline stream acts (answer card, the one agree card, gated moves) keep to the measure */
.cols.plan .main .turns.chat .plan-act { align-self: stretch; max-width: 100%; }

/* ── the plan's preview / branch panes (2026-08-14: the branch rows had no styles at all —
     they rendered as a wall of raw inline links, worst on a phone) ─────────────────────── */
.cols.plan .plan-pane { max-width: 900px; width: 100%; margin: 0 auto; padding: 14px 16px; }
.cols.plan .plan-pane .klabel { font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--hint); margin-bottom: 6px; }
.cols.plan .branch-order {
  display: flex; align-items: center; gap: 8px;
  padding: 9px 10px; margin: 6px 0;
  border: 1px solid var(--border-variant); border-radius: 6px;
  text-decoration: none; color: var(--text);
  background: var(--surface);
}
.cols.plan .branch-order:hover { border-color: var(--border); }
.cols.plan .branch-order .ttl {
  flex: 1 1 auto; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px;
}
.cols.plan .branch-order .pill, .cols.plan .branch-order .chip { flex: none; white-space: nowrap; }

/* ── the identity doors: /sign-in, /register, /sign-out ────────────────────
   MULTI-TENANCY. AshAuthentication.Phoenix renders SignInLive with class names
   supplied by an overrides module; `FoundryWeb.AuthOverrides` points them here,
   so the stock (Tailwind-shaped) doors wear the board's own Zed look instead. */

.auth-page {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 24px;
  background: var(--background);
}

.auth-card {
  width: min(92vw, 380px);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 28px 26px 24px;
}

.auth-banner { text-align: center; margin-bottom: 18px; }
/* The wordmark lives inside this <a>, so its color is set HERE, not on .auth-brand:
   an anchor with no `color` falls back to the UA link color (blue, and dark purple
   once visited) — which on the dark card read as an unreadable dark-on-dark wordmark.
   `var(--text)` is the board's own brand color (the chrome's `.brand` uses it too). */
.auth-brand-link {
  text-decoration: none;
  color: var(--text);
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
/* The board's factory glyph beside the wordmark, matching the chrome's
   `<.icon name="factory" /> foundry` (lib/foundry_web/layouts.ex). Masked from the
   same vendored SVG so it paints in `currentColor` and tracks the text in either theme. */
.auth-brand-link::before {
  content: "";
  width: 19px;
  height: 19px;
  flex: none;
  background-color: currentColor;
  -webkit-mask: var(--auth-brand-glyph) center / contain no-repeat;
  mask: var(--auth-brand-glyph) center / contain no-repeat;
}
.auth-brand {
  font-size: 19px;
  font-weight: 600;
  letter-spacing: 0.3px;
  color: var(--text);
  --auth-brand-glyph: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%20fill='none'%3E%3Cpath%20d='M2%2012.9C2%2013.51%202.49%2014%203.1%2014H12.9C13.51%2014%2014%2013.51%2014%2012.9V6.2L9.8%209.2V6.2L5.6%209.2V3.1C5.6%202.49%205.11%202%204.5%202H3.1C2.49%202%202%202.49%202%203.1V12.9Z'%20stroke='black'%20stroke-width='1.2'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3Cpath%20d='M4.9%2011.5H4.91M8%2011.5H8.01M11.1%2011.5H11.11'%20stroke='black'%20stroke-width='1.2'%20stroke-linecap='round'%20stroke-linejoin='round'/%3E%3C/svg%3E");
}

.auth-strategy { margin: 0; }
.auth-pw { margin: 0; }
.auth-form-root { margin: 0; }
.auth-form { display: block; }
.auth-slot { margin: 8px 0; }

/* the one that must exist: hide the inactive form (no Tailwind `.hidden` here) */
.auth-hidden { display: none !important; }

.auth-h2 {
  font-size: 15px;
  font-weight: 600;
  color: var(--text);
  margin: 0 0 14px;
}

.auth-field { margin: 0 0 12px; }

.auth-label {
  display: block;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-muted);
  font-weight: 600;
  margin: 0 0 5px;
}

.auth-input {
  width: 100%;
  background: var(--editor);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 8px 9px;
  font: inherit;
  font-size: 13px;
}
.auth-input:focus { outline: none; border-color: var(--text-accent); }
.auth-input-error { border-color: var(--error); }

.auth-submit {
  width: 100%;
  margin-top: 6px;
  background: var(--info);
  color: var(--editor);
  border: 1px solid var(--info);
  border-radius: 4px;
  padding: 9px 12px;
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.auth-submit:hover { filter: brightness(1.08); }
.auth-submit:disabled { background: var(--element); border-color: var(--border); color: var(--text-placeholder); filter: none; cursor: not-allowed; }

.auth-interstitial {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 14px;
  font-size: 12px;
}

.auth-toggler {
  color: var(--text-accent);
  text-decoration: none;
  font-size: 12px;
}
.auth-toggler:hover { text-decoration: underline; }

/* INVITE-ONLY registration (owner decision, 2026-08-19). The ONE way to /register is the
   /join/:token → /register?invite=<token> bounce; the sign-in page's stock "Register" toggle links
   to the bare, token-less /register — a form that cannot succeed (RegisterWithInvite refuses it
   server-side). Hide that toggle so the dead door is not offered. The register form's own
   "Already have an account? Sign in" toggle links to /sign-in and is unaffected. */
.auth-toggler[href^="/register"] { display: none; }

.auth-error, .auth-error-text { color: var(--error); text-align: center; font-size: 12px; margin-bottom: 8px; }

.auth-error-ul {
  list-style: none;
  color: var(--error);
  font-size: 11px;
  margin: 5px 0 0;
  padding: 0;
}
.auth-error-li { margin: 1px 0; }

.auth-remember {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 8px 0 2px;
  font-size: 12px;
  color: var(--text-muted);
}
.auth-checkbox { accent-color: var(--info); }
.auth-checkbox-label { font-size: 12px; color: var(--text-muted); }

.auth-info { font-size: 13px; color: var(--text-muted); margin: 0 0 14px; }

.auth-hr { position: relative; margin: 14px 0; }
.auth-hr-outer { position: absolute; inset: 0; display: flex; align-items: center; }
.auth-hr-inner { width: 100%; border-top: 1px solid var(--border-variant); }
.auth-hr-text-outer { position: relative; display: flex; justify-content: center; font-size: 12px; }
.auth-hr-text-inner { padding: 0 8px; background: var(--surface); color: var(--text-muted); }

.auth-flash {
  position: fixed;
  top: 10px;
  right: 10px;
  width: min(90vw, 320px);
  z-index: 50;
  border-radius: 6px;
  border: 1px solid var(--border);
  padding: 9px 11px;
  font-size: 12px;
  background: var(--surface);
  color: var(--text);
}
.auth-flash-info { border-color: var(--success); color: var(--success); }
.auth-flash-error { border-color: var(--error); color: var(--error); }

/* ── the logout control in the board chrome ──────────────────────────────── */
.logout-form { display: inline-flex; margin: 0; }
.logout-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 24px;
  padding: 0 8px;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 4px;
  color: var(--text-muted);
  font-size: 12px;
  cursor: pointer;
}
.logout-btn:hover { background: var(--element-hover); color: var(--text); }

/* ── base rules for classes used everywhere, defined nowhere ─────────────────
   .hint, .dim and .radio-row appear across profile/settings/installations (and
   beyond) but only ever had descendant overrides (.convo-open .hint, .statusbar
   .dim) — unstyled, they inherited whatever container they sat in. The admin
   pages' .section wrapper made that a 10px UPPERCASE placeholder-grey mess.
   .chip.warn is used by the automation template gallery and had no rule. */
.hint { font-size: 12px; color: var(--text-muted); }
.dim { color: var(--text-placeholder); }
.radio-row { display: flex; gap: 8px; align-items: flex-start; font-size: 12.5px; }
.chip.warn { border-color: var(--warning); color: var(--warning); }

/* ── the stage pill + timeline gutter + stages surface (rail-4, 2026-08-17) ──
   The plan header's ONE status control: a chip-metric CLICKABLE pill (see the
   chip-family rule in this file's header) carrying a 3-dot sliding window
   (behind · current · ahead) + the current stage's name; its popover reveals
   the full line. The thread's machine moves render as a left timeline gutter,
   and the stages surface shows the whole agreed change list, cut or not. */

.pillbtn {
  display: inline-flex; align-items: center; gap: 5px;
  border: 1px solid var(--border); border-radius: 999px; background: var(--element);
  padding: 1.5px 8px; cursor: pointer;
  font: 600 10.5px/1.4 ui-sans-serif, -apple-system, "Segoe UI", system-ui, sans-serif;
  color: var(--text); letter-spacing: 0.02em; white-space: nowrap;
}
.pillbtn:hover { border-color: var(--text-accent); background: var(--element-hover); }
.pillbtn:focus-visible { outline: 2px solid var(--text-accent); outline-offset: 1px; }
.pillbtn .chev { color: var(--text-placeholder); font-size: 7px; }
.segs { display: inline-flex; gap: 2px; }
.segs .sg { width: 5px; height: 5px; border-radius: 50%; background: var(--element-selected); }
.segs .sg.done { background: var(--success); }
.segs .sg.cur { background: var(--info); }
.segs .sg.cur.paused { background: var(--warning); }
@media (prefers-reduced-motion: no-preference) {
  .segs .sg.cur.working { animation: sgpulse 1.4s infinite; }
  @keyframes sgpulse { 50% { opacity: 0.45; } }
}

.pillpop-wrap { position: relative; display: inline-flex; }
.pillpop {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 8; min-width: 300px;
  border: 1px solid var(--border); border-radius: 8px; background: var(--surface); padding: 8px;
}
.pillpop .pp-head { display: flex; align-items: baseline; gap: 8px; padding: 2px 6px 7px;
  border-bottom: 1px solid var(--border-variant); margin-bottom: 5px; }
.pillpop .pp-head .t { font-size: 10px; text-transform: uppercase; letter-spacing: 0.07em;
  font-weight: 600; color: var(--text-placeholder); }
.pillpop .pp-head .pos { margin-left: auto; font-size: 11px; color: var(--text-muted); }
.pillpop .pp-row { display: flex; align-items: baseline; gap: 8px; padding: 4px 6px; font-size: 12px;
  border-radius: 5px; color: var(--text-muted); }
.pillpop .pp-row b { color: var(--text); font-weight: 650; }
.pillpop .pp-row .pm { flex: none; width: 14px; text-align: center; }
.pillpop .pp-row.done .pm { color: var(--success); }
.pillpop .pp-row.cur { background: var(--element); color: var(--text); }
.pillpop .pp-row.cur .pm { color: var(--info); }
.pillpop .pp-fact { font-size: 11.5px; color: var(--text-muted); }
.pillpop .pp-row .pt { margin-left: auto; font-size: 10.5px; color: var(--text-placeholder); }
.pillpop .pp-foot { display: flex; align-items: center; gap: 10px; border-top: 1px solid var(--border-variant);
  margin-top: 6px; padding: 7px 6px 2px; font-size: 11px; color: var(--text-placeholder); }
.pillpop .pp-foot .lin { margin-left: auto; font-size: 11px; }

/* the thread's machine moves: a left timeline gutter — dot on a guide line, mono time,
   destination-colored. Full-width rows (align-self stretch beats the bubble centering). */
.cols.plan .main .turns.chat .plan-ev {
  align-self: stretch; display: flex; gap: 10px; align-items: baseline;
  padding: 2px 0 2px 6px; margin-left: 4px; border-left: 1px solid var(--border-variant);
  font-size: 12px; color: var(--text-muted); max-width: none;
}
.plan-ev .edot { flex: none; width: 7px; height: 7px; border-radius: 50%;
  background: var(--text-muted); margin-left: -10.5px; position: relative; top: -1px;
  border: 1.5px solid var(--editor); }
.plan-ev.ev-to-paused .edot { background: var(--warning); }
.plan-ev.ev-to-flowing .edot, .plan-ev.ev-to-drafting .edot { background: var(--info); }
.plan-ev.ev-to-landing .edot, .plan-ev.ev-to-syncing .edot, .plan-ev.ev-to-review .edot { background: var(--hint); }
.plan-ev.ev-to-done .edot { background: var(--success); }
.plan-ev.ev-to-cut .edot { background: var(--text-accent); }
.plan-ev .et { flex: none; width: 38px; font-size: 10.5px; color: var(--text-placeholder);
  font-family: "Zed Mono", ui-monospace, monospace; }
.plan-ev .emove { color: var(--text); }
.plan-ev .ewhy { color: var(--text-muted); }
.plan-ev .etry { margin-left: 4px; font-size: 10px; border: 1px solid var(--warning);
  color: var(--warning); border-radius: 7px; padding: 0 6px; font-weight: 600; white-space: nowrap; }

/* the stages surface's rows: cut rows link, ghost rows dash, machine rows group apart */
.stgrow {
  display: flex; align-items: center; gap: 10px;
  border: 1px solid var(--border); border-radius: 7px; background: var(--surface);
  padding: 9px 12px; margin-bottom: 8px; font-size: 12.5px;
  color: var(--text); text-decoration: none;
}
a.stgrow:hover { border-color: var(--text-accent); }
.stgrow .idx {
  flex: none; width: 22px; height: 22px; border-radius: 50%;
  border: 1px solid var(--border); background: var(--element);
  display: flex; align-items: center; justify-content: center;
  font-size: 10.5px; font-weight: 650; color: var(--text-muted);
}
.stgrow.done .idx { border-color: var(--success); color: var(--success); }
.stgrow.cur { border-color: color-mix(in srgb, var(--info) 55%, var(--border)); }
.stgrow.cur .idx { border-color: var(--info); color: var(--info); }
.stgrow.ghost { border-style: dashed; background: var(--element); }
.stgrow.ghost .ttl2 { color: var(--text-muted); }
.stgrow.machine { opacity: 0.85; }
.stgrow.machine .idx { border-radius: 5px; }
.stgrow .ttl2 { flex: 1; min-width: 0; }
.stgrow .dur { font-size: 11px; color: var(--text-placeholder); flex: none; }

/* the answer-first brief: clamped in the scroll flow, one click to the full text */
/* the in-flow brief must OUT-SPECIFY .cols.order .order-brief (0,3,0) or it double-pads
   and keeps the 34vh pinned cap — the live-review round 2 finding. */
.cols.order .order-brief.inflow { flex: none; padding: 0; margin: 0 0 12px; }
.cols.order .order-brief.inflow .card { max-height: none; }
.brief-clamp { display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical; overflow: hidden; }
.brief-toggle { font-size: 11px; margin-top: 4px; }
