/* ============================================================================
   jops — Component Layer
   Built on tokens.css. Implements the chamfered-panel instrument grammar.
   ============================================================================ */

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

html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }

body {
  margin: 0;
  background:
    radial-gradient(1200px 700px at 78% -8%, rgba(45, 120, 150, 0.10), transparent 60%),
    radial-gradient(1000px 600px at 8% 108%, rgba(120, 90, 200, 0.07), transparent 55%),
    var(--bg);
  color: var(--ink);
  font-family: var(--font-prose);
  font-size: var(--fs-base);
  line-height: 1.5;
  letter-spacing: 0.01em;
}

/* faint structural grid over the whole hull — barely-there instrument texture */
body::before {
  content: ""; position: fixed; inset: 0; pointer-events: none; z-index: var(--z-hull);
  background-image:
    linear-gradient(var(--line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(120% 120% at 50% 0%, #000 35%, transparent 100%);
  opacity: 0.5;
}

/* ----------------------------------------------------------------------------
   TYPE PRIMITIVES
   ---------------------------------------------------------------------------- */
.label {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--ink-2);
}
.label--tick { font-size: var(--fs-micro); letter-spacing: var(--ls-wide); color: var(--ink-3); }
.mono   { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.prose  { font-family: var(--font-prose); }
.dim    { color: var(--ink-3); }
.faint  { color: var(--ink-faint); }
.bright { color: var(--ink-bright); }
/* the explanatory-sentence voice: the ONE token for empty/error/degraded prose
   and small inline metadata (replaces 30+ inline font-size:12px literals so the
   small-text size stays in lockstep with --fs-sm if it ever retunes). */
.hint   { font-size: var(--fs-sm); }

/* ----------------------------------------------------------------------------
   PANEL — the foundational chamfered module.
   Two stacked layers give us a hairline frame AND a cut corner: a border-box
   clipped to an octagon, with an inner fill clipped to the same octagon.
   ---------------------------------------------------------------------------- */
.panel {
  --c: var(--chamfer);
  position: relative;
  background: var(--panel);
  clip-path: polygon(
    var(--c) 0, calc(100% - var(--c)) 0, 100% var(--c),
    100% calc(100% - var(--c)), calc(100% - var(--c)) 100%,
    var(--c) 100%, 0 calc(100% - var(--c)), 0 var(--c));
  /* The hairline is an inset 1px shadow that follows the clip — a uniform
     perpendicular stroke that stays even through every 45° cut corner. (Two
     stacked octagon layers cannot: a 1px outset moves a diagonal edge only
     ~0.7px, so the frame thins to nothing at the chamfer.) (DL5) */
  box-shadow: inset 0 0 0 1px var(--line);
  padding: var(--s4);
}
.panel--raised { background: var(--panel-2); }
.panel--well   { background: var(--well); }
.panel--flush  { padding: 0; }

/* a focused/active/watched panel earns a brighter frame + corner brackets.
   Brackets sit inset from the corners (on the straight edges) so the octagon
   clip never eats them — the "targeting frame" on a panel the mirror is watching. */
.panel--active { background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line-strong); }
.corner {
  position: absolute; width: 13px; height: 13px; pointer-events: none;
  border: 1.5px solid var(--accent); opacity: 0.85;
  filter: drop-shadow(0 0 4px var(--accent-glow));
}
.corner.tl { top: 7px;    left: 7px;    border-right: 0; border-bottom: 0; }
.corner.tr { top: 7px;    right: 7px;   border-left: 0;  border-bottom: 0; }
.corner.bl { bottom: 7px; left: 7px;    border-right: 0; border-top: 0; }
.corner.br { bottom: 7px; right: 7px;   border-left: 0;  border-top: 0; }

/* connection lattice — the Agatha-King crosshatch, as a subtle accent texture */
.lattice {
  background-image:
    linear-gradient(45deg,  var(--line-soft) 1px, transparent 1px),
    linear-gradient(-45deg, var(--line-soft) 1px, transparent 1px);
  background-size: 14px 14px;
}

/* ----------------------------------------------------------------------------
   PANEL HEADER — title + ruler ticks + optional status, with a divider.
   ---------------------------------------------------------------------------- */
.phead {
  display: flex; align-items: center; gap: var(--s3);
  padding-bottom: var(--s2); margin-bottom: var(--s3);
  border-bottom: 1px solid var(--line);
}
.phead__title {
  font-family: var(--font-label);
  text-transform: uppercase;
  letter-spacing: var(--ls-label);
  font-size: var(--fs-label);
  font-weight: 700;
  color: var(--accent-bright);
  text-shadow: 0 0 12px var(--accent-glow);
}
/* a small index glyph before the title — the panel "callsign" */
.phead__title::before {
  content: "▸"; color: var(--accent); margin-right: 7px; opacity: 0.8;
  text-shadow: 0 0 8px var(--accent-glow);
}
.phead__rule {
  flex: 1; height: 8px; align-self: center;
  background-image: repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 6px);
  mask-image: linear-gradient(90deg, #000, transparent 85%);
  opacity: 0.8;
}
.phead__meta { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: 0.08em; }

/* ----------------------------------------------------------------------------
   STATUS CHIP — the honest-mirror badge. Strict color = strict meaning.
   ---------------------------------------------------------------------------- */
.chip {
  --cc: var(--ink-2); --cw: transparent; --cl: var(--line);
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-label);
  text-transform: uppercase; letter-spacing: 0.1em;
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  padding: var(--s1) var(--s2) 3px;
  color: var(--cc);
  background: var(--cw);
  position: relative;
  clip-path: var(--clip-oct-sm);
  box-shadow: inset 0 0 0 1px var(--cl);
}
.chip__dot { width: 6px; height: 6px; border-radius: 50%; background: var(--cc); box-shadow: 0 0 8px var(--cc); }
.chip--ok    { --cc: var(--ok-bright);    --cw: var(--ok-wash);    --cl: var(--ok-line); }
.chip--nudge { --cc: var(--nudge-bright); --cw: var(--nudge-wash); --cl: var(--nudge-line); }
.chip--alarm { --cc: var(--alarm-bright); --cw: var(--alarm-wash); --cl: var(--alarm-line); }
.chip--defer { --cc: var(--defer-bright); --cw: var(--defer-wash); --cl: var(--defer-line); }
.chip--accent{ --cc: var(--accent-bright);--cw: var(--accent-wash);--cl: var(--accent-glow); }
.chip--ghost { --cc: var(--ink-3); --cw: transparent; --cl: var(--line); }

/* a louder ALARM banner — same octagon as every panel, with a status rail.
   The 3px colored rail is a pseudo inset past the chamfers so the cut corners
   never "bite" it (L3). */
.alertbar {
  --rail-color: var(--alarm);
  position: relative;
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--alarm-wash);
  box-shadow: inset 0 0 0 1px var(--alarm-line);
  clip-path: var(--clip-oct);
}
.alertbar::before {
  content: ""; position: absolute; left: 0; top: var(--chamfer); bottom: var(--chamfer);
  width: 3px; background: var(--rail-color); box-shadow: 0 0 10px -2px var(--rail-color);
}
.alertbar--nudge { --rail-color: var(--nudge); background: var(--nudge-wash); box-shadow: inset 0 0 0 1px var(--nudge-line); }
/* success state — reuses the alertbar layout but the ok/green palette (DL3: red
   is reserved for alarm; an "earned rest" message must not read as danger). */
.alertbar--ok { --rail-color: var(--ok); background: var(--ok-wash); box-shadow: inset 0 0 0 1px var(--ok-line); }
.alertbar__icon { font-family: var(--font-label); font-weight: 800; letter-spacing: 0.1em; }

/* ----------------------------------------------------------------------------
   TAG CHIP — categorical (areas) vs queryable kinds. Areas get a pip.
   ---------------------------------------------------------------------------- */
.tag {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-mono); font-size: var(--fs-micro);
  letter-spacing: 0.04em; color: var(--ink-2);
  padding: 3px var(--s2); background: var(--panel-2);
  box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct-sm);
}
.tag__pip { width: 7px; height: 7px; clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%); }
.tag--gps      .tag__pip { background: var(--area-gps); }      .tag--gps { color: #cfe0ff; }
.tag--labor    .tag__pip { background: var(--area-labor); }    .tag--labor { color: #ffd7f4; }
.tag--personal .tag__pip { background: var(--area-personal); } .tag--personal { color: #f3dcbf; }
.tag--kind { font-family: var(--font-mono); color: var(--ink-3); }
.tag--kind b { color: var(--accent-bright); font-weight: 600; }

/* ----------------------------------------------------------------------------
   BUTTON — chamfered chip with tactile press (Expanse physical-button DNA)
   ---------------------------------------------------------------------------- */
.btn {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-label); font-weight: 700; color: var(--ink-2);
  background: var(--panel-2); border: 0; cursor: pointer;
  padding: var(--s2) var(--s4);
  clip-path: var(--clip-oct-sm);
  box-shadow: inset 0 0 0 1px var(--line);
  transition: color var(--fast) var(--ease), background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.btn:hover { color: var(--ink-bright); background: var(--panel-3); box-shadow: inset 0 0 0 1px var(--line-strong); }
.btn:active { transform: translateY(1px); }
.btn--primary { color: var(--void); background: var(--accent); box-shadow: 0 0 18px -4px var(--accent-glow); }
.btn--primary:hover { background: var(--accent-bright); color: var(--void); }
.btn--ghost { background: transparent; }

/* ----------------------------------------------------------------------------
   COMMAND BAR — the query line. The Roci's command-line ↔ front-end duality.
   ---------------------------------------------------------------------------- */
.cmd {
  display: flex; align-items: center; gap: var(--s3);
  background: var(--well); padding: var(--s3) var(--s4);
  box-shadow: inset 0 0 0 1px var(--line-strong), inset 0 0 24px -8px var(--accent-glow);
  clip-path: var(--clip-oct);
}
.cmd__sigil { color: var(--accent); font-family: var(--font-mono); font-weight: 700; }
.cmd__input { flex: 1; font-family: var(--font-mono); font-size: var(--fs-md); color: var(--ink); }
.cmd .k-field { color: var(--accent-bright); }
.cmd .k-op    { color: var(--nudge); }
.cmd .k-val   { color: var(--ink); }
.cmd__caret { width: 8px; height: 1.1em; background: var(--accent); animation: blink 1.1s steps(1) infinite; }
@keyframes blink { 50% { opacity: 0; } }

/* ----------------------------------------------------------------------------
   COMMITMENT CARD — state + computed health + goal prose + next-action pointer.
   Left rail color = HEALTH (honest mirror), not area.
   ---------------------------------------------------------------------------- */
.commit { --rail: var(--ok); display: grid; gap: var(--s3); }
.commit__rail {
  position: absolute; left: 0; top: 10px; bottom: 10px; width: 3px;
  background: var(--rail); box-shadow: 0 0 12px -2px var(--rail);
}
.commit.is-alarm { --rail: var(--alarm); }
.commit.is-nudge { --rail: var(--nudge); }
.commit.is-ok    { --rail: var(--ok); }
.commit.is-defer { --rail: var(--defer); }
.commit__top { display: flex; align-items: flex-start; gap: var(--s3); justify-content: space-between; }
.commit__title { font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-lg); color: var(--ink-bright); line-height: 1.25; }
.commit__goal {
  font-family: var(--font-prose); font-style: italic; color: var(--ink-2);
  font-size: var(--fs-md); padding-left: var(--s3); border-left: 2px solid var(--line);
}
/* state pills — an EXCLUSIVE field rendered as ONE segmented readout: a single
   chamfered group, hairline-divided into cells, with exactly one cell lit.
   The joined form is the point — it says "pick one of these", not "three toggles". */
.commit__states {
  display: inline-flex; align-items: stretch;
  clip-path: var(--clip-oct-sm);
  box-shadow: inset 0 0 0 1px var(--line);
}
.state {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.12em;
  font-size: var(--fs-micro); font-weight: 700; padding: 4px var(--s2); color: var(--ink-3);
  border-left: 1px solid var(--line); display: flex; align-items: center;
}
.state:first-child { border-left: 0; }
.state.is-on { color: var(--accent-bright); background: var(--accent-wash); }

/* next-action pointer */
.nextaction {
  display: flex; align-items: center; gap: var(--s2);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-2);
}
.nextaction__arrow { color: var(--accent); }

/* ----------------------------------------------------------------------------
   TASK ROW
   ---------------------------------------------------------------------------- */
.task { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line-soft); }
.task:hover { background: var(--panel-2); }
.task__check {
  width: 16px; height: 16px; flex: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 11px; line-height: 1; color: transparent;
  box-shadow: inset 0 0 0 1px var(--line-strong);
  clip-path: polygon(3px 0,calc(100% - 3px) 0,100% 3px,100% calc(100% - 3px),calc(100% - 3px) 100%,3px 100%,0 calc(100% - 3px),0 3px);
}
/* completion carries a glyph, never color alone (DL4/DL10) */
.task.is-done .task__check { background: var(--ok); box-shadow: inset 0 0 0 1px var(--ok-line); color: var(--void); }
.task.is-done .task__check::after { content: "✓"; font-weight: 700; }
.task.is-dropped .task__check { box-shadow: inset 0 0 0 1px var(--line); color: var(--ink-faint); }
.task.is-dropped .task__check::after { content: "✕"; font-weight: 700; }
.task.is-done .task__title { color: var(--ink-faint); text-decoration: line-through; }
.task.is-dropped .task__title { color: var(--ink-faint); text-decoration: line-through dotted; }
.task__star { font-size: 14px; color: var(--ink-faint); cursor: pointer; }
.task.is-must .task__star { color: var(--nudge-bright); text-shadow: 0 0 10px var(--nudge-line); }
.task__title { flex: 1; color: var(--ink); }
.task__meta { display: flex; gap: var(--s2); align-items: center; }
.deadline { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); }
.deadline.is-near { color: var(--nudge-bright); }
.deadline.is-over { color: var(--alarm-bright); }

/* ----------------------------------------------------------------------------
   LEDGER STREAM — the P6 audit log as a terminal readout (Roci command-line).
   ---------------------------------------------------------------------------- */
.ledger { font-family: var(--font-mono); font-size: var(--fs-sm); line-height: 1.7; }
.ledger__row { display: grid; grid-template-columns: 92px 64px 1fr; gap: var(--s3); padding: 2px 0; }
.ledger__ts  { color: var(--ink-3); }
.ledger__op  { letter-spacing: 0.06em; }
.op-insert { color: var(--ok); } .op-update { color: var(--accent); } .op-delete { color: var(--alarm); }
.ledger__msg .b { color: var(--ink); } .ledger__msg .arr { color: var(--ink-3); padding: 0 4px; }
/* JOURNAL variant — append-only log entries are ts + message only (no op column),
   so they use a 2-col grid; otherwise the message squeezes into the op slot. */
.ledger--journal .ledger__row { grid-template-columns: 92px 1fr; }
.ledger--journal .ledger__msg { white-space: pre-wrap; }

/* ── FULL-SURFACE LEDGER (promoted from ledger.html — the promoted P6 audit
     surface; any audit/version view reuses this before→after diff grammar). It
     EXTENDS .ledger above: the stream is the focal surface, so rows get more air,
     a wider ts column (the full date+time on one line), and a hover affordance on
     linkable (tombstone) rows. The before→after payload is NEVER abbreviated. ── */
.ledger--full { font-size: var(--fs-base); line-height: 1.8; }
.ledger--full .ledger__row { grid-template-columns: 118px 70px 1fr; padding: var(--s1) 0; border-bottom: 1px solid var(--line-soft); align-items: start; }
.ledger--full .ledger__ts { white-space: nowrap; }
.ledger--full .ledger__row:last-child { border-bottom: 0; }
/* the inline before→after grammar (single-field), shared with the multi diff */
.ledger__before { color: var(--ink-faint); }
.ledger__before--empty { color: var(--ink-mute); }
.ledger__after  { color: var(--ink); }
.ledger__arrow  { color: var(--ink-3); padding: 0 5px; }
.ledger__field  { color: var(--accent-bright); }
/* linkable rows (tombstones resolve to the tombview) — a quiet hover lift; NO
   edit/delete/revert affordance ever appears, only "view tombstone". */
.ledger__row--link { text-decoration: none; color: inherit; }
.ledger--full .ledger__row--link:hover { background: var(--panel-2); }
.ledger__row--link:focus-visible { outline: none; box-shadow: var(--focus-ring-in); }
.ledger__resolve { color: var(--ink-3); margin-left: var(--s2); white-space: nowrap; }
.ledger__row--link:hover .ledger__resolve,
.ledger__row--link:focus-visible .ledger__resolve { color: var(--accent-bright); }
/* the tombstone glyph — op-red, paired with the DELETE word (DL14: glyph+word+color) */
.tombglyph { color: var(--alarm); margin-right: 4px; }
.is-tomb .ledger__msg .b { color: var(--ink-2); }   /* a tombstoned item's name reads past-tense (dimmer) */

/* ── MULTI-FIELD DIFF (promoted) — a compact two-column before→after diff that
     scales past one field: field · before → after, one row each, recessed under
     the message. Tabular mono so the arrows align down the column. ── */
.ledger__diff {
  display: grid; gap: 2px; margin-top: 4px; margin-bottom: 2px;
  padding: var(--s2) var(--s3); background: var(--bg);
  box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct-sm);
  font-size: var(--fs-sm);
}
.ledger__diffrow { display: grid; grid-template-columns: 92px 1fr auto 1fr; gap: var(--s2); align-items: baseline; }
.ledger__diffrow .ledger__field { white-space: nowrap; }
.ledger__diffrow .ledger__before { text-align: right; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ledger__diffrow .ledger__after  { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ledger__diffrow .ledger__arrow  { color: var(--accent); padding: 0; }

/* ── HONEST PAGINATION (promoted from ledger.html — reusable on any large list,
     Query/Inbox). The true total, always; a chronological log loads OLDER — we
     never truncate-and-claim-complete. ── */
.lpage {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  margin-top: var(--s4); padding-top: var(--s3); border-top: 1px solid var(--line);
}
.lpage__count { font-size: var(--fs-sm); color: var(--ink-2); }
.lpage__count b { color: var(--ink-bright); font-weight: 600; }
.lpage__rule {
  flex: 1; height: 8px; min-width: var(--s5); align-self: center;
  background-image: repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 6px);
  mask-image: linear-gradient(90deg, transparent, #000 30%, transparent 100%); opacity: 0.6;
}
.lpage__more { padding: var(--s2) var(--s4); }

/* ── handheld (≤640): the full-ledger's fixed ts/op columns shrink so the 3-col
     grid never overflows; and the multi-field diff GROUPS PER FIELD — each field's
     before→after stays one unit (the arrow stays WITH the pair, never orphaned to
     its own line), with a hairline divider between fields so 3 fields read as 3
     units, not 12 loose mono lines. ── */
@media (max-width: 640px) {
  .ledger--full .ledger__row { grid-template-columns: 88px 56px 1fr; }
  /* each field = ONE labeled unit: the field name on its own line, then the
     before → after pair flowing together inline (the arrow never orphans). A
     hairline divider + --s2 between fields so 3 fields read as 3 units, not 12
     loose lines. Drop the grid → block flow so the pair stays one line. */
  .ledger__diffrow {
    display: block;
    padding-bottom: var(--s2); margin-bottom: var(--s2);
    border-bottom: 1px solid var(--line-soft);   /* the per-field divider */
  }
  .ledger__diffrow:last-child { padding-bottom: 0; margin-bottom: 0; border-bottom: 0; }
  .ledger__diffrow .ledger__field { display: block; margin-bottom: 2px; }
  /* before → after, kept inline as one flowing unit */
  .ledger__diffrow .ledger__before,
  .ledger__diffrow .ledger__arrow,
  .ledger__diffrow .ledger__after {
    display: inline; text-align: left; white-space: normal; overflow: visible;
  }
  .ledger__diffrow .ledger__arrow { padding: 0 5px; }
  .lpage__more { flex: 1; min-height: 44px; }   /* touch floor (DL13) */
}

/* ----------------------------------------------------------------------------
   HABIT GRID — the DECK 01-12 status grid, repurposed for streaks.
   ---------------------------------------------------------------------------- */
.habitgrid { display: grid; gap: var(--s3); }
.habit-row { display: grid; grid-template-columns: 140px 1fr auto; gap: var(--s3); align-items: center; }
.habit-row__name { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.08em; font-size: var(--fs-label); color: var(--ink-2); }
.cells { display: flex; gap: 5px; }
.cell {
  position: relative; width: 18px; height: 18px;
  box-shadow: inset 0 0 0 1px var(--line-soft);     /* future / N-A: barely there */
  clip-path: polygon(3px 0,calc(100% - 3px) 0,100% 3px,100% calc(100% - 3px),calc(100% - 3px) 100%,3px 100%,0 calc(100% - 3px),0 3px);
  background: var(--well);
}
.cell.hit  { background: var(--ok); box-shadow: inset 0 0 0 1px var(--ok-line), 0 0 8px -2px var(--ok); }
.cell.miss { background: transparent; box-shadow: inset 0 0 0 1px var(--line); }   /* a logged miss is explicit */
/* today, not yet logged: accent ring + wash + a center pip — never confused with a blank future cell */
.cell.today { background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent); }
.cell.today::after { content: ""; position: absolute; inset: 0; margin: auto; width: 4px; height: 4px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 6px var(--accent); }
.streak { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-3); text-align: right; min-width: 46px; }
.streak b { color: var(--ok-bright); font-size: var(--fs-md); }

/* ----------------------------------------------------------------------------
   LAYOUT HELPERS
   ---------------------------------------------------------------------------- */
.stack    { display: grid; gap: var(--s3); }
.stack-lg { display: grid; gap: var(--s5); }
.row      { display: flex; gap: var(--s3); align-items: center; }
.row-wrap { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; }
.between  { justify-content: space-between; }
.grid-2   { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
.grid-2--wide { grid-template-columns: 1.3fr 1fr; }
.grid-3   { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s4); }
.spacer   { flex: 1; }

/* ----------------------------------------------------------------------------
   APP CHROME — the rail / mode switcher (lens chooser)
   ---------------------------------------------------------------------------- */
/* the desktop track floors the content column at 0 (minmax(0,1fr), not a bare
   1fr = minmax(auto,1fr)) so a wide child can never push the grid — and the
   fractional 1fr track never rounds 1px past the viewport — in the 641–760px
   squeeze band while the rail is still present. Pairs with .main{min-width:0}. */
.app { display: grid; grid-template-columns: 232px minmax(0, 1fr); min-height: 100vh; position: relative; z-index: var(--z-base); }
.rail { border-right: 1px solid var(--line); padding: var(--s5) var(--s4); background: linear-gradient(180deg, var(--panel) 0%, var(--bg) 100%); }
.brand { display: flex; align-items: baseline; gap: var(--s2); margin-bottom: var(--s6); }
.brand__mark { font-family: var(--font-label); font-weight: 800; font-size: 22px; letter-spacing: 0.18em; color: var(--ink-bright); text-shadow: var(--text-glow); }
.brand__sub  { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: 0.18em; }
.navgroup { margin-bottom: var(--s5); }
.navgroup__title { margin-bottom: var(--s2); }
.navitem {
  display: flex; align-items: center; gap: var(--s3); padding: 7px var(--s3);
  color: var(--ink-2); cursor: pointer; border-left: 2px solid transparent;
  font-size: var(--fs-base);
}
.navitem:hover { background: var(--panel-2); color: var(--ink); }
.navitem.is-on { color: var(--ink-bright); border-left-color: var(--accent); background: var(--accent-wash); }
.navitem__count { margin-left: auto; font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); }
.navitem__count.has-alarm { color: var(--alarm-bright); }
.navitem__count.has-nudge { color: var(--nudge-bright); }
.navdot { width: 8px; height: 8px; clip-path: polygon(50% 0,100% 50%,50% 100%,0 50%); }

/* pack rows to the top — .main is a viewport-tall grid item, so without this its
   auto rows absorb the slack and sparse screens balloon (the giant query box). */
.main { padding: var(--s6) var(--s7); max-width: 1180px; align-content: start; }

/* visible item ID badge — KIND · <dim head><highlighted tail>. The tail is the
   speakable short handle; the head is the time-clustered (low-signal) prefix. */
.idbadge { font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em; color: var(--ink-3); white-space: nowrap; }
.idbadge__kind { color: var(--ink-3); }
.idbadge__dim  { color: var(--ink-faint); }
.idbadge__key  { color: var(--accent-bright); border-bottom: 1px solid var(--line-strong); text-shadow: 0 0 8px var(--accent-wash); padding-bottom: 1px; }

/* header search trigger — compact ⌘K affordance replacing the full-width cmd bar */
.hsearch { display: inline-flex; align-items: center; gap: 6px; padding: 5px var(--s2); }
.hsearch__icon { opacity: .75; }
.hsearch:hover .hsearch__icon { opacity: 1; }
.hsearch .label { color: var(--ink-3); }
.page-title { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.1em; font-size: var(--fs-xl); color: var(--ink-bright); font-weight: 700; }
.page-sub { font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-3); }

/* big readout number (the Razorback/Roci hero value) */
.readout { font-family: var(--font-mono); font-size: var(--fs-display); font-weight: 600; color: var(--ink-bright); line-height: 1; letter-spacing: -0.01em; }
.readout--ok { color: var(--ok-bright); text-shadow: 0 0 18px var(--ok-line); }

/* ----------------------------------------------------------------------------
   KNOWLEDGE / GRAPH  — proves the language reads prose and visualizes Links.
   ---------------------------------------------------------------------------- */
.note-body { font-family: var(--font-prose); font-size: var(--fs-md); line-height: 1.7; color: var(--ink); max-width: 64ch; }
.note-body p { margin: 0 0 var(--s4); }
.note-body .wikilink { color: var(--accent-bright); text-decoration: none; box-shadow: inset 0 -1px 0 var(--accent-dim); cursor: pointer; }
.note-body .wikilink::before { content: "[["; color: var(--accent-dim); }
.note-body .wikilink::after  { content: "]]"; color: var(--accent-dim); }

/* backlink / linked-item row, kind-tagged */
.linkrow { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line-soft); }
.linkrow:hover { background: var(--panel-2); }
.kindtag {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.1em;
  font-size: var(--fs-micro); font-weight: 700; padding: 3px 6px; width: 78px; text-align: center;
  color: var(--ink-3); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct-sm);
}
/* Kind is categorical metadata, never a status (DL3) and never a chart series
   color (DL17 law 4): differentiate kinds by the WORD + ink tiers, never the
   reserved system palette. Only k-note keeps the structural cyan (it is the
   knowledge/link kind, and cyan is structural, not a status). */
.kindtag.k-note   { color: var(--accent-bright); box-shadow: inset 0 0 0 1px var(--accent-glow); }
.kindtag.k-commit { color: var(--ink);   box-shadow: inset 0 0 0 1px var(--line-strong); }
.kindtag.k-task   { color: var(--ink-2); }
.kindtag.k-person { color: var(--ink-2); box-shadow: inset 0 0 0 1px var(--line); }
.linkrow__title { flex: 1; color: var(--ink); }
.linkrow__why { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); font-style: italic; }

/* the mini graph canvas */
.graph { position: relative; height: 320px; background: var(--well); overflow: hidden;
  clip-path: var(--clip-oct); }
.gnode {
  position: absolute; transform: translate(-50%,-50%);
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em;
  padding: 5px 9px; color: var(--ink-2); background: var(--panel-2); white-space: nowrap;
  box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct-sm); cursor: pointer; z-index: 2;
}
.gnode.is-focus { color: var(--void); background: var(--accent); box-shadow: 0 0 22px -2px var(--accent-glow); font-weight: 600; }
/* graph kind cues: ink tiers, never system colors (DL3); cyan stays on the
   focus / you-are-here node only. */
.gnode.n-commit { box-shadow: inset 0 0 0 1px var(--line-strong); color: var(--ink); }
.gnode.n-person { box-shadow: inset 0 0 0 1px var(--line); color: var(--ink-2); }
.gnode.n-task   { color: var(--ink-3); }
.gedge { position: absolute; height: 1px; background: linear-gradient(90deg, var(--accent-glow), transparent); transform-origin: 0 0; pointer-events: none; z-index: 1; }

/* ----------------------------------------------------------------------------
   FOCUS — the keyboard-first promise made visible (DL10). One cyan ring.
   Un-clipped controls take a real outline; chamfered controls clip an outline
   away, so they take an inset accent ring instead (see --focus-ring-in).
   ---------------------------------------------------------------------------- */
:where(a, .navitem, .input, .linkrow, [tabindex]):focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-soft);
}
:where(.btn, .chip, .state, .task__check, .gnode, .tag, .cell):focus-visible {
  outline: none; box-shadow: var(--focus-ring-in);
}
/* on an accent-filled control the cyan ring would vanish — invert it to a dark
   inset ring + the accent glow so focus stays unmistakable. */
.btn--primary:focus-visible { box-shadow: inset 0 0 0 2px var(--void), 0 0 18px -2px var(--accent-glow); }
.gnode.is-focus:focus-visible { box-shadow: inset 0 0 0 2px var(--void), 0 0 22px -2px var(--accent-glow); }
:focus:not(:focus-visible) { outline: none; }

/* ----------------------------------------------------------------------------
   INPUT — the ONE place --radius-soft lives. Full state set (DL15).
   ---------------------------------------------------------------------------- */
.field { display: grid; gap: 6px; }
.field__hint { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); }
.field__hint.is-error { color: var(--alarm-bright); }
.input {
  font-family: var(--font-mono); font-size: var(--fs-base); color: var(--ink);
  background: var(--well); border: 0; width: 100%;
  padding: var(--s2) var(--s3);
  box-shadow: inset 0 0 0 1px var(--line); border-radius: var(--radius-soft);
  transition: box-shadow var(--fast) var(--ease);
}
.input::placeholder { color: var(--ink-3); }
.input:hover { box-shadow: inset 0 0 0 1px var(--line-strong); }
.input:focus-visible { outline: none; box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px var(--accent-wash); }
.input.is-invalid { box-shadow: inset 0 0 0 1px var(--alarm-line); }
.input.is-invalid:focus-visible { box-shadow: inset 0 0 0 1px var(--alarm), 0 0 0 3px var(--alarm-wash); }
.input:disabled { color: var(--ink-faint); background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-soft); cursor: not-allowed; }

/* ----------------------------------------------------------------------------
   WELL — the recessed surface that holds a verbatim/typed string (DL1). ONE
   component, two contexts: the inbox's verbatim capture record and the capture
   modal's type-here well were the same idea built twice — now unified (DL5).
   RESTING is a quiet recessed hairline (`--line-strong`), like .cmd. Variants:
     · --clip-oct  octagon silhouette (inbox verbatim line)
     · --soft      --radius-soft, the one permitted roundness, for type-here (DL5)
   The accent focus GLOW is an explicit state (.is-focus / :focus-within), NEVER
   the default — exactly one focal control may emit per view (DL2 budget).
   ---------------------------------------------------------------------------- */
.well {
  background: var(--well);
  color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  padding: var(--s4);
}
.well--clip-oct { clip-path: var(--clip-oct); }
.well--soft     { border-radius: var(--radius-soft); }
/* the focal well lights the accent glow — applied to ONE well per view (DL2) */
.well.is-focus, .well:focus-within {
  box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px var(--accent-wash);
}

.btn:disabled, .btn[aria-disabled="true"] {
  color: var(--ink-faint); background: var(--panel); cursor: not-allowed;
  box-shadow: inset 0 0 0 1px var(--line-soft);
}
.btn.is-loading { color: transparent; pointer-events: none; position: relative; }
.btn.is-loading::after {
  content: ""; position: absolute; inset: 0; margin: auto; width: 12px; height: 12px;
  border: 2px solid var(--accent-dim); border-top-color: var(--accent); border-radius: 50%;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* ----------------------------------------------------------------------------
   EMPTY STATE — a surface with nothing to show still has to say so (DL15).
   ---------------------------------------------------------------------------- */
.empty { display: grid; gap: var(--s2); justify-items: center; text-align: center; padding: var(--s6) var(--s4); }
.empty__glyph { font-size: 20px; color: var(--ink-faint); }
.empty__title { font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label); font-size: var(--fs-label); color: var(--ink-2); }
.empty__hint  { font-family: var(--font-prose); font-size: var(--fs-sm); color: var(--ink-3); max-width: 46ch; line-height: 1.55; }

/* ----------------------------------------------------------------------------
   LOADING — structure-only skeleton, never a spinner on a whole panel (DL2:
   calm). The shimmer is the one ambient motion we permit, and only while data
   is genuinely in flight; prefers-reduced-motion stills it.
   ---------------------------------------------------------------------------- */
.skel {
  background: linear-gradient(90deg, var(--panel-2) 25%, var(--panel-3) 50%, var(--panel-2) 75%);
  background-size: 200% 100%; animation: skel 1.4s var(--ease) infinite;
  border-radius: var(--radius-soft); height: 12px;
}
.skel--title { height: 18px; width: 52%; }
.skel--short { width: 36%; }
@keyframes skel { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ----------------------------------------------------------------------------
   ERROR — a query/operation that failed is itself system status. Honest, not
   hidden (DL4): an alarm-framed well that states what broke and the remedy.
   ---------------------------------------------------------------------------- */
.errpanel { background: var(--alarm-wash); box-shadow: inset 0 0 0 1px var(--alarm-line); }
.errpanel .phead__title { color: var(--alarm-bright); text-shadow: none; }
.errpanel .phead__title::before { content: "▲"; color: var(--alarm); }

/* ----------------------------------------------------------------------------
   RESPONSIVE & DENSITY (DL13) — the fixed rail is desktop-only. Below 760px the
   two-up grids stack; below 640px the rail becomes a horizontal tab bar and the
   main column takes the full width. Touch targets never drop below 44px.
   ---------------------------------------------------------------------------- */
@media (max-width: 760px) {
  .grid-2, .grid-3 { grid-template-columns: minmax(0, 1fr); }
  .grid-2--wide   { grid-template-columns: minmax(0, 1fr); }
  .main { padding: var(--s5) var(--s4); }
  /* THE 641–760px SQUEEZE FIX, promoted GLOBAL (was a screen-local patch that
     only some screens remembered). The locked .app desktop track is 232px 1fr
     (= 232px minmax(auto,1fr)) until 640px, so the main column won't shrink below
     its content min-content while the rail is still present — a long mono secret,
     a wide filter bar, or a fixed-min control then forces the page ~14px past the
     viewport. Floor the main track at 0 so nothing overflows in the squeeze band. */
  .main { min-width: 0; }
  /* a .panel that is ALSO a grid/flex container (e.g. Settings' .seccard) keeps the
     CSS default min-width:auto (= min-content), which resists shrinking below its
     content and pokes ~1px past the viewport at the tight end of the band. Floor it
     to 0 too — panels are full-width blocks, so this only bites in the squeeze case. */
  .panel { min-width: 0; }

  /* ── MARKER-ROW BAND FIX (DL13 "stacked" intent) ──
     In the 641–760 stacked band the 232px rail is STILL present, so `main` is only
     ~360–410px wide — as narrow as a handheld's full-width column. The dense
     horizontal "marker rows" (commit-rows, findings, group-headers, directory/
     prose result rows) have a min-content wider than that and, since their wrap /
     min-width:0 / truncation rules previously fired only at ≤640, they forced the
     document past the viewport in this band (drift +152, query/people +60,
     commitments +30, deferred +18). The band needs the SAME row treatment as the
     handheld column, not the desktop two-up. So we lift the existing ≤640 dense-row
     shrink/wrap rules to apply through ≤760. Handheld-only concerns (44px touch
     floors, padding retunes, the tab-bar rail) STAY at ≤640 below — this block is
     purely "let the dense rows shrink & wrap while the rail eats the width." Every
     value is an existing token; no new magic numbers, no rendered change at ≥760
     or ≤640 (those bands already had this treatment or the desktop one). */

  /* commit-row title line + foot + goal — wrap, don't nowrap-overflow */
  .commitrow__line { flex-wrap: wrap; row-gap: var(--s2); }
  .commitrow__title { flex: 1 1 100%; order: 2; white-space: normal; }
  .commitrow__status { order: 1; }
  .commitrow__states { order: 3; }
  .commitrow__goal { white-space: normal; }
  /* the foot keeps its default wrapping ROW (NOT a column) in this band: the
     next-action line (min-width:0 → ellipsis) and the flex:none remedy cluster
     simply wrap past each other when main is narrow. Forcing a column here let the
     inline-flex __next size to its nowrap content and overrun; the wrapping row
     truncates correctly. The column stack stays a ≤640 touch concern. The __next
     must be allowed to shrink to the foot width so its ellipsis engages. */
  .commitrow__next { max-width: 100%; }

  /* prose-row + dir-row result rows — wrap their head/main, drop the last-seen
     meta to its own full-width line so the name cluster can shrink */
  .prose-row__head { flex-wrap: wrap; row-gap: var(--s2); }
  .prose-row__excerpt { white-space: normal; }
  .dir-row__main { flex-wrap: wrap; }
  .dir-row__last { width: 100%; }

  /* the drift group-header — the worst offender (+152). Let the inline cluster
     (glyph + name + count pill + sub + rule + lens-link + chevron) wrap, and drop
     the elastic ruler (it only exists to fill slack — in the narrow band there is
     none) so the header fits the narrow main instead of forcing nowrap width. */
  .grouphd { flex-wrap: wrap; row-gap: var(--s1); }
  .grouphd__rule { display: none; }

  /* the drift finding row — stack the body over its remedy buttons so neither the
     prose head nor the remedy cluster forces a min-content wider than main */
  .finding { flex-direction: column; align-items: stretch; }

  /* any page header carrying a primary action wraps instead of forcing width;
     its right-hand control cluster (chips + primary button) wraps within itself too */
  header.row.between { flex-wrap: wrap; row-gap: var(--s3); }
  header.row.between > .row { flex-wrap: wrap; row-gap: var(--s2); }
}
@media (max-width: 640px) {
  /* minmax(0,1fr), not 1fr: a bare 1fr track is minmax(auto,1fr) and won't
     shrink below the rail's min-content, so the single column blew out to
     ~430px on a 390px viewport and overflow-x:hidden silently clipped the
     right ~40px (any right-aligned control there became unreachable). The
     0 floor clamps the track to the viewport so nothing is clipped. */
  .app { grid-template-columns: minmax(0, 1fr); max-width: 100%; overflow-x: hidden; }
  .rail {
    border-right: 0; border-bottom: 1px solid var(--line);
    padding: var(--s2) var(--s4); background: var(--panel);
    display: flex; align-items: center; gap: var(--s3);
    overflow-x: auto; position: sticky; top: 0; z-index: var(--z-rail);
    min-width: 0; max-width: 100%;
  }
  .rail .brand { margin: 0; flex: none; }
  .rail .navgroup { display: flex; gap: var(--s1); margin: 0; flex: none; }
  /* secondary groups (lenses, saved queries) live behind a menu on mobile in
     production; the proof simply lets them scroll with the surfaces. */
  .rail .navgroup__title { display: none; }
  .navitem {
    white-space: nowrap; border-left: 0; border-bottom: 2px solid transparent;
    padding: var(--s2) var(--s3); min-height: 44px;
  }
  .navitem.is-on { border-left: 0; border-bottom-color: var(--accent); }
  .navitem__count { margin-left: var(--s1); }
  .stat { grid-template-columns: 1fr; gap: var(--s3); }
  .lane { grid-template-columns: 48px 1fr 36px; }
  /* The habit-row's name column is a fixed 140px on desktop; let it shrink on
     handheld (minmax floor of 0) so the 7-cell grid + streak fit within the
     viewport instead of forcing the panel — and the page — to overflow. */
  .habit-row { grid-template-columns: minmax(0, 1fr) auto auto; column-gap: var(--s2); }
}

/* ----------------------------------------------------------------------------
   DENSITY — the same language, dialed denser (DL13). Opt in with
   <html data-density="compact"> (an operator preference, not a separate theme):
   it only retunes padding, row height, and chamfer — never the vocabulary.
   ---------------------------------------------------------------------------- */
[data-density="compact"] {
  --chamfer: 8px; --chamfer-lg: 12px;
}
[data-density="compact"] .panel    { padding: var(--s3); }
[data-density="compact"] .main     { padding: var(--s5) var(--s5); }
[data-density="compact"] .stack-lg { gap: var(--s4); }
[data-density="compact"] .phead    { padding-bottom: var(--s1); margin-bottom: var(--s2); }
[data-density="compact"] .task     { padding-top: 5px; padding-bottom: 5px; }
[data-density="compact"] .cmd      { padding: var(--s2) var(--s3); }
[data-density="compact"] .linkrow,
[data-density="compact"] .navitem  { padding-top: 5px; padding-bottom: 5px; }

/* ============================================================================
   DATA-VIZ / CHARTS (DL17) — sovereign inline-SVG instrument readouts.
   The Agatha King's "Engineering System Overview" rebuilt in jops discipline:
   its archetypes and emissive-on-dark feel, NONE of its density. Every mark
   emits in --mark (default --accent); a status color enters a chart ONLY when
   the data crosses a threshold (DL3). The anchored number is the truth (a
   .readout); the chart is the context. One status class on the chart root
   (.chart--ok / --nudge / --alarm) recolors every mark inside it.
   ============================================================================ */
:where(.spark,.bars,.gauge,.markers,.rangebar) { --mark: var(--accent); --mark-wash: var(--accent-wash); }
.chart--ok    { --mark: var(--ok);    --mark-wash: var(--ok-wash); }
.chart--nudge { --mark: var(--nudge); --mark-wash: var(--nudge-wash); }
.chart--alarm { --mark: var(--alarm); --mark-wash: var(--alarm-wash); }

/* — STAT: KPI block — anchored number + context + chart + trend delta — */
.stat { display:grid; grid-template-columns: minmax(108px,auto) 1fr auto; gap: var(--s4); align-items:center; }
.stat__fig   { display:grid; gap:3px; }
.stat__chart { min-width:0; }   /* lets the chart shrink inside the grid */
.stat__trend { display:inline-flex; align-items:baseline; gap:6px; font-family:var(--font-mono); font-size:var(--fs-sm); color:var(--ink-3); white-space:nowrap; }
.stat__trend.is-up   { color: var(--ok-bright); }
.stat__trend.is-down { color: var(--nudge-bright); }
.stat__trend .arr { font-size:0.85em; }

/* — SPARK / STRIP-LANE: trend over time, axis-less (the DSR/TLP/MAZ lanes) — */
.spark { display:block; position:relative; width:100%; height:var(--spark-h); }
.spark svg { width:100%; height:100%; display:block; overflow:visible; }
.spark__area   { fill: var(--mark-wash); }
.spark__line   { fill:none; stroke: var(--mark); stroke-width:var(--chart-stroke); vector-effect:non-scaling-stroke; stroke-linejoin:round; stroke-linecap:round; }
.spark__target { stroke: var(--ink-faint); stroke-width:1; stroke-dasharray:3 3; vector-effect:non-scaling-stroke; }
/* the live-value dot is an overlay (so it stays a true circle under the
   stretched viewBox) — and the one emissive accent the budget allows here */
.spark__dot { position:absolute; width:6px; height:6px; border-radius:50%; transform:translate(-50%,-50%); background:var(--mark); box-shadow:0 0 6px var(--mark); }

/* a labeled strip-chart lane: [callsign] [spark] [scale] */
.lane { display:grid; grid-template-columns: 56px 1fr 40px; gap: var(--s3); align-items:center; }
.lane__id    { font-family:var(--font-mono); font-size:var(--fs-micro); letter-spacing:0.08em; color:var(--ink-3); }
.lane__scale { font-family:var(--font-mono); font-size:var(--fs-micro); color:var(--ink-bright); text-align:right; font-variant-numeric:tabular-nums; }

/* — BARS: distribution / comparison over a small N — */
.bars { position:relative; display:flex; align-items:flex-end; gap:3px; height:var(--bars-h); }
.bars__bar { flex:1 1 0; min-width:2px; background:var(--mark); opacity:0.30; }
.bars__bar.is-on  { opacity:0.95; }
.bars__bar.is-low { background:var(--nudge); opacity:1; }   /* below target — meaningful */
/* the threshold is positional too, never color-alone (DL10): a dashed target rule */
.bars__target { position:absolute; left:0; right:0; border-top:1px dashed var(--tick); pointer-events:none; }

/* — GAUGE: one value against its range/target (the radial meters up top) — */
.gauge { position:relative; width:var(--gauge-d); height:var(--gauge-d); }
.gauge svg { width:100%; height:100%; transform:rotate(-90deg); }
.gauge__track { fill:none; stroke: var(--line); stroke-width:6; }
.gauge__val   { fill:none; stroke: var(--mark); stroke-width:6; stroke-linecap:round; filter: drop-shadow(0 0 3px var(--mark)); }
.gauge__num   { position:absolute; inset:0; display:grid; place-items:center; font-family:var(--font-mono); font-size:var(--fs-md); color:var(--ink-bright); font-variant-numeric:tabular-nums; }

/* — MARKERS: discrete events over a timeline (the CFV event row) — */
.markers { position:relative; height:18px; background:var(--well); box-shadow: inset 0 0 0 1px var(--line); }
.markers__base { position:absolute; left:0; right:0; top:50%; height:1px; background:var(--line); }
/* past events are quiet ink; only NOW glows accent + runs full-height (DL2 budget) */
.markers__tick { position:absolute; top:4px; bottom:4px; width:2px; background:var(--ink-3); transform:translateX(-50%); }
.markers__tick.is-now  { top:1px; bottom:1px; background:var(--accent); box-shadow:0 0 6px var(--accent); }
.markers__tick.is-miss { background:var(--ink-faint); }

/* — RANGEBAR: a value within min–max, with an optional target notch — */
.rangebar { position:relative; height:8px; background:var(--well); box-shadow: inset 0 0 0 1px var(--line); }
.rangebar__fill   { position:absolute; left:0; top:0; bottom:0; background:var(--mark); box-shadow:0 0 8px -2px var(--mark); }
.rangebar__target { position:absolute; top:-2px; bottom:-2px; width:2px; background:var(--ink-bright); box-shadow:0 0 0 1px var(--void); }

[data-density="compact"] .stat { gap: var(--s3); }

/* ============================================================================
   CROSS-SCREEN VOCABULARY (promoted — DL5: one component, not near-duplicates)
   These row/atom forms recur across surfaces (Commitments survey, Query results,
   Commitment detail). They were screen-local in batch-1 only because app.css was
   frozen mid-loop; both reviewers asked for the promotion. Canonicalized from the
   SUPERSET declaration (commitments.html for .commitrow). Every value tokenized;
   no new colors. Promoting changes NO rendered pixel on the signed-off screens.
   ============================================================================ */

/* ── COLLAPSED COMMITMENT CARD-ROW — the survey/result row (DL4 health rail).
     One collapsed row = rail + body, cut in the standard octagon. The rail sits
     INSIDE the clip (inset past the chamfers, like .alertbar / .commit__rail) so
     the cut corners never bite it. Health color comes from --rail, set by is-*. ── */
.commitrow {
  --rail: var(--ok);
  position: relative;
  background: var(--panel);
  box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct);
  padding: var(--s4) var(--s4) var(--s4) var(--s5);
  transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
  cursor: pointer;
}
.commitrow.is-alarm { --rail: var(--alarm); }
.commitrow.is-nudge { --rail: var(--nudge); }
.commitrow.is-ok    { --rail: var(--ok); }
.commitrow.is-defer { --rail: var(--defer); }
.commitrow.is-back  { --rail: var(--ink-faint); }   /* parked by choice: no glow, faint */

.commitrow__rail {
  position: absolute; left: 0; top: var(--chamfer); bottom: var(--chamfer);
  width: 3px; background: var(--rail); box-shadow: 0 0 12px -2px var(--rail);
}
/* backburner rails don't emit — a parked thing is quiet */
.commitrow.is-back .commitrow__rail { box-shadow: none; opacity: 0.7; }

/* hover/focus lifts the row and brightens the frame — the "act here" affordance */
.commitrow:hover,
.commitrow:focus-visible {
  background: var(--panel-2);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  outline: none;
}
.commitrow:focus-visible { box-shadow: var(--focus-ring-in); }

.commitrow__open {
  color: var(--ink-3); opacity: 0; transition: opacity var(--fast) var(--ease);
  white-space: nowrap;
}
.commitrow:hover .commitrow__open,
.commitrow:focus-visible .commitrow__open { opacity: 1; color: var(--accent-bright); }

.commitrow__main { display: grid; gap: var(--s2); min-width: 0; }

/* the title line — status word, title, area pip, state pills, open affordance */
.commitrow__line { display: flex; align-items: center; gap: var(--s3); min-width: 0; }

/* the inline status: glyph + WORD + color (DL4 — never color alone). It mirrors
   the rail so the half-second scan and the read agree. */
.commitrow__status {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.12em;
  font-size: var(--fs-micro); font-weight: 800; line-height: 1;
  color: var(--rail); white-space: nowrap; flex: none;
  display: inline-flex; align-items: center; gap: 5px;
}
.is-back .commitrow__status { color: var(--ink-faint); }    /* parked words stay quiet */
.is-defer .commitrow__status { color: var(--defer-bright); }
.commitrow__glyph { font-size: 0.95em; }

.commitrow__title {
  font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-md);
  color: var(--ink-bright); line-height: 1.2; margin: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: 0 1 auto;
}
.is-quiet .commitrow__title { color: var(--ink-2); }

/* the state pills, shrunk to survey density (same exclusive grammar) */
.commitrow__states { flex: none; }
.commitrow__states .state { padding: 3px var(--s2); }

/* the goal — PROSE voice, truncated to one line. border-left echoes .commit__goal. */
.commitrow__goal {
  font-family: var(--font-prose); font-style: italic; color: var(--ink-2);
  font-size: var(--fs-sm); line-height: 1.4;
  padding-left: var(--s3); border-left: 2px solid var(--line);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* an active commitment with no goal is itself an alarm finding (P4) */
.commitrow__goal.is-missing {
  font-style: normal; color: var(--alarm-bright);
  border-left-color: var(--alarm-line);
}

/* the foot row: next-action line on the left, the in-place remedy on the right */
.commitrow__foot { display: flex; align-items: center; gap: var(--s3); min-width: 0; flex-wrap: wrap; }
.commitrow__next {
  font-size: var(--fs-sm); color: var(--ink-2); min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  display: inline-flex; align-items: center; gap: 6px;
}
.commitrow__next.is-lit { color: var(--ink); }
.commitrow__next.is-broken { color: var(--alarm-bright); }
.commitrow__quietmeta { color: var(--ink-3); white-space: nowrap; }

/* the remedy buttons stay visible while collapsed — act-in-place from the survey */
.commitrow__remedy { display: flex; gap: var(--s2); flex: none; }
.commitrow__remedy .btn { padding: 5px var(--s3); }

/* DEGRADED rows: NO rail, NO status word, flush-left (we computed nothing). */
.commitrow.is-degraded { padding-left: var(--s4); cursor: pointer; }

/* ── handheld: the dense single-line layout must not crush at 390px. The line/
     title/status/states/goal/foot WRAP rules now live in the ≤760 marker-row band
     above (the rail is still present 641–760, so that band needs the same wrap);
     here we keep only the handheld-specific tightening: padding, tapping the whole
     row through (hide the hover __open), and the touch-floor remedy stack. ── */
@media (max-width: 640px) {
  .commitrow { padding: var(--s3) var(--s3) var(--s3) var(--s4); }
  .commitrow__open { display: none; }       /* the whole row taps through on touch */
  /* on touch, the foot stacks to a column so the remedy buttons go full-width */
  .commitrow__foot { flex-direction: column; align-items: stretch; }
  .commitrow__remedy { margin-top: var(--s1); }
  .commitrow__remedy .btn { flex: 1; min-height: 44px; }   /* touch floor (DL13) */
}

/* ── TASK-ROW ATOMS — the next-action designation toggle, the soft reorder grip,
     and the designated-row marking. Used on Commitment detail (and Query task
     rows). DL14: the ▸ designation pointer is a STRUCTURAL glyph — it takes
     --accent (cyan), NEVER a status color; the de-designated and lit states are
     both cyan so activation never reads as a health change (DL3). ── */

/* the SOFT reorder grip. Ghost dots (a drag affordance), NOT a chain/link icon:
   order is advisory, never a dependency or sequence (P5). */
.task__grip {
  flex: none; width: 12px; height: 18px; cursor: grab;
  background-image: radial-gradient(var(--ink-mute) 1.1px, transparent 1.3px);
  background-size: 5px 5px; background-position: center;
  opacity: 0.7; transition: opacity var(--fast) var(--ease);
}
.task:hover .task__grip { opacity: 1; background-image: radial-gradient(var(--ink-3) 1.1px, transparent 1.3px); }
.task__grip:hover { background-image: radial-gradient(var(--accent-dim) 1.1px, transparent 1.3px); }
.task__grip:active { cursor: grabbing; }
.task__grip--inline { display: inline-block; vertical-align: -3px; width: 10px; height: 12px; margin-right: 6px; opacity: 1; }

/* the next-action DESIGNATION toggle. A per-OPEN-task ▸ button. Lit = THE singular
   next action; all siblings are visibly de-designated (exclusivity made visible,
   P4/P14). Completed/dropped rows get .task__nodesig (a dash), never a toggle. */
.task__desig {
  flex: none; width: 20px; height: 20px; padding: 0; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-mono); font-size: 13px; line-height: 1;
  color: var(--ink-mute);                 /* de-designated: barely there */
  background: transparent; border: 0;
  box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct-sm);
  transition: color var(--fast) var(--ease), box-shadow var(--fast) var(--ease), background var(--fast) var(--ease);
}
.task__desig:hover { color: var(--accent-bright); box-shadow: inset 0 0 0 1px var(--accent-glow); }
.task__desig.is-on {
  color: var(--accent-bright); background: var(--accent-wash);
  box-shadow: inset 0 0 0 1px var(--accent-glow), 0 0 10px -3px var(--accent);
}
.task__desig:focus-visible { outline: none; box-shadow: var(--focus-ring-in); }
/* the row that holds the designated next action lifts a hair so the WHOLE row
   reads as "the one" — the structural pointer is cyan (DL14), health stays on rail/chip. */
.task.is-next { background: var(--accent-wash); box-shadow: inset 2px 0 0 var(--accent); }
.task.is-next .task__title { color: var(--ink-bright); }
/* the non-designable placeholder — a quiet dash, aligned to the toggle column */
.task__nodesig {
  flex: none; width: 20px; text-align: center; color: var(--ink-mute);
  font-family: var(--font-mono); font-size: 13px;
}
.task.is-defer .task__nodesig { color: var(--defer); }

/* ── KIND-ROW FORMS — recur wherever heterogeneous results render (Query, search).
     A note row (title + prose excerpt, ~64ch measure) and a person/directory row
     (name + area pip + open-loop count + last interaction). ── */
.prose-row {
  background: var(--panel); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct); padding: var(--s4); cursor: pointer;
  transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.prose-row:hover, .prose-row:focus-visible { background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line-strong); outline: none; }
.prose-row:focus-visible { box-shadow: var(--focus-ring-in); }
.prose-row__main { display: grid; gap: var(--s2); }
.prose-row__head { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.prose-row__title { font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-md); color: var(--ink-bright); line-height: 1.2; margin: 0; }
.prose-row__excerpt {
  font-family: var(--font-prose); font-size: var(--fs-sm); color: var(--ink-2);
  line-height: 1.55; margin: 0; max-width: 64ch;          /* the prose measure (DL6) */
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.prose-row__excerpt .wikilink { color: var(--accent-bright); text-decoration: none; box-shadow: inset 0 -1px 0 var(--accent-dim); }
.prose-row__open, .dir-row__open { color: var(--ink-3); opacity: 0; transition: opacity var(--fast) var(--ease); white-space: nowrap; }
.prose-row:hover .prose-row__open, .prose-row:focus-visible .prose-row__open,
.dir-row:hover .dir-row__open, .dir-row:focus-visible .dir-row__open { opacity: 1; color: var(--accent-bright); }
/* the open-loop rows and linked-note rows on Person record drill to their item's
   detail (Meeting-prep flow): open loops → Commitment detail, linked notes →
   Note detail. They borrow the dir-row__open reveal grammar so the affordance
   reads identically to the People directory rows. */
.looprow[tabindex], .linkrow[tabindex] { cursor: pointer; }
.looprow:hover .dir-row__open, .looprow:focus-visible .dir-row__open,
.linkrow:hover .dir-row__open, .linkrow:focus-visible .dir-row__open { opacity: 1; color: var(--accent-bright); }

.dir-row {
  background: var(--panel); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct); padding: var(--s3) var(--s4); cursor: pointer;
  transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.dir-row:hover, .dir-row:focus-visible { background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line-strong); outline: none; }
.dir-row:focus-visible { box-shadow: var(--focus-ring-in); }
.dir-row__main { display: flex; align-items: center; gap: var(--s3); }
.dir-row__avatar {
  flex: none; width: 30px; height: 30px; display: flex; align-items: center; justify-content: center;
  font-size: var(--fs-micro); font-weight: 600; letter-spacing: 0.04em; color: var(--ink-2);
  background: var(--panel-3); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct-sm);
}
.dir-row__name { font-family: var(--font-prose); font-weight: 600; font-size: var(--fs-md); color: var(--ink-bright); }
.dir-row__loops { flex: none; }
.dir-row__last { font-size: var(--fs-micro); color: var(--ink-3); white-space: nowrap; }

/* (The prose-row/dir-row/page-header wrap rules formerly here at ≤640 are now in
   the ≤760 marker-row band block above — the rail is present 641–760, so that band
   needs the same wrap. No handheld-only rule remained for this group.) */

/* ── INHERITED-AREA pip — effective-tag honesty (P3/P5). An OWN area tag has a
     FILLED diamond pip; an INHERITED one is an OUTLINE (hollow) diamond + a
     "↑inherited" mono note, so the UI never shows an inherited area as the
     task's own. Appears anywhere a task shows inherited area. ── */
.tag--inherited {
  background: transparent; color: var(--ink-3);
  box-shadow: inset 0 0 0 1px var(--line);
}
.tag--inherited .tag__pip {
  background: transparent;
  box-shadow: inset 0 0 0 1.5px var(--area-labor);   /* hollow = not its own */
}
.tag--inherited.tag--gps      .tag__pip { box-shadow: inset 0 0 0 1.5px var(--area-gps); }
.tag--inherited.tag--personal .tag__pip { box-shadow: inset 0 0 0 1.5px var(--area-personal); }
.tag__inh { color: var(--ink-faint); font-size: var(--fs-micro); letter-spacing: 0.02em; margin-left: 2px; }

/* ============================================================================
   GROUP-HEADER (promoted — shared by DRIFT and DEFERRED)
   ----------------------------------------------------------------------------
   ONE sectioning anatomy for a grouped surface: a family glyph + word + a LIVE
   count + a collapse chevron + an optional "open as lens →" link + a degraded-
   banner slot. It is the chip-count (index.html) promoted to a header. Used two
   ways, ONE component:
     · Drift   — the severity family (ALARM / NUDGE families / all-clear), where
                 the glyph+color+count IS the mirror's status (▲/◆/●).
     · Deferred— the date bucket (Today / This week / Later), a NEUTRAL grouping
                 (the rows carry the ◇ violet, not the header) — set .grouphd--plain.
   The all-clear ● green-zero is the SAME component (.grouphd.is-clear). DL4: the
   header is glyph+WORD+color, never color alone. Every value tokenized.
   ============================================================================ */
.group { display: grid; gap: var(--s3); }
.grouphd {
  --hd: var(--ink-2);                       /* family color drives glyph+count+rule */
  display: flex; align-items: center; gap: var(--s3);
  width: 100%; padding: var(--s2) var(--s3); cursor: pointer;
  background: transparent; border: 0; text-align: left;
  border-bottom: 1px solid var(--line);
}
.grouphd:hover { background: var(--panel-2); }
.grouphd:focus-visible { outline: none; box-shadow: var(--focus-ring-in); }
/* the family glyph — status color (Drift) or accent pointer (Deferred plain) */
.grouphd__glyph { color: var(--hd); font-size: 0.95em; line-height: 1; flex: none; filter: drop-shadow(0 0 6px transparent); }
.grouphd__name {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-label); font-weight: 700; color: var(--hd); white-space: nowrap;
}
/* the live count — the promoted chip-count, now a small octagon pill on the header */
.grouphd__count {
  font-family: var(--font-mono); font-size: var(--fs-micro); font-weight: 600;
  color: var(--hd); padding: 2px var(--s2) 3px; line-height: 1;
  background: transparent; box-shadow: inset 0 0 0 1px var(--hd);
  clip-path: var(--clip-oct-sm); flex: none; font-variant-numeric: tabular-nums;
  opacity: 0.92;
}
.grouphd__sub { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: 0.04em; white-space: nowrap; }
.grouphd__rule {
  flex: 1; height: 8px; align-self: center; min-width: var(--s5);
  background-image: repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 6px);
  mask-image: linear-gradient(90deg, transparent, #000 30%, transparent 100%); opacity: 0.7;
}
.grouphd__lens {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-micro); color: var(--ink-3); white-space: nowrap; flex: none;
}
.grouphd:hover .grouphd__lens { color: var(--accent-bright); }
.grouphd__chev { color: var(--ink-3); font-size: 0.9em; flex: none; transition: transform var(--fast) var(--ease); }
.grouphd.is-collapsed .grouphd__chev { transform: rotate(-90deg); }

/* the family-color variants — DL3/DL14 (glyph+word+color always agree) */
.grouphd--alarm { --hd: var(--alarm-bright); }
.grouphd--alarm .grouphd__glyph { filter: drop-shadow(0 0 6px var(--alarm-line)); }
.grouphd--nudge { --hd: var(--nudge-bright); }
.grouphd--nudge .grouphd__glyph { filter: drop-shadow(0 0 6px var(--nudge-line)); }
.grouphd--defer { --hd: var(--defer-bright); }
.grouphd--plain { --hd: var(--ink-2); }              /* Deferred buckets: neutral header, ◇ lives on the rows */
.grouphd--plain .grouphd__glyph { color: var(--accent); }
/* the ALL-CLEAR green-zero — a resolved/empty family collapsed to one quiet line */
.grouphd.is-clear { --hd: var(--ok-bright); cursor: default; }
.grouphd.is-clear:hover { background: transparent; }
.grouphd.is-clear .grouphd__glyph { filter: drop-shadow(0 0 6px var(--ok-line)); }
.grouphd.is-clear .grouphd__count { opacity: 0; pointer-events: none; }  /* a zero family needs no count pill */

/* the body the header toggles */
.group__body { display: grid; gap: var(--s2); padding-top: var(--s3); }
.grouphd.is-collapsed + .group__body { display: none; }

/* the DEGRADED banner slot — a per-group amber strip when one D7 VIEW is down.
   We OMIT the group's findings and say so; we NEVER fabricate a nudge (DL15).
   This is the group-header-EMBEDDED sibling of the canonical .degradebar (below);
   it matches .degradebar--line's look but carries the group's margin context.
   Use .degradebar / .degradebar--line for standalone banners — do NOT mint a 4th. */
.group__degraded {
  display: flex; align-items: center; gap: var(--s2);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--nudge-bright);
  padding: var(--s2) var(--s3); margin-top: var(--s2);
  background: var(--nudge-wash); box-shadow: inset 0 0 0 1px var(--nudge-line);
  clip-path: var(--clip-oct);
}
.group__degraded .g { color: var(--nudge); font-weight: 800; flex: none; }

/* ============================================================================
   DEGRADED BANNER (CANONICAL) — the ONE "couldn't compute this" honesty banner.
   A D7-derived view is down; we say so plainly and NEVER fabricate a result
   (no "0 open loops"). Amber + ◆ caution (never red — degraded is "I don't
   know", not "you have a problem"), and deliberately DISTINCT from the green ●
   .goodnews "nothing is open" state — that distinction is load-bearing.

   Variants:
     · .degradebar           two-line: ◆ __icon + __msg + __sub (the details use)
     · .degradebar--line     one-line: ◆ .g + a single terse "X unavailable" line
   .group__degraded above is the group-header-embedded sibling and matches the
   --line look; prefer this canonical .degradebar for new banners.
   ============================================================================ */
.degradebar {
  display: flex; align-items: flex-start; gap: var(--s3);
  padding: var(--s3) var(--s4);
  background: var(--nudge-wash); box-shadow: inset 0 0 0 1px var(--nudge-line);
  clip-path: var(--clip-oct);
}
.degradebar__icon { color: var(--nudge-bright); font-family: var(--font-label); font-weight: 800; flex: none; line-height: 1.5; }
.degradebar__msg { color: var(--nudge-bright); font-weight: 600; font-size: var(--fs-sm); }
.degradebar__sub { font-size: var(--fs-micro); color: var(--ink-3); line-height: 1.55; margin-top: 3px; }
/* the terse one-line variant — a single mono caution line (the people/group form) */
.degradebar--line {
  align-items: center; gap: var(--s2); padding: var(--s2) var(--s3);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--nudge-bright);
}
.degradebar--line .g { color: var(--nudge); font-weight: 800; flex: none; }

/* ── DRIFT FINDING ROW — a per-item nudge/alarm carrying its P4 remedy, acting
     IN PLACE. It is the alertbar's grammar, dialed to a list row (status word +
     finding + remedy buttons). The rail/word color mirrors the family. ── */
.finding {
  --fc: var(--nudge);
  position: relative; display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4) var(--s3) var(--s5);
  background: var(--panel); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct);
}
.finding::before {
  content: ""; position: absolute; left: 0; top: var(--chamfer); bottom: var(--chamfer);
  width: 3px; background: var(--fc); box-shadow: 0 0 10px -2px var(--fc);
}
.finding.is-alarm { --fc: var(--alarm); background: var(--alarm-wash); box-shadow: inset 0 0 0 1px var(--alarm-line); }
.finding.is-nudge { --fc: var(--nudge); }
.finding__body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.finding__head {
  font-family: var(--font-prose); font-weight: 600; font-size: var(--fs-sm); color: var(--ink-bright);
  line-height: 1.35;
}
.finding__head .commitrow__glyph { color: var(--fc); margin-right: 4px; }
.finding.is-alarm .finding__head .commitrow__glyph { color: var(--alarm-bright); }
.finding.is-nudge .finding__head .commitrow__glyph { color: var(--nudge-bright); }
.finding__sub { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: 0.03em; }
.finding__remedy { display: flex; gap: var(--s2); flex: none; align-items: center; }
.finding__remedy .btn { padding: 5px var(--s3); }
/* the DRILL affordance: a finding names a real item; this opens that item's
   detail (Reconcile-drift flow: Drift → finding → Commitment/Note detail to
   prune + stamp). Quiet accent link to the RIGHT of the in-place remedies, so
   the fast path (remedy buttons) still reads first. */
.finding__open {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.03em;
  color: var(--ink-3); white-space: nowrap; flex: none; cursor: pointer;
  text-decoration: none; padding: 5px var(--s2);
  transition: color var(--fast) var(--ease);
}
.finding__open:hover, .finding__open:focus-visible { color: var(--accent-bright); }
.finding__open .arr { color: var(--accent); margin-left: 2px; }

/* ============================================================================
   HABIT DETAIL CARD (promoted — Habits screen, reusable)
   ----------------------------------------------------------------------------
   A per-habit surface: schedule readout + the full .cells grid + a three-up
   stat-block (current streak · longest streak · completion rate — each an
   anchored DL17 number) + retire/schedule controls. The three-up stat-block is
   its own atom (.statset) — a row of labeled .readout figures with a divider,
   reusable wherever an at-a-glance number trio belongs. DL17 law 2: the number
   is the truth; if a derived view is down the readout says so, never a fake.
   ============================================================================ */
.habitcard__head { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.habitcard__name { font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-lg); color: var(--ink-bright); line-height: 1.2; }
.sched {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em; color: var(--ink-2);
  padding: 2px var(--s2) 3px; background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct-sm);
}
.sched b { color: var(--accent-bright); font-weight: 600; }

/* the three-up anchored-number block (DL17 stat-block lineage) */
.statset { display: flex; align-items: stretch; gap: 0; }
.statset__cell { flex: 1; display: grid; gap: 3px; padding: 0 var(--s4); border-left: 1px solid var(--line); }
.statset__cell:first-child { border-left: 0; padding-left: 0; }
.statset__num { font-family: var(--font-mono); font-weight: 600; font-size: var(--fs-xl); color: var(--ink-bright); line-height: 1; letter-spacing: -0.01em; }
.statset__num.is-ok { color: var(--ok-bright); }
.statset__num .u { font-size: var(--fs-sm); color: var(--ink-3); font-weight: 500; margin-left: 2px; }
.statset__lbl { font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label); font-size: var(--fs-micro); color: var(--ink-3); }
/* DL17 law 2: a derived stat we could not compute says so — never a fabricated number */
.statset__num.is-unavailable { font-family: var(--font-label); font-size: var(--fs-sm); color: var(--nudge-bright); letter-spacing: var(--ls-label); text-transform: uppercase; }

/* the MTWTFSS weekday-set / N×week schedule editor — segmented, the .state grammar
   reused for an exclusive-ish set (the weekday toggles are independent; one octagon
   group). Inputs stay the only --radius-soft surface; this is a chamfered control. */
.weekset { display: inline-flex; align-items: stretch; clip-path: var(--clip-oct-sm); box-shadow: inset 0 0 0 1px var(--line); }
.weekset__day {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.06em;
  font-size: var(--fs-micro); font-weight: 700; color: var(--ink-3);
  min-width: 26px; padding: 5px 0; text-align: center; cursor: pointer;
  border-left: 1px solid var(--line); background: transparent;
}
.weekset__day:first-child { border-left: 0; }
.weekset__day.is-on { color: var(--accent-bright); background: var(--accent-wash); }
.weekset__day:hover { color: var(--ink-bright); }
.weekset__day:focus-visible { outline: none; box-shadow: var(--focus-ring-in); }

/* ============================================================================
   SEGMENTED CONTROL (promoted — DL5: one component, not near-duplicates)
   ----------------------------------------------------------------------------
   The EXCLUSIVE-segmented-readout grammar (the .state / .weekset lineage): one
   chamfered octagon group, hairline-divided into cells, exactly one lit. It was
   instantiated 3+ times as near-identical screen-local copies — Insights'
   time-range (.rangeseg), Ledger's op-filter (.opseg), Settings' day-start
   (.dialset) — which is the DL5 "near-duplicate" risk both reviewers flagged.
   Canonicalized here as ONE base (.seg / .seg__opt) with modifiers. The cells
   differ ONLY in their type voice + interior padding, so those are the modifiers;
   the shell, the divider grammar, the lit/hover/focus states are shared.
   Pixel-parity preserved: each former class maps to base + its exact modifiers.
     · --label  : condensed uppercase 11/micro·700 voice  (rangeseg, opseg)
     · --mono   : tabular mono 12/sm·500 voice             (dialset day-start)
     · --pad-{5,6,7}: the interior y-padding the signed-off instance used
     · --insert/--update/--delete : Ledger's op-color-on-lit (the one extra)
   ============================================================================ */
.seg { display: inline-flex; align-items: stretch; clip-path: var(--clip-oct-sm); box-shadow: inset 0 0 0 1px var(--line); }
.seg__opt {
  color: var(--ink-3); background: transparent; border: 0; cursor: pointer;
  border-left: 1px solid var(--line); display: flex; align-items: center;
  padding: var(--seg-pad-y, 6px) var(--s3);
  transition: color var(--fast) var(--ease), background var(--fast) var(--ease);
}
.seg__opt:first-child { border-left: 0; }
.seg__opt:hover { color: var(--ink-bright); }
.seg__opt.is-on { color: var(--accent-bright); background: var(--accent-wash); }
.seg__opt:focus-visible { outline: none; box-shadow: var(--focus-ring-in); }
/* type-voice modifiers — the only per-instance difference besides padding */
.seg__opt--label {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.1em;
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
}
.seg__opt--mono {
  font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 500;
  font-variant-numeric: tabular-nums;
}
/* interior y-padding presets (each preserves a signed-off instance's exact metrics) */
.seg--pad5 .seg__opt { --seg-pad-y: 5px; }   /* Settings day-start */
.seg--pad6 .seg__opt { --seg-pad-y: 6px; }   /* Ledger op-filter   */
.seg--pad7 .seg__opt { --seg-pad-y: 7px; }   /* Insights time-range */
/* a custom-range cell sits a hair brighter (Insights "custom ▾") */
.seg__opt--custom { color: var(--ink-2); }
/* OP-COLOR-ON-LIT (the one screen-specific addition, Ledger's filter): an op
   cell lights in its OWN op color so the control is a live legend of the
   stream's INSERT/UPDATE/DELETE key (DL3 — color still means one thing). */
.seg__opt--insert.is-on { color: var(--ok-bright);     background: var(--ok-wash); }
.seg__opt--update.is-on { color: var(--accent-bright); background: var(--accent-wash); }
.seg__opt--delete.is-on { color: var(--alarm-bright);  background: var(--alarm-wash); }

/* ── CHART GRID (promoted from insights.html — reusable on any analysis surface).
     A responsive instrument grid WIDER than .grid-2: as many ~320px columns as
     fit, so a wide monitor reads 3-up, a laptop 2-up, a phone 1-up. Each panel is
     an instrument answering one question. Its drill link is a quiet structural
     pointer (cyan on hover) — a chart is a finding, never a dead end. ── */
.chartgrid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: var(--s4);
  align-items: start;
}
.chartgrid__drill {
  display: inline-block; margin-top: var(--s3);
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-micro); font-weight: 700; color: var(--ink-3);
  text-decoration: none; transition: color var(--fast) var(--ease);
}
.chartgrid__drill:hover, .chartgrid__drill:focus-visible { color: var(--accent-bright); }

/* ── DOWN-IS-GOOD GLYPH (promoted from insights.html — DL17 honesty marker). On a
     series where FALLING is the good direction (drift count, inbox backlog), the
     default accent line must not read as decline. The ▾ glyph + word say so; it is
     NOT a status color (the line stays the structural accent, DL17 law 4). ── */
.downgood {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em;
  color: var(--ink-3); white-space: nowrap;
}
.downgood::first-letter { color: var(--accent); }   /* tint just the ▾ arrow */

/* ── RUNS TABLE (new — Agent Operations #17). The audit-grade backing for the
     cost charts: per-run usage GROUPED BY WAKE (run_id). It is the Ledger's
     terminal-readout DNA (mono, recessed well, tabular-nums), extended with a
     wake header that carries the wake's rolled-up cost, then its phase rows.
     A flat .ledger row could not carry the 4-column phase·model·tokens·cost
     anatomy NOR the wake-grouping, so this is its own small atom rather than a
     forced overload of .ledger. Cost figures here are INK, never a status color
     (DL17 law 4 — cost is information, not an alarm). tabular-nums right-align so
     dollars and token counts read down the column. ── */
.runs { font-family: var(--font-mono); font-size: var(--fs-sm); font-variant-numeric: tabular-nums; }
.runs__wake { margin-bottom: var(--s3); }
.runs__wake:last-child { margin-bottom: 0; }
/* the wake header — the run_id + when + rolled cost, a hair brighter than its rows */
.runs__whead {
  display: grid; grid-template-columns: 120px 1fr auto; gap: var(--s3); align-items: baseline;
  padding: var(--s1) 0; border-bottom: 1px solid var(--line);
}
.runs__wid   { color: var(--accent-bright); letter-spacing: 0.04em; }
.runs__wmeta { color: var(--ink-3); font-size: var(--fs-micro); }
.runs__wcost { color: var(--ink-bright); font-weight: 600; }
/* a phase row inside a wake — phase · model · tokens(in/out) · cost */
.runs__row {
  display: grid; grid-template-columns: 96px 96px 1fr auto; gap: var(--s3); align-items: baseline;
  padding: 2px 0 2px var(--s3); color: var(--ink-2);
}
.runs__phase { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.08em; font-size: var(--fs-micro); font-weight: 700; color: var(--ink-3); }
.runs__model { color: var(--ink-3); }
.runs__tok   { color: var(--ink-2); }
.runs__cost  { color: var(--ink); text-align: right; }
/* handheld: the phase row stacks model+tokens under the phase·cost line so nothing
   truncates in a single mono column (matches the spec's 390 reflow). */
@media (max-width: 560px) {
  .runs__whead { grid-template-columns: 1fr auto; }
  .runs__wmeta { grid-column: 1 / -1; order: 3; }
  .runs__row {
    grid-template-columns: 1fr auto; row-gap: 1px; padding-left: var(--s2);
    padding-bottom: var(--s2); border-bottom: 1px solid var(--line-soft);
  }
  .runs__model { grid-column: 1; grid-row: 2; }
  .runs__tok   { grid-column: 1 / -1; grid-row: 3; }
}

/* a habit cell that is EXPECTED today but unchecked carries a GENTLE amber ◆ —
   surfacing, not nagging (P17): NO red, the miss is still just a dark empty cell.
   This marks the today cell's at-risk state without inventing an "overdue" entity. */
.cell.at-risk { box-shadow: inset 0 0 0 1px var(--nudge-line); background: var(--nudge-wash); }
.cell.at-risk::after { content: "◆"; position: absolute; inset: 0; display: grid; place-items: center; font-size: 9px; color: var(--nudge-bright); }
/* a backdate-able past empty (expected, unchecked) — tappable, a hair more present
   than an inert future cell, but NOT a miss-treatment (it's a correction, not a make-up) */
.cell.backdatable { cursor: pointer; box-shadow: inset 0 0 0 1px var(--line); }
.cell.backdatable:hover { box-shadow: inset 0 0 0 1px var(--accent-glow); background: var(--accent-wash); }
/* the today CHECK-IN row (the act) — a habit row lifted as the focal interaction */
.checkin { display: grid; grid-template-columns: 1fr auto; gap: var(--s3); align-items: center; padding: var(--s2) var(--s3); border-bottom: 1px solid var(--line-soft); }
.checkin:hover { background: var(--panel-2); }
.checkin__name { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.08em; font-size: var(--fs-base); color: var(--ink); }
.checkin__act { display: flex; align-items: center; gap: var(--s3); }
/* the tap-to-check-in cell — the today cell, sized as a real touch target */
.checkin__cell {
  position: relative; width: 28px; height: 28px; flex: none; cursor: pointer;
  background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent);
  clip-path: polygon(4px 0,calc(100% - 4px) 0,100% 4px,100% calc(100% - 4px),calc(100% - 4px) 100%,4px 100%,0 calc(100% - 4px),0 4px);
}
.checkin__cell::after { content: ""; position: absolute; inset: 0; margin: auto; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 6px var(--accent); }
.checkin__cell.is-checked { background: var(--ok); box-shadow: inset 0 0 0 1px var(--ok-line), 0 0 8px -2px var(--ok); }
.checkin__cell.is-checked::after { content: "✓"; width: auto; height: auto; border-radius: 0; background: transparent; box-shadow: none; color: var(--void); font-family: var(--font-mono); font-weight: 700; font-size: 14px; display: grid; place-items: center; }
.checkin.is-at-risk .checkin__name { color: var(--ink-bright); }
.checkin__flag { font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.1em; font-size: var(--fs-micro); font-weight: 700; color: var(--nudge-bright); white-space: nowrap; }

@media (max-width: 640px) {
  /* .grouphd / .grouphd__rule / .finding column-stack now live in the ≤760 marker-
     row band above (rail present 641–760 → same wrap). Here: handheld touch floors
     and the statset/checkin stacking only. */
  .finding__remedy { margin-top: var(--s1); }
  .finding__remedy .btn { flex: 1; min-height: 44px; }
  .statset { flex-direction: column; gap: var(--s3); }
  .statset__cell { border-left: 0; padding: 0; border-top: 1px solid var(--line); padding-top: var(--s3); }
  .statset__cell:first-child { border-top: 0; padding-top: 0; }
  .checkin__cell { width: 44px; height: 44px; }      /* touch floor (DL13) */
}

/* ============================================================================
   PROSE-BODY EDITOR (promoted — shared by NOTE DETAIL + PERSON RECORD)
   ----------------------------------------------------------------------------
   The in-place refinement surface for a P6-versioned PROSE body (a note body or
   a person's profile body — same grammar, two contexts; DL5 "one component, not
   near-duplicates"). It is the .well's recessed-data lineage in its --soft form
   (the ONE permitted roundness — a text-entry surface; DL5), wearing the PROSE
   voice + the wide ~64ch measure (DL6/DL8). The accent focus GLOW is an explicit
   :focus-within state, never the default (DL2 emission budget — one focal well
   per view). "refined N×" + history are first-class affordances (P6: refining is
   a logged new version, never a silent overwrite). Full state set (DL15):
   default · :hover · :focus-within · .is-saving. Every value tokenized.
   ============================================================================ */
.proseedit { display: grid; gap: var(--s2); }
.proseedit__head { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
/* the refined-count affordance — a quiet mono chip; clicking it opens P6 history.
   It is a FACT readout (mono), not a status, so it stays ink — never a system color. */
.proseedit__refined {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em;
  color: var(--ink-3); padding: 2px var(--s2) 3px; cursor: pointer;
  background: transparent; box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct-sm); white-space: nowrap;
}
.proseedit__refined:hover { color: var(--accent-bright); box-shadow: inset 0 0 0 1px var(--accent-glow); }
.proseedit__refined b { color: var(--ink-2); font-weight: 600; }
.proseedit__refined:hover b { color: var(--accent-bright); }
/* the editable body well — recessed, --radius-soft (the type-here surface, DL5),
   carrying the PROSE voice + leading + the 64ch measure of .note-body. */
.proseedit__body {
  font-family: var(--font-prose); font-size: var(--fs-md); line-height: 1.7; color: var(--ink);
  background: var(--well); box-shadow: inset 0 0 0 1px var(--line-strong);
  border-radius: var(--radius-soft); padding: var(--s4) var(--s5);
  max-width: 66ch;            /* 64ch measure + the --s5 padding either side */
  min-height: 7em; outline: none;
  transition: box-shadow var(--fast) var(--ease);
}
.proseedit__body:hover { box-shadow: inset 0 0 0 1px var(--accent-glow); }
/* the focal-well glow — the ONE emissive control while editing (DL2) */
.proseedit__body:focus, .proseedit__body.is-focus, .proseedit.is-editing .proseedit__body {
  box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px var(--accent-wash);
}
.proseedit__body p { margin: 0 0 var(--s4); }
.proseedit__body p:last-child { margin-bottom: 0; }
.proseedit__body .wikilink { color: var(--accent-bright); text-decoration: none; box-shadow: inset 0 -1px 0 var(--accent-dim); cursor: pointer; }
.proseedit__body .wikilink::before { content: "[["; color: var(--accent-dim); }
.proseedit__body .wikilink::after  { content: "]]"; color: var(--accent-dim); }
/* the editor foot — a saving indicator + the explicit refine/save action. The
   note body is NEVER read-only for being orphaned (P9): editing is always live. */
.proseedit__foot {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  min-height: 20px;
}
.proseedit__status {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em;
  color: var(--ink-3); display: inline-flex; align-items: center; gap: 6px;
}
/* the in-flight SAVING state — a quiet cyan dot + word (never a layout shift, DL15) */
.proseedit.is-saving .proseedit__status { color: var(--accent-bright); }
.proseedit__savedot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--ink-mute);
}
.proseedit.is-saving .proseedit__savedot {
  background: var(--accent); box-shadow: 0 0 8px var(--accent);
  animation: skel 1.1s var(--ease) infinite;
}
.proseedit.is-saved .proseedit__status { color: var(--ok-bright); }
.proseedit.is-saved .proseedit__savedot { background: var(--ok); box-shadow: 0 0 8px var(--ok); animation: none; }

/* ============================================================================
   LINK-CREATE MODAL (promoted — shared by NOTE DETAIL + PERSON RECORD)
   ----------------------------------------------------------------------------
   The P9 universal-link composer. CRITICAL (P9): there is NO link-type
   dropdown/enum — a link carries only a TARGET and an OPTIONAL free-text "why".
   The picker scopes across ALL kinds (note/task/commitment/person). One octagon
   dialog on the --z-modal rung over a scrim (DL16). Every value tokenized.
   ============================================================================ */
.scrim {
  position: fixed; inset: 0; z-index: var(--z-modal);
  background: rgba(2, 4, 9, 0.72);
  display: grid; place-items: start center; padding: var(--s7) var(--s4);
  overflow-y: auto;
}
/* [hidden] must win over display:grid — otherwise the invisible scrim covers
   the whole page and swallows every click (DL16: an overlay that's "closed"
   must not be in the stacking flow at all). */
.scrim[hidden] { display: none; }
.modal {
  position: relative; width: 100%; max-width: 560px;
  background: var(--panel); box-shadow: var(--lift), inset 0 0 0 1px var(--line-strong);
  clip-path: var(--clip-oct-lg); padding: var(--s5);
  display: grid; gap: var(--s4);
}
.modal__head { display: flex; align-items: center; gap: var(--s3); }
.modal__title {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-label); font-weight: 700; color: var(--accent-bright);
  text-shadow: 0 0 12px var(--accent-glow);
}
.modal__title::before { content: "▸"; color: var(--accent); margin-right: 7px; opacity: 0.8; }
.modal__close {
  margin-left: auto; flex: none; width: 26px; height: 26px; cursor: pointer;
  display: flex; align-items: center; justify-content: center; color: var(--ink-3);
  font-family: var(--font-mono); font-size: 15px; line-height: 1;
  background: transparent; border: 0; box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct-sm);
}
.modal__close:hover { color: var(--ink-bright); box-shadow: inset 0 0 0 1px var(--line-strong); }
.modal__close:focus-visible { outline: none; box-shadow: var(--focus-ring-in); }
/* the explicit "no link-type" honesty note — renders P9 as a visible promise */
.modal__note {
  font-family: var(--font-prose); font-size: var(--fs-sm); color: var(--ink-3);
  line-height: 1.5; max-width: 56ch;
}
.modal__note b { color: var(--ink-2); font-style: italic; font-weight: 500; }
/* the target picker — a search field over ALL kinds, then a scrollable result
   list of .linkrow forms (kind-tagged, the SAME atom the panes render). */
.picker { display: grid; gap: var(--s2); }
.picker__results {
  background: var(--well); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct); max-height: 232px; overflow-y: auto;
}
.picker__results .linkrow { cursor: pointer; }
.picker__results .linkrow.is-picked {
  background: var(--accent-wash); box-shadow: inset 2px 0 0 var(--accent);
}
.picker__results .linkrow.is-picked .linkrow__title { color: var(--ink-bright); }
/* the chosen-target confirmation line */
.picker__chosen {
  display: flex; align-items: center; gap: var(--s3);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-2);
}
.picker__chosen .b { color: var(--ink-bright); }
.modal__foot { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.modal__foot .spacer { flex: 1; }

/* ============================================================================
   PERSON AGGREGATION (NEW — PERSON RECORD's two-pane glance, the heart of the
   screen). Two computed panes ABOVE THE FOLD: OPEN LOOPS (the louder pane — the
   waiting Tasks/Commitments) and WHAT I KNOW (the linked Notes). The eye lands
   here FIRST (P10: a person record is a COMPUTED AGGREGATION, not a stored CRM
   table). Both panes are labeled `computed`. Every value tokenized.
   ============================================================================ */
.aggpanes { display: grid; grid-template-columns: 1.25fr 1fr; gap: var(--s4); align-items: start; }
/* the LOUDER pane — open loops. A brighter frame so the eye lands here first;
   the pane is structural (cyan), the per-row state pills carry the item's health. */
.aggpane { position: relative; }
.aggpane--loud { box-shadow: inset 0 0 0 1px var(--line-strong); }
/* the computed badge on each pane head — a small mono "computed" honesty mark */
.computedtag {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.06em;
  color: var(--ink-3); white-space: nowrap;
}
.computedtag::before { content: "ƒ "; color: var(--accent); opacity: 0.8; }
/* an open-loop row — a .linkrow carrying the LINKED item's OWN state pill + title.
   The waiting item's health pill is the loud signal (DL4 status-first). */
.looprow { display: flex; align-items: center; gap: var(--s3); padding: var(--s3); border-bottom: 1px solid var(--line-soft); }
.looprow:last-child { border-bottom: 0; }
.looprow:hover { background: var(--panel-2); }
.looprow__main { flex: 1; min-width: 0; display: grid; gap: 3px; }
.looprow__title { font-family: var(--font-prose); font-weight: 600; font-size: var(--fs-md); color: var(--ink-bright); line-height: 1.25; }
.looprow__why { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); font-style: italic; }
/* the GOOD-NEWS no-loops state — calm, healthy, NOT an alarm and NOT a blank.
   Green ● + word: "nothing is open" (distinct from the degraded "I don't know"). */
.goodnews {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s4); background: var(--ok-wash); box-shadow: inset 0 0 0 1px var(--ok-line);
  clip-path: var(--clip-oct);
}
.goodnews__glyph { color: var(--ok-bright); font-size: var(--fs-lg); flex: none; line-height: 1; filter: drop-shadow(0 0 8px var(--ok-line)); }
.goodnews__title { font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label); font-size: var(--fs-label); font-weight: 700; color: var(--ok-bright); }
.goodnews__sub { font-family: var(--font-prose); font-size: var(--fs-sm); color: var(--ink-2); line-height: 1.45; }

/* ============================================================================
   INTERACTION-LOG COMPOSER (NEW — PERSON RECORD). Append-only (P6/P14): writes a
   NEW log_entry, NEVER mutates a past one. Auto-timestamp + an OPTIONAL backdate.
   It sits atop the .ledger append-log (reused). Full state set (DL15):
   empty · :focus-within · filled · .is-saving. Every value tokenized.
   ============================================================================ */
.logcompose {
  display: grid; gap: var(--s3);
  background: var(--well); box-shadow: inset 0 0 0 1px var(--line-strong);
  border-radius: var(--radius-soft); padding: var(--s4);   /* DL5: a type-here well shares the .proseedit silhouette, not the octagon */
  transition: box-shadow var(--fast) var(--ease);
}
.logcompose:focus-within { box-shadow: inset 0 0 0 1px var(--accent), 0 0 0 3px var(--accent-wash); }
.logcompose__field {
  font-family: var(--font-prose); font-size: var(--fs-md); line-height: 1.6; color: var(--ink);
  background: transparent; border: 0; outline: none; width: 100%; resize: vertical; min-height: 3em;
}
.logcompose__field::placeholder { color: var(--ink-3); }
.logcompose__foot { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
/* the auto-timestamp readout (mono — a machine-true fact) + the backdate toggle */
.logcompose__when {
  font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.04em; color: var(--ink-3);
  display: inline-flex; align-items: center; gap: 6px;
}
.logcompose__when b { color: var(--ink-2); }
.logcompose__backdate { display: inline-flex; align-items: center; gap: 6px; }
.logcompose__backdate .input { width: auto; padding: 4px var(--s2); font-size: var(--fs-micro); }

@media (max-width: 760px) {
  .aggpanes { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 640px) {
  .modal { padding: var(--s4); }
  .scrim { padding: var(--s5) var(--s3); }
  .proseedit__body { padding: var(--s3) var(--s4); }
  .modal__foot .btn, .logcompose__foot .btn { min-height: 44px; }
}

/* ============================================================================
   DESTRUCTIVE-ACTION CONFIRM (SHARED — Tags merge/retire + Settings day-start/
   token rotate·revoke/GCal disconnect). ONE confirm pattern over the .scrim/
   .modal grammar at --z-modal (DL16). It states the BLAST RADIUS (consequence)
   and, where the op is logged/recoverable, the LEDGER note (P6). The frame
   severity is HONEST and matched to the act (DL3):
     · default        --nudge caution  (a re-derive / reversible shift — NOT red)
     · .confirm--alarm --alarm          (truly destructive/irreversible — revoke)
   It is .modal with a status rail + a consequence block + a severity-marked
   primary. Red is NEVER the default frame — only a real alarm earns it.
   ============================================================================ */
.confirm {
  --cf: var(--nudge); --cf-bright: var(--nudge-bright);
  --cf-wash: var(--nudge-wash); --cf-line: var(--nudge-line);
  max-width: 512px; padding-left: var(--s6);
}
.confirm--alarm { --cf: var(--alarm); --cf-bright: var(--alarm-bright); --cf-wash: var(--alarm-wash); --cf-line: var(--alarm-line); }
/* the severity rail — a 3px colored stripe inset past the chamfers (like .alertbar) */
.confirm::before {
  content: ""; position: absolute; left: 0; top: var(--chamfer-lg); bottom: var(--chamfer-lg);
  width: 3px; background: var(--cf); box-shadow: 0 0 12px -2px var(--cf);
}
/* the title carries the family glyph + WORD + color (DL4 — never color alone) */
.confirm .modal__title { color: var(--cf-bright); text-shadow: 0 0 12px var(--cf-line); }
.confirm .modal__title::before { content: attr(data-glyph); color: var(--cf); }
/* the consequence statement — what this DOES, plainly (the P4 remedy pattern) */
.confirm__what {
  font-family: var(--font-prose); font-size: var(--fs-md); line-height: 1.55; color: var(--ink);
}
.confirm__what b { color: var(--cf-bright); font-weight: 600; }
/* the blast-radius readout — the exact N it touches, in the machine-true MONO voice */
.confirm__blast {
  display: flex; align-items: center; gap: var(--s3);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-2);
  padding: var(--s3) var(--s4);
  background: var(--cf-wash); box-shadow: inset 0 0 0 1px var(--cf-line);
  clip-path: var(--clip-oct);
}
.confirm__blast .n { color: var(--cf-bright); font-weight: 600; }
/* the LEDGER-recoverability note (P6) — a quiet ok-tinted line where it applies */
.confirm__ledger {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ok-bright);
  letter-spacing: 0.03em;
}
.confirm__ledger::before { content: "✓"; color: var(--ok); }
/* the irreversible note — for an --alarm confirm with NO recovery */
.confirm__irrev {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--alarm-bright);
  letter-spacing: 0.03em;
}
.confirm__irrev::before { content: "▲"; }
/* the destructive primary — a severity-colored fill, NOT the cyan affirmative.
   Cyan --primary is reserved for "go" (DL7); a consequence button wears its
   own severity so the eye reads the weight of the act before it clicks. */
.btn--danger {
  color: var(--void); background: var(--cf, var(--alarm));
  box-shadow: 0 0 18px -4px var(--cf, var(--alarm));
}
.btn--danger:hover { color: var(--void); background: var(--cf-bright, var(--alarm-bright)); box-shadow: inset 0 0 0 1px var(--cf-bright, var(--alarm-bright)); }
.btn--danger:focus-visible { outline: none; box-shadow: inset 0 0 0 2px var(--void), 0 0 18px -2px var(--cf, var(--alarm)); }

/* ============================================================================
   TOGGLE SWITCH (SHARED — Settings GCal connect / TOTP, recurs anywhere a
   boolean is set). CHAMFERED, per DL5 — an octagon track + octagon knob, NEVER
   a rounded iOS pill. Carries glyph+WORD+color state (DL4): OFF is ink + "off",
   ON is --ok + "on" (a connection/credential being on is a healthy go-state).
   Full state set (DL15): default · hover · focus · checked · disabled. Built as
   a real <button role="switch"> so it's keyboard-first and announces its state.
   ============================================================================ */
.toggle {
  --tg: var(--ink-faint);
  display: inline-flex; align-items: center; gap: var(--s2);
  background: transparent; border: 0; cursor: pointer; padding: 0;
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-micro); font-weight: 700; color: var(--tg);
}
.toggle__track {
  position: relative; width: 44px; height: 22px; flex: none;
  background: var(--well); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: polygon(5px 0,calc(100% - 5px) 0,100% 5px,100% calc(100% - 5px),calc(100% - 5px) 100%,5px 100%,0 calc(100% - 5px),0 5px);
  transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
/* the knob — a small octagon that slides; chamfered to match the track (DL5) */
.toggle__knob {
  position: absolute; top: 3px; left: 3px; width: 16px; height: 16px;
  background: var(--ink-3);
  clip-path: polygon(4px 0,calc(100% - 4px) 0,100% 4px,100% calc(100% - 4px),calc(100% - 4px) 100%,4px 100%,0 calc(100% - 4px),0 4px);
  transition: left var(--fast) var(--ease), background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.toggle:hover .toggle__track { box-shadow: inset 0 0 0 1px var(--line-strong); }
.toggle[aria-checked="true"] { --tg: var(--ok-bright); }
.toggle[aria-checked="true"] .toggle__track { background: var(--ok-wash); box-shadow: inset 0 0 0 1px var(--ok-line); }
.toggle[aria-checked="true"] .toggle__knob { left: 25px; background: var(--ok); box-shadow: 0 0 8px -1px var(--ok); }
.toggle:focus-visible { outline: none; }
.toggle:focus-visible .toggle__track { box-shadow: var(--focus-ring-in); }
.toggle:disabled { cursor: not-allowed; --tg: var(--ink-faint); }
.toggle:disabled .toggle__track { background: var(--bg); box-shadow: inset 0 0 0 1px var(--line-soft); }
.toggle:disabled .toggle__knob { background: var(--ink-mute); box-shadow: none; }
/* TOUCH FLOOR (DL13) — the 22px visual track is below the 44px tap minimum on
   handheld. Grow the tap area to 44px (the visual track stays 22px, centered);
   the toggle gates a destructive confirm, so it must be comfortably tappable. */
@media (max-width: 640px) {
  .toggle { min-height: 44px; }
}

/* ----------------------------------------------------------------------------
   MOTION SAFETY — honor the operator's OS setting (DL9). Drop the caret blink,
   the skeleton shimmer, the spinner, and collapse transitions to instant.
   ---------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001ms !important; animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important; scroll-behavior: auto !important;
  }
  .cmd__caret { animation: none; opacity: 1; }
}

/* ============================================================================
   CAPTURE MODAL — promoted from screens/capture.html (now a global component,
   D15). Rides the canonical .scrim/.modal grammar; these are the additive
   capture-specifics + the transient toast. One scrim spec system-wide (DL16).
   ============================================================================ */
.capture {
  max-width: 620px;
  background: var(--panel-2);
  box-shadow:
    inset 0 0 0 1px var(--line-strong),
    0 24px 64px -20px rgba(0,0,0,0.85),
    0 0 40px -12px var(--accent-glow);
}
.well-input {
  min-height: 116px;
  font-family: var(--font-prose);
  font-size: var(--fs-lg);
  line-height: 1.5;
  width: 100%;
  color: var(--ink);
  resize: vertical;
}
.well-input::placeholder { color: var(--ink-3); }
/* the blinking caret — the one permitted motion here (DL9) */
.caret {
  display: inline-block; width: 2px; height: 1.15em; vertical-align: text-bottom;
  margin-left: 1px; background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
  animation: blink 1.1s steps(1) infinite;
}
.tagline {
  display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap;
  margin-top: var(--s4);
}
.tagline__legend { color: var(--ink-3); }
.tagline__input {
  flex: 1; min-width: 180px;
  background: transparent;
  box-shadow: inset 0 0 0 1px var(--line-soft);
  font-family: var(--font-mono);
}
.tagline__input:hover { box-shadow: inset 0 0 0 1px var(--line); }
/* stacked variant: legend on its own line above the tag type-ahead */
.tagline--stack { flex-direction: column; align-items: stretch; gap: var(--s2); }

/* ---- tagEntry: the shared, case-insensitive tag type-ahead ----------------
   Used at every tag-entry point (capture overlay + inbox triage). Suggests
   existing tags to reuse and gates new-tag creation behind a confirm step. */
.tagentry { display: block; }
.tagentry__row { display: flex; align-items: center; gap: var(--s2); }
.tagentry__kind { width: auto; flex: none; }
.tagentry__field { flex: 1; min-width: 0; }
.tagentry__field .input { width: 100%; font-family: var(--font-mono); }
/* inline (in-flow) so the octagon clip-path of the triage card never clips it */
.tagentry__menu {
  margin-top: var(--s2);
  background: var(--panel-2);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  border-radius: var(--radius-soft);
  padding: var(--s2); max-height: 220px; overflow-y: auto;
}
.tagentry__menuhd { display: block; padding: 2px var(--s2) var(--s2); color: var(--ink-3); }
.tagentry__opt {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s3);
  width: 100%; text-align: left; background: none; border: 0; cursor: pointer;
  padding: var(--s2) var(--s2); color: var(--ink-2); font-family: var(--font-mono);
  border-radius: var(--radius-soft);
}
.tagentry__opt:hover, .tagentry__opt:focus-visible { background: var(--panel-3); color: var(--ink-bright); outline: none; }
.tagentry__opt .label { color: var(--ink-3); }
.tagentry__x {
  margin-left: 4px; background: none; border: 0; cursor: pointer;
  color: var(--ink-3); font-size: var(--fs-micro); line-height: 1;
}
.tagentry__x:hover { color: var(--ink-bright); }
.tagentry__confirm {
  display: flex; align-items: center; flex-wrap: wrap; gap: var(--s2);
  margin-top: var(--s2); padding: var(--s2) var(--s3);
  box-shadow: inset 0 0 0 1px var(--nudge-line);
  border-radius: var(--radius-soft); font-size: var(--fs-sm); color: var(--ink-2);
}
.tagentry__confirm-msg b { color: var(--ink-bright); }
.tagentry__did { color: var(--ink-3); }
.tagentry__didbtn { padding: 2px var(--s2); }
.capture__foot {
  display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap;
  margin-top: var(--s5);
  padding-top: var(--s4); border-top: 1px solid var(--line);
}
.capture__hint { color: var(--ink-3); }

/* THE TOAST (--z-toast) — transient confirmation, bottom-center. */
.toast {
  position: fixed; left: 50%; bottom: var(--s6); transform: translateX(-50%);
  z-index: var(--z-toast);
  display: inline-flex; align-items: center; gap: var(--s3);
  padding: var(--s2) var(--s4);
  background: var(--panel-3);
  box-shadow: inset 0 0 0 1px var(--ok-line), 0 16px 40px -16px rgba(0,0,0,0.8);
  clip-path: var(--clip-oct);
}
.toast--nudge { box-shadow: inset 0 0 0 1px var(--nudge-line), 0 16px 40px -16px rgba(0,0,0,0.8); }
.toast__glyph { color: var(--ok-bright); text-shadow: 0 0 10px var(--ok-line); font-weight: 700; }
.toast--nudge .toast__glyph { color: var(--nudge-bright); text-shadow: 0 0 10px var(--nudge-line); }
.toast__text  { font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label); font-size: var(--fs-label); font-weight: 700; color: var(--ink-bright); }
.toast__sub   { font-size: var(--fs-micro); color: var(--ink-3); }

/* command palette — the ⌘K modal list (DL10 universal entry). Rides .scrim/.modal. */
.palette { max-width: 640px; padding: 0; gap: 0; }
.palette__input {
  width: 100%; border: 0; background: var(--well);
  box-shadow: inset 0 0 0 1px var(--line);
  border-radius: var(--radius-soft) var(--radius-soft) 0 0;
  padding: var(--s4) var(--s5); font-family: var(--font-mono); font-size: var(--fs-md); color: var(--ink);
}
.palette__list { list-style: none; margin: 0; padding: var(--s2); max-height: 50vh; overflow-y: auto; }
.palette__item { display: flex; align-items: center; gap: var(--s3); padding: var(--s2) var(--s3); cursor: pointer; color: var(--ink-2); }
.palette__item.is-active, .palette__item:hover { background: var(--panel-3); color: var(--ink-bright); }
.palette__item .label { color: var(--ink-3); margin-left: auto; }

@media (max-width: 640px) {
  .well-input { font-size: var(--fs-md); min-height: 96px; }
}

/* Rail capture button (D15) — the persistent, visible never-lossy ingress (P7/I1). */
.rail__capture {
  display: flex; align-items: center; justify-content: center; gap: var(--s2);
  width: 100%; margin-bottom: var(--s4);
}

/* ============================================================================
   COMMITMENT DETAIL WORKBENCH — promoted from screens/commitment-detail.html
   (now a real screen, D15). The detail shell + health rail, editable head,
   focal next-action, review pane, trigger bar, order note. task__desig /
   task__grip / task__nodesig / is-next were promoted earlier.
   ============================================================================ */
.detail { --rail: var(--ok); position: relative; }
.detail.is-alarm { --rail: var(--alarm); }
.detail.is-nudge { --rail: var(--nudge); }
.detail.is-ok    { --rail: var(--ok); }
.detail.is-defer { --rail: var(--defer); }
.detail.is-back  { --rail: var(--ink-faint); }
.detail__rail {
  position: absolute; left: 0; top: var(--chamfer); bottom: var(--chamfer);
  width: 3px; background: var(--rail); box-shadow: 0 0 12px -2px var(--rail);
}
.detail.is-back .detail__rail, .detail.is-dimmed .detail__rail { box-shadow: none; opacity: 0.6; }
.detail__head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--s4); flex-wrap: wrap; }
.detail__title { font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-xl); color: var(--ink-bright); line-height: 1.15; margin: 0; }
.detail__statewrap { flex: none; }
.detail__states .state { padding: 6px var(--s3); cursor: pointer; }
.detail__states .state:hover:not(.is-on) { color: var(--ink-2); background: var(--panel-2); }
.detail__section { margin-top: var(--s5); display: grid; gap: var(--s3); }
.detail__sub { display: block; }
.detail__alarm { margin-top: var(--s4); }
.detail__goal { font-family: var(--font-prose); font-style: italic; color: var(--ink); font-size: var(--fs-md); line-height: 1.5; padding-left: var(--s4); border-left: 2px solid var(--line-strong); }
.is-dimmed .detail__goal { color: var(--ink-faint); border-left-color: var(--line); }
.detail__focalnext { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; margin-top: var(--s4); padding: var(--s3) var(--s4); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-glow); clip-path: var(--clip-oct); }
.detail__focalnext-title { font-family: var(--font-prose); font-weight: 600; font-size: var(--fs-md); color: var(--ink-bright); }
.detail__tasks { display: grid; gap: 0; }
.detail__addtask { justify-self: start; margin-top: var(--s2); }
.task__grip--inline { display: inline-block; vertical-align: -3px; width: 10px; height: 12px; margin-right: 6px; opacity: 1; }
.detail__ordernote { font-family: var(--font-prose); font-style: italic; font-size: var(--fs-sm); color: var(--ink-3); line-height: 1.5; margin: var(--s2) 0 0; max-width: 60ch; }
.reviewpane { display: grid; gap: var(--s3); background: var(--well); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct); padding: var(--s4); }
.reviewpane__when { font-size: var(--fs-md); color: var(--ink-bright); }
.reviewpane__cadence { font-size: var(--fs-sm); color: var(--ink-2); padding-top: var(--s3); border-top: 1px solid var(--line-soft); }
.reviewpane__stamp { justify-self: start; }
.reviewpane.is-overdue .reviewpane__when { color: var(--nudge-bright); }
.reviewpane.is-overdue .reviewpane__cadence { color: var(--nudge-bright); }
.triggerbar { --rail-color: var(--defer); position: relative; display: flex; align-items: center; gap: var(--s3); margin-top: var(--s4); padding: var(--s3) var(--s4); background: var(--defer-wash); box-shadow: inset 0 0 0 1px var(--defer-line); clip-path: var(--clip-oct); }
.triggerbar::before { content: ""; position: absolute; left: 0; top: var(--chamfer); bottom: var(--chamfer); width: 3px; background: var(--defer); box-shadow: 0 0 10px -2px var(--defer); }
.triggerbar__icon { font-family: var(--font-label); font-weight: 800; letter-spacing: 0.1em; font-size: var(--fs-label); color: var(--defer-bright); white-space: nowrap; flex: none; }
.triggerbar__date { font-size: var(--fs-md); color: var(--defer-bright); font-weight: 600; }
.triggerbar__note { font-family: var(--font-prose); color: var(--ink-2); font-size: var(--fs-sm); line-height: 1.45; margin-top: 3px; }
.detail__history { max-height: none; }
.is-dimmed .detail__title { color: var(--ink-2); }
@media (max-width: 640px) {
  .detail { padding-left: var(--s5) !important; }
  .detail__head { gap: var(--s3); }
  .detail__statewrap { width: 100%; }
  .detail__states { width: 100%; }
  .detail__states .state { flex: 1; justify-content: center; min-height: 40px; }
  .detail__title { font-size: var(--fs-lg); }
  .task__grip { display: none; }
  .reviewpane__stamp, .detail__addtask { width: 100%; justify-self: stretch; min-height: 44px; }
  .triggerbar { flex-wrap: wrap; }
}

/* ============================================================================
   QUERY / RESULTS — promoted from screens/query.html (now a real screen, D15).
   The heterogeneous result column gutter, the results header, the parse-error
   frame (a malformed query the engine refuses ≠ a valid empty result), and the
   echoed-query readout. prose-row / dir-row / tag--inherited were promoted
   earlier (Knowledge / People reuse them).
   ============================================================================ */
.results { display: grid; gap: var(--s2); }
.resrow { position: relative; }
.reskind { position: absolute; left: calc(-1 * var(--s7)); top: var(--s3); width: calc(var(--s7) - var(--s2)); text-align: right; color: var(--ink-3); }
@media (max-width: 980px) { .reskind { position: static; width: auto; text-align: left; display: inline-block; margin-bottom: var(--s1); } }
.resrow--task { background: var(--panel); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct); border-bottom: 0; padding-left: var(--s4); padding-right: var(--s4); }
.resrow--task:hover { background: var(--panel-2); }
.resultbar { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.resultbar__count { font-size: var(--fs-xl); }
.saveview { color: var(--accent-bright); }
.saveview:hover { color: var(--void); background: var(--accent); }
.cmd--invalid { box-shadow: inset 0 0 0 1px var(--alarm-line), inset 0 0 24px -8px var(--alarm-wash); }
.parsehint { display: flex; align-items: flex-start; gap: var(--s3); margin-top: var(--s3); padding: var(--s3) var(--s4); background: var(--alarm-wash); box-shadow: inset 0 0 0 1px var(--alarm-line); clip-path: var(--clip-oct); }
.parsehint__icon { color: var(--alarm-bright); font-family: var(--font-label); font-weight: 800; flex: none; line-height: 1.4; }
.parsehint__msg { color: var(--alarm-bright); font-weight: 600; font-size: var(--fs-sm); }
.parsehint__fix { color: var(--ink-2); font-size: var(--fs-sm); line-height: 1.5; margin-top: 3px; }
.parsehint__fix .mono, .parsehint__msg .mono { color: var(--ink-bright); }
.echoquery { font-size: var(--fs-sm); padding: var(--s2) var(--s3); margin: var(--s2) 0; color: var(--ink-2); }
@media (max-width: 760px) { .resrow--task { flex-wrap: wrap; } }

/* ============================================================================
   INBOX spawn-builder + queue — promoted from screens/inbox.html (real screen).
   The verbatim captured line, the directive panels, the queue rows, inbox-zero.
   ============================================================================ */
.verbatim { font-size: var(--fs-md); line-height: 1.4; padding: var(--s3) var(--s4); box-shadow: inset 0 0 0 1px var(--line-strong), inset 0 0 20px -10px var(--accent-glow); margin-bottom: var(--s4); }
.verbatim::before { content: "\201C"; color: var(--accent-dim); margin-right: 2px; }
.verbatim::after  { content: "\201D"; color: var(--accent-dim); margin-left: 2px; }
.spawn { display: grid; gap: var(--s4); }
.directive { background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct); padding: var(--s4); }
.directive__head { display: flex; align-items: center; gap: var(--s3); }
.kindsel .state { padding: 5px var(--s2); cursor: pointer; }
.directive__drop { padding: 4px var(--s2); color: var(--ink-3); }
.directive__drop:hover { color: var(--alarm-bright); }
.directive__star[aria-pressed="true"] { color: var(--nudge-bright); box-shadow: inset 0 0 0 1px var(--nudge-line); text-shadow: 0 0 10px var(--nudge-line); }
.spawn__commit { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; padding-top: var(--s4); border-top: 1px solid var(--line); }
.spawn__add { align-self: start; }
.qrow { display: flex; align-items: center; gap: var(--s3); padding: var(--s3); border-bottom: 1px solid var(--line-soft); }
.qrow:hover { background: var(--panel-2); }
.qrow.is-current { background: var(--accent-wash); box-shadow: inset 2px 0 0 var(--accent); }
.qrow__mark { width: 16px; text-align: center; color: var(--accent); flex: none; }
.qrow__body { flex: 1; min-width: 0; display: grid; gap: 2px; }
.qrow__text { color: var(--ink); font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.qrow__age  { color: var(--ink-3); }
.zero { box-shadow: inset 0 0 0 1px var(--ok-line); }
.zero .phead__title { color: var(--ok-bright); text-shadow: 0 0 12px var(--ok-wash); }
.zero__glyph { color: var(--ok-bright); text-shadow: 0 0 16px var(--ok-line); font-size: 24px; }
.zero__title { color: var(--ok-bright); }

/* ============================================================================
   LIBRARIAN PHASE 1 — the incoming-knowledge section on /knowledge.
   A located capture field (.dropknow) + a read-only holding pen of knowledge-lane
   captures (.qrow--incoming) + a provenance marker (.origin). Specs:
   docs/design/screens/knowledge-queue-section.{spec,craft}.md.
   ============================================================================ */

/* DROP-KNOWLEDGE field — the located capture affordance on /knowledge (P7).
   The one --radius-soft surface (.input) + the one affirmative .btn--primary.
   Full-width input; the DROP button is a fixed thumb target (DL13 >=44px at 390). */
.dropknow { display: flex; gap: var(--s2); align-items: stretch; }
.dropknow .input { flex: 1; min-width: 0; }
@media (max-width: 640px) {
  /* handheld: guarantee the 44px touch floor on BOTH controls (DL13). The desktop
     .input/.btn padding lands ~34-36px; bump to 44 on handheld only. */
  .dropknow .input,
  .dropknow .btn { min-height: 44px; }
  .dropknow .btn { padding-inline: var(--s4); }
}

/* INCOMING (knowledge holding pen): the Inbox queue row, action-stripped.
   id handle + age share one mono meta line under the capture text. The row is
   inert — read-only transparency, never a triage target (spec section 2). */
.qrow--incoming { cursor: default; align-items: flex-start; }
.qrow--incoming:hover { background: transparent; }
.qrow__meta { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
.qrow__meta .idbadge { font-size: var(--fs-micro); }

/* ORIGIN MARKER — provenance for origin=librarian notes (Librarian Phase 1).
   PROVENANCE, NOT STATUS (DL3): ink tiers only — never the system palette
   (green/amber/red/violet = status), never structural cyan (= interaction/focus),
   never an area hue (= lens). A quiet byline fact, sibling to .idbadge. Lowercase
   (provenance prose, not an instrument LABEL); mono micro; no status glyph.
   origin=human is the UNMARKED default — zero instances until Phase 3. */
.origin {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--font-mono);
  font-size: var(--fs-micro);
  letter-spacing: 0.03em;
  color: var(--ink-3);
  white-space: nowrap;
  text-transform: none;
}
.origin::before {
  content: ""; width: 9px; height: 1px; background: var(--ink-faint); flex: none;
}
.origin__who { color: var(--ink-2); }

/* ============================================================================
   NOTE DETAIL (Knowledge) — promoted from screens/note-detail.html (real screen).
   The reading column, note header, the two link panes (editable outbound vs
   computed read-only backlinks), and the collapsible graph pane. proseedit /
   linkrow / kindtag / graph / gnode were promoted earlier.
   ============================================================================ */
.main--reading { max-width: 920px; }
.readcol { display: grid; gap: var(--s5); }
.notehead { display: grid; gap: var(--s3); }
.notehead__title { font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-xl); color: var(--ink-bright); line-height: 1.2; margin: 0; letter-spacing: -0.005em; }
.notehead__meta { gap: var(--s2); }
.linkpanes { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); align-items: start; }
.linkpane__add { justify-self: start; margin-top: var(--s3); }
.linkpane--computed { background: var(--void); box-shadow: inset 0 0 0 1px var(--line-soft); }
.linkpane__note { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); line-height: 1.5; margin: var(--s3) 0 0; }
.linkrow--editable .linkrow__title { flex: 1; }
.linkrow__rm { flex: none; width: 22px; height: 22px; padding: 0; cursor: pointer; margin-left: var(--s2); display: flex; align-items: center; justify-content: center; font-family: var(--font-mono); font-size: 12px; line-height: 1; color: var(--ink-mute); background: transparent; border: 0; box-shadow: inset 0 0 0 1px transparent; clip-path: var(--clip-oct-sm); transition: color var(--fast) var(--ease), box-shadow var(--fast) var(--ease); }
.linkrow--editable:hover .linkrow__rm, .linkrow--editable:focus-within .linkrow__rm { opacity: 1; }
.linkrow__rm:hover { color: var(--accent-bright); box-shadow: inset 0 0 0 1px var(--accent-glow); }
.graphpane__toggle { width: 100%; background: transparent; border: 0; text-align: left; cursor: pointer; margin-bottom: 0; padding-bottom: var(--s2); }
.graphpane__toggle .grouphd__chev { transition: transform var(--fast) var(--ease); }
.graphpane__toggle[aria-expanded="true"] .grouphd__chev { transform: rotate(0deg); }
.graphpane__toggle .grouphd__chev.is-collapsed { transform: rotate(-90deg); }
.graphpane__body { margin-top: var(--s3); }
@media (max-width: 760px) { .linkpanes { grid-template-columns: minmax(0, 1fr); } }

/* ============================================================================
   PEOPLE / PERSON RECORD — promoted from screens/person-record.html (real).
   aggpanes / aggpane / looprow / proseedit / dir-row were promoted earlier.
   ============================================================================ */
.dirlist { display: grid; gap: var(--s2); }
.person__avatar { flex: none; width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; font-size: var(--fs-sm); font-weight: 600; letter-spacing: 0.04em; color: var(--ink-2); background: var(--panel-3); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct-sm); }
.person__name { font-family: var(--font-prose); font-weight: 650; font-size: var(--fs-xl); color: var(--ink-bright); line-height: 1.1; margin: 0; letter-spacing: -0.005em; }
/* inline contact next to the id — compact, replaces the old full-width card */
.person__contact { font-family: var(--font-mono); font-size: var(--fs-micro); letter-spacing: 0.03em; color: var(--ink-3); }
.contactgrid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s4); }
.contactgrid__cell { display: grid; gap: 3px; min-width: 0; }
.contactgrid__val { font-size: var(--fs-sm); color: var(--ink); word-break: break-word; }
.cmd--scoped .cmd__scope { font-family: var(--font-mono); color: var(--accent-dim); white-space: nowrap; flex: none; }
@media (max-width: 640px) { .contactgrid { grid-template-columns: minmax(0, 1fr); gap: var(--s3); } }
/* ============================================================================
   LONG-TAIL (Insights/Tags/Ledger/Settings) — promoted screen-local CSS (D15).
   ============================================================================ */
/* --- insights --- */
  /* The time-range segmented control, the responsive .chartgrid, and the .downgood
     honesty glyph are now PROMOTED into app.css (consumed below as the unified .seg
     primitive + the shared .chartgrid / .downgood — both reviewers asked for the
     promotion). Only the true one-off below stays screen-local. */

  /* — DISTRIBUTION COUNT CLUSTER (true one-off). An anchored ok/nudge/alarm count
       trio above the .bars (DL17 law 2: the number is the truth). glyph+word+color. — */
  .distfig { display: inline-flex; flex-direction: column; gap: 2px; }
  .distfig__num { font-family: var(--font-mono); font-weight: 600; font-size: var(--fs-xl); color: var(--ink-bright); line-height: 1; font-variant-numeric: tabular-nums; }

  /* handheld: the hero range control + window note already wrap (.row.between
     flex-wrap). The chartgrid auto-collapses to one column under 320px min. No
     screen-local handheld rule needed beyond the global header wrap in app.css. */
/* --- tags --- */
/* ── SCREEN-LOCAL: the tag-manager row + its kind grouping. A genuine gap — no
     existing component is a "tag identity row" (usage count + inline rename +
     merge/retire actions). Built from tokens; reuses .tag / .grouphd grammar. ── */
.taggroups { display: grid; gap: var(--s5); }
.taggroup__hd {           /* the kind header — the .grouphd anatomy, area-aware */
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s2) 0; margin-bottom: var(--s1); border-bottom: 1px solid var(--line);
}
.taggroup__kind {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label);
  font-size: var(--fs-label); font-weight: 700; color: var(--ink-2); white-space: nowrap;
}
.taggroup__rule {
  flex: 1; height: 8px; align-self: center; min-width: var(--s5);
  background-image: repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 6px);
  mask-image: linear-gradient(90deg, transparent, #000 30%, transparent 100%); opacity: 0.7;
}
.taggroup__count {
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3);
  letter-spacing: 0.04em; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.taggroup__body { display: grid; gap: var(--s2); }

/* the manager ROW: [tag-chip] [usage bar+count] [row-actions]. Cut in the
   standard octagon; hover lifts the frame (the "act here" affordance). */
.tagrow {
  display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: var(--s3);
  align-items: center; padding: var(--s2) var(--s3);
  background: var(--panel); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct);
  transition: background var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.tagrow:hover { background: var(--panel-2); box-shadow: inset 0 0 0 1px var(--line-strong); }
.tagrow__id { display: flex; align-items: center; gap: var(--s3); min-width: 0; }
/* the usage readout — an anchored MONO number (DL17 law 2) + a tiny range bar
   for shape. The number is the truth; the bar is the context. Not a status. */
.tagusage { display: flex; align-items: center; gap: var(--s2); white-space: nowrap; }
.tagusage__bar { width: 64px; }   /* a .rangebar instance */
.tagusage__n {
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-bright);
  font-variant-numeric: tabular-nums; min-width: 28px; text-align: right;
}
.tagusage__lbl { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); letter-spacing: 0.04em; }
.tagrow__acts { display: flex; gap: var(--s2); flex: none; }
.tagrow__acts .btn { padding: 5px var(--s3); }

/* ── THE RENAME-INLINE AFFORDANCE — the chip becomes an editable well IN PLACE.
     Reuses the .input/.well lineage (the one --radius-soft surface, DL5) + the
     mono voice (a tag id is machine-true). The "applies to N items" line makes
     propagation legible: rename is identity-stable, so it's safe + low-friction
     (no modal). The active row swaps .tag for this. ── */
.renamewell { display: grid; gap: 6px; min-width: 0; flex: 1; }
.renamewell__row { display: flex; align-items: center; gap: var(--s2); }
.renamewell .input { width: auto; min-width: 160px; }
.renamewell__applies {
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3);
  letter-spacing: 0.03em;
}
.renamewell__applies b { color: var(--accent-bright); font-weight: 600; }

/* the ORPHAN/UNUSED group reads quieter — it's a P2-family NUDGE, never an alarm.
   A faint amber edge says "retire?" without nagging. */
.tagrow--orphan { box-shadow: inset 0 0 0 1px var(--nudge-line); background: var(--nudge-wash); }
.tagrow--orphan .tagusage__n { color: var(--nudge-bright); }

/* ── THE MERGE PICKER — a typeahead of VALID targets, each showing usage + the
     "N → M items" preview line. It's the .picker grammar (note-detail) dialed to
     a tag target. Lives inside the merge .modal. ── */
.mergepick { display: grid; gap: var(--s2); }
.mergerow {
  display: grid; grid-template-columns: minmax(0,1fr) auto; gap: var(--s3);
  align-items: center; padding: var(--s2) var(--s3);
  border-bottom: 1px solid var(--line-soft); cursor: pointer;
}
.mergerow:last-child { border-bottom: 0; }
.mergerow:hover { background: var(--panel-2); }
.mergerow.is-picked { background: var(--accent-wash); box-shadow: inset 2px 0 0 var(--accent); }
.mergerow__usage { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.mergerow__preview {
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3);
  letter-spacing: 0.03em; margin-top: 2px;
}
.mergerow.is-picked .mergerow__preview { color: var(--accent-bright); }
.mergerow__preview .arr { color: var(--ink-3); padding: 0 4px; }

/* let the main grid track shrink below content min-content in the 641–760px
   squeeze band (the locked .app rule is 232px 1fr until 640px), and let the
   inline rename row wrap its controls so its fixed-min input never forces the
   column wider than the viewport while the rail is still present. */
@media (max-width: 760px) {
  /* (the squeeze-band fix `.main{min-width:0}` is now GLOBAL in app.css's 760
     block — no longer duplicated per-screen.) */
  .renamewell__row { flex-wrap: wrap; }
  .renamewell .input { min-width: 0; flex: 1; }
}
@media (max-width: 640px) {
  .tagrow { grid-template-columns: minmax(0,1fr); row-gap: var(--s2); }
  .tagrow__acts { flex-wrap: wrap; }
  .tagrow__acts .btn { flex: 1; min-height: 44px; }
  .renamewell .input { min-width: 0; flex: 1; }
}
/* --- ledger --- */
  /* — FILTER BAR (gap #1). Recessed like the .cmd query line; groups laid out in
       a wrapping row so it holds from desktop to 390px. Filtering never mutates. — */
  .lfilter {
    display: flex; align-items: center; gap: var(--s4); flex-wrap: wrap;
    background: var(--well); padding: var(--s3) var(--s4);
    box-shadow: inset 0 0 0 1px var(--line-strong);
    clip-path: var(--clip-oct);
  }
  .lfilter__group { display: flex; align-items: center; gap: var(--s2); min-width: 0; }
  .lfilter__group--grow { flex: 1 1 200px; }
  .lfilter__group--grow .input { width: 100%; }
  /* the date-range input sized to its content so the full "from → to" never clips */
  .lfilter__range { width: 26ch; flex: none; }
  .lfilter__clear { margin-left: auto; padding: var(--s2) var(--s3); }
  /* a "selected kind" tag-chip — the accent wash marks an active filter (cyan =
     interactive selection, never a status; DL3). */
  .tag.is-on { color: var(--accent-bright); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-glow); }
  .tag.is-on.tag--kind { color: var(--accent-bright); }

  /* The op segmented control, the full-surface ledger row + before→after diff
     grammar, and the honest .lpage pagination footer are now PROMOTED into
     app.css's LEDGER section (both reviewers asked: any audit/version view reuses
     the before→after diff; .lpage is reusable on any large list). The op-color-on-
     lit lives there as the .seg__opt--insert/update/delete modifier. Only the
     surface-specific compositions (.lfilter, .tombview, .lskel) stay screen-local. */

  /* — TOMBSTONE-RESOLVED VIEW (gap #4). A read-only record of a deleted item —
       framed as deleted (alarm hairline + ⊟), its last state preserved and dimmed.
       NO restore/edit on the body: the record is permanent, proving delete ≠ erase. — */
  .tombview {
    background: var(--well); box-shadow: inset 0 0 0 1px var(--alarm-line);
    clip-path: var(--clip-oct); padding: var(--s5); display: grid; gap: var(--s3);
  }
  .tombview__head { display: flex; align-items: baseline; gap: var(--s3); flex-wrap: wrap; }
  .tombview__op {
    font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.12em;
    font-weight: 800; color: var(--alarm-bright);
  }
  .tombview__when { font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3); }
  .tombview__title { font-family: var(--font-mono); font-size: var(--fs-lg); color: var(--ink-2); }
  .tombview__body {
    display: grid; gap: var(--s2); padding: var(--s3) var(--s4);
    background: var(--bg); box-shadow: inset 0 0 0 1px var(--line); clip-path: var(--clip-oct-sm);
  }
  .tombview__field { display: grid; grid-template-columns: 92px 1fr; gap: var(--s3); font-family: var(--font-mono); font-size: var(--fs-sm); }
  .tombview__k { color: var(--ink-3); text-transform: uppercase; letter-spacing: 0.06em; font-size: var(--fs-micro); align-self: center; }
  .tombview__v { color: var(--ink-faint); }   /* a record of what WAS — dimmed, not live */
  .tombview__note {
    font-family: var(--font-prose); font-size: var(--fs-sm); color: var(--ink-3);
    line-height: 1.55; max-width: 64ch;
  }

  /* — LOADING skeleton ledger row layout (matches .ledger__row's 3-col grid) — */
  .lskel { display: grid; grid-template-columns: 118px 70px 1fr; gap: var(--s3); align-items: center; }

  /* — HANDHELD (390px) — only the .lfilter-local tweak stays here; the full-ledger
       row shrink, the per-field diff grouping, and the .lpage touch floor are now
       in app.css (promoted with their components). — */
  @media (max-width: 640px) {
    .lfilter__clear { margin-left: 0; }
  }
/* --- settings --- */
/* ── SCREEN-LOCAL: the SECTION CARD with a header status chip. The .panel/.phead
     anatomy + a chip slot in the header (a genuine gap — no existing "config
     section" component). Built from tokens; reuses .chip for the status. ── */
.seccard { display: grid; gap: var(--s4); }
.seccard__hd { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.seccard__num {
  font-family: var(--font-mono); font-size: var(--fs-micro); color: var(--ink-3);
  letter-spacing: 0.08em; white-space: nowrap;
}
.seccard__chip { margin-left: auto; }
.secrow {           /* a label : control line inside a card */
  display: grid; grid-template-columns: 150px 1fr; gap: var(--s4); align-items: center;
}
.secrow__lbl { font-family: var(--font-label); text-transform: uppercase; letter-spacing: var(--ls-label); font-size: var(--fs-label); color: var(--ink-2); }
.secrow__val { font-family: var(--font-mono); font-size: var(--fs-base); color: var(--ink); display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.secrow__note { font-family: var(--font-prose); font-size: var(--fs-sm); color: var(--ink-3); line-height: 1.5; }
.secrow__note b { color: var(--ink-2); }

/* ── THE DAY-START PICKER — the day-start hour is an exclusive choice rendered as
     ONE octagon group, exactly one cell lit. It consumes the unified .seg
     segmented-control primitive in app.css (DL5 — was the near-duplicate .dialset;
     now base .seg + the --mono voice + --pad5 to preserve its exact metrics). ── */

/* ── THE TOKEN ROW — label · scope-badge · masked secret · [show][rotate][revoke].
     The scope-badge VISIBLY distinguishes input-only Shortcuts vs full AI (the
     D11 boundary made legible). The secret is MONO (machine-true) + masked. ── */
.tokenrow {
  display: grid; grid-template-columns: 1fr auto; gap: var(--s3);
  align-items: center; padding: var(--s3) var(--s4);
  background: var(--well); box-shadow: inset 0 0 0 1px var(--line);
  clip-path: var(--clip-oct);
}
.tokenrow__main { display: grid; gap: 5px; min-width: 0; }
.tokenrow__top { display: flex; align-items: center; gap: var(--s3); flex-wrap: wrap; }
.tokenrow__label { font-family: var(--font-prose); font-weight: 600; font-size: var(--fs-md); color: var(--ink-bright); }
/* the SCOPE badge — the D11 security boundary. INPUT-ONLY is the calm cyan
   input-only badge (a narrow capability). AI-ONLY must read as a BROADER, HEAVIER
   scope — but NOT by borrowing a status hue: --defer violet means "parked /
   out-of-working-set" (P16), the OPPOSITE of an AI token's broad live reach, so
   reusing it overloaded a color (DL3: a color means ONE thing). Instead the wider
   scope is carried by INK-TIER WEIGHT — bright ink on a raised --panel-3 fill with
   a --line-strong frame — so it reads visibly heavier than the calm cyan badge
   with no second status meaning. Glyph+word, the mark is a non-status pointer. */
.scopebadge {
  font-family: var(--font-label); text-transform: uppercase; letter-spacing: 0.1em;
  font-size: var(--fs-micro); font-weight: 700; line-height: 1;
  padding: var(--s1) var(--s2) 3px; white-space: nowrap;
  clip-path: var(--clip-oct-sm); display: inline-flex; align-items: center; gap: 5px;
}
.scopebadge--input { color: var(--accent-bright); background: var(--accent-wash); box-shadow: inset 0 0 0 1px var(--accent-glow); }
.scopebadge--ai    { color: var(--ink-bright); background: var(--panel-3); box-shadow: inset 0 0 0 1px var(--line-strong); font-weight: 800; }
.tokenrow__secret {
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-2);
  letter-spacing: 0.06em; word-break: break-all;
}
.tokenrow__scopenote { font-family: var(--font-prose); font-size: var(--fs-micro); color: var(--ink-3); line-height: 1.5; }
.tokenrow__acts { display: flex; gap: var(--s2); flex: none; align-items: center; }
.tokenrow__acts .btn { padding: 5px var(--s3); }

/* the field:value power-tool pointer (the ONLY power surface offered — NOT SQL) */
.powertool {
  display: flex; align-items: center; gap: var(--s3);
  padding: var(--s3) var(--s4); background: var(--well);
  box-shadow: inset 0 0 0 1px var(--line-strong); clip-path: var(--clip-oct);
  font-family: var(--font-mono); font-size: var(--fs-sm); color: var(--ink-2);
}
.powertool__sigil { color: var(--accent); font-weight: 700; }

/* 641–760px is the squeeze band: the 232px rail is still present (DL13: ≥760 =
   full instrument), so the main column is narrow. Collapse the two-col rows to a
   single column here (not only at handheld) so a long mono secret/sub never
   forces the page wider than the viewport. */
@media (max-width: 760px) {
  /* (the squeeze-band fix `.main{min-width:0}` is now GLOBAL in app.css's 760
     block — no longer duplicated per-screen.) */
  .secrow { grid-template-columns: minmax(0,1fr); row-gap: var(--s2); }
  .tokenrow { grid-template-columns: minmax(0,1fr); row-gap: var(--s3); }
  .tokenrow__acts { flex-wrap: wrap; }
  .powertool { flex-wrap: wrap; }
  .seg { flex-wrap: wrap; }   /* the day-start seg may wrap its cells in the squeeze band */
  /* an alertbar carrying a trailing remedy button (backups / gcal) must wrap it
     in the squeeze band so the button never forces the column wider than the
     viewport (the rail is still present until 640px). */
  .alertbar { flex-wrap: wrap; }
  .alertbar .btn { flex: 1; }
}
@media (max-width: 640px) {
  .tokenrow__acts .btn { flex: 1; min-height: 44px; }
}

/* Closeout fixes (D15 review): handheld touch floor for the sacred Capture
   action (DL13 ≥44px), and make the ledger message column flex so the Person
   interaction log keeps a comfortable measure (DL6). */
@media (max-width: 640px) {
  .rail__capture { min-height: 44px; }
}
.ledger__row { align-items: baseline; }
.ledger__msg { flex: 1; min-width: 0; }
