/* Tabellion control-tower styles — the ratified 1b "Rubric Ledger" design system
   (ADR DS-001), translated 1:1 from the design token layer into a single served
   stylesheet. Order: @font-face · color tokens (light :root + dark override) ·
   type · spacing · shape/motion · base element rules · component classes.
   Light = "reading room" (default) · dark = "lamplight" ([data-theme="dark"]). */

/* ============================================================ fonts
   Self-hosted, Latin+Cyrillic (OFL). Ratified pair: Literata (variable 300–800,
   opsz) + PT Mono. URLs are relative to this stylesheet at /static/app.css. */
/* cyrillic-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/literata-300-800-cyrillic-ext.woff2") format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/literata-300-800-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* latin-ext */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/literata-300-800-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Literata';
  font-style: normal;
  font-weight: 300 800;
  font-display: swap;
  src: url("fonts/literata-300-800-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* cyrillic-ext */
@font-face {
  font-family: 'PT Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/pt-mono-400-cyrillic-ext.woff2") format("woff2");
  unicode-range: U+0460-052F, U+1C80-1C8A, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
}
/* cyrillic */
@font-face {
  font-family: 'PT Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/pt-mono-400-cyrillic.woff2") format("woff2");
  unicode-range: U+0301, U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
}
/* latin-ext */
@font-face {
  font-family: 'PT Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/pt-mono-400-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'PT Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("fonts/pt-mono-400-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============================================================ color tokens
   Semantic aliases chain to base scales; dark swaps BASE values only. */
:root{
/* base — paper & ink */
--paper-0:#F3F0E7; /* substrate */
--paper-1:#FBF9F2; /* page */
--paper-2:#FDFCF7; /* well: diff blocks, inputs */
--ink-1:#211D14;
--ink-2:#4A443A;
--ink-3:#6B6353;
--line-1:#D9D2C0; /* structural hairline */
--line-2:#E6E0CF; /* minor hairline */
/* base — rubric (madder): attention AND error, separated by glyph + fill */
--rubric:#9C3A21;
--rubric-deep:#7C2B16;
--rubric-wash:#F3E4DB;
/* base — semantic */
--moss:#4A6B50;  --moss-wash:#E9EEE5;
--ochre:#8F6413; --ochre-wash:#F2EAD4;
--scrim:rgba(33,29,20,.45);
/* semantic aliases (use these in components) */
--surface-app:var(--paper-0);
--surface-page:var(--paper-1);
--surface-well:var(--paper-2);
--text-body:var(--ink-1);
--text-secondary:var(--ink-2);
--text-muted:var(--ink-3);
--rule-strong:var(--line-1);
--rule-soft:var(--line-2);
--attention:var(--rubric);           /* "the human's pen is needed" */
--attention-strong:var(--rubric-deep);
--attention-wash:var(--rubric-wash);
--status-ok:var(--moss);       --status-ok-wash:var(--moss-wash);
--status-warn:var(--ochre);    --status-warn-wash:var(--ochre-wash);
--status-crit:var(--rubric);   --status-crit-wash:var(--rubric-wash); /* crit = filled chip + ✕ glyph */
--action-ink:var(--ink-1);           /* solid-ink actions */
--on-action-ink:var(--paper-1);
--focus:var(--ink-1);
--just-changed:var(--attention-wash);
}
[data-theme="dark"]{
--paper-0:#171310;
--paper-1:#1E1913;
--paper-2:#262017;
--ink-1:#EAE3D0;
--ink-2:#C7BCA6;
--ink-3:#9C927B;
--line-1:#3A3325;
--line-2:#2E2820;
--rubric:#CE6A44;
--rubric-deep:#E08B66;
--rubric-wash:#3A2416;
--moss:#82AB8B;  --moss-wash:#243020;
--ochre:#C09A45; --ochre-wash:#332B14;
--scrim:rgba(8,6,3,.62);
}

/* ============================================================ type
   Serif carries content and actions; mono carries the record. */
:root{
--font-serif:"Literata",Georgia,"Times New Roman",serif;
--font-mono:"PT Mono","Courier New",monospace;
/* scale (px) */
--text-2xs:10px;  /* marginalia, chips */
--text-xs:11px;   /* mono record lines */
--text-sm:12px;   /* dense serif, table cells */
--text-md:13.5px; /* body */
--text-lg:16px;   /* entry titles */
--text-xl:21px;   /* section heads */
--text-2xl:28px;  /* page display */
--text-3xl:38px;  /* screen display */
--text-4xl:52px;  /* hero numerals, wordmark */
/* leading */
--leading-tight:1.1;
--leading-snug:1.35;
--leading-body:1.55;
--leading-record:1.75; /* mono marginalia stacks */
/* weight (Literata variable axis) */
--w-body:400;
--w-medium:500;
--w-display:640;
--w-black:800;
/* optical size: displays cut at opsz 60, text at auto */
--opsz-display:"opsz" 60;
/* tracking */
--tracking-caps:.14em;
--tracking-display:-.005em;
--measure:62ch;
}

/* ============================================================ spacing
   A line-rhythm system: multiples of 4, generous at entry level. */
:root{
--sp-1:4px;
--sp-2:8px;
--sp-3:12px;
--sp-4:16px;
--sp-5:24px;
--sp-6:32px;
--sp-7:48px;
--sp-8:64px;
--rail-w:140px;      /* the marginalia rail */
--rail-w-narrow:96px;
--page-pad:var(--sp-5);
}

/* ============================================================ shape + motion
   Shape law: 0 radius, structure from rules, never shadows.
   Motion law: nothing moves for its own sake; change settles like ink. */
:root{
--radius:0;
--rule-w:1px;
--rule-w-heavy:1.5px;
--rubric-bar:3px;          /* inset left bar marking attention */
--ease-settle:cubic-bezier(.2,.7,.2,1);
--dur-1:120ms;
--dur-2:200ms;
--dur-3:320ms;
--dur-wash:900ms;
}

/* ============================================================ base element rules */
*,*::before,*::after{box-sizing:border-box}
body{margin:0;background:var(--surface-app);color:var(--text-body);font-family:var(--font-serif);font-size:var(--text-md);font-weight:var(--w-body);line-height:var(--leading-body);-webkit-font-smoothing:antialiased}
a{color:var(--text-body);text-decoration:underline;text-decoration-color:var(--attention);text-decoration-thickness:1px;text-underline-offset:3px;transition:color var(--dur-1) var(--ease-settle)}
a:hover{color:var(--attention)}
:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:0}
::selection{background:var(--attention-wash)}
hr{border:0;border-top:var(--rule-w) solid var(--rule-strong);margin:var(--sp-5) 0}
code,kbd,samp{font-family:var(--font-mono);font-size:.92em}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}

/* ============================================================ component classes
   The templ-facing contract. Semantic HTML + these classes + tokens.
   Status is always glyph + color (✓ ▲ ✕ ◌ ●); unbacked values render — or a pending chip. */

/* --- text roles --- */
.kicker{font:500 var(--text-2xs)/1 var(--font-mono);letter-spacing:var(--tracking-caps);text-transform:uppercase;color:var(--text-muted)}
.display{font-weight:var(--w-display);font-variation-settings:var(--opsz-display);letter-spacing:var(--tracking-display);line-height:var(--leading-tight)}
.record{font-family:var(--font-mono);font-size:var(--text-xs);line-height:var(--leading-record)}
.pending-value{color:var(--text-muted)}

/* --- actions: ink acts --- */
.btn{display:inline-block;font-family:var(--font-serif);font-size:var(--text-sm);font-weight:var(--w-display);background:var(--action-ink);color:var(--on-action-ink);border:var(--rule-w) solid var(--action-ink);border-radius:var(--radius);padding:7px 18px;cursor:pointer;transition:background var(--dur-1) var(--ease-settle),color var(--dur-1) var(--ease-settle)}
.btn:hover{background:var(--ink-2);border-color:var(--ink-2)}
.btn:active{transform:translateY(1px)}
.btn[disabled],.btn.is-inflight{opacity:.5;pointer-events:none}
.btn--quiet{background:transparent;color:var(--text-body);border-color:var(--rule-strong)}
.btn--quiet:hover{background:transparent;color:var(--text-body);border-color:var(--ink-1)}
.link-action{display:inline;background:none;border:none;padding:0;font-family:var(--font-serif);font-size:var(--text-sm);color:var(--text-body);text-decoration:underline;text-decoration-color:var(--attention);text-decoration-thickness:1px;text-underline-offset:3px;cursor:pointer}
.link-action:hover{color:var(--attention)}

/* --- status vocabulary: chips carry glyph + word --- */
.chip{display:inline-block;font-family:var(--font-mono);font-size:var(--text-2xs);line-height:1;padding:3px 8px;border:var(--rule-w) solid currentColor;border-radius:var(--radius);white-space:nowrap;vertical-align:1px}
.chip--ok{color:var(--status-ok)}
.chip--warn{color:var(--status-warn)}
.chip--pending{color:var(--attention)}
.chip--crit{color:var(--on-action-ink);background:var(--status-crit);border-color:var(--status-crit)}
.chip--neutral{color:var(--text-muted)}
.badge{display:inline-block;font-family:var(--font-mono);font-size:var(--text-2xs);line-height:1;padding:3px 6px;background:var(--attention);color:var(--paper-1);border-radius:var(--radius)}

/* --- forms --- */
.field{display:block;margin-bottom:var(--sp-4)}
.field__label{display:block;font:500 var(--text-2xs)/1 var(--font-mono);letter-spacing:var(--tracking-caps);text-transform:uppercase;color:var(--text-secondary);margin-bottom:var(--sp-2)}
.field__help{font-size:var(--text-sm);color:var(--text-muted);margin-top:var(--sp-1);font-style:italic}
.field__error{font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--attention);margin-top:var(--sp-1)}
.input,.select select,.textarea{width:100%;font-family:var(--font-serif);font-size:var(--text-md);color:var(--text-body);background:var(--surface-well);border:var(--rule-w) solid var(--rule-strong);border-radius:var(--radius);padding:8px 10px;transition:border-color var(--dur-1) var(--ease-settle)}
.input:hover,.select select:hover{border-color:var(--ink-3)}
.input:focus-visible,.select select:focus-visible{border-color:var(--ink-1);outline-offset:0}
.input::placeholder{color:var(--text-muted);font-style:italic}
.input[aria-invalid="true"]{border-color:var(--attention);box-shadow:inset var(--rubric-bar) 0 0 var(--attention)}
.input--mono{font-family:var(--font-mono);font-size:var(--text-sm)}
.select{position:relative;display:block}
.select select{appearance:none;padding-right:var(--sp-6);cursor:pointer}
.select::after{content:"⌄";position:absolute;right:10px;top:50%;transform:translateY(-58%);pointer-events:none;color:var(--text-secondary)}
.choice{display:grid;grid-template-columns:auto 1fr;gap:var(--sp-3);align-items:baseline;border:var(--rule-w) solid var(--rule-strong);padding:var(--sp-3) var(--sp-4);cursor:pointer;transition:border-color var(--dur-1) var(--ease-settle)}
.choice+.choice{margin-top:var(--sp-2)}
.choice:hover{border-color:var(--ink-3)}
.choice__mark{font-family:var(--font-mono);font-size:var(--text-sm);color:var(--text-muted)}
.choice.is-checked{border-color:var(--ink-1);box-shadow:inset var(--rubric-bar) 0 0 var(--attention)}
.choice.is-checked .choice__mark{color:var(--attention)}
.choice__title{display:block;font-size:var(--text-md);font-weight:var(--w-medium)}
.choice__desc{display:block;font-size:var(--text-sm);color:var(--text-muted);margin-top:2px}
.choice input{position:absolute;opacity:0;pointer-events:none}

/* --- the record: entries, feed rows, tables --- */
.entry{display:grid;grid-template-columns:var(--rail-w) 1fr;border-bottom:var(--rule-w) solid var(--rule-soft)}
.entry__rail{padding:var(--sp-3) var(--sp-2) var(--sp-3) var(--sp-4);border-right:var(--rule-w) solid var(--rule-strong);font-family:var(--font-mono);font-size:var(--text-2xs);line-height:var(--leading-record);color:var(--text-muted)}
.entry__rail b{color:var(--text-body);font-weight:400}
.entry__body{padding:var(--sp-3) var(--sp-4) var(--sp-4)}
.entry--attention{box-shadow:inset var(--rubric-bar) 0 0 var(--attention)}
.entry__path{font-family:var(--font-mono);font-size:var(--text-xs);margin:0 0 var(--sp-1)}
.entry__quote{font-size:var(--text-sm);font-style:italic;color:var(--ink-2);margin:0 0 var(--sp-3)}
.feed-row{display:grid;grid-template-columns:var(--rail-w) 1fr;border-bottom:var(--rule-w) solid var(--rule-soft);font-size:var(--text-sm)}
.feed-row .entry__rail{padding-top:var(--sp-2);padding-bottom:var(--sp-2)}
.feed-row__body{padding:var(--sp-2) var(--sp-4);line-height:var(--leading-body)}
.ledger-head{display:flex;flex-wrap:wrap;gap:var(--sp-1) var(--sp-4);justify-content:space-between;align-items:baseline;padding:var(--sp-3) var(--sp-4);border-bottom:var(--rule-w) solid var(--rule-strong)}
.ledger-head h2,.ledger-head h3{font-size:var(--text-lg);font-weight:var(--w-display);font-variation-settings:var(--opsz-display);margin:0}
.ledger-head .record{color:var(--text-muted)}
.page{background:var(--surface-page);border:var(--rule-w) solid var(--rule-strong)}
/* A wide ledger scrolls inside its own region rather than scrolling the page (shift 85b). The
   agents key ledger is seven columns and cannot fit a 390px viewport at any breaking rule; with
   the masthead's overflow fixed it was the last thing making a tower page scroll sideways
   (MEASURED 538px at 390 once the e2e run has minted its keys). `auto`, not `hidden`: every cell
   stays reachable. The region is named and takes a tab stop in the markup, so a keyboard can
   reach it; at desktop width it never scrolls and shows nothing. */
.ledger-scroll{overflow-x:auto}
.ledger-scroll:focus-visible{outline:var(--rule-w-heavy) solid var(--focus);outline-offset:2px}
.ledger-table{width:100%;border-collapse:collapse}
.ledger-table th{font:500 var(--text-2xs)/1 var(--font-mono);letter-spacing:var(--tracking-caps);text-transform:uppercase;text-align:left;color:var(--text-muted);padding:var(--sp-2) var(--sp-4);border-bottom:var(--rule-w) solid var(--rule-strong)}
.ledger-table td{font-size:var(--text-sm);padding:var(--sp-2) var(--sp-4);border-bottom:var(--rule-w) solid var(--rule-soft);vertical-align:baseline}
/* Mono cells carry machine values — absolute paths, URLs, key ids, shas — which have no space to
   break at, so a table row's minimum width is the longest of them. With the masthead's 657px
   overflow gone (H-084, shift 85b) that was the next thing to scroll the setup page sideways at
   phone width: MEASURED 482px at a 390px viewport, from one `td.mono` holding the vault path.
   Breaking inside such a value keeps it reachable; the alternative hides it off-screen.
   It is `anywhere` and not `break-word`, MEASURED on this box at a 390px viewport against the real
   page: `anywhere` takes the break opportunity into the column's MINIMUM width (cell 277px → 160px,
   page 482px → 390px) while `break-word` does not (page stays 482px) — they differ only in
   intrinsic sizing, which is the whole of what a table column is laid out from. At 1280px the cell
   is the same 750px under every one of them: a break happens only when there is nothing left to
   give. */
.ledger-table td.num,.ledger-table td.mono{font-family:var(--font-mono);font-size:var(--text-xs)}
.ledger-table td.mono{overflow-wrap:anywhere}
/* …but not inside a scroll region, where the column can keep its natural width because the
   region scrolls instead of the page. MEASURED at 390px on the agents ledger: breaking stacks a
   key id down a five-glyph column (region 505px wide), while not breaking keeps
   `akey_80dc18baef5ca421` on one line and scrolls (634px). A machine value reads better whole. */
.ledger-scroll .ledger-table td.mono{overflow-wrap:normal}
.ledger-table td.num{text-align:right}
.ledger-table tr:hover td{background:var(--surface-well)}

/* --- diff: the hero --- */
.diff{border:var(--rule-w) solid var(--rule-soft);background:var(--surface-well);font-family:var(--font-mono);font-size:var(--text-xs);line-height:1.7}
.diff__line{display:grid;grid-template-columns:44px 1fr;padding:3px 10px 3px 0}
.diff__gutter{text-align:right;padding-right:10px;color:var(--attention);font-weight:700}
.diff__del{color:var(--text-muted);text-decoration:line-through;text-decoration-color:var(--attention);text-decoration-thickness:1.5px}
.diff__ins{background:var(--attention-wash)}
.diff__ctx{color:var(--text-secondary)}
.diff__meta{display:flex;justify-content:space-between;padding:var(--sp-1) var(--sp-3);border-bottom:var(--rule-w) solid var(--rule-soft);color:var(--text-muted);font-size:var(--text-2xs)}

/* --- overlay: modal, drawer, toast --- */
.scrim{position:fixed;inset:0;background:var(--scrim);z-index:40}
.modal{position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:41;width:min(560px,calc(100vw - var(--sp-6)));background:var(--surface-page);border:var(--rule-w) solid var(--ink-1)}
.modal__head{display:flex;justify-content:space-between;align-items:baseline;padding:var(--sp-4);border-bottom:var(--rule-w) solid var(--rule-strong)}
.modal__head h2{font-size:var(--text-lg);font-weight:var(--w-display);font-variation-settings:var(--opsz-display);margin:0}
.modal__body{padding:var(--sp-4)}
.modal__foot{display:flex;gap:var(--sp-4);align-items:center;padding:var(--sp-4);border-top:var(--rule-w) solid var(--rule-strong)}
.drawer{position:fixed;top:0;right:0;bottom:0;z-index:41;width:min(420px,90vw);background:var(--surface-page);border-left:var(--rule-w) solid var(--ink-1);overflow:auto}
.toast-region{position:fixed;bottom:var(--sp-5);left:50%;transform:translateX(-50%);z-index:50;display:grid;gap:var(--sp-2);justify-items:center}
.toast{font-family:var(--font-mono);font-size:var(--text-xs);background:var(--ink-1);color:var(--paper-1);padding:var(--sp-2) var(--sp-4);border-radius:var(--radius)}
[data-theme="dark"] .toast{background:var(--paper-2);color:var(--ink-1);border:var(--rule-w) solid var(--line-1)}
.toast__dismiss{color:inherit;text-decoration-color:currentColor;margin-left:var(--sp-3)}
.link-action[disabled],.link-action.is-inflight{opacity:.5;pointer-events:none}

/* --- shell: masthead + tabs --- */
/* The masthead WRAPS BY CONTENT, not at a pixel breakpoint (H-084, shift 85b). Before this rule
   the header was a nowrap flex row whose minimum content width was 657px, so every tower page
   scrolled sideways at phone width while nothing in <main> exceeded the viewport. A width-keyed
   media query would have to be re-measured every time the header grows — a longer vault label, a
   sixth nav tab, a status chip — and would silently stop firing between its breakpoint and the new
   minimum. Wrapping keys on the content itself, so it cannot go stale. row-gap is deliberately
   tighter than column-gap: a wrapped header should still read as a header, not as a stack. */
.masthead{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-2) var(--sp-5);padding:var(--sp-3) var(--page-pad);background:var(--surface-page);border-bottom:var(--rule-w-heavy) solid var(--ink-1)}
.wordmark{font-family:var(--font-serif);font-weight:var(--w-black);font-variation-settings:var(--opsz-display);font-size:var(--text-lg);letter-spacing:-.01em}
.wordmark::after{content:".";color:var(--attention)}
/* The tab strip wraps inside itself too, so the nav never becomes the one item that cannot fit
   the line it is on (302px of tabs today; shift 86b adds a sixth). */
.masthead__nav{display:flex;flex-wrap:wrap;gap:var(--sp-2) var(--sp-4)}
.tab{font-size:var(--text-sm);color:var(--text-secondary);text-decoration:none;padding:var(--sp-1) 0}
.tab:hover{color:var(--text-body)}
.tab[aria-current="page"]{color:var(--text-body);font-weight:var(--w-display);box-shadow:inset 0 -2px 0 var(--attention)}
.tab[aria-disabled="true"]{color:var(--text-muted);cursor:not-allowed;pointer-events:none}
.masthead__meta{font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--text-muted)}
/* The tail — vault meta, theme toggle, Sign out — is ONE flex item, so a wrapping header moves
   the whole group to the next row instead of stranding Sign out alone on a row of its own
   (measured: it did, between 660 and 760px). `margin-left:auto` moved here from .masthead__meta,
   which is why the desktop header is pixel-identical to the pre-85b one; the column gap repeats
   the masthead's own so the three items keep the spacing they had as direct children. */
.masthead__tail{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-2) var(--sp-5);margin-left:auto;max-width:400px;min-width:0}
/* The semantic-search health chip (H-112, shift 87) takes its OWN line inside the tail, and the
   two rules above it are what make that free. max-width caps what the tail contributes to the
   header's max-content width, so the chip's reason no longer decides where the header wraps;
   min-width:0 lets the tail shrink below that cap on a narrow line, without which a long dlopen
   reason pushed the page 74px past a 390px viewport (measured, both halves). Re-derive the
   threshold rather than trusting these figures: web/e2e/tests/layout.spec.ts bisects for it and
   prints it when it fails. At this landing it was 847px before the chip, 934 with it, against
   that spec's 1000px ceiling; on the header's own row the same chip wanted 1109-1217px, which is
   why it is not there. The reason clips with an ellipsis and the whole line rides the title. */
.masthead__semantic{flex:0 1 100%;display:flex;justify-content:flex-end;align-items:baseline;gap:var(--sp-2);min-width:0}
.masthead__why{font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}

/* --- empty / pending / error states --- */
.state{padding:var(--sp-7) var(--sp-5);text-align:center}
.state__glyph{font-family:var(--font-mono);font-size:var(--text-2xl);color:var(--text-muted);display:block;margin-bottom:var(--sp-3)}
.state__title{font-size:var(--text-lg);font-weight:var(--w-display);font-variation-settings:var(--opsz-display);margin:0 0 var(--sp-1)}
.state__hint{font-size:var(--text-sm);color:var(--text-muted);font-style:italic;margin:0}
.state--error .state__glyph{color:var(--attention)}
.state--ok .state__glyph{color:var(--status-ok)}

/* --- SSE morph states --- */
.is-inflight{opacity:.55;pointer-events:none;cursor:progress}
.just-changed{animation:eng-wash var(--dur-wash) var(--ease-settle)}
@keyframes eng-wash{from{background-color:var(--just-changed)}to{background-color:transparent}}
.busy-line{display:inline-block;font-family:var(--font-mono);font-size:var(--text-2xs);color:var(--text-muted)}
.busy-line::after{content:"◌";color:var(--attention);margin-left:6px;animation:eng-breathe 1.6s var(--ease-settle) infinite}
@keyframes eng-breathe{0%,100%{opacity:.35}50%{opacity:1}}

/* --- control-tower layout (promoted from the design kit's inline styles;
   no inline-style soup — these carry the values the kit set inline) --- */
.tower-main{max-width:980px;margin:0 auto;padding:var(--sp-6) var(--sp-5) var(--sp-8)}
.daybook__value{font-variant-numeric:tabular-nums}
.daybook__value--unread{color:var(--status-warn);border-bottom:1px dotted currentColor}
.daybook{color:var(--text-muted);margin:0 0 var(--sp-2)}
.tower-foot{color:var(--text-muted);margin:var(--sp-5) 0 0}
.attention{color:var(--attention)}
.page + .page{margin-top:var(--sp-5)}
.entry__actions{display:flex;gap:var(--sp-4);align-items:center;flex-wrap:wrap;margin-top:var(--sp-2)}
.theme-toggle{margin-left:var(--sp-4)}
.masthead__out{margin-left:var(--sp-3)}
.login{max-width:420px;margin:var(--sp-7) auto var(--sp-5);padding:0 var(--page-pad)}
.login__card{padding:var(--sp-5)}
.login__form{margin-top:var(--sp-4)}

/* --- onboarding (E1-f): the day-book notice + the setup page --- */
.notice{display:flex;gap:var(--sp-3);align-items:baseline;padding:var(--sp-3) var(--sp-4);margin:0 0 var(--sp-5);background:var(--surface-page);border:var(--rule-w) solid var(--rule-strong);font-size:var(--text-sm)}
.notice--attention{box-shadow:inset var(--rubric-bar) 0 0 var(--attention)}
.notice__glyph{font-family:var(--font-mono);color:var(--attention)}
.notice__body{margin:0}
.setup__title{font-size:var(--text-2xl);margin:var(--sp-1) 0 var(--sp-3)}
.setup__lede{max-width:var(--measure);color:var(--text-secondary);margin:0 0 var(--sp-5)}
.setup__facts th{width:var(--rail-w);white-space:nowrap}
.setup__facts td.num{text-align:left}
.setup__action{display:grid;gap:var(--sp-2);justify-items:start;padding:var(--sp-4)}
.setup__action .field__help{margin:0;max-width:var(--measure)}
.setup__outcome{margin:0;min-height:1.75em}
.setup__outcome--ok{color:var(--status-ok)}
.setup__outcome--error{color:var(--attention)}

/* --- first-run wizard (E1-n shift 40). Only what the existing component classes do not carry:
   the step panel's body padding, the two-control action row, the choice group's top gap, the
   advanced sub-section's rule, and the focus ring the .choice radio-card has always needed and
   never had — its <input> is opacity:0, so :focus-visible on the input alone is invisible and the
   card would be keyboard-reachable with nothing on screen to say so. Everything else on this
   surface (.page, .ledger-head, .ledger-table, .choice, .field, .input, .btn, .state, .chip)
   was already here and unrendered. --- */
.wizard-main{max-width:760px;margin:0 auto;padding:var(--sp-7) var(--page-pad) var(--sp-8)}
.wizard__body{padding:var(--sp-4)}
.wizard__value{font-family:var(--font-mono);font-size:var(--text-sm);margin:0;overflow-wrap:anywhere}
.wizard__choices{border:0;margin:var(--sp-4) 0 0;padding:0;min-inline-size:0}
.wizard__choices legend{padding:0;margin-bottom:var(--sp-2)}
.wizard__actions{display:flex;gap:var(--sp-4);align-items:center;flex-wrap:wrap;margin-top:var(--sp-4)}
.wizard__form{margin:0}
.wizard__advanced{border-left:var(--rule-w) solid var(--rule-soft);padding-left:var(--sp-4);margin:0 0 var(--sp-4)}
.wizard__advanced .field__help{margin:0 0 var(--sp-3);font-style:normal}
.wizard__prose{max-width:var(--measure);margin:0}
.wizard__body .field:last-of-type{margin-bottom:0}
.choice:has(input:focus-visible){outline:2px solid var(--focus);outline-offset:2px}

/* --- agents: keys and sessions (U1c + U4, shift 54). Only what the existing component classes
   do not already carry: the page's title/lede rhythm (the setup page's, on this page's own stem
   rather than borrowing a foreign one), the mint form's body padding, the one-time reveal's
   emphasis, and the outcome line. Everything else on this surface (.page, .ledger-head,
   .ledger-table, .chip, .field, .input, .btn, .state, .link-action, .pending-value) was already
   here. --- */
.agents__title{font-size:var(--text-2xl);margin:var(--sp-1) 0 var(--sp-3)}
.agents__lede{max-width:var(--measure);color:var(--text-secondary);margin:0 0 var(--sp-5)}
.agents__mint{padding:var(--sp-4)}
.agents__mint .field{max-width:var(--measure)}
.agents__mint .field__help{max-width:var(--measure)}
.agents__outcome{margin:var(--sp-3) 0 0;min-height:1.75em}
.agents__outcome--ok{color:var(--status-ok)}
.agents__outcome--error{color:var(--attention)}
.agents__error{padding:var(--sp-3) var(--sp-4);margin:0}
.agents__reveal{box-shadow:inset var(--rubric-bar) 0 0 var(--attention)}
.agents__reveal-body{padding:var(--sp-4)}
.agents__secret{margin:0 0 var(--sp-3)}
.agents__secret code{display:block;font-family:var(--font-mono);font-size:var(--text-sm);word-break:break-all;background:var(--surface-well);border:var(--rule-w) solid var(--rule-strong);border-radius:var(--radius);padding:var(--sp-3);user-select:all}
.agents__reveal-meta{color:var(--text-muted);margin:0 0 var(--sp-1)}

/* Lesson observations retain their line breaks and stay within the ledger on small screens. */
.lesson-framing { padding: var(--sp-4); }
.lesson-statement {
  margin: var(--sp-3) 0;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}
#lesson-proposals .entry__rail { overflow-wrap: anywhere; }

/* Countersign detail: the existing ledger rail, diff well and ink action tokens. */
.edit-detail__title{font-size:var(--text-2xl);margin:var(--sp-1) 0 var(--sp-5)}
.edit-detail__entry{border-left:var(--rubric-bar) solid var(--attention)}
.edit-detail .entry__rail{overflow-wrap:anywhere}
.edit-detail .entry__body{min-width:0}
.edit-detail__reason{white-space:pre-wrap;overflow-wrap:anywhere}
.edit-detail__diff,.edit-detail__current{overflow:auto;white-space:pre;font-family:var(--font-mono);font-size:var(--text-xs);padding:var(--sp-3);background:var(--surface-well);border:var(--rule-w) solid var(--rule-soft)}
.edit-detail__diff code{font:inherit}
.edit-detail__diff .diff__hunk{color:var(--attention)}
.edit-detail__matches{color:var(--status-ok)}
.edit-detail details{margin:var(--sp-4) 0}
.edit-detail summary{cursor:pointer;text-decoration:underline;text-decoration-color:var(--attention);text-underline-offset:3px}
@media(max-width:600px){.edit-detail__entry{grid-template-columns:var(--rail-w-narrow) minmax(0,1fr)}}

/* Inbox captures share the ledger anatomy of edit review. */
.inbox-detail__title{font-size:var(--text-2xl);margin:var(--sp-1) 0 var(--sp-5)}
.inbox-detail__entry{border-left:var(--rubric-bar) solid var(--attention)}
.inbox-row .entry__rail,.inbox-detail .entry__rail{overflow-wrap:anywhere}
.inbox-row .entry__body,.inbox-detail .entry__body{min-width:0}
.inbox-row__preview{white-space:pre-wrap;overflow-wrap:anywhere}
.inbox-detail__body{overflow:auto;white-space:pre-wrap;overflow-wrap:anywhere;font-family:var(--font-mono);font-size:var(--text-xs);padding:var(--sp-3);background:var(--surface-well);border:var(--rule-w) solid var(--rule-soft)}
.inbox-detail details{margin:var(--sp-4) 0}
.inbox-detail summary{cursor:pointer;text-decoration:underline;text-decoration-color:var(--attention);text-underline-offset:3px}
/* Triage actions (shift 85b): the destination field takes its own line and the two verdict
   controls share the row beneath it. They used to be siblings of a centred flex row in which one
   of them was a two-row form, so Decline was vertically centred against the FORM and landed 28px
   above the File button and 124px to its right. A block wrapper + one flex row inside the form is
   what puts them on one line; the measure keeps the path field from running the page's full width. */
.inbox-actions{margin-top:var(--sp-2);max-width:var(--measure)}
@media(max-width:600px){.inbox-detail__entry{grid-template-columns:var(--rail-w-narrow) minmax(0,1fr)}}

/* --- voices (H-091, D-787, shift 86b). Only what the existing component classes do not already
   carry: the page's title/lede rhythm on its own stem, the two forms' body padding, the bind
   row, the outcome line and the editor's height. This surface is the FIRST render of .textarea
   and .select — both have been in the token layer since E0-s with nothing drawing them — so the
   only thing added for them is the editor's own min-height and resize handle; everything else
   (.page, .ledger-head, .ledger-table, .ledger-scroll, .field, .input, .btn, .state,
   .link-action, .pending-value) was already here. --- */
.voices__title{font-size:var(--text-2xl);margin:var(--sp-1) 0 var(--sp-3)}
.voices__lede{max-width:var(--measure);color:var(--text-secondary);margin:0 0 var(--sp-5)}
.voices__form{padding:var(--sp-4)}
.voices__form .field{max-width:var(--measure)}
.voices__form .field__help{max-width:var(--measure)}
.voices__body{min-height:11em;resize:vertical;line-height:var(--leading-body)}
.voices__actions{display:flex;gap:var(--sp-4);align-items:center;flex-wrap:wrap}
.voices__note{margin:0 0 var(--sp-4)}
/* The status region is ALWAYS in the document (an aria-live region cannot be created on demand
   and still be announced), but an EMPTY one reserves no band: a fresh page would otherwise open
   with a blank strip between the lede and the first panel. The two kinded variants carry the
   height and the rhythm, so the line only takes room once it has something to say. */
.voices__outcome{margin:0}
.voices__outcome--ok,.voices__outcome--error{margin:0 0 var(--sp-4);min-height:1.75em}
.voices__outcome--ok{color:var(--status-ok)}
.voices__outcome--error{color:var(--attention)}
.voices__error{padding:var(--sp-3) var(--sp-4);margin:0}
.voices__edit{white-space:nowrap}
