/* Yarness admin console (ADR-0031) — unified with the dashboard's "Reclaim" design system.
   The design language (colors · accent · fonts · radius) is the shared SINGLE SOURCE OF TRUTH in
   tokens.css (= the dashboard baseline; kept byte-identical, guarded by uiTokensSync.test.ts) and
   is linked BEFORE this file. Only this UI's layout var + shell/login/table styling live here. */
:root { --rail-w: 220px; }

* { box-sizing: border-box; }
html, body { height: 100%; }
body { margin: 0; font: 14px/1.5 var(--ui); background: var(--bg); color: var(--text); }
[hidden] { display: none !important; }
.muted { color: var(--dim); }
.mono { font-family: var(--mono); }
.ok { color: var(--ok); } .err { color: var(--err); }
a { color: inherit; text-decoration: none; }

/* Scrollbars — thin, theme-aware (matches the dashboard). */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-thumb { background-color: var(--line); border: 3px solid transparent; background-clip: padding-box; border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background-color: var(--muted); }

/* ---------- controls ---------- */
input, button, textarea, select {
  font: inherit; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r); padding: 8px 10px;
}
input::placeholder { color: var(--faint); }
input:focus, textarea:focus, select:focus { outline: none; border-color: var(--accent); }
button { cursor: pointer; }
button.primary {
  background: var(--accent); border-color: var(--accent); color: #14120d;
  font-weight: 700; letter-spacing: .08em; text-transform: uppercase; font-size: 12px;
  box-shadow: 0 0 16px -4px var(--accent);
}
button.primary:hover { filter: brightness(1.06); }
button.secondary, button.ghost { background: transparent; border-color: var(--border); color: var(--text); }
button.secondary:hover, button.ghost:hover { border-color: var(--accent); }
button:disabled { opacity: .5; cursor: default; filter: none; }
.iconbtn { background: transparent; border: 0; padding: 6px 8px; color: var(--muted); border-radius: var(--r); font-size: 15px; }
.iconbtn:hover { background: var(--raised); color: var(--text); }

/* ---------- login ---------- */
#login { height: 100vh; display: grid; place-items: center; }
#login .card {
  position: relative; width: 340px; padding: 26px 24px;
  background: var(--panel); border: 1px solid var(--border); border-radius: var(--r);
}
#login .card::before, #login .card::after { content: ""; position: absolute; width: 11px; height: 11px; }
#login .card::before { top: -1px; left: -1px; border-top: 1px solid var(--accent); border-left: 1px solid var(--accent); }
#login .card::after { bottom: -1px; right: -1px; border-bottom: 1px solid var(--accent); border-right: 1px solid var(--accent); }
.brand { font-family: var(--ui); font-weight: 700; font-size: 20px; letter-spacing: .06em; }
.brand b { color: var(--accent-ink); }
.brand .tag { font-family: var(--mono); font-size: 10px; letter-spacing: .18em; text-transform: uppercase; color: var(--dim); }
#login .sub { color: var(--dim); font-family: var(--mono); font-size: 12px; margin: 8px 0 18px; }
label { display: block; font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .12em; color: var(--dim); margin: 14px 0 5px; }
input, select, textarea { width: 100%; }
button.wide { width: 100%; margin-top: 22px; padding: 11px; }

/* ---------- app shell ---------- */
#app { height: 100vh; display: grid; grid-template-rows: 54px 1fr; grid-template-columns: var(--rail-w) 1fr;
  grid-template-areas: "top top" "side main"; }
#topbar { grid-area: top; display: flex; align-items: center; gap: 14px; padding: 0 20px;
  background: var(--panel); border-bottom: 1px solid var(--border); }
#topbar .brand { font-size: 16px; }
.spacer { flex: 1; }
#whoami { font-family: var(--mono); font-size: 12px; color: var(--dim); }
#whoami b { color: var(--text); font-weight: 600; }

#side { grid-area: side; background: var(--panel); border-right: 1px solid var(--border); padding: 10px; }
.nav { display: flex; flex-direction: column; gap: 1px; }
.navitem { position: relative; text-align: left; background: transparent; border: 0; color: var(--muted);
  padding: 10px 12px; border-radius: var(--r); font-family: var(--ui); font-weight: 600; font-size: 12.5px;
  letter-spacing: .06em; text-transform: uppercase; cursor: pointer; }
.navitem:hover { background: var(--raised); color: var(--text); }
.navitem.active { background: var(--accent-dim); color: var(--accent-ink); }
.navitem.active::before { content: ""; position: absolute; left: -10px; top: 50%; transform: translateY(-50%);
  width: 3px; height: 16px; background: var(--accent); }

/* In-page tabs (EntropyHub: a project's Tickets / Agents). Shares .navitem's type treatment so a tab reads
   as navigation, but runs horizontally with the active marker UNDER the label — the sidebar's marker is a
   left-edge bar, which would sit in the middle of a row here. */
.subnav { display: flex; flex-direction: row; gap: 4px; border-bottom: 1px solid var(--border); }
.subnav .navitem { border-radius: var(--r) var(--r) 0 0; }
.subnav .navitem.active::before { left: 0; right: 0; top: auto; bottom: -1px; transform: none;
  width: auto; height: 2px; }

/* Main view — faint technical grid canvas (matches the dashboard's #view). */
#main { grid-area: main; overflow: auto; padding: 24px 26px;
  background-image: linear-gradient(var(--border-2) 1px, transparent 1px), linear-gradient(90deg, var(--border-2) 1px, transparent 1px);
  background-size: 34px 34px; background-position: -1px -1px; }

/* ---------- content ---------- */
.pagehead { display: flex; align-items: baseline; gap: 12px; margin-bottom: 18px; }
.pagehead h1 { font-family: var(--ui); font-size: 22px; font-weight: 700; letter-spacing: .01em; margin: 0; }
.pagehead .muted { font-family: var(--mono); font-size: 12.5px; }

.card { position: relative; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r);
  padding: 16px 18px; margin-bottom: 16px; }
.card::before, .card::after { content: ""; position: absolute; width: 11px; height: 11px; }
.card::before { top: -1px; left: -1px; border-top: 1px solid var(--accent); border-left: 1px solid var(--accent); }
.card::after { bottom: -1px; right: -1px; border-bottom: 1px solid var(--accent); border-right: 1px solid var(--accent); }
.card h2 { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .18em; color: var(--dim); margin: 0 0 12px; }

.formrow { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; }
.formrow > div { flex: 1; min-width: 140px; }
.formrow label { margin-top: 0; }
.check { display: inline-flex; align-items: center; gap: 6px; font-family: var(--ui); font-size: 13px; color: var(--text); text-transform: none; letter-spacing: 0; }
.check input { width: auto; }

table { width: 100%; border-collapse: collapse; }
th, td { text-align: left; padding: 10px 12px; border-bottom: 1px solid var(--border-2); font-size: 13px; vertical-align: middle; }
th { color: var(--faint); font-family: var(--mono); font-weight: 600; font-size: 10px; letter-spacing: .14em; text-transform: uppercase; }
tr:hover td { background: var(--raised); }
td .rowbtn { padding: 4px 9px; font-size: 11px; margin-right: 6px; }

.pill { display: inline-block; padding: 2px 9px; border-radius: 20px; background: var(--panel-2); border: 1px solid var(--border); color: var(--muted); font-family: var(--mono); font-size: 11px; font-weight: 600; }
.pill.admin { background: var(--accent-dim); border-color: var(--accent); color: var(--accent-ink); }
.pill.on { color: var(--det-ink); border-color: var(--det); }
code { background: var(--panel-2); border: 1px solid var(--border); border-radius: var(--r); padding: 0 5px; font-family: var(--mono); font-size: 12px; }

.empty { color: var(--dim); font-family: var(--mono); font-size: 12.5px; padding: 8px 2px; }
.tree { font-family: var(--mono); font-size: 12.5px; }
.tree .p { margin-top: 10px; color: var(--accent-ink); }
.tree .t { margin-left: 18px; color: var(--text); }
.tree .t .s { color: var(--dim); }

/* Org accordions + inline link buttons + the staged-access save bar (ADR-0032). */
.linkbtn { color: var(--accent-ink); font-family: var(--mono); font-size: 11.5px; margin-right: 12px; }
.linkbtn:hover { text-decoration: underline; }
.acc { position: relative; border: 1px solid var(--border); border-radius: var(--r); background: var(--panel); margin-bottom: 10px; }
.acc > summary { cursor: pointer; list-style: none; display: flex; align-items: center; gap: 12px; padding: 12px 16px; font-family: var(--ui); font-weight: 600; }
.acc > summary::-webkit-details-marker { display: none; }
.acc > summary::before { content: "▸"; color: var(--dim); display: inline-block; transition: transform .12s ease; }
.acc[open] > summary::before { transform: rotate(90deg); }
.acc-t { font-size: 14px; }
.acc-net { margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--muted); }
.acc .acc-body { padding: 2px 16px 14px; }
.acc.proj { background: var(--panel-2); margin: 8px 0; }
.acc.proj .acc-body { padding: 2px 14px 10px; }
#savebar { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%); z-index: 30; display: flex; align-items: center; gap: 14px; background: var(--panel); border: 1px solid var(--accent); border-radius: var(--r); padding: 10px 16px; box-shadow: 0 12px 40px -10px rgba(0,0,0,.5); font-size: 13px; }
#savebar b { color: var(--accent-ink); }
#savebar button { padding: 7px 14px; font-size: 12px; }

#toast { position: fixed; right: 20px; bottom: 20px; background: var(--panel); border: 1px solid var(--accent);
  border-radius: var(--r); padding: 10px 14px; font-size: 13px; box-shadow: 0 8px 30px -12px rgba(0,0,0,.5); }
#toast.err { border-color: var(--err); color: var(--err); }
#toast.ok { border-color: var(--ok); }

/* Schedule timeline (v28) — layout only; every colour comes from tokens.css.
   Structure: a horizontally scrollable board where each ROW is one task — a sticky left rail plus a
   7-column day track holding the task's bar. Rows are grouped into assignee swimlanes. */
.sched-bar { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
/* The org/region pickers are <label class="check">, which otherwise inherits the global
   `label { margin: 14px 0 5px }` — that dropped them below the buttons, so the agent-token button next
   to them looked misaligned. Reset the margin and stop the global `select { width:100% }` stretching. */
.sched-bar .check { margin: 0; }
.sched-bar .check select { width: auto; }
.tc-btn { background: none; border: 0; padding: 0; color: var(--accent-ink); font-family: var(--mono); font-size: 11px; cursor: pointer; }
.tc-btn:hover { text-decoration: underline; }

/* A CONTINUOUS, horizontally-scrolling timeline (Jira-roadmap style): a sticky left rail + a
   fixed-width day strip (--tl-day × --tl-n columns) that all rows share, so bars line up as you scroll.
   --tl-n (the column count) is set inline per render; --tl-day MUST match SCHED_DAYW in app.js. */
.tl { --tl-rail: 190px; --tl-day: 46px; margin-top: 14px; overflow: auto; min-height: 480px; max-height: 80vh;
  border: 1px solid var(--border); border-radius: var(--r); background: var(--panel);
  display: flex; flex-direction: column; align-items: stretch; }
/* Fill the min-height when there are only a few rows: the last lane grows and its final row stretches,
   so the day gridlines run to the bottom (empty timeline space, Jira-style) instead of a blank slab.
   Content in that stretched row aligns to the TOP so a lone task isn't floated in the middle. */
.tl-lane:last-child { flex: 1 1 auto; display: flex; flex-direction: column; }
.tl-lane:last-child .tl-row:last-child { flex: 1 1 auto; }
.tl-lane:last-child .tl-row:last-child .tl-rail { align-items: flex-start; }
.tl-lane:last-child .tl-row:last-child .tl-bar,
.tl-lane:last-child .tl-row:last-child .tl-over { align-self: start; }
.tl-head, .tl-row { display: grid; grid-template-columns: var(--tl-rail) calc(var(--tl-day) * var(--tl-n)); align-items: stretch; }
.tl-track { display: grid; grid-template-columns: repeat(var(--tl-n), var(--tl-day)); position: relative; }

/* date axis — sticky on top; two rows (week band + day letters/dates) */
.tl-head { position: sticky; top: 0; z-index: 4; background: var(--panel-2); border-bottom: 1px solid var(--line); }
.tl-head-rail { position: sticky; left: 0; z-index: 5; background: var(--panel-2);
  font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: .18em; color: var(--dim);
  display: flex; align-items: flex-end; padding: 6px 10px; }
.tl-weeks { border-bottom: 1px solid var(--border-2); }
.tl-wk { grid-row: 1; padding: 5px 8px; font-family: var(--mono); font-size: 11px; color: var(--muted);
  border-left: 1px solid var(--line); white-space: nowrap; }
.tl-col { grid-row: 1; padding: 4px 0; text-align: center; font-family: var(--mono); font-size: 10px;
  color: var(--dim); border-left: 1px solid var(--border-2); line-height: 1.35; }
.tl-col b { display: block; font-size: 11px; color: var(--muted); font-weight: 600; }
.tl-col.wk-start { border-left-color: var(--line); }
.tl-col.is-today { color: var(--accent-ink); background: var(--accent-dim); box-shadow: inset 0 2px 0 var(--accent); }
.tl-col.is-today b { color: var(--accent-ink); }
.tl-col.is-wknd { background: var(--panel-2); }

/* swimlanes + rows */
.tl-lane { border-bottom: 1px solid var(--line); }
.tl-lane:last-child { border-bottom: 0; }
.tl-lane-head { position: sticky; left: 0; z-index: 3; display: flex; align-items: center; gap: 8px; padding: 6px 10px;
  background: var(--panel-2); border-bottom: 1px solid var(--border-2); font-size: 12.5px; width: var(--tl-rail); }
.tl-av { display: inline-flex; align-items: center; justify-content: center; width: 19px; height: 19px; border-radius: 50%;
  background: var(--accent-dim); color: var(--accent-ink); border: 1px solid var(--accent-line); font-family: var(--mono); font-size: 10px; }
.tl-lane-head .muted { font-family: var(--mono); font-size: 11px; }
/* project group band — one level ABOVE the assignee swimlanes (a flat sibling of .tl-lane so the
   last-lane height stretch and the drag hit-testing stay untouched) */
.tl-group-head { position: sticky; left: 0; z-index: 3; display: flex; align-items: center; gap: 8px; padding: 7px 10px;
  background: var(--accent-dim); border-top: 1px solid var(--accent-line); border-bottom: 1px solid var(--border-2);
  width: var(--tl-rail); font-size: 12.5px; }
.tl-group-head b { color: var(--accent-ink); }
.tl-group-head .muted { font-family: var(--mono); font-size: 11px; }
.tl-proj { color: var(--accent-ink); font-size: 11px; }
.tl-row { border-top: 1px solid var(--border-2); }
.tl-row:first-of-type { border-top: 0; }
.tl-rail { position: sticky; left: 0; z-index: 2; display: flex; align-items: center; gap: 6px; padding: 5px 10px;
  background: var(--panel); border-right: 1px solid var(--line); overflow: hidden; width: var(--tl-rail); }
.tl-row:hover .tl-rail { background: var(--raised); }
.tl-name { font-size: 12.5px; color: var(--text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 1; }
.tl-name.is-done { color: var(--dim); text-decoration: line-through; }
.tl-flow { color: var(--det-ink); font-size: 11px; }
.tl-dot { width: 7px; height: 7px; border-radius: 50%; flex: 0 0 auto; background: var(--dim); }

/* day cells (gridlines + today / weekend tint + a stronger divider each Monday) */
.tl-cell { grid-row: 1; border-left: 1px solid var(--border-2); min-height: 36px; }
.tl-cell.wk-start { border-left-color: var(--line); }
/* today reads as a continuous "now" band: an accent rule on both edges of the column, on every row */
.tl-cell.is-today { background: var(--accent-dim); box-shadow: inset 2px 0 0 var(--accent), inset -2px 0 0 var(--accent); }
.tl-cell.is-wknd { background: var(--panel-2); }
.tl-track.drop .tl-cell { background: var(--accent-dim); }

/* the bar: planned segment (draggable) + hatched overrun. Columns are narrow, so labels are allowed
   to overflow the bar to the right (a common roadmap treatment) rather than truncate to nothing. */
.tl-bar { grid-row: 1; z-index: 1; margin: 5px 2px; padding: 0 7px; border-radius: 9px; height: 26px; display: flex; align-items: center; gap: 5px;
  min-width: 0; cursor: grab; border: 1px solid var(--border); background: var(--raised); color: var(--text); font-size: 11.5px; overflow: visible; white-space: nowrap; }
.tl-bar:active { cursor: grabbing; }
.tl-bar.cut-l { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: 0; }
.tl-bar.cut-r { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }
.tl-lbl { white-space: nowrap; overflow: visible; } /* labels may spill past a short bar to stay readable */
.tl-bar.is-planned { background: var(--accent-dim); border-color: var(--accent-line); color: var(--accent-ink); }
.tl-bar.is-active { background: var(--accent); border-color: var(--accent); color: #1b1812; }
.tl-bar.is-blocked { background: transparent; border-color: var(--warn); color: var(--warn); }
.tl-bar.is-done { background: var(--panel-2); border-color: var(--det); color: var(--det-ink); }
.tl-bar.is-cancelled { background: var(--panel-2); border-style: dashed; color: var(--dim); }
.tl-dot.is-planned { background: var(--accent); } .tl-dot.is-active { background: var(--accent); }
.tl-dot.is-blocked { background: var(--warn); } .tl-dot.is-done { background: var(--det); }
.tl-dot.is-cancelled { background: var(--faint); }
.tl-pair { font-family: var(--mono); font-size: 11px; color: var(--det-ink); }
/* progress: a thin fill along the bottom of the planned bar (width = %) + a small % label */
.tl-fill { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--accent); opacity: .85;
  border-bottom-left-radius: 9px; pointer-events: none; }
.tl-bar.is-active .tl-fill { background: #1b1812; opacity: .3; } /* on the filled active bar a dark underline reads */
.tl-pct { font-family: var(--mono); font-size: 10px; opacity: .7; }
.tl-bar:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* resize handles at each end; reveal on hover/focus so bars stay clean at rest */
.tl-handle { position: absolute; top: 0; bottom: 0; width: 8px; cursor: col-resize; touch-action: none; }
.tl-handle-l { left: -1px; } .tl-handle-r { right: -1px; }
.tl-bar { position: relative; touch-action: none; }
.tl-bar:hover .tl-handle, .tl-bar:focus-visible .tl-handle { background: var(--accent); border-radius: 3px; }
.tl-empty { grid-column: 1 / -1; align-self: center; padding-left: 12px; color: var(--dim); font-family: var(--mono); font-size: 12px; }
.tl-over { grid-row: 1; z-index: 1; height: 26px; margin: 5px 3px 5px 0; border-radius: 0 9px 9px 0; border: 1px dashed var(--err);
  background: repeating-linear-gradient(45deg, transparent, transparent 4px, var(--accent-dim) 4px, var(--accent-dim) 8px); }

/* live drag feedback: a snapping ghost bar in the target track, a highlighted target lane, a floating date label */
.tl-ghost { grid-row: 1; z-index: 5; height: 26px; margin: 5px 0; border-radius: 9px; pointer-events: none;
  border: 1px dashed var(--accent); background: var(--accent-dim); box-shadow: 0 2px 10px -4px var(--accent); }
.tl-track.lane-hot { background: color-mix(in srgb, var(--accent) 6%, transparent); }
.tl-datelabel { position: fixed; z-index: 50; transform: translateX(-50%); pointer-events: none; white-space: nowrap;
  background: var(--text); color: var(--panel); font-family: var(--mono); font-size: 11px; padding: 3px 8px; border-radius: var(--r); box-shadow: 0 6px 20px -8px rgba(0,0,0,.6); }

/* backlog strip */
.tl-backlog { margin-top: 14px; }
.tl-chip { display: inline-flex; align-items: center; gap: 6px; margin: 0 7px 7px 0; padding: 4px 10px; border-radius: 12px;
  background: var(--panel-2); border: 1px solid var(--border); font-size: 12px; cursor: grab; touch-action: none; }
.tl-chip:active { cursor: grabbing; }
.tl-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

/* toast "Undo" action */
.toast-act { background: none; border: 1px solid currentColor; color: inherit; border-radius: var(--r); padding: 1px 8px; margin-left: 4px; font-size: 12px; cursor: pointer; }
.toast-act:hover { background: var(--accent-dim); }

/* task detail / edit panel (right-side sheet) */
.sc-panel { position: fixed; top: 0; right: 0; bottom: 0; width: 360px; max-width: 92vw; z-index: 40; overflow: auto;
  background: var(--panel); border-left: 1px solid var(--accent); box-shadow: -18px 0 50px -20px rgba(0,0,0,.55); padding: 16px 18px; }
.sc-panel-hd { display: flex; align-items: center; justify-content: space-between; margin-bottom: 10px; }
.sc-panel-hd b { font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .16em; color: var(--dim); }
.sc-panel label { margin: 12px 0 4px; }
.sc-panel input, .sc-panel select, .sc-panel textarea { width: 100%; }
.sc-panel textarea { resize: vertical; font: inherit; }
/* Rendered markdown, wherever it appears (app.js `md`). Shared by the to-do detail view and hub threads.
   ⚠ Wide content — code and tables — scrolls INSIDE its own box, so the page body never scrolls sideways. */
.md > :first-child { margin-top: 0; } .md > :last-child { margin-bottom: 0; }
.md p { margin: 6px 0; }
.md h4, .md h5, .md h6 { margin: 12px 0 4px; font-size: 13px; font-weight: 600; }
.md ul, .md ol { margin: 6px 0; padding-left: 20px; }
.md li { margin: 2px 0; }
.md code { font-family: var(--mono); font-size: 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
.md a { color: var(--accent); text-decoration: underline; }
.md pre { margin: 8px 0; padding: 9px 11px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r); overflow-x: auto; position: relative; }
.md pre code { background: none; border: 0; padding: 0; font-size: 12px; line-height: 1.5; white-space: pre; }
/* The language, if the fence named one — a label on the block, not a badge competing with the code. */
.md pre[data-lang]::before { content: attr(data-lang); position: absolute; top: 3px; right: 8px;
  font-family: var(--mono); font-size: 10px; letter-spacing: .08em; color: var(--faint); }
.md blockquote { margin: 8px 0; padding: 2px 0 2px 10px; border-left: 3px solid var(--line); color: var(--muted); }
.md hr { margin: 12px 0; border: 0; border-top: 1px solid var(--line); }
.md table { margin: 8px 0; border-collapse: collapse; font-size: 12.5px; display: block; overflow-x: auto; }
.md th, .md td { border: 1px solid var(--line); padding: 4px 8px; text-align: left; }
.md th { background: var(--panel); font-weight: 600; }
.md td { font-variant-numeric: tabular-nums; }

/* Detail read view: rendered markdown styled like the textarea box; click swaps to raw edit. */
.sp-md { min-height: 300px; max-height: 55vh; overflow: auto; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r); padding: 8px 10px; cursor: text; }
.sp-md:hover { border-color: var(--line); }
.sp-md:focus { outline: none; border-color: var(--accent); }
.sp-md > :first-child { margin-top: 0; } .sp-md > :last-child { margin-bottom: 0; }
.sp-md p { margin: 6px 0; }
.sp-md h4, .sp-md h5, .sp-md h6 { margin: 10px 0 4px; font-size: 13px; font-weight: 600; }
.sp-md ul, .sp-md ol { margin: 6px 0; padding-left: 20px; }
.sp-md li { margin: 2px 0; }
.sp-md code { font-family: var(--mono); font-size: 12px; background: var(--panel); border: 1px solid var(--line); border-radius: 4px; padding: 0 4px; }
.sp-md a { color: var(--accent); text-decoration: underline; }
.sp-md-empty { color: var(--faint); }
.sc-flow { margin-top: 12px; font-family: var(--mono); font-size: 11px; color: var(--det-ink); }
.sc-panel-ft { display: flex; align-items: center; gap: 8px; margin-top: 18px; }

/* schedule ops chat drawer — a wider .sc-panel that flex-fills; the log scrolls internally */
.sc-panel.sc-chat { width: 560px; padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.sc-panel.sc-chat .sc-panel-hd { margin: 0; padding: 11px 14px; border-bottom: 1px solid var(--line); }
.sc-chat-log { flex: 1 1 auto; overflow-y: auto; padding: 12px 14px; display: flex; flex-direction: column; gap: 8px; }
.sc-msg { padding: 7px 10px; border-radius: 10px; font-size: 13px; white-space: pre-wrap; word-break: break-word; max-width: 90%; }
.sc-user { align-self: flex-end; background: var(--accent-dim); border: 1px solid var(--accent-line); color: var(--accent-ink); }
.sc-assistant { align-self: flex-start; background: var(--panel-2); border: 1px solid var(--line); }
.sc-tool { align-self: flex-start; background: transparent; color: var(--muted); font-family: var(--mono); font-size: 11px; padding: 2px; }
.sc-error { align-self: flex-start; color: var(--err); font-size: 12px; }
.sc-proposal { align-self: stretch; border: 1px solid var(--accent-line); border-radius: 10px; padding: 8px 10px; background: var(--accent-dim); }
.sc-prop-hd { font-size: 12px; color: var(--accent-ink); margin-bottom: 5px; }
.sc-prop-note { white-space: pre-wrap; font-size: 12.5px; margin: 0 0 8px; max-height: 220px; overflow: auto; font-family: var(--mono); }
.sc-proposal.is-applied { opacity: .55; }
.sc-chat-in { display: flex; gap: 8px; padding: 11px 14px; border-top: 1px solid var(--line); }
.sc-chat-in textarea { flex: 1; resize: none; font: inherit; }
.sc-del { color: var(--err); border-color: var(--err); }
.sc-del:hover { background: var(--err); color: var(--panel); }
@media (max-width: 900px) { .tl { --tl-rail: 140px; } }

/* ---- hub ticket page (ADR-0061): a reading column of conversation, a sidebar of state ---- */
.tk { display: grid; grid-template-columns: minmax(0, 1fr) 260px; gap: 18px; align-items: start; }
.tk-main { min-width: 0; }                       /* min-width:0 or a wide code block stretches the grid */
.tk-side { display: flex; flex-direction: column; gap: 12px; }
.tk-side .card { margin: 0; }
.tk-side label { display: block; margin: 10px 0 4px; }
.tk-side label:first-of-type { margin-top: 0; }
.tk-side select, .tk-side input, .tk-side button { width: 100%; }

.tk-crumbs { font-size: 12px; color: var(--muted); margin-bottom: 4px; }
.tk-crumbs a { color: var(--muted); text-decoration: none; }
.tk-crumbs a:hover { color: var(--text); text-decoration: underline; }
.tk-title { margin: 0 0 8px; font-size: 21px; line-height: 1.25; text-wrap: balance; }
.tk-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; margin-bottom: 16px; font-size: 12px; }
.tk-id { font-size: 11px; }
.tk-banner { margin-bottom: 12px; text-align: left; }

/* The timeline. Comments are boxes; events are quiet lines between them, never competing for attention. */
.tk-msg { border: 1px solid var(--border); border-radius: var(--r); background: var(--panel); margin-bottom: 12px; }
.tk-msg-hd { display: flex; align-items: center; gap: 7px; padding: 7px 11px; font-size: 12px;
  background: var(--panel-2); border-bottom: 1px solid var(--border); border-radius: var(--r) var(--r) 0 0; }
.tk-body { padding: 10px 12px; overflow-wrap: anywhere; }
.tk-act { color: var(--muted); text-decoration: none; font-size: 11px; }
.tk-act:hover { color: var(--accent-ink); text-decoration: underline; }
.tk-evt { margin: 0 0 12px; padding-left: 8px; border-left: 2px solid var(--border);
  font-family: var(--mono); font-size: 11px; color: var(--muted); }
/* What a reply answers: one collapsed line, and a link that jumps to it. */
.tk-quote { display: block; margin: 8px 12px 0; padding: 4px 8px; border-left: 2px solid var(--line);
  background: var(--panel-2); color: var(--muted); font-size: 11.5px; text-decoration: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tk-quote:hover { color: var(--text); }
/* The jump has to land somewhere visible. ⚠ Not `:target` — that needs the URL fragment, and on this
   console the hash IS the route, so a quote link can never set one without navigating away. */
.tk-msg.is-found { animation: tk-found 1.6s ease-out; }
@keyframes tk-found { from { border-color: var(--accent); background: var(--accent-dim); } to { border-color: var(--border); background: var(--panel); } }
@media (prefers-reduced-motion: reduce) { .tk-msg.is-found { animation: none; border-color: var(--accent); } }

.tk-compose { padding: 12px; }
.tk-compose textarea { width: 100%; resize: vertical; font: inherit; }
.tk-modes { margin-bottom: 8px; }
.tk-preview { min-height: 96px; padding: 8px 10px; background: var(--panel-2);
  border: 1px solid var(--border); border-radius: var(--r); }
.tk-compose-ft { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-top: 10px; }
.tk-replying { display: flex; align-items: center; gap: 6px; margin-bottom: 8px; padding: 4px 8px;
  background: var(--accent-dim); border: 1px solid var(--accent-line); border-radius: var(--r);
  color: var(--accent-ink); font-size: 12px; }
.tk-replying .iconbtn { padding: 0 4px; font-size: 12px; color: var(--accent-ink); }

/* One column when there is no room for two — the sidebar goes under the conversation, not beside it. */
@media (max-width: 860px) { .tk { grid-template-columns: minmax(0, 1fr); } }

/* ---- agent chat drawer (ADR-0062). Reuses the ops-chat vocabulary above; only what differs is here. ---- */
#chat-panel { width: 620px; }
.chat-sessions { display: flex; gap: 4px; padding: 8px 12px; border-bottom: 1px solid var(--line); overflow-x: auto; }
.chat-sessions .navitem { flex: 0 0 auto; display: flex; align-items: center; gap: 5px; padding: 4px 8px; font-size: 11px; }
.chat-unread { background: var(--accent-dim); color: var(--accent-ink); border-color: var(--accent-line); }
.sc-chat-log .md { font-size: 13px; }
.sc-chat-log .md pre { max-height: 340px; }
/* Queued, not delivered — dashed because it has not happened yet. */
.chat-pending { border-style: dashed; opacity: .85; }
.chat-queued { margin-top: 4px; font-size: 10.5px; color: var(--accent-ink); font-family: var(--mono); }
.chat-trunc { margin-top: 4px; font-size: 10.5px; color: var(--faint); font-family: var(--mono); }
/* Who sent it — only ever present on a turn the hub DELIVERED, never on a mirrored transcript line. */
.chat-from { font-size: 10.5px; color: var(--accent-ink); font-family: var(--mono); margin-bottom: 3px; }
/* The hidden-activity line. Clickable, and it says the count so a busy session never reads as a quiet one. */
.chat-activity { align-self: center; cursor: pointer; text-decoration: underline dotted var(--line); text-underline-offset: 3px; }
.chat-activity:hover { color: var(--accent-ink); }
a.chat-open { color: inherit; text-decoration: underline dotted var(--line); text-underline-offset: 3px; }
a.chat-open:hover { color: var(--accent-ink); text-decoration-color: var(--accent); }
@media (max-width: 700px) { #chat-panel { width: 100vw; } }

/* ================================================================================================
   PHONE. Measured before writing any of this: at 390px the shell gave the content column
   118 PIXELS — the fixed sidebar rail took the rest — and the page scrolled sideways at 427px
   against a 390px viewport. Every rule below is aimed at a number from that measurement, not at a
   guess about what "mobile" needs.
   ================================================================================================ */
@media (max-width: 760px) {
  /* ⚠ The rail becomes a ROW, not a drawer. A drawer needs a button, a state, an overlay and a way
     out of it; a horizontal strip of the same buttons needs none of those and keeps every
     destination one tap away — on a console whose whole job is getting to one session quickly. */
  #app { grid-template-columns: 1fr; grid-template-areas: "top" "side" "main"; grid-template-rows: auto auto 1fr; }
  /* ⚠⚠ min-width: 0 OR THE SCROLLER DOES NOT SCROLL. A grid item defaults to min-width:auto, so
     #side grew to fit the whole nav row (875px) and stretched the page to 783px instead of clipping
     it — the overflow-x:auto below was inert. The same note already sits on .tk-main; it caught me
     anyway, because there the wide child was a code block and here it is the navigation itself. */
  #app > * { min-width: 0; }

  #side { border-right: 0; border-bottom: 1px solid var(--border); padding: 6px 8px; }
  .nav { flex-direction: row; gap: 4px; overflow-x: auto; -webkit-overflow-scrolling: touch;
    scrollbar-width: none; }
  .nav::-webkit-scrollbar { display: none; }
  /* ⚠ flex: 0 0 auto or the items compress to unreadable slivers instead of scrolling. */
  .nav .navitem { flex: 0 0 auto; padding: 9px 12px; min-height: 40px; }
  /* The active marker is a LEFT BAR in the sidebar, which lands mid-row here — move it under. */
  .navitem.active::before { left: 6px; right: 6px; top: auto; bottom: 2px; transform: none;
    width: auto; height: 2px; }

  #topbar { padding: 0 12px; gap: 8px; }
  /* ⚠ The identity is the first thing to go. It is reassurance, not navigation, and at 390px it was
     pushing "Sign out" off the edge — a control you cannot reach is worse than one you cannot see. */
  #whoami { display: none; }

  #main { padding: 14px 12px; }
  .pagehead { flex-wrap: wrap; gap: 4px 10px; }
  .pagehead h1 { font-size: 19px; }
  .card { padding: 13px 12px; }

  /* ⚠ 140px was two-per-row at 390 and left each field ~170px. One field per row is the honest
     layout on a phone; the desktop rule is untouched. */
  .formrow > div { min-width: 100%; }

  /* ⚠ Tables scroll INSIDE themselves rather than widening the page. A body that scrolls sideways
     makes every vertical swipe feel like it is fighting something. */
  .card > table, .card > div > table { display: block; overflow-x: auto; white-space: nowrap; }

  /* Touch targets. Measured at 25x35 (theme) and 199x39 (nav) — under the 44px anyone can hit. */
  /* Measured at 25x35 (theme), 199x39 (nav) and 38-39px (fields) — all under the 44px anyone can
     reliably hit with a thumb. */
  button, .navitem, input, select, textarea { min-height: 44px; }
  #theme, #logout { min-width: 44px; }
}

/* ⚠ Short viewports, which a phone in landscape and a phone with the keyboard up both are. A 48vh
   transcript on a 400px-tall window is 190px of terminal with the composer pushed off screen. */
@media (max-height: 620px) {
  /* basis-0 flex sizes the pane now; only the floor changes on short viewports. */
  #sc-transcript { min-height: 110px; }
}


/* ================================================================================================
   SESSION CONTROL — refined in Claude Design ("Yarness Reclaim", session-control-v2).

   The shape it settled on: SETUP LIVES IN THE SIDEBAR under the Sessions tab, and the main column is
   the conversation alone. That deleted the in-page two-pane rail entirely — one less layout, one less
   toggle, one less thing to keep responsive — and removed a real duplication, since the old
   "sessions on the device" chip row listed exactly what the sidebar sub-tabs already list.
   ================================================================================================ */

/* ⚠ The sidebar is wider now because it carries the sessions and their states, not just eight words. */
:root { --rail-w: 320px; }

/* ⚠ RESTORED after the two-pane block was cut: removing that block took the DESKTOP side-hidden rules
   with it, so hiding the sidebar left a 320px empty track where the pane had been — which reads as a
   rendering bug rather than a hidden pane. Caught by the test that pinned it, not by looking. */
#app.side-hidden { grid-template-columns: 0 1fr; }
#app.side-hidden #side { display: none; }

/* ⚠ A READING WIDTH. A terminal transcript stretched across a 2560px monitor is unreadable, and the
   cap belongs on the column rather than on the pane inside it. */
/* ⚠ A reading-width cap so a transcript is not stretched edge-to-edge on a 2560px monitor — widened
   2026-08-27 (operator ask) now that the body is a clean conversation, not raw terminal columns.
   `overflow-wrap: anywhere` on the pane still breaks the odd unbroken path. Raise or drop the cap to
   go wider still. */
.sc-col { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; width: 100%; max-width: 1600px; }
/* ⚠ #view SITS BETWEEN #main AND THE COLUMN, and that broke the height chain: making #main a flex
   column did nothing because its only child is #view, an ordinary block with auto height — so
   .sc-col's flex:1 resolved against content and the transcript sat at its 220px floor on a 900px
   screen. Measured, not spotted by reading.

   Scoped with :has() rather than styling #view globally: every other tab shares that element, and a
   flex column would quietly change all of them. */
/* ⚠ overflow HIDDEN, not auto (operator ask 2026-08-26: the whole chat must fit the browser window
   like chatgpt/claude — composer pinned at the bottom, the LOG the thing that scrolls). With #main
   scrollable, any content growth handed the PAGE the scrollbar and the composer slid off-screen;
   hiding it here is what forces every scroll to happen inside the transcript and the drawers, which
   both carry their own overflow. Scoped: every other tab keeps its page scroll. */
#main:has(.sc-col) { display: flex; flex-direction: column; min-height: 0; overflow: hidden; }
#main:has(.sc-col) > #view { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; }

/* ⚠ min-height: 0 — THE ONE LINK THAT BROKE THE WHOLE CHAIN (measured in chromium 2026-08-26: col
   bounded at 547px, card at 2763px inside it). A flex child's default min-height is min-CONTENT, so
   the card refused to shrink below the transcript's full backlog and the composer was clipped by
   #main's overflow:hidden with nothing scrollable anywhere. */
.sc-card { display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; margin-bottom: 0; position: relative; }
/* ONE shared vertical center for the whole header (operator ask 2026-08-28): the session title, the
   state + transport pills, and the verb cluster all align on the row's centre. Was `baseline` with the
   pills force-centered on top of it — three different anchors, so the pills read off from the title and
   the buttons. Centering the row makes them one line and drops the per-pill override. */
.sc-head { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; }
/* The title keeps a readable floor and ellipsizes; the pills ride as one cluster that drops to a second
   line at narrow widths rather than crushing the title (design refine 2026-08-30). */
.sc-title { min-width: 180px; flex: 0 1 auto; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-head-pills { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; flex-wrap: wrap; }
/* A working title button: label swapped by JS, spinner drawn here — one visual for close/restart/
   any future long verb. Honest progress beats a fire-and-forget toast. */
.sc-busy { opacity: .75; pointer-events: none; }
.sc-busy::after { content: ""; display: inline-block; width: 10px; height: 10px; margin-left: 7px;
  border: 2px solid var(--accent); border-top-color: transparent; border-radius: 50%;
  vertical-align: -1px; animation: sc-spin .7s linear infinite; }
@keyframes sc-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .sc-busy::after { animation: none; border-top-color: var(--accent); } }
.sc-danger { padding: 3px 9px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  white-space: nowrap; color: var(--err); border-color: var(--err); }
/* Session verbs as ONE segmented control (SessionControlV2 sync 2026-08-27): a bordered group with
   hairline dividers on the header's right. sc-verb-lead drops the left divider on whichever verb is
   first-VISIBLE (Restart hides on an ended session) so a hidden button never leaves a floating rule.
   No min-height here on purpose: the mobile 44px touch floor still applies for tappability. */
.sc-verbs { display: flex; align-items: center; align-self: center; flex: 0 0 auto;
  border: 1px solid var(--border); border-radius: var(--r); overflow: hidden; }
.sc-verbs > button { border: 0; border-left: 1px solid var(--border); border-radius: 0;
  padding: 3px 10px; font-size: 11px; letter-spacing: .06em; text-transform: uppercase;
  white-space: nowrap; background: transparent; color: var(--muted); box-shadow: none; }
.sc-verbs > button:hover { background: var(--panel-2); color: var(--text); }
.sc-verbs > button.sc-verb-lead { border-left: 0; }
.sc-verbs > .sc-tools { font-size: 15px; line-height: 1; padding: 2px 10px; letter-spacing: 0; text-transform: none; }
/* Close: red text, filled red on HOVER — was a permanently red-outlined button that shouted on every visit. */
.sc-verbs > .sc-danger { color: var(--err); }
.sc-verbs > .sc-danger:hover { background: var(--err); color: var(--panel); }

/* ⚠ flex:1 with a min-height floor, NOT a fixed 48vh. A viewport-height guess wasted a tall screen and
   overflowed a short one; the floor is what stops the pane collapsing to nothing on a small window.
   `overflow-wrap:anywhere` because a pane line can be one unbroken path with no space to break at. */
/* ⚠ flex-basis 0, not auto: with basis auto the pane's CONTENT is the starting size, so a long
   backlog inflated the card before shrink could act. Basis 0 means the transcript takes exactly the
   leftover space — content never sizes anything, it only scrolls. */
.sc-transcript { overflow-wrap: anywhere; overflow-y: scroll; overflow-x: hidden;
  flex: 1 1 0; min-height: min(320px, 52vh); margin: 0; padding: 12px 14px;
  border: 1px solid var(--border); border-radius: var(--r); background: var(--panel-2);
  font-family: var(--ui); font-size: 13.5px; line-height: 1.5; color: var(--text); }
/* ── the MARKDOWN chat (ADR-0073). The conversation renders from the transcript, so it reads as a
   message thread — prose in the UI face, code/tables in mono. mdToHtml emits only the tags below. */
.sc-md > :first-child { margin-top: 0; }
.sc-md > :last-child { margin-bottom: 0; }
.sc-md .md-p { margin: 0 0 10px; }
.sc-md .md-p.muted { color: var(--dim); }
.sc-md .md-h { margin: 14px 0 6px; font-weight: 700; line-height: 1.3; }
.sc-md h1.md-h { font-size: 1.35em; } .sc-md h2.md-h { font-size: 1.2em; } .sc-md h3.md-h { font-size: 1.08em; }
.sc-md code { font-family: var(--mono); font-size: .9em; background: var(--panel); border: 1px solid var(--border); border-radius: 3px; padding: 0 4px; }
.sc-md .md-code { font-family: var(--mono); font-size: 12px; background: var(--panel); border: 1px solid var(--border); border-radius: var(--r); padding: 9px 11px; margin: 0 0 10px; white-space: pre-wrap; overflow-wrap: anywhere; }
.sc-md .md-code code { background: none; border: 0; padding: 0; white-space: inherit; }
/* Fallback: the raw terminal capture shown when no transcript stream is reaching the console (see
   liveIsScrape / renderCombined). Monospace <pre>, but it WRAPS (`pre-wrap`) rather than scrolling
   sideways — no horizontal scroll anywhere in the transcript (operator ask 2026-08-28). Its internal
   spacing is kept, only over-wide lines fold. */
.sc-md .sc-scrape { margin: 0; font-family: var(--mono); font-size: 12px; line-height: 1.45;
  color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }
/* A tool call is a machine ACTION, not prose: its own mono row — the tool name tinted the design's
   "deterministic" green, the target muted, led by a ⚙ — so a run of calls scans apart from the agent's
   words (operator ask 2026-08-28). Emitted by mdToHtml when a line is `⚙ \`name\` <what>`. */
.sc-md .md-tool { display: flex; gap: 8px; align-items: baseline; margin: 3px 0; font-family: var(--mono);
  font-size: 12px; line-height: 1.5; }
.sc-md .md-tool-name { flex: 0 0 auto; white-space: nowrap; color: var(--det-ink); font-weight: 600; }
.sc-md .md-tool-name::before { content: "⚙"; margin-right: 6px; opacity: .6; font-weight: 400; }
.sc-md .md-tool-what { color: var(--muted); overflow-wrap: anywhere; }
/* the USER turn — our `> ❯ …` blockquote marker rendered as an accent-edged block, so whose words are whose reads at a glance. */
.sc-md .md-quote { margin: 0 0 10px; padding: 4px 12px; border-left: 3px solid var(--accent); background: var(--accent-dim); color: var(--accent-ink); font-weight: 600; }
.sc-md .md-list { margin: 0 0 10px; padding-left: 22px; }
.sc-md .md-list li { margin: 2px 0; }
.sc-md .md-hr { border: 0; border-top: 1px solid var(--border); margin: 12px 0; }
.sc-md .md-table { border-collapse: collapse; margin: 0 0 10px; width: 100%; table-layout: fixed; }
.sc-md .md-table th, .sc-md .md-table td { border: 1px solid var(--border); padding: 4px 9px; text-align: left; font-size: .95em; overflow-wrap: anywhere; word-break: break-word; vertical-align: top; }
.sc-md .md-table th { background: var(--panel); font-weight: 700; }
.sc-md a { color: var(--accent-ink); text-decoration: underline; }

/* ⚠ ONE row (operator ask 2026-08-27): the session's own status on the LEFT, what your last message is
   doing on the RIGHT. Both single-line so neither ever grows the layout and steals the transcript. */
.sc-statusbar { display: flex; justify-content: space-between; align-items: baseline; gap: 12px;
  min-height: 18px; padding: 3px 2px 0; }
.sc-status { font-family: var(--mono); font-size: 12px; color: var(--dim);
  flex: 0 1 auto; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sc-activity { font-family: var(--mono); font-size: 12px; color: var(--muted);
  flex: 0 0 auto; white-space: nowrap; }
/* Pushes the ⋯ toggle to the right end of the header row. */
.sc-head-gap { flex: 1 1 auto; }
.sc-tools { font-size: 15px; line-height: 1; padding: 2px 9px; }
/* ⚠ OVERLAY, not a flow child (operator ask 2026-08-27): anchored to the card's bottom-right so it
   costs the transcript ZERO height, scrolls internally, and the ⋯ / ✕ toggle its [hidden] attribute. */
.sc-tools-panel { position: absolute; right: 10px; bottom: 10px; z-index: 20;
  width: min(560px, calc(100% - 20px)); max-height: 72%; overflow: auto;
  background: var(--panel); border: 1px solid var(--accent); border-radius: var(--r);
  box-shadow: 0 14px 44px -12px rgba(0,0,0,.55); padding: 12px 14px; }
.sc-tools-panel[hidden] { display: none; }
.sc-tools-hd { display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;
  font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: .14em; color: var(--dim); }
/* The mode pill is a READ-ONLY indicator (2026-08-28) — the session's permission mode, beside the state
   and transport pills. Accent-tinted so the mode reads at a glance; not pressable. */
.sc-mode { background: var(--accent-dim); border-color: var(--accent-line);
  color: var(--accent-ink); text-transform: none; letter-spacing: 0; }

/* A dialog (/model, a permission prompt) is the session WAITING ON YOU — so it wears the same amber
   "waiting" language as its sidebar dot (§nav-dot-wait): an amber-framed panel with a soft glow, the
   menu kept mono in a recessed well (its column alignment carries meaning), and the answer keys as
   themed keycaps that light to accent-yellow — the console's action colour — on hover. */
.sc-dialog { margin: 0 0 8px; padding: 10px 12px 12px; background: var(--panel);
  border: 1px solid var(--warn); border-radius: var(--r); box-shadow: 0 0 16px -6px var(--warn); }
.sc-dialog-text { white-space: pre-wrap; margin: 0 0 10px; padding: 9px 11px; font-size: 12.5px;
  line-height: 1.5; color: var(--text); background: var(--bg); border: 1px solid var(--border);
  border-radius: var(--r); max-height: 26vh; overflow: auto; }
.sc-keys { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
/* The hint is the "waiting on you" cue — its own line above the keys, amber, led by the same pulsing
   amber dot as the sidebar row, so the dialog and its session read as one waiting state. */
.sc-keys-hint { flex: 1 1 100%; display: flex; align-items: center; gap: 7px; margin: 0 0 3px;
  font-family: var(--mono); font-size: 11px; color: var(--warn); }
.sc-keys-hint::before { content: ""; width: 7px; height: 7px; flex: 0 0 auto; border-radius: 1px;
  background: var(--warn); box-shadow: 0 0 6px var(--warn); animation: nav-pulse 1.6s ease-in-out infinite; }
.sc-keys .sc-key { padding: 4px 11px; min-width: 30px; text-align: center; font-size: 12px;
  background: var(--panel-2); border: 1px solid var(--border); color: var(--text); border-radius: var(--r); }
.sc-keys .sc-key:hover { background: var(--accent); border-color: var(--accent); color: #14120d; }

/* Messages sent but not yet taken by the session (operator ask 2026-09-01).
   ⚠ Sits directly above the composer on purpose: it answers "did that send?" in the place the
   operator is already looking, which the Recent drawer — collapsed, inside an overlay — did not. */
.sc-pending { display: flex; flex-direction: column; gap: 4px; margin: 0 0 8px; }
.sc-pending-row { display: flex; align-items: baseline; gap: 8px; font-size: 12px; min-width: 0; }
/* The message itself may be long; it wraps rather than pushing the state pill off the row. */
/* The MESSAGE keeps a floor and yields the rest: it is the thing the operator sent and must stay
   readable, so it never shrinks below a few characters however long the reason beside it runs. */
.sc-pending-text { flex: 0 1 auto; min-width: 10ch; max-width: 50%; overflow-wrap: anywhere; color: var(--text); }
/* ⚠ `min-width: 0` + `overflow-wrap: anywhere` are LOAD-BEARING. A flex item's default `min-width: auto`
   will not shrink below its content's minimum, and a reason that quotes a pane can carry a 200-char
   unbreakable run of `─` — which blew the row out sideways, crushed the message to one letter per line,
   and pushed the Clear button clean off-screen (operator: "a failed msg which can not be cleared",
   2026-09-02). Capped to a few lines with the full text on hover, so a long quote informs, not floods. */
.sc-pending-why {
  flex: 1 1 0; min-width: 0; overflow-wrap: anywhere; font-size: 11px;
  display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.sc-pending-row > .sc-pending-clear { flex: 0 0 auto; }

.sc-compose { display: flex; gap: 8px; align-items: stretch; }
.sc-text { flex: 1 1 200px; min-width: 0; font-family: inherit; resize: none; }
/* The send column holds only the Send button now (the mode moved to the top bar, read-only) — one
   full-height button beside the composer. */
.sc-send { display: flex; flex-direction: column; align-items: stretch; gap: 4px; }
.sc-send #sc-send { min-width: 96px; flex: 1 1 auto; }
/* The picker sits UNDER Send, small: pasting is the path this feature is for and must stay the obvious
   one, while the button is the fallback for a file already on disk. */
.sc-send .sc-attach-btn { flex: 0 0 auto; font-size: 11px; padding: 0; }

/* ADR-0079: the pictures waiting to go, BELOW the box.
   ⚠ The token rides beside each thumbnail because the token is what the operator's own sentence refers
   to — a strip of anonymous thumbnails leaves them guessing which [Img..] was which. Wraps rather than
   scrolls: eight is the ceiling, and a second row is easier to read than a horizontal scroller. */
.sc-attach { display: flex; flex-wrap: wrap; gap: 8px; margin: 6px 0 0; }
.sc-attach-item {
  display: flex; align-items: center; gap: 6px; padding: 3px 6px 3px 3px;
  border: 1px solid var(--line, #ddd); border-radius: 6px; background: var(--panel, transparent);
  font-size: 11px; max-width: 100%; min-width: 0;
}
/* A fixed box with `object-fit: cover`, so a panorama and a portrait screenshot make the same-shaped
   chip and the strip does not reflow as pictures arrive. */
.sc-attach-thumb { width: 34px; height: 34px; object-fit: cover; border-radius: 4px; display: block; flex: 0 0 auto; }
.sc-attach-tok { flex: 0 0 auto; }
.sc-attach-size { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-attach-x { flex: 0 0 auto; padding: 0 2px; }
.sc-note { margin: 8px 0 0; font-size: 12px; }

/* Consulted when something looks wrong, not while working — but the relay's failures are quiet by
   nature, so they stay on the page rather than behind a route. */
.sc-drawers { display: flex; gap: 16px; margin-top: 10px; flex-wrap: wrap; flex: 0 0 auto; }
.sc-drawer { flex: 1 1 320px; }
/* ⚠ AN OPEN DRAWER SCROLLS ITSELF, BOUNDED. A long Recent history inside the card squeezed the
   transcript down to its min-height floor and handed the PAGE the scrollbar — the terminal stopped
   filling the window and the thing that scrolled was everything except the history (found live).
   The drawer is the consult-when-wrong region; it gets a bounded window, and the transcript keeps
   the room the flex column gives it. */
.sc-drawer > div { overflow-y: auto; max-height: 32vh; }
.sc-drawer > summary { cursor: pointer; font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .12em; color: var(--dim); padding: 4px 0; }

/* ⚠ Modals, because creating and closing a session are decisions — one with three fields and a
   warning, the other irreversible for a warm session. Both were previously competing for space with
   the conversation on every single visit. */
.sc-modal { position: fixed; inset: 0; z-index: 60; background: rgba(20, 18, 13, .45);
  display: flex; align-items: center; justify-content: center; padding: 16px; }
.sc-modal-card { width: 420px; max-width: 92vw; margin: 0; max-height: 88vh; overflow-y: auto; }
.sc-modal-danger { border-color: var(--err); }
.sc-confirm-q { margin: 0; font-size: 13.5px; }
.sc-hint { margin: 8px 0 0; font-size: 11px; }
.sc-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 16px; }

/* ⚠ "＋ New session" opens the modal and sits with the sessions it creates, at the top of the sub-list
   — the one place an operator is already looking. It reads as an empty SLOT, not a competing control
   (SessionControlV2 sync 2026-08-27): dashed + transparent, quiet until hover lights it with the accent. */
.nav-sub .sc-new-btn { margin: 2px 4px 8px; font-size: 11px; letter-spacing: .08em;
  text-transform: uppercase; background: transparent; border: 1px dashed var(--border); color: var(--muted); }
.nav-sub .sc-new-btn:hover { background: var(--accent-dim); border-color: var(--accent); color: var(--accent-ink); }
/* Session rows lead with a state DOT + glow (SessionControlV2 sync): working = green, idle = faint,
   "waiting on you" (prompting/trust) = amber + pulse with an amber-tinted word. The word alone read the
   same at a glance; the dot is what a scan catches. */
/* The session list reads as NESTED under the Sessions tab (SessionControlV2 sync): indented, with a
   faint left rail. The active row's accent bar sits ON that rail instead of floating 10px out. */
.nav-sub { margin-left: 14px; padding-left: 8px; border-left: 1px solid var(--border-2); }
.nav-sub .navitem.active::before { left: -9px; width: 2px; height: 14px; }
.nav-sub .navitem { display: flex; align-items: center; gap: 8px; }
.nav-name { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* The Sessions tab shows a live count of its sessions (SessionControlV2 sync) — pushed to the right
   edge, quiet mono so it reads as a tally, not a second label. */
.navitem.nav-parent { display: flex; align-items: center; gap: 6px; }
.nav-parent .nav-label { flex: 1; text-align: left; }
.nav-count { flex: 0 0 auto; font-family: var(--mono); font-size: 10px; letter-spacing: 0;
  text-transform: none; color: var(--dim); }
.nav-dot { width: 7px; height: 7px; flex: 0 0 auto; border-radius: 1px; background: var(--faint); }
.nav-dot-ok { background: var(--ok); box-shadow: 0 0 6px var(--ok); }
.nav-dot-wait { background: var(--warn); box-shadow: 0 0 6px var(--warn); animation: nav-pulse 1.6s ease-in-out infinite; }
.nav-state { flex: 0 0 auto; font-size: 10px; text-transform: uppercase; letter-spacing: .06em; color: var(--dim); }
.nav-state-wait { color: var(--warn); }
/* Sessions are GROUPED BY AGENT (operator ask 2026-08-30): every reachable agent is a header — presence
   dot + label + engine badge + tally — and its sessions are the rows beneath it. The header reads quieter
   than the rows it owns, so a scan lands on the sessions; the group is context, not a target. Its "＋"
   starts a session on THAT agent (shown only when the device offered roots). */
.nav-group { display: flex; align-items: center; gap: 7px; padding: 8px 8px 3px; margin-top: 2px; }
.nav-group:first-of-type { margin-top: 0; }
.nav-gdot { width: 6px; height: 6px; flex: 0 0 auto; border-radius: 50%; background: var(--faint); }
.nav-gdot-on { background: var(--ok); box-shadow: 0 0 6px var(--ok); }
.nav-gname { flex: 1; min-width: 0; text-align: left; overflow: hidden; text-overflow: ellipsis;
  white-space: nowrap; font-size: 11px; font-weight: 600; letter-spacing: .04em; color: var(--text); }
.nav-engine { flex: 0 0 auto; font-family: var(--mono); font-size: 9px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--dim); border: 1px solid var(--border-2); border-radius: var(--r); padding: 0 4px; }
/* ADR-0075: a messaging-capable agent (a coordinator/"PM"). Accent-coloured so it stands apart from the
   dim engine pill — this agent may relay text into OTHER agents' sessions. */
.nav-msg { flex: 0 0 auto; font-family: var(--mono); font-size: 9px; text-transform: uppercase;
  letter-spacing: .04em; color: var(--accent-ink); border: 1px solid var(--accent-ink); border-radius: var(--r);
  padding: 0 4px; cursor: default; }
.nav-gcount { flex: 0 0 auto; font-family: var(--mono); font-size: 10px; color: var(--dim); }
.nav-gnew { flex: 0 0 auto; background: transparent; border: 0; color: var(--muted); cursor: pointer;
  font-size: 13px; line-height: 1; padding: 0 2px; min-height: 0; }
.nav-gnew:hover { color: var(--accent-ink); }
/* Each agent's sessions sit in their OWN indented block under a second-level rail, so tab > agent >
   session reads as three nested steps, not one flat list (design refine 2026-08-30). The block's bottom
   margin is the air between groups. */
.nav-gitems { display: flex; flex-direction: column; margin: 0 0 6px 10px; padding-left: 8px; border-left: 1px solid var(--border-2); }
/* The active row's accent bar sits ON the second-level rail rather than floating out past it. */
.nav-gitems .navitem.active::before { left: -9px; }
/* ADR-0074: a NODE sub-header appears ONLY when an agent spans more than one machine — agent → node →
   session. Quieter and smaller than the agent header; its sessions indent under it via .nav-gitems. */
.nav-node { display: flex; align-items: center; gap: 6px; padding: 3px 8px 2px 16px; }
.nav-ndot { width: 5px; height: 5px; flex: 0 0 auto; border-radius: 50%; background: var(--faint); }
.nav-ndot-on { background: var(--ok); box-shadow: 0 0 5px var(--ok); }
.nav-nname { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 10px; letter-spacing: .02em; color: var(--dim); }
.nav-nram { flex: 0 0 auto; font-family: var(--mono); font-size: 9px; color: var(--dim); letter-spacing: 0; }
/* The Claude account's weekly limit on a node (operator ask 2026-09-02): the sidebar's compact mark beside RAM,
   and the header pill. Quiet until it matters — amber from 80%, red from 95% — so a healthy fleet stays grey. */
.nav-nusage { flex: 0 0 auto; font-family: var(--mono); font-size: 9px; color: var(--dim); letter-spacing: 0; }
/* ONE row per machine above the agent groups (operator feedback 2026-09-02): the machine's name, then its weekly
   and 5-hour marks. Reads like a node sub-header, set off from the groups below by a hairline. */
.nav-usage-row { display: flex; align-items: center; gap: 8px; padding: 4px 8px 5px 10px; margin: 2px 0 3px; border-bottom: 1px solid var(--line); }
.nav-usage-row .nav-nname { font-size: 10px; color: var(--muted); }
.usage-pill { font-family: var(--mono); }
.nav-nusage.usage-hi, .usage-pill.usage-hi { color: var(--warn); border-color: var(--warn); }
.nav-nusage.usage-crit, .usage-pill.usage-crit { color: var(--err); border-color: var(--err); font-weight: 600; }
/* ADR-0074 device(node): a node that is ALSO a registered device wears its duties as a small tag, so the
   machine reads as one thing — its name plus what yarness has it do (capture/parse/serve). */
.nav-nduty { flex: 0 0 auto; max-width: 45%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 8.5px; letter-spacing: .02em; color: var(--dim); padding: 0 5px; border: 1px solid var(--border-2);
  border-radius: var(--r); }
.nav-ncount { flex: 0 0 auto; font-family: var(--mono); font-size: 9px; color: var(--dim); }
/* No-device gates: a bare identity with no node running as it. Muted, at the bottom, so it is visible
   without being mistaken for something you can start a session on. */
@keyframes nav-pulse { 50% { opacity: .3; } }
@media (prefers-reduced-motion: reduce) { .nav-dot-wait, .sc-keys-hint::before { animation: none; } }

@media (max-width: 760px) {
  /* The sidebar is a horizontal strip on a phone, so its width token must not apply. */
  :root { --rail-w: 220px; }
  /* ⚠ flex:0 0 auto once STACKED. The desktop rule is flex:1 1 320px so two drawers share a row;
     in a column that same rule makes them GROW to fill the height, which flung "Recent" to the bottom
     of a very tall page with 600px of nothing above it. */
  .sc-drawers { flex-direction: column; gap: 8px; }
  .sc-drawer { flex: 0 0 auto; }
}

/* ================================================================================================
   PHONE — the drawer, from the mobile design ("session-control-mobile").

   ⚠ This REPLACES the horizontal nav strip. A strip kept every destination one tap away but had
   nowhere to put the sessions and their states, which is now most of what the sidebar carries — the
   strip would have scrolled a dozen items sideways past the thing you were looking for.
   ================================================================================================ */
#side-scrim { display: none; }

@media (max-width: 760px) {
  /* The sidebar leaves the grid entirely and becomes an overlay. */
  #app { grid-template-columns: 1fr; grid-template-areas: "top" "main"; grid-template-rows: 54px 1fr; }
  #app.side-hidden { grid-template-columns: 1fr; }

  #side {
    position: fixed; top: 0; bottom: 0; left: 0; z-index: 71;
    width: 290px; max-width: 85vw;
    border-right: 1px solid var(--accent);
    box-shadow: 18px 0 50px -20px rgba(0, 0, 0, .55);
    overflow-y: auto;
    /* ⚠ transform, not `display`, so it can animate and so its scroll position survives a close. */
    transform: translateX(0);
    transition: transform .18s ease;
  }
  /* `display:none` on the desktop rule would defeat the transform; override it here. */
  #app.side-hidden #side { display: block; transform: translateX(-100%); }

  #side-scrim { display: block; position: fixed; inset: 0; z-index: 70; background: rgba(20, 18, 13, .45); }
  #app.side-hidden #side-scrim { display: none; }

  /* The nav is a column again inside the drawer — the strip layout was the thing being replaced. */
  .nav { flex-direction: row; }
  #side .nav { flex-direction: column; overflow-x: visible; }
  #side .nav .navitem { flex: 0 0 auto; }
  .navitem.active::before { left: -10px; right: auto; top: 50%; bottom: auto;
    transform: translateY(-50%); width: 3px; height: 16px; }
  .nav-sub .navitem.active::before { left: -7px; width: 2px; height: 14px; }

  /* ⚠ ONE ROW for the ticking line and both pills. The stacked pill column beside Send was wider than
     390px allows, and it pushed the composer into a sliver. */
  .sc-compose { flex-wrap: wrap; }
  /* ⚠ Side by side on a phone, not stacked: two full-width buttons in a column would push the transcript
     up by a whole row for a control that is used once in a while. */
  .sc-send { flex: 1 1 100%; flex-direction: row; align-items: center; }
  .sc-send #sc-send { flex: 1 1 auto; }
  .sc-send .sc-attach-btn { flex: 0 0 auto; padding: 0 8px; }
  .sc-send #sc-send { flex: 1; min-width: 0; }
  .sc-text { flex: 1 1 100%; }
  .sc-transcript { min-height: 180px; font-size: 12px; }
  .sc-keys .sc-key { flex: 1; font-size: 13px; }
  .sc-keys-hint { flex: 1 1 100%; }
  /* No page heading on a phone: the card header already names the session, and the strap line cost
     three lines of a screen that has few. */
  .pagehead { display: none; }
}

/* ⚠ Staleness stays VISIBLE rather than inside a drawer. "reported 4h ago" is how an operator finds
   out the worker died rather than that the session is quiet, and it is the one fact that explains an
   unresponsive console. */
.sc-age { font-size: 11px; margin-top: 8px; font-family: var(--mono); }

/* ⚠ The standing warnings are worth having and not worth six lines of every visit. Collapsed, but
   present — they explain that this types into a LIVE shell and that the transcript is not history,
   which are the two things a newcomer gets wrong. */
.sc-note > summary { cursor: pointer; font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .12em; color: var(--dim); padding: 6px 0 0; }
.sc-note-body { margin: 6px 0 0; font-size: 12px; }

/* ---- model / effort badge (operator ask 2026-09-02) --------------------------------------------
   ⚠ The QUIETEST thing on a session row: it sits on every one, so it whispers. No fill and a faint
   hairline, on-palette (the first version used an off-language cold-grey `--chip` that does not
   exist, so it fell back to a blue-grey chip on a warm UI). The effort reads dimmer still. */
.model-pill {
  padding: 1px 7px; border-radius: 20px;
  background: transparent; border: 1px solid var(--border-2);
  color: var(--dim); font-family: var(--mono); font-weight: 500; font-size: 10px;
  letter-spacing: .01em; vertical-align: middle;
}
.navitem .model-pill, .chat-sessions .model-pill { margin-left: 6px; }
/* On an ACTIVE (accent) row the hairline would fight the fill — lift it to an accent tint instead. */
.navitem.active .model-pill { border-color: var(--accent-line); color: var(--accent-ink); }

/* The "clear" on a settled pending row: a dismiss must not shout, so it is muted-to-text on hover,
   not the accent `.linkbtn` yellow. Pushed to the row's end. */
.sc-pending-clear {
  margin-left: auto; color: var(--dim); font-family: var(--mono); font-size: 10px;
  text-transform: uppercase; letter-spacing: .1em;
}
.sc-pending-clear:hover { color: var(--text); text-decoration: none; }

/* ---- debug log panel (operator ask 2026-09-02) -------------------------------------------------
   ⚠ Fixed and on top of everything: it must be usable while the view underneath is the broken thing.
   Constrained height with its own scroll so it never pushes page content around. On-palette and in the
   Reclaim language — sharp `--r` radius, warm panel/border, the soft drop shadow the toasts use. */
.dbg-panel {
  position: fixed; right: 14px; bottom: 14px; z-index: 9999;
  width: min(720px, calc(100vw - 28px)); max-height: min(46vh, 420px);
  display: flex; flex-direction: column;
  background: var(--panel); color: var(--text);
  border: 1px solid var(--border); border-radius: var(--r);
  box-shadow: 0 12px 40px -10px rgba(0, 0, 0, .5);
  font-size: 11.5px; overflow: hidden;
}
.dbg-hd {
  display: flex; align-items: center; gap: 8px; padding: 8px 10px;
  background: var(--panel-2); border-bottom: 1px solid var(--border);
  font-family: var(--ui); font-weight: 600;
}
.dbg-hd b { font-size: 11px; text-transform: uppercase; letter-spacing: .12em; color: var(--muted); }
.dbg-hd .muted { color: var(--dim); font-family: var(--mono); font-size: 10px; }
.dbg-hd .spacer { flex: 1; }
.dbg-body { overflow: auto; padding: 6px 10px 10px; font-family: var(--mono); line-height: 1.7; }
.dbg-row { display: grid; grid-template-columns: 58px 46px minmax(0, auto) minmax(0, 1fr); gap: 10px; padding: 1px 0; }
.dbg-t { color: var(--dim); }
.dbg-c { color: var(--faint); text-transform: uppercase; font-size: 9.5px; letter-spacing: .06em; align-self: center; }
.dbg-e { white-space: nowrap; color: var(--text); }
.dbg-d { color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* ⚠ The render channel is the one worth spotting at a glance — it is the branch that decides what the
   operator is looking at, and the reason this panel exists at all. Accent, not a cold hex. */
.dbg-render .dbg-e { color: var(--accent-ink); }
.dbg-net .dbg-e { color: var(--muted); }
.dbg-relay .dbg-e { color: var(--det-ink); }

/* ---- queued message in the chat pane (operator ask 2026-09-02) ---------------------------------
   The operator's own voice (the same `.md-quote` shape a taken prompt renders as), but visibly NOT
   yet taken: the accent fill drops to a dashed hairline and dim ink, with a small "queued" tag — the
   same way Claude Code shows a message it is holding until the turn ends. When the session takes it,
   the transcript paints the real, solid quote and this one disappears. */
.sc-md .sc-queued, .sc-transcript .sc-queued {
  margin: 6px 0 10px; padding: 4px 12px;
  border-left: 3px dashed var(--accent-line); background: transparent;
  color: var(--muted); font-weight: 500;
}
.sc-queued-tag {
  display: inline-block; margin-right: 8px; padding: 0 6px; border-radius: 20px;
  border: 1px solid var(--accent-line); color: var(--accent-ink);
  font-family: var(--mono); font-size: 9.5px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em; vertical-align: 1px;
}
/* A safeguard fallback on the newest turn: shown INSIDE the model badge as an arrow to what answered,
   so the configured model stays the headline and the fallback is visibly a per-turn detail. */
.model-pill-fb { border-color: var(--warn); }
.model-fb { margin-left: 5px; color: var(--warn); }

/* ADR-0078 v2 shell: the tab strip above the column, the unread dot, the sidebar filter. */
.sc-tabs { display: flex; align-items: center; gap: 4px; overflow-x: auto; padding: 0 0 6px; margin: 0 0 6px; border-bottom: 1px solid var(--border-2); scrollbar-width: thin; }
.sc-tab { display: inline-flex; align-items: center; gap: 6px; flex: 0 0 auto; max-width: 220px; padding: 4px 8px; border: 1px solid var(--border-2);
  border-radius: 6px; background: transparent; color: var(--dim); font-size: 12px; cursor: pointer; }
.sc-tab.active { color: var(--fg); border-color: var(--border); background: var(--bg-2, rgba(127,127,127,.08)); }
.sc-tab-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sc-tab-dot { width: 7px; height: 7px; border-radius: 1px; background: var(--faint); flex: 0 0 auto; }
.sc-tab-working .sc-tab-dot { background: var(--ok); box-shadow: 0 0 6px var(--ok); }
.sc-tab-wait .sc-tab-dot { background: var(--warn); box-shadow: 0 0 6px var(--warn); animation: nav-pulse 1.6s ease-in-out infinite; }
.sc-tab-unread .sc-tab-dot { background: var(--accent, #3b82f6); }
.sc-tab-gone { text-decoration: line-through; opacity: .6; }
.sc-tab-x { opacity: .5; padding: 0 2px; } .sc-tab-x:hover { opacity: 1; color: var(--err); }
.sc-tab-bell { margin-left: auto; flex: 0 0 auto; border: 0; background: transparent; cursor: pointer; opacity: .6; font-size: 13px; } .sc-tab-bell.on { opacity: 1; }
.sc-tab-split { flex: 0 0 auto; border: 1px solid var(--border-2); border-radius: 6px; background: transparent; color: var(--dim); cursor: pointer; padding: 2px 7px; font-size: 13px; }
.sc-tab-split.on { color: var(--fg); border-color: var(--border); }
/* Two columns side by side on a wide screen (ADR-0078 §8, split view): the tab strip spans both. */
.sc-col-split { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; max-width: none; }
.sc-col-split > .sc-tabs { grid-column: 1 / -1; }
.sc-card-split { min-width: 0; }
.nav-dot-unread { background: var(--accent, #3b82f6); }
.nav-group-wait .nav-gname { color: var(--warn); }
.nav-filter { width: 100%; box-sizing: border-box; margin: 4px 0 6px; padding: 3px 6px; font-size: 11px; border: 1px solid var(--border-2); border-radius: 4px; background: transparent; color: var(--fg); }

/* ADR-0078 v2 column: one node per transcript BLOCK (rendered once, reconciled by key). */
.sc-block { margin: 0 0 10px; }
.sc-block-pending { opacity: 0.55; }
.sc-block-failed { opacity: 0.85; border-left: 3px solid var(--err, #c0392b); padding-left: 8px; }
.sc-block-retry { display: block; margin-top: 4px; font-size: 12px; }
.sc-block-marker { text-align: center; color: var(--muted, #888); font-size: 12px; margin: 14px 0; }
.sc-newbelow { position: sticky; bottom: 8px; margin: -34px auto 0; display: block; width: max-content;
  padding: 4px 12px; border-radius: 999px; border: 1px solid var(--ok, #2e7d32); background: var(--bg, #fff);
  color: var(--ok, #2e7d32); font-size: 12px; cursor: pointer; z-index: 2; }

/* v2 scrape block (ADR-0078 §3): the pane screenshot that stands in while a session has no markdown
   blocks — same mono, wrapping treatment as v1's fallback so the two builds read alike. */
.sc-block-scrape .sc-scrape { margin: 0; font-family: var(--mono); font-size: 12px; line-height: 1.45;
  color: var(--text); white-space: pre-wrap; overflow-wrap: anywhere; }

/* ADR-0078 §12 turn metrics: a turn's cost as a quiet mono row after its final answer, and the column's
   running totals as a chip beside the session's own status (the activity line keeps the right edge). */
.sc-block-turn { font-family: var(--mono); font-size: 11.5px; color: var(--dim); margin: 2px 0 14px; padding-left: 2px;
  overflow-wrap: anywhere; }
.sc-metrics { font-family: var(--mono); font-size: 12px; color: var(--dim); white-space: nowrap; }
.sc-statusbar .sc-activity { margin-left: auto; }

/* ADR-0077 §8 (S2): a node's home hub in the sidebar, and the Devices tab's home panel. */
.nav-nhome { font-size: 10px; color: var(--dim); margin-left: 6px; white-space: nowrap; }
.sc-home-row { display: flex; flex-wrap: wrap; gap: 14px; align-items: baseline; margin: 6px 0 10px; }
.sc-home-row select { font-family: var(--mono); font-size: 12px; }
.sc-probe { font-size: 12px; margin-top: 4px; }
.sc-probe th { font-weight: 500; color: var(--muted); text-align: left; padding-right: 12px; }
.sc-probe td { padding: 2px 12px 2px 0; }
