/* Zero Witness — Legal.
 *
 * A STYLESHEET OF ITS OWN, and the duplication with chat.css is the known cost
 * rather than an oversight. This repo already records why the two :root blocks
 * in index.css and chat.css are deliberately not shared: one tokens file would
 * couple pages that are otherwise edited independently, and the coupling is
 * worse than the copying. The same argument holds a third time — and this page
 * carries components chat.css does not have at all (a matters table, an
 * authorities list, a research result) and lacks most of what fills it (a cast,
 * a lorebook editor, a model picker, thirteen tier tiles).
 *
 * IF YOU ADD A TOKEN, ADD IT TO BOTH THEMES. An undefined custom property
 * invalidates the whole declaration rather than falling back, which is how a
 * Done button once resolved to transparent and every focus ring using it was
 * silently invisible. Nothing warns you; the file parses and the rule does not
 * apply.
 */

:root {
  --bg: #11141a;
  --surface: #171b22;
  --surface-2: #1c212a;
  --border: #262b35;
  --text: #e9e8e4;
  --text-muted: #8b92a0;
  --text-dim: #565d6b;
  --brass: #b08d57;
  --brass-dim: #8a6f45;
  --brass-ring: rgba(176,141,87,0.30);
  --you-bubble: rgba(176,141,87,0.11);
  --you-bubble-line: rgba(176,141,87,0.26);
  --signal: #6b93b5;
  --warn: #c98a4b;
  --warn-bg: rgba(201,138,75,0.10);
  --warn-line: rgba(201,138,75,0.45);
  --danger: #b57a7a;
  --danger-bg: rgba(181,122,122,0.10);
  --danger-line: rgba(181,122,122,0.40);
  /* RED IS FOR WHAT HAS TO BE DEALT WITH BEFORE FILING, AMBER FOR A WARNING
     (owner's direction, 15 Sep 2026). A citation to check, a name that resolves
     to a different case, words that differ from the opinion: --bad. A dissent,
     a coverage caveat, "no support found": --warn. --danger stays the quieter
     rose it was, because it also colours ordinary delete buttons. */
  --bad: #e5696b;
  --bad-bg: rgba(229,105,107,0.12);
  --bad-line: rgba(229,105,107,0.50);
  --serif: 'Spectral', Georgia, serif;
  --sans: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;
  --rail-w: 262px;
  /* The phone tab bar's height, named because three rules depend on agreeing
     with it: the bar itself, the rail overlay stopping above it, and the pane
     and composer doing the same. Defined HERE, in the base block, because the
     light theme redefines colours only — and an undefined custom property
     invalidates the whole declaration rather than falling back, which this
     repo has already paid for once. */
  --tabbar-h: 56px;
}

/* Light is opt-in per visit and never remembered — no localStorage, no
   prefers-color-scheme. Reload and it is dark again, which is the same
   behaviour the other three pages have. */
html[data-theme="light"] {
  --bg: #f6f4ef;
  --surface: #ffffff;
  --surface-2: #eeebe3;
  --border: #ddd7c9;
  --text: #201d19;
  --text-muted: #5b5548;
  --text-dim: #8a8375;
  --brass: #9c7a3f;
  --brass-dim: #b08d57;
  --brass-ring: rgba(156,122,63,0.28);
  --you-bubble: rgba(156,122,63,0.13);
  --you-bubble-line: rgba(156,122,63,0.30);
  --signal: #3d6a8f;
  --warn: #9a5f1d;
  --warn-bg: rgba(154,95,29,0.10);
  --warn-line: rgba(154,95,29,0.40);
  --danger: #9d5757;
  --danger-bg: rgba(157,87,87,0.10);
  --danger-line: rgba(157,87,87,0.40);
  --bad: #b3261e;
  --bad-bg: rgba(179,38,30,0.08);
  --bad-line: rgba(179,38,30,0.40);
}

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

/* A FIXED HEIGHT, NOT A MINIMUM. With min-height alone the body grows with the
   conversation, the pane's overflow-y has nothing to overflow against, the whole
   document scrolls instead, and the composer slides off the bottom of the page.
   dvh first so mobile browser chrome collapsing does not crop the composer. */
body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  display: flex;
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}

button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: none; cursor: pointer; }
:focus-visible { outline: 2px solid var(--brass-dim); outline-offset: 2px; }
code, .mono { font-family: var(--mono); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--surface); color: var(--text);
  padding: 10px 14px; border: 1px solid var(--brass); border-radius: 5px;
}
.skip:focus { left: 8px; top: 8px; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   The rail
   ========================================================================== */

.rail {
  width: var(--rail-w);
  flex: none;
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 16px 12px 12px;
  overflow: hidden;
}

.rail-brand { display: flex; align-items: center; gap: 9px; padding: 0 6px 14px; }
.rail-brand a { display: inline-flex; align-items: center; gap: 9px; text-decoration: none; color: inherit; }
/* The brand's own bolt — see .vf-bolt in verify.css, which is the same mask
   at 22px. Box at the file's own aspect (1.448) so nothing letterboxes. */
.bolt {
  display: block; width: 26px; height: 18px; flex: none;
  background: var(--brass);
  -webkit-mask: url(/img/zerowitness-bolt.png) center / contain no-repeat;
          mask: url(/img/zerowitness-bolt.png) center / contain no-repeat;
}
.rail-name { font: 600 11px/1 var(--sans); letter-spacing: .14em; text-transform: uppercase; }
.rail-tag {
  font: 600 9.5px/1 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--brass); background: rgba(176,141,87,.15);
  padding: 3px 6px; border-radius: 3px;
}

/* The matter's identity. Sets no `display`, so the UA's own [hidden] rule hides
   it and there is no second rule to forget — the trap this repo records six
   times over. */
.rail-matter {
  padding: 0 6px 13px;
  border-bottom: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 3px;
}
.rail-matter-name {
  font: 400 15px/1.3 var(--serif);
  text-align: left; width: 100%;
  overflow-wrap: anywhere;
}
.rail-matter-name:hover { color: var(--brass); }
.rail-matter-line { font: 400 11.5px/1.4 var(--sans); color: var(--text-muted); }
.rail-matter-stage { font: 400 11.5px/1.4 var(--sans); color: var(--text-dim); }
/* A BUTTON NOW, NOT A LINE. It still has to read as a statement at rest —
   where a matter runs is the fact the rail exists to keep in view — so it takes
   no border and no fill until it is hovered or focused, and the word that says
   it can be pressed appears then. */
.rail-matter-runs {
  display: flex; align-items: center; gap: 6px;
  font: 400 11px/1.4 var(--sans); color: var(--text-dim);
  margin-top: 4px; padding: 3px 6px; width: calc(100% + 12px); margin-left: -6px;
  border-radius: 5px; text-align: left; cursor: pointer;
}
.rail-matter-runs svg { width: 12px; height: 12px; flex: none; stroke: currentColor; fill: none; }
.rail-matter-runs.is-server { color: var(--signal); }
.rail-matter-runs:hover { background: var(--surface); color: var(--text); }
.rail-matter-runs:focus-visible { outline: 2px solid var(--brass-dim); outline-offset: 1px; }
.rail-matter-change {
  margin-left: auto; color: var(--brass);
  font: 500 10.5px/1.4 var(--sans);
  opacity: 0; transition: opacity .12s ease;
}
.rail-matter-runs:hover .rail-matter-change,
.rail-matter-runs:focus-visible .rail-matter-change { opacity: 1; }
/* A hover-only affordance does not exist on a phone — the rule this repo has
   already paid for twice — so below the rail's own breakpoint it is always on. */
@media (max-width: 900px) {
  .rail-matter-change { opacity: 1; }
}

.rail-dests {
  display: flex; flex-direction: column; gap: 1px;
  padding-top: 12px;
  overflow-y: auto;
}
.rail-dest {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  padding: 8px 10px; border-radius: 5px; text-align: left; width: 100%;
  font: 400 12.5px/1.35 var(--sans); color: var(--text-muted);
}
.rail-dest:hover { background: var(--surface); color: var(--text); }
.rail-dest[aria-current="page"] { background: var(--surface-2); color: var(--text); font-weight: 500; }
.rail-dest .n { font: 400 11px/1 var(--sans); color: var(--text-dim); font-variant-numeric: tabular-nums; }
.rail-dest[aria-current="page"] .n { color: var(--text-muted); }
/* Authorities keeps a hairline of the accent when it holds something that could
   not be confirmed. Not a badge: this is a standing state of the matter, not an
   alert about the last thing that happened. */
.rail-dest.has-bad .n { color: var(--bad); }

.rail-foot {
  margin-top: auto; padding: 13px 6px 0; border-top: 1px solid var(--border);
  display: flex; flex-direction: column; gap: 7px;
}
.rail-where { display: flex; align-items: flex-start; gap: 7px; font: 400 11px/1.45 var(--sans); color: var(--text-muted); }
.rail-where .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--brass); flex: none; margin-top: 5px; }
.rail-where .dot.is-off { background: var(--text-dim); }
.rail-where code { color: var(--text); font-size: 11px; overflow-wrap: anywhere; }
.rail-note { font: 400 10.5px/1.45 var(--sans); color: var(--text-dim); }
.rail-vault { display: block; margin-top: 4px; color: var(--brass); }
.rail-vault .linkish { font: inherit; color: var(--brass); background: none; border: 0; padding: 0;
  text-decoration: underline; cursor: pointer; }
.rail-vault .linkish:focus-visible { outline: 2px solid var(--brass-ring); outline-offset: 2px; }
/* Matches chat.css's .saved-manage-btn, so Settings looks the same on both pages. */
.rail-settings {
  display: flex; align-items: center; gap: 8px; background: none; border: none; padding: 0;
  cursor: pointer; font: 500 12px/1.4 var(--sans); color: var(--text-muted); text-align: left;
}
.rail-settings svg { width: 13px; height: 13px; flex: 0 0 auto; }
.rail-settings:hover { color: var(--text); }
.rail-settings:focus-visible { outline: 2px solid var(--brass-dim); outline-offset: 3px; border-radius: 3px; }
.rail-coverage { text-decoration: none; }
.page-head p .cov-link, .note-line .cov-link { color: var(--brass); text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.page-head p .cov-link:hover, .note-line .cov-link:hover { color: var(--text); }
.rail-foot-row { display: flex; align-items: center; gap: 10px; padding-top: 2px; }
.rail-foot-row button { font: 400 11.5px/1 var(--sans); color: var(--text-dim); }
.rail-foot-row button:hover { color: var(--text-muted); }

/* ==========================================================================
   The main column
   ========================================================================== */

.main { flex: 1; display: flex; flex-direction: column; min-width: 0; }

.slim {
  height: 44px; flex: none;
  border-bottom: 1px solid var(--border);
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 0 18px;
}
.slim-left { display: flex; align-items: center; gap: 10px; min-width: 0; }
.slim-right { display: flex; align-items: center; gap: 8px; flex: none; }

/* It SHRINKS rather than clips, and the order it gives things up is the whole
   point: the model name goes first (it is one tap away in the sheet), the mode
   and the tier both stay, because those two are the entire reason shrinking this
   control is defensible at all. */
.run-pill {
  display: inline-flex; align-items: center; gap: 8px;
  border: 1px solid var(--border); border-radius: 99px;
  padding: 5px 12px; max-width: 340px; min-width: 0;
  font: 400 11.5px/1.3 var(--sans); color: var(--text-muted);
  white-space: nowrap; overflow: hidden;
}
.run-pill .where { overflow: hidden; text-overflow: ellipsis; }
.run-pill:hover { border-color: var(--brass-dim); color: var(--text); }
.run-pill .where { color: var(--text); }
.run-pill .model { color: var(--text-dim); }
.run-pill svg { width: 11px; height: 11px; flex: none; stroke: currentColor; fill: none; }

.tier {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font: 600 10.5px/1 var(--sans); letter-spacing: .03em; text-transform: uppercase;
  padding: 4px 7px; border-radius: 3px;
}
.tier.is-strongest { background: rgba(176,141,87,.15); color: var(--brass); }
.tier.is-strong { background: rgba(107,147,181,.15); color: var(--signal); }
.tier .pips { display: inline-flex; gap: 2px; }
.tier .pips i { width: 4px; height: 7px; border-radius: 1px; background: currentColor; opacity: .3; }
.tier .pips i.on { opacity: 1; }

.slim-btn {
  font: 400 11.5px/1 var(--sans); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 5px; padding: 6px 10px;
}
.slim-btn:hover { color: var(--text); border-color: var(--text-dim); }
.slim-btn.is-danger:hover { color: var(--danger); border-color: var(--danger-line); }

/* ==========================================================================
   Panes — every destination renders into one
   ========================================================================== */

.pane { flex: 1; min-height: 0; overflow-y: auto; }
.pane-inner { padding: 26px 30px 40px; max-width: 1040px; }

/* THE FIRST PAINT, which legal.js replaces the moment it renders. It is real
   page content rather than a crawler decoy, so it is set to be read: one column
   at a comfortable measure, the same type scale the rest of the surface uses. */
.intro { max-width: 66ch; padding-top: 6px; }
.intro h1 { font: 400 27px/1.25 var(--serif); letter-spacing: -0.01em; margin: 0 0 10px; }
.intro-lede { font: 400 14px/1.65 var(--sans); color: var(--text-muted); margin: 0 0 30px; }
.intro h2 {
  font: 500 10.5px/1.4 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-dim); margin: 30px 0 12px;
}
.intro-list { margin: 0; }
.intro-list dt { font: 500 13.5px/1.45 var(--sans); color: var(--text); margin-top: 16px; }
.intro-list dt:first-child { margin-top: 0; }
.intro-list dd {
  margin: 4px 0 0; font: 400 12.5px/1.65 var(--sans); color: var(--text-muted);
}
.intro > p { font: 400 12.5px/1.65 var(--sans); color: var(--text-muted); margin: 0 0 12px; }
.intro-foot { border-top: 1px solid var(--border); padding-top: 14px; margin-top: 26px !important; }
.intro-foot a { color: var(--brass); }
.intro-foot a:hover { color: var(--text); }

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 18px; margin-bottom: 18px; }
.page-head h1 { font: 400 21px/1.25 var(--serif); font-weight: 400; }
.page-head p { font: 400 12px/1.5 var(--sans); color: var(--text-dim); max-width: 62ch; margin-top: 4px; }

.btn {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  border: 1px solid var(--border); border-radius: 5px; padding: 7px 13px;
  font: 500 12px/1 var(--sans); color: var(--text-muted);
}
.btn:hover { color: var(--text); border-color: var(--text-dim); }
.btn.is-primary { border-color: rgba(176,141,87,.35); color: var(--brass); }
.btn.is-primary:hover { background: rgba(176,141,87,.08); border-color: var(--brass); }
.btn.is-danger { color: var(--danger); border-color: var(--danger-line); }
.btn.is-danger:hover { background: var(--danger-bg); }
.btn[disabled] { opacity: .45; cursor: default; }

.empty {
  border: 1px dashed var(--border); border-radius: 9px;
  padding: 26px 24px; display: flex; flex-direction: column; gap: 7px; align-items: flex-start;
}
.empty h2 { font: 400 16px/1.35 var(--serif); font-weight: 400; }
.empty p { font: 400 12.5px/1.6 var(--sans); color: var(--text-muted); max-width: 60ch; }

.note-line {
  border-left: 2px solid var(--brass); padding: 2px 0 2px 12px;
  font: 400 12px/1.6 var(--sans); color: var(--text-muted); max-width: 70ch;
  margin-top: 18px;
}
.note-line b { color: var(--text); font-weight: 500; }
.note-line.is-warn { border-left-color: var(--warn); }
.note-line.is-bad { border-left-color: var(--bad); }
.note-line.is-bad b { color: var(--bad); }

/* ---------- The matters table ---------- */

.matters { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.matter-row {
  display: grid;
  grid-template-columns: minmax(0,1.6fr) minmax(0,1fr) minmax(0,.8fr) minmax(0,.9fr) minmax(0,1fr) auto;
  gap: 10px; align-items: center; width: 100%; text-align: left;
  padding: 13px 16px; border-bottom: 1px solid var(--surface-2);
}
.matter-row:last-child { border-bottom: none; }
.matter-head {
  background: var(--surface); border-bottom: 1px solid var(--border);
  padding: 9px 16px;
}
.matter-head span {
  font: 600 9.5px/1 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim);
}
.matter-open { display: contents; }
.matter-row.is-open { background: rgba(176,141,87,.05); }
.matter-row:hover { background: var(--surface); }
/* A <button> centres its own text in the UA stylesheet, which beats the row's
   inherited alignment. */
.matter-title { display: flex; flex-direction: column; gap: 2px; min-width: 0; text-align: left; }
.matter-title .nm { font: 500 13.5px/1.3 var(--sans); overflow-wrap: anywhere; }
.matter-title .sub { font: 400 11px/1.35 var(--sans); color: var(--text-dim); }
.matter-cell { font: 400 12px/1.35 var(--sans); color: var(--text-muted); min-width: 0; overflow-wrap: anywhere; }
.matter-cell.is-empty { color: var(--text-dim); }
.matter-when { font: 400 12px/1.35 var(--sans); color: var(--text-dim); text-align: right; }
.matter-tools { display: flex; gap: 6px; justify-content: flex-end; }
.icon-btn {
  width: 26px; height: 26px; border-radius: 4px; display: inline-flex;
  align-items: center; justify-content: center; color: var(--text-dim);
}
.icon-btn:hover { background: var(--surface-2); color: var(--text); }
.icon-btn.is-danger:hover { color: var(--danger); }
.icon-btn svg { width: 14px; height: 14px; stroke: currentColor; fill: none; stroke-width: 1.6; }

/* A posture is a COLUMN rather than a footnote: it is the one fact about a
   matter that cannot be taken back, so it belongs beside the forum and not
   behind a click. */
.posture {
  display: inline-flex; align-self: start; white-space: nowrap;
  font: 500 10.5px/1 var(--sans); border-radius: 3px; padding: 4px 7px;
}
.posture.is-device { color: var(--brass); background: rgba(176,141,87,.13); }
.posture.is-hybrid { color: var(--text-muted); background: var(--surface-2); }
.posture.is-hosted { color: var(--signal); background: rgba(107,147,181,.13); }

/* ---------- A list of rows (chats, documents, transcripts) ---------- */

.rows { border: 1px solid var(--border); border-radius: 8px; overflow: hidden; }
.row {
  display: flex; align-items: center; gap: 12px; width: 100%; text-align: left;
  padding: 12px 16px; border-bottom: 1px solid var(--surface-2);
}
.row:last-child { border-bottom: none; }
.rows > .row:hover { background: var(--surface); }
.row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.row-title { font: 400 13px/1.4 var(--sans); overflow-wrap: anywhere; }
.row-sub { font: 400 11px/1.4 var(--sans); color: var(--text-dim); }
.row-tools { display: flex; gap: 6px; flex: none; }
.row-when { font: 400 11.5px/1.4 var(--sans); color: var(--text-dim); flex: none; }

.confirm {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 16px; border-bottom: 1px solid var(--surface-2);
  background: var(--surface);
}
.confirm p { flex: 1; min-width: 220px; font: 400 12px/1.55 var(--sans); color: var(--text-muted); }
.confirm b { color: var(--text); font-weight: 500; }

/* ---------- Authorities ---------- */

.auth-filters { display: flex; gap: 6px; flex-wrap: wrap; }
.chip {
  font: 500 11px/1 var(--sans); color: var(--text-muted);
  border: 1px solid var(--border); border-radius: 99px; padding: 6px 11px;
}
.chip:hover { color: var(--text); border-color: var(--text-dim); }
.chip[aria-pressed="true"] { background: var(--brass); border-color: var(--brass); color: var(--bg); }
.chip.is-bad { color: var(--bad); border-color: var(--bad-line); }
.chip.is-bad[aria-pressed="true"] { background: var(--bad); border-color: var(--bad); color: var(--bg); }

/* "Cited in": which document in the matter the list is narrowed to. */
.auth-source { display: inline-flex; align-items: center; gap: 6px; font: 400 12px/1 var(--sans); color: var(--text-muted); }
.auth-source select {
  font: 400 12px/1.2 var(--sans); color: var(--text); background: var(--surface);
  border: 1px solid var(--border); border-radius: 999px; padding: 5px 10px; max-width: 260px;
}
.auth-source select:focus-visible { outline: 2px solid var(--brass-ring); outline-offset: 1px; }

/* AMBER, NOT BRASS, and the split is the convention this project already set:
   amber means something leaves the device. Every other chip in that row filters
   a file on our own disk; this one is the only control on the page that sends
   anything, and a chip that looked like its neighbours would say the two were
   the same kind of choice. Same reasoning as the chat page's internet chip. */
.chip.is-out[aria-pressed="true"] {
  background: var(--warn); border-color: var(--warn); color: var(--bg);
}

/* A hit CourtListener answered rather than our own disk. A left edge and
   nothing else: the provenance is already in words in the foot, and this is the
   glance version of it rather than a second claim. */
.hit.is-remote { border-left: 2px solid var(--warn-line); }

/* WHAT RESEARCH SEARCHES: case law, statutes, regulations, rules. A segmented
   control rather than four more chips, because it is a different KIND of choice
   from the chips under the box — those narrow a search, this one decides what
   is being searched — and a control that looked like its neighbours would say
   the two were the same. 36px rather than the chips' 24: it is the first thing
   a hand reaches for on this pane. */
.source-switch {
  display: inline-flex; gap: 2px; padding: 3px; margin-bottom: 10px;
  border: 1px solid var(--border); border-radius: 99px; background: var(--surface);
  max-width: 100%; overflow-x: auto;
}
.source-switch button {
  font: 500 12px/1 var(--sans); color: var(--text-muted);
  padding: 0 14px; min-height: 30px; border-radius: 99px; white-space: nowrap;
}
.source-switch button:hover { color: var(--text); }
.source-switch button[aria-pressed="true"] { background: var(--brass); color: var(--bg); }

/* A provision rather than a case: no authority level, so a neutral edge, and
   a rule no longer in force is dimmed and says so in its badge. */
.hit.is-law, .auth-card.is-law { border-left-color: var(--text-dim); }
.is-law .auth-badge { background: var(--surface-2); color: var(--text-muted); }
.hit.is-gone { opacity: .72; }

.auth-card {
  border: 1px solid var(--border); border-left-width: 2px; border-radius: 6px;
  padding: 13px 16px; display: flex; flex-direction: column; gap: 6px;
  margin-bottom: 9px;
}
.auth-card.is-binding, .auth-card.is-binding-on-state-law { border-left-color: var(--brass); }
.auth-card.is-persuasive { border-left-color: var(--signal); }
.auth-card.is-unknown { border-left-color: var(--text-dim); }
.auth-card.is-bad { border-left-color: var(--bad); border-color: var(--bad-line); }
.auth-top { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; }
.auth-id { display: flex; align-items: baseline; gap: 9px; flex-wrap: wrap; min-width: 0; }
.auth-case { font: 400 15px/1.3 var(--serif); font-style: italic; overflow-wrap: anywhere; }
.auth-cite { font: 400 12.5px/1.3 var(--mono); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.auth-badge {
  flex: none; font: 600 9.5px/1 var(--sans); letter-spacing: .07em; text-transform: uppercase;
  border-radius: 3px; padding: 4px 8px; white-space: nowrap;
}
.is-binding .auth-badge, .is-binding-on-state-law .auth-badge { background: rgba(176,141,87,.15); color: var(--brass); }
.is-persuasive .auth-badge { background: rgba(107,147,181,.15); color: var(--signal); }
.is-unknown .auth-badge { background: var(--surface-2); color: var(--text-muted); }
.is-bad .auth-badge { background: var(--bad-bg); color: var(--bad); }
.auth-meta { font: 400 11.5px/1.5 var(--sans); color: var(--text-muted); }

/* The docket line, under the authority's own metadata and quieter than it:
   what the court published is the answer, the docket is context around it.
   Drawn only when the corpus holds it — see docketLine() for why an absence is
   never rendered as a blank. */
.auth-docket { font: 400 11px/1.5 var(--sans); color: var(--text-dim); margin-top: 3px; }
.auth-meta .why { color: var(--text-dim); }
.is-bad .auth-meta { color: var(--bad); }
.auth-actions { display: flex; gap: 12px; align-items: center; padding-top: 2px; }
.auth-actions a, .auth-actions button {
  font: 400 11px/1.4 var(--sans); color: var(--text-dim); text-decoration: none;
}
.auth-actions a:hover, .auth-actions button:hover { color: var(--brass); }

/* ---------- Research ---------- */

.search-box {
  border: 1px solid var(--border); border-radius: 9px; background: var(--surface);
  padding: 13px 15px; display: flex; flex-direction: column; gap: 11px;
}
.search-box:focus-within { border-color: var(--brass-dim); }
.search-box input[type="search"] {
  background: none; border: none; outline: none; width: 100%;
  font: 400 14px/1.4 var(--sans);
}
.search-box input::placeholder { color: var(--text-dim); }
.search-tools { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
.search-go {
  width: 28px; height: 28px; border-radius: 50%; background: var(--brass);
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.search-go svg { width: 14px; height: 14px; stroke: var(--bg); fill: none; stroke-width: 2.4; stroke-linecap: round; }
.search-go[disabled] { opacity: .4; }

.hit {
  border: 1px solid var(--border); border-left-width: 2px; border-radius: 6px;
  padding: 12px 15px; display: flex; flex-direction: column; gap: 5px; margin-bottom: 9px;
}
.hit.is-binding, .hit.is-binding-on-state-law { border-left-color: var(--brass); }
.hit.is-persuasive { border-left-color: var(--signal); }
.hit.is-unknown { border-left-color: var(--text-dim); }
.hit-snip { font: 400 12px/1.65 var(--sans); color: var(--text-muted); }
.hit-snip mark { background: rgba(176,141,87,.22); color: var(--text); border-radius: 2px; padding: 0 2px; }
.hit-foot { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; font: 400 11px/1.4 var(--sans); color: var(--text-dim); }
.hit-foot button, .hit-foot a { font: inherit; color: var(--text-dim); text-decoration: none; }
.hit-foot button:hover, .hit-foot a:hover { color: var(--brass); }
.result-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 14px;
  font: 400 11.5px/1.4 var(--sans); color: var(--text-dim); margin: 14px 0 10px;
}

/* ==========================================================================
   The conversation
   ========================================================================== */

.convo { display: flex; flex-direction: column; gap: 20px; padding: 26px 30px 8px; max-width: 1040px; }

.msg { display: flex; flex-direction: column; gap: 6px; }
.msg.you { align-items: flex-end; }
.msg-who { font: 400 11px/1 var(--sans); color: var(--text-dim); }
.msg.you .msg-who { text-align: right; }
.msg-who em { font-style: italic; }
.msg-body { font: 400 13.5px/1.75 var(--sans); max-width: 90%; overflow-wrap: anywhere; }
/* Your own side is bubbled and the reply is flat, and the asymmetry is the
   design rather than a compromise: a reply carries code blocks, source cards and
   chips, and a tinted container fights all three. Three round corners and one
   clipped, pointing back at its own byline. */
.msg.you .msg-body {
  background: var(--you-bubble);
  border: 1px solid var(--you-bubble-line);
  border-radius: 14px 14px 4px 14px;
  padding: 11px 15px;
  max-width: 62%;
  white-space: pre-wrap;
}
.msg-body p + p { margin-top: 10px; }
.msg-body ul, .msg-body ol { margin: 8px 0 8px 20px; }
.msg-body li { margin: 3px 0; }
.msg-body pre {
  background: var(--surface); border: 1px solid var(--border); border-radius: 6px;
  padding: 11px 13px; overflow-x: auto; margin: 10px 0;
  font: 400 12px/1.6 var(--mono);
}
.msg-body code { font: 400 12.5px/1.5 var(--mono); background: var(--surface-2); border-radius: 3px; padding: 1px 4px; }
.msg-body pre code { background: none; padding: 0; }
.msg-body blockquote { border-left: 2px solid var(--border); padding-left: 12px; color: var(--text-muted); margin: 10px 0; }
.msg-body h2, .msg-body h3 { font: 400 16px/1.35 var(--serif); margin: 14px 0 6px; }
.msg-note { font: 400 11.5px/1.5 var(--sans); color: var(--text-dim); margin-top: 6px; }
.msg-note.is-warn { color: var(--warn); }

.msg-status { font: 400 12px/1.5 var(--sans); color: var(--text-dim); }
.caret { display: inline-block; width: 7px; height: 14px; background: var(--brass); vertical-align: -2px; animation: blink 1s steps(2) infinite; }
@keyframes blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .caret { animation: none; } }

.notice {
  border: 1px solid var(--border); border-left: 2px solid var(--brass-dim);
  border-radius: 6px; background: var(--surface); padding: 11px 14px;
  font: 400 12px/1.6 var(--sans); color: var(--text-muted); max-width: 640px;
}
.notice.is-warn { border-left-color: var(--warn); color: var(--warn); }
.notice b { color: var(--text); font-weight: 500; }
.notice .acts { display: flex; gap: 8px; margin-top: 10px; flex-wrap: wrap; }

/* ---------- Inline chips (board 05) ---------- */
/* An inline chip marks WHERE a claim came from without leaving the sentence.
   Built by splitting text nodes, never by writing HTML — renderMarkdown()
   escapes the model's output before a tag is produced and this must not undo
   that. */
.inline-chip {
  display: inline-flex; align-items: baseline; gap: 5px;
  border: 1px solid var(--border); border-left-width: 2px; border-radius: 3px;
  padding: 1px 6px; margin: 0 1px;
  font: 500 11px/1.4 var(--sans);
  white-space: nowrap; vertical-align: baseline;
}
.inline-chip-tag { font: 600 9px/1.4 var(--sans); letter-spacing: .07em; opacity: .75; }
.inline-chip-level {
  font: 600 9px/1.4 var(--sans); letter-spacing: .05em; text-transform: uppercase;
  opacity: .85; padding-left: 4px; border-left: 1px solid currentColor;
}
/* The case file is the quiet one: it never left the device, so it is stated
   rather than highlighted. */
.inline-chip.is-file { background: var(--surface-2); border-left-color: var(--text-dim); color: var(--text-muted); }
.inline-chip.is-file .inline-chip-tag { color: var(--text-dim); }
.inline-chip.is-law { background: rgba(176,141,87,.10); border-color: rgba(176,141,87,.30); }
.inline-chip.is-law.is-binding,
.inline-chip.is-law.is-binding-state { border-left-color: var(--brass); color: var(--brass); }
.inline-chip.is-law.is-persuasive { border-left-color: var(--signal); color: var(--signal); background: rgba(107,147,181,.10); }
.inline-chip.is-law.is-plain { border-left-color: var(--brass-dim); color: var(--text-muted); }
/* The one that must not be quiet. */
.inline-chip.is-law.is-bad {
  background: var(--bad-bg); border-color: var(--bad-line);
  border-left-color: var(--bad); color: var(--bad);
}

/* ---------- The two boxes under a reply ---------- */
/* Never one list: these are two bodies of material with two different privacy
   postures, and collapsing them into "sources" loses the distinction the whole
   feature exists to draw. */
.answer-sources {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--border); border-radius: 8px;
  margin: 12px 0 0; max-width: 640px; overflow: hidden;
}
.src-box { padding: 12px 15px; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.src-box + .src-box { border-left: 1px solid var(--border); }
.src-eyebrow { font: 600 10.5px/1.3 var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--text-dim); }
.src-box:last-child .src-eyebrow { color: var(--brass); }
.answer-sources p { font: 400 11.5px/1.45 var(--sans); color: var(--text-muted); }

.msg-authorities {
  margin: 10px 0 0; border: 1px solid var(--border); border-left: 2px solid var(--brass);
  border-radius: 8px; background: var(--surface); padding: 11px 14px 4px; max-width: 640px;
}
.msg-authorities.has-bad { border-left-color: var(--bad); }
.auth-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  font: 600 10.5px/1.3 var(--sans); letter-spacing: .09em; text-transform: uppercase;
  color: var(--text-dim); padding-bottom: 8px;
}
.has-bad .auth-head { color: var(--bad); }
.auth-forum { letter-spacing: .03em; text-transform: none; font-weight: 400; color: var(--text-dim); }
.auth-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: 2px 10px;
  align-items: baseline; padding: 9px 0; border-top: 1px solid var(--border);
}
.auth-row .auth-cite { font: 500 12px/1.4 var(--mono); }
.auth-label {
  font: 600 10px/1 var(--sans); letter-spacing: .03em; text-transform: uppercase;
  padding: 3px 7px; border-radius: 3px; white-space: nowrap; justify-self: end;
  background: var(--bad-bg); color: var(--bad);
}
/* The reason spans all three columns on its own line — a hover would not exist
   on a phone, which this repo records three times over. */
.auth-why { grid-column: 1 / -1; font: 400 11px/1.45 var(--sans); color: var(--text-dim); }

/* ==========================================================================
   The composer
   ========================================================================== */

.composer-wrap { flex: none; padding: 0 30px 20px; max-width: 1040px; width: 100%; }

/* ONE BOX, and the border belongs to the composer rather than to the field: a
   bordered input beside four other bordered controls reads as a toolbar that
   happens to contain a text field. Two rows at every width — five controls plus
   a textarea in one row leaves the textarea 78px at 375px, measured. */
.composer {
  border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  padding: 12px 14px; display: flex; flex-direction: column; gap: 11px;
}
.composer:focus-within { border-color: var(--brass-dim); }
.composer textarea {
  background: none; border: none; outline: none; resize: none; width: 100%;
  font: 400 13.5px/1.55 var(--sans); max-height: 180px; overflow-y: auto;
}
.composer textarea::placeholder { color: var(--text-dim); }
.composer-tools { display: flex; align-items: center; justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.tools-start, .tools-end { display: flex; align-items: center; gap: 9px; }
.tool-btn { width: 26px; height: 26px; display: inline-flex; align-items: center; justify-content: center; color: var(--text-muted); border-radius: 4px; }
.tool-btn:hover { color: var(--text); background: var(--surface-2); }
.tool-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 1.6; stroke-linecap: round; }
.tool-btn.is-on { color: var(--brass); }
.tool-btn[disabled] { opacity: .4; cursor: default; }

.send {
  width: 30px; height: 30px; border-radius: 50%; background: var(--brass);
  display: inline-flex; align-items: center; justify-content: center; flex: none;
}
.send svg { width: 15px; height: 15px; stroke: var(--bg); fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.send.busy { background: var(--danger); }
.composer-note { font: 400 11px/1.5 var(--sans); color: var(--text-dim); text-align: center; margin-top: 9px; }

.attach-chip {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  border: 1px solid var(--border); border-radius: 7px; background: var(--surface-2);
  padding: 9px 12px; margin-bottom: 10px;
  font: 400 12px/1.5 var(--sans); color: var(--text-muted);
}
.attach-chip.is-bad { border-color: var(--danger-line); color: var(--danger); }
.attach-chip .nm { color: var(--text); }
.attach-chip .sp { flex: 1; }

/* Recording, live. The chip grows a transcript pane, so it wraps rather than
   staying the one tight row an attachment needs. */
.attach-chip.is-live { flex-wrap: wrap; border-color: var(--brass-dim); }
.attach-chip.is-live .sp { flex: 1 1 200px; }
.attach-chip .rec-dot {
  display: inline-block; width: 7px; height: 7px; border-radius: 50%;
  background: var(--danger); margin-right: 6px; vertical-align: baseline;
  animation: rec-pulse 1.6s ease-in-out infinite;
}
@keyframes rec-pulse { 0%, 100% { opacity: 1 } 50% { opacity: .35 } }
@media (prefers-reduced-motion: reduce) { .attach-chip .rec-dot { animation: none } }

/* The words so far, capped and scrolling, pinned to the newest line. */
.live-text {
  flex: 1 1 100%;
  max-height: 128px; overflow-y: auto;
  font: 400 12.5px/1.6 var(--sans); color: var(--text);
  border-top: 1px solid var(--border); padding-top: 8px; margin-top: 2px;
}
.live-partial { color: var(--text-dim); }
.live-empty { color: var(--text-dim); font-size: 12px; }
.live-note {
  flex: 1 1 100%;
  font: 400 11.5px/1.5 var(--sans); color: var(--warn);
}

/* The button while it is live. The dot in the chip carries the pulse; this
   just has to read as engaged. */
#recordBtn.is-recording { color: var(--danger); border-color: var(--danger-line); }

/* ==========================================================================
   Windows — one shell, several occupants
   ========================================================================== */

.win { position: fixed; inset: 0; z-index: 70; display: flex; align-items: center; justify-content: center; padding: 24px; }
.win[hidden] { display: none; }
.win-scrim { position: absolute; inset: 0; background: rgba(10,12,16,.62); }
html[data-theme="light"] .win-scrim { background: rgba(60,55,45,.35); }
.win-card {
  position: relative; z-index: 1; width: 100%; max-width: 720px; max-height: 86vh;
  background: var(--bg); border: 1px solid var(--border); border-radius: 12px;
  display: flex; flex-direction: column; overflow: hidden;
}
.win-body { overflow-y: auto; padding: 18px 20px 22px; }

/* A STICKY STRIP, NOT A PINNED BUTTON. `.win-close` absolutely positioned inside
   a scroll container scrolls away with the content — the one control named for
   finishing leaves the screen on any pane longer than the window. A bare pinned
   button instead hangs over whatever is scrolling beneath it; the strip carries
   the surface colour so content passes under it. Negative margins pull it flush
   to the body's own edges, so its stuck position is its resting one and there is
   no jump on the first scroll. */
/* `top` MATCHES THE NEGATIVE TOP MARGIN AND THAT IS LOAD-BEARING. A sticky
   element with `top: 0` is constrained to the scroll container's PADDING box, so
   a strip pulled above that by a negative margin is pushed back down by exactly
   the padding — measured here as a 7px overlap of the strip on the first line
   under it, which looks like a spacing mistake and is a positioning one. Setting
   `top` to the same negative value puts the constraint back on the border box,
   where the strip already sits, so its stuck position IS its resting position
   and nothing jumps on the first scroll. */
.win-topbar {
  position: sticky; top: -18px; z-index: 2;
  display: flex; align-items: center; justify-content: flex-end; gap: 8px;
  background: var(--bg); border-bottom: 1px solid transparent;
  margin: -18px -20px 10px; padding: 12px 20px;
}
.win h2 { font: 400 19px/1.3 var(--serif); font-weight: 400; margin-bottom: 4px; }
.win .sub { font: 400 12.5px/1.6 var(--sans); color: var(--text-muted); margin-bottom: 16px; max-width: 64ch; }

.field { display: flex; flex-direction: column; gap: 5px; margin-bottom: 14px; }
.field label { font: 500 11.5px/1.3 var(--sans); color: var(--text); }
.field .hint { font: 400 11px/1.5 var(--sans); color: var(--text-dim); }
.field input[type="text"], .field select, .field textarea {
  background: var(--surface); border: 1px solid var(--border); border-radius: 5px;
  padding: 9px 11px; font: 400 13px/1.4 var(--sans); width: 100%; outline: none;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--brass-dim); }
.field textarea { resize: vertical; min-height: 76px; }
.field-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }

/* ---------- The court combobox ----------
   234 courts in a native <select> is a list you scroll rather than a control
   you use, so the Court field is an input that filters and a list under it.
   The input keeps .field's own look for free — `.field input[type="text"]`
   reaches it as a descendant — and everything here is the list and the clear.

   `.combo-list` SETS display, so it carries its own [hidden] rule. Seventh
   instance of that trap in this repo: the attribute hides nothing against a
   rule that sets display, and the failure is a list permanently open rather
   than anything that throws. */
.combo { position: relative; }
.combo-input { padding-right: 30px !important; }
.combo-clear {
  position: absolute; top: 0; right: 0; width: 30px; height: 100%;
  display: flex; align-items: center; justify-content: center;
  font: 400 16px/1 var(--sans); color: var(--text-dim);
  background: none; border: 0; cursor: pointer;
}
.combo-clear:hover { color: var(--text); }

.combo-list {
  position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 5;
  max-height: 300px; overflow-y: auto;
  display: block;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 6px; box-shadow: 0 8px 24px rgba(0,0,0,0.35);
}
.combo-list[hidden] { display: none; }

/* 44px, which is the figure this repo already settled for the mode sheet's own
   segments: the number is about a fingertip and not about a viewport, and a row
   in a picker is the thing being aimed at rather than a line being read. It
   costs two visible rows out of the list's height, which is the right way round
   to lose that argument. */
.combo-row {
  display: flex; align-items: center; gap: 8px;
  min-height: 44px; padding: 7px 11px; cursor: pointer;
  border-bottom: 1px solid var(--border);
}
.combo-row:last-child { border-bottom: none; }
.combo-row:hover, .combo-row[data-cursor] { background: var(--surface); }
.combo-row[aria-selected="true"] .combo-name { color: var(--brass); }
.combo-name { font: 400 12.5px/1.4 var(--sans); color: var(--text); flex: 1; }
.combo-cite { font: 400 11px/1.4 var(--sans); color: var(--text-dim); flex: none; }

.combo-more, .combo-empty {
  padding: 8px 11px; font: 400 11px/1.5 var(--sans); color: var(--text-dim);
}
.combo-more { border-top: 1px solid var(--border); }

.eyebrow { font: 600 10px/1.3 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); margin: 20px 0 9px; }

/* A SEGMENTED TRACK, because posture is a scale from "nothing leaves" to "it all
   runs there" rather than three unrelated options. 44px minimum because the
   number is about a fingertip and not about a viewport. */
.segments { display: flex; border: 1px solid var(--border); border-radius: 7px; overflow: hidden; }
.segment {
  flex: 1; min-height: 44px; padding: 8px 12px;
  font: 500 12px/1.35 var(--sans); color: var(--text-muted);
  border-right: 1px solid var(--border);
}
.segment:last-child { border-right: none; }
.segment:hover { background: var(--surface); color: var(--text); }
.segment[aria-pressed="true"] { background: var(--brass); color: var(--bg); }
.segment-why { font: 400 11.5px/1.55 var(--sans); color: var(--text-muted); margin-top: 9px; }
.segment-why .cost { color: var(--text-dim); }

.win-actions { display: flex; gap: 9px; flex-wrap: wrap; margin-top: 20px; }

/* ---------- The mode sheet ---------- */
/* A CARD ANCHORED UNDER THE PILL above 900px and a full window below it — one
   element, two shapes, swapping jobs at the same breakpoint the rail uses. The
   JS half CLEARS the inline geometry below the breakpoint rather than setting
   it, because inline geometry beats a media query outright. */
.sheet { position: fixed; z-index: 60; }
.sheet[hidden] { display: none; }
.sheet-inner {
  width: 480px; max-width: calc(100vw - 24px);
  background: var(--bg); border: 1px solid var(--border); border-radius: 10px;
  padding: 15px 16px 16px; overflow-y: auto;
}
.sheet h3 { font: 400 15px/1.35 var(--serif); font-weight: 400; }
.sheet .eyebrow { margin: 0 0 4px; color: var(--brass); }
.sheet .eyebrow.is-yours { color: var(--text-dim); }
.sheet .reason { font: 400 12px/1.55 var(--sans); color: var(--text-muted); margin: 5px 0 14px; }

.option {
  display: flex; gap: 12px; flex-wrap: wrap; align-items: flex-start; width: 100%;
  text-align: left; border: 1px solid var(--border); border-radius: 8px;
  padding: 12px 14px; margin-bottom: 9px;
}
.option:hover { border-color: var(--text-dim); }
.option[aria-pressed="true"] { border-color: var(--brass); background: rgba(176,141,87,.06); }
.option[disabled] { opacity: .75; cursor: default; }
.option-text { flex: 1 1 250px; display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.option-name { font: 500 13px/1.35 var(--sans); }
.option-gain { font: 400 11.5px/1.5 var(--sans); color: var(--text-muted); }
.option-cost { font: 400 11.5px/1.5 var(--sans); color: var(--text-dim); }
.option-blocked { font: 400 11.5px/1.5 var(--sans); color: var(--danger); }

.pick-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  width: 100%; text-align: left; border-top: 1px solid var(--border);
  padding: 12px 2px 2px; margin-top: 4px;
}
.pick-row .lbl { font: 600 10px/1.3 var(--sans); letter-spacing: .1em; text-transform: uppercase; color: var(--text-dim); }
.pick-row .val { font: 400 13px/1.4 var(--sans); }
.pick-row .val small { color: var(--text-dim); font-size: 11.5px; }

.sheet .win-topbar { top: -15px; margin: -15px -16px 8px; padding: 11px 16px; }

@media (max-width: 899px) {
  .sheet { inset: 0; display: flex; }
  .sheet-inner {
    width: 100%; max-width: none; border: none; border-radius: 0;
    padding: 18px 20px 22px;
  }
  /* The strip is re-cut here because the sheet's padding moves from the outer
     element to the inner one at this width. BOTH RULES ARE (0,2,0) AND A MEDIA
     QUERY BREAKS NO TIES, so source order decides — which means this one has to
     come after the base rule above, not before it. Written the other way round
     first, and the base rule silently won on a phone. */
  .sheet .win-topbar { top: -18px; margin: -18px -20px 10px; padding: 12px 20px; }
}

/* ==========================================================================
   Narrow
   ========================================================================== */

@media (max-width: 899px) {
  body { flex-direction: column; }
  .rail {
    position: fixed; inset: 0; z-index: 50; width: 100%;
    background: var(--bg); border-right: none; padding: 16px 16px 20px;
    /* It stops ABOVE the tab bar rather than under it. The bar is persistent
       chrome, and covering the way out of a panel with the panel is the trap
       the project panel's missing Close button already was in chat.js. */
    bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
    /* The base rule is `overflow: hidden`, which is right for a column beside
       the pane and wrong for a full-screen menu: seven destinations, the matter
       block and the foot are taller than a short phone once the bar takes its
       56px, and hidden would clip the end of it with nothing to say so. */
    overflow-y: auto;
  }
  .rail[hidden] { display: none; }
  .main {
    flex: 1; min-height: 0;
    padding-bottom: calc(var(--tabbar-h) + env(safe-area-inset-bottom, 0px));
  }
  .slim { padding: 0 14px; }
  .pane-inner, .convo { padding-left: 16px; padding-right: 16px; }
  .composer-wrap { padding-left: 16px; padding-right: 16px; }
  /* (0,2,0), because `.matter-row` below is (0,1,0) and sets `display` too —
     the header carries BOTH classes, so at equal specificity source order would
     hand it back its row layout. */
  .matters .matter-head { display: none; }
  .matter-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 6px 10px; }
  .matter-title { flex: 1 1 100%; }
  .matter-cell, .matter-when, .posture { flex: 0 0 auto; }
  .matter-when { text-align: left; }
  .matter-tools { margin-left: auto; }
  .msg-body { max-width: 100%; }
  .msg.you .msg-body { max-width: 88%; }
  .answer-sources { grid-template-columns: 1fr; }
  .src-box + .src-box { border-left: none; border-top: 1px solid var(--border); }
  .inline-chip { white-space: normal; }
  .auth-row { grid-template-columns: 1fr; }
  .auth-label { justify-self: start; }
  .page-head { flex-direction: column; align-items: flex-start; gap: 12px; }
}

/* The rail button only exists where the rail is an overlay. Above the
   breakpoint the rail IS the control, and a button that opens what is already on
   screen is chrome. */
.rail-toggle { display: none; }
.rail-toggle svg { width: 15px; height: 15px; display: none; }
@media (max-width: 899px) { .rail-toggle { display: inline-flex; align-items: center; gap: 6px; } }

@media (max-width: 620px) {
  .run-pill .model { display: none; }
  /* The word goes and the icon arrives: at this width every pixel the menu
     keeps is one the mode pill gives up, and the pill is carrying a disclosure. */
  .rail-toggle svg { display: block; }
  .rail-toggle-word { display: none; }
  .rail-toggle { padding: 6px 8px; }
  .slim { gap: 8px; }
}

/* ---- The phone's tab bar ----------------------------------------------------
   chat.css's bar on this surface, deliberately the same object: same height,
   same 10px label under an 18px icon, same brass for the one you are on. A
   lawyer moving between the two pages should not have to learn a second shape.

   The LOOK is shared by writing it twice and the behaviour is not shared at
   all, which is this repo's standing arrangement for two pages that keep no
   tokens file between them — and here it is more than an arrangement: legal.js
   is a module and chat.js is a classic script, so there was never a way to
   share the code even if the destinations matched, which they do not.

   Hidden entirely above 900px, where the rail is this. Matched by hand to
   syncRail()'s and show()'s own `window.innerWidth < 900` in legal.js, as every
   pair of that kind here must be: if one moves, they all move. */
.tabbar { display: none; }
@media (max-width: 899px) {
  .tabbar {
    display: flex;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
    height: var(--tabbar-h);
    /* The home-indicator strip on a phone, so the row of tabs is not under it.
       Zero everywhere else. */
    padding-bottom: env(safe-area-inset-bottom, 0px);
    background: var(--surface);
    border-top: 1px solid var(--border);
  }
  .tabbar .tab {
    flex: 1 1 0; min-width: 0;
    display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
    background: none; border: none; cursor: pointer;
    color: var(--text-dim); font: 400 10px/1 var(--sans);
  }
  /* "Authorities" is eleven characters in a 75px tab at 375px. It fits, and it
     is the one label here that must not be abbreviated into a guess — so it
     shrinks rather than wraps or clips if a narrower phone turns up. */
  .tabbar .tab span {
    max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  }
  .tabbar .tab svg { width: 18px; height: 18px; flex: none; }
  .tabbar .tab.on { color: var(--brass); }
  .tabbar .tab:focus-visible { outline: 2px solid var(--brass-dim); outline-offset: -3px; }
  /* The count that can turn red is the whole reason Authorities is in the bar
     rather than the Checker, so it has to be visible ON the bar: a dot on the
     icon, in the same red the rail's own count uses. */
  .tabbar .tab.has-bad svg { overflow: visible; }
  .tabbar .tab.has-bad { position: relative; }
  .tabbar .tab.has-bad::after {
    content: ''; position: absolute; top: 8px; left: 50%; margin-left: 4px;
    width: 6px; height: 6px; border-radius: 50%;
    background: var(--bad); border: 1px solid var(--surface);
  }
}

/* ---------- Checking a draft ---------- */
/* The public verifier's shapes, in the matter. Deliberately the same objects —
   a dashed drop zone, a panel listing exactly what will be sent — because
   somebody who has used /verify.html should recognise this as the same act,
   and the checkpoint is the part that must not look different anywhere. */
.draft-drop {
  border: 1px dashed var(--border);
  border-radius: 10px;
  background: var(--surface);
  padding: 30px 26px;
  display: flex; flex-direction: column; align-items: center; gap: 15px;
  color: var(--text-dim);
}
.draft-drop.is-over { border-color: var(--brass); background: var(--surface-2); }
.draft-drop svg { width: 26px; height: 26px; }
.draft-drop-text { text-align: center; display: flex; flex-direction: column; gap: 5px; }
.draft-drop-text strong { font: 500 13.5px/1.4 var(--sans); color: var(--text); }
.draft-drop-text span { font: 400 12px/1.4 var(--sans); color: var(--text-dim); }
.draft-drop-actions { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; }

.draft-textarea {
  width: 100%; margin-top: 16px;
  background: var(--surface); color: var(--text);
  border: 1px solid var(--border); border-radius: 8px;
  padding: 13px 15px;
  font: 400 13.5px/1.6 var(--sans);
  resize: vertical;
}
.draft-textarea:focus { outline: none; border-color: var(--brass-dim); }

.draft-lede { font: 400 13.5px/1.7 var(--sans); color: var(--text-muted); margin-bottom: 16px; max-width: 66ch; }
.draft-lede b { color: var(--text); font-weight: 500; }

.draft-panel { border: 1px solid var(--border); border-radius: 9px; background: var(--surface); overflow: hidden; }
.draft-panel-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
  padding: 10px 16px; border-bottom: 1px solid var(--border);
  font: 600 10px/1.3 var(--sans); letter-spacing: .09em; text-transform: uppercase; color: var(--text-dim);
}
.draft-cites {
  list-style: none; margin: 0; padding: 14px 16px;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 7px 18px;
  font: 400 12.5px/1.5 var(--mono); font-variant-numeric: tabular-nums;
}
.draft-times { color: var(--text-dim); font-size: 11px; }
.draft-panel-foot {
  padding: 11px 16px 13px; border-top: 1px solid var(--border);
  font: 400 11.5px/1.5 var(--sans); color: var(--text-muted);
}

@media (max-width: 899px) {
  .draft-cites { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------------
   What each case is cited for

   THE PASSAGE IS THE OBJECT AND THE VERDICT IS A LABEL ON IT, which is what the
   weighting here has to carry: the badge is small and quiet, the quoted passage
   is set in the reading face at reading size. Every other check on this page is
   mechanical and can afford to lead with its answer; this one is a model's
   judgement, so the evidence leads and the judgement annotates.

   NO ALARM COLOUR ON "no support found". It borrows --warn, which on this page
   already means "work through this before filing" rather than "this is wrong" —
   and a red row would assert exactly the thing the copy is careful never to
   claim. The supported state takes brass, the accent this site spends sparingly.
   --------------------------------------------------------------------------- */
.prop-list {
  list-style: none; margin: 0; padding: 14px 16px;
  display: flex; flex-direction: column; gap: 12px;
}
.prop-list li { display: flex; flex-direction: column; gap: 3px; }
.prop-list .prop-cite {
  font: 600 10px/1.3 var(--sans); letter-spacing: .07em; text-transform: uppercase; color: var(--text-dim);
}
.prop-list .prop-text { font: 400 13px/1.6 var(--serif); color: var(--text); }
.prop-cut { font: 400 11px/1.5 var(--sans); color: var(--text-muted); }

.prop-card {
  border: 1px solid var(--border); border-left: 3px solid var(--text-dim);
  border-radius: 9px; background: var(--surface);
  padding: 13px 16px 14px; margin: 0 0 10px;
}
.prop-card.is-supported { border-left-color: var(--brass); }
.prop-card.is-notfound { border-left-color: var(--warn); border-color: var(--warn-line); }

.prop-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.prop-id { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 9px; min-width: 0; }
.prop-case { font: 500 13.5px/1.4 var(--serif); color: var(--text); }
.prop-card .prop-cite {
  font: 400 11.5px/1.4 var(--mono); font-variant-numeric: tabular-nums; color: var(--text-dim);
}
.prop-badge {
  flex: none; padding: 2px 8px; border-radius: 999px;
  font: 600 10px/1.6 var(--sans); letter-spacing: .05em; text-transform: uppercase;
  background: var(--surface-2); color: var(--text-dim);
}
.is-supported .prop-badge { background: rgba(176,141,87,0.12); color: var(--brass); }
.is-notfound .prop-badge { background: var(--warn-bg); color: var(--warn); }

.prop-claim { margin: 9px 0 0; font: 400 13px/1.65 var(--serif); color: var(--text); }
.prop-k {
  font: 600 10px/1.3 var(--sans); letter-spacing: .07em; text-transform: uppercase; color: var(--text-dim);
  margin-right: 5px;
}
.prop-why { margin: 7px 0 0; font: 400 12px/1.6 var(--sans); color: var(--text-muted); }

.prop-passages { margin: 10px 0 0; }
.prop-passages > summary {
  cursor: pointer; list-style: none;
  font: 600 10px/1.4 var(--sans); letter-spacing: .07em; text-transform: uppercase; color: var(--text-dim);
}
.prop-passages > summary::-webkit-details-marker { display: none; }
.prop-passages > summary::before { content: '\25B8\00a0'; display: inline-block; }
.prop-passages[open] > summary::before { content: '\25BE\00a0'; }
.prop-passages > summary:hover { color: var(--text); }
.prop-passage {
  margin: 9px 0 0; padding: 9px 13px;
  border-left: 2px solid var(--border); background: var(--surface-2);
  font: 400 12.5px/1.7 var(--serif); color: var(--text);
  white-space: pre-wrap; overflow-wrap: anywhere;
}

/* Quotations. The card, head, badge and passage are the proposition check's;
   what differs is the state vocabulary. Altered is the loud one and not-found
   the quiet one: an alteration is a discrepancy we established, an absence may
   be a gap in our copy. A dissent is loud whatever the words did, because words
   genuinely in the case can still argue for what the court declined to hold. */
.quote-card.is-exact { border-left-color: var(--brass); }
.quote-card.is-exact .prop-badge { background: rgba(176,141,87,0.12); color: var(--brass); }
.quote-card.is-dissent { border-left-color: var(--warn); border-color: var(--warn-line); }
.quote-card.is-dissent .prop-badge { background: var(--warn-bg); color: var(--warn); }
.quote-card.is-altered { border-left-color: var(--bad); border-color: var(--bad-line); }
.quote-card.is-altered .prop-badge { background: var(--bad-bg); color: var(--bad); }
.quote-card.is-notfound { border-left-color: var(--text-dim); }
.quote-where { margin: 6px 0 0; font: 400 12px/1.6 var(--sans); color: var(--text-dim); }
.quote-where b { color: var(--text-muted); font-weight: 600; }
.quote-where.is-warn { color: var(--warn); }
.quote-diff {
  margin: 9px 0 0; padding: 9px 12px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 6px;
  font: 400 12.5px/1.75 var(--serif); color: var(--text-muted); overflow-wrap: anywhere;
}
.quote-d-removed { text-decoration: line-through; color: var(--text); }
.quote-d-added { background: var(--bad-bg); color: var(--bad); border-radius: 3px; padding: 0 2px; }
.quote-legend { margin: 5px 0 0; font: 400 11px/1.5 var(--sans); color: var(--text-dim); }

/* On the authority card, where it has to survive the results screen closing. */
.auth-cited {
  margin: 8px 0 0; padding-top: 8px; border-top: 1px solid var(--border);
  font: 400 12px/1.6 var(--serif); color: var(--text-muted);
}
.auth-cited-k {
  font: 600 10px/1.3 var(--sans); letter-spacing: .07em; text-transform: uppercase;
  margin-right: 5px; color: var(--text-dim);
}
.auth-cited.is-ok .auth-cited-k { color: var(--brass); }
.auth-cited.is-warn .auth-cited-k { color: var(--warn); }
.auth-cited.is-bad .auth-cited-k { color: var(--bad); }

/* WHERE IN THE MATTER IT WAS CITED. The list holds one row per citation however
   many times it was relied on, so this is the only thing on the card that
   answers "which document is this from" — the line beside it answers when.
   Sits above .auth-actions and takes that row's own type, so the card reads as
   two quiet footer lines rather than gaining a third weight. */
.auth-where {
  display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap;
  margin: 8px 0 0;
  font: 400 11.5px/1.5 var(--sans); color: var(--text-muted);
}
.auth-where-k {
  font: 600 10px/1.3 var(--sans); letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-dim);
}
.auth-where-sep { color: var(--text-dim); }
/* A chat is reachable and a draft is not — "Check a draft" indexes nothing —
   so only one of the two is a control, and it has to look like one. */
.auth-where button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font: inherit; color: var(--brass); text-decoration: underline;
  text-underline-offset: 2px; text-align: left;
}
.auth-where button:hover { color: var(--text); }

/* The search phrase above the headline — see `.h1-kicker` in index.css for why
   it is inside the <h1>. Smaller here than on the marketing pages, because this
   heading is 27px rather than 46px and a kicker must not outweigh its own
   headline. */
.intro-kicker {
  display: block;
  font: 600 10px/1.4 var(--sans);
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--brass);
  margin-bottom: 7px;
}

/* ---------- Cited by ----------
   A LIST, NEVER A VERDICT: no red, amber or green anywhere in it. The level
   beside a citing case is binding/persuasive for THIS matter's forum — the same
   brass and blue the cards use — and says nothing about what that case did with
   the one it cites. */
.cited-by { margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); display: flex; flex-direction: column; gap: 8px; }
.cited-by-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; font: 400 12px/1.5 var(--sans); color: var(--text-muted); }
.cited-by-head b { color: var(--text); font-weight: 600; font-variant-numeric: tabular-nums; }
.cited-by-tools { display: inline-flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.cited-by-sort { font: 400 12px/1.2 var(--sans); color: var(--text); background: var(--surface); border: 1px solid var(--border); border-radius: 999px; padding: 4px 9px; }
.cited-by-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; }
.cited-by-row { padding: 7px 0 7px 10px; border-top: 1px solid var(--border); border-left: 2px solid var(--text-dim); }
.cited-by-row:first-child { border-top: none; }
.cited-by-row.is-binding, .cited-by-row.is-binding-on-state-law { border-left-color: var(--brass); }
.cited-by-row.is-persuasive { border-left-color: var(--signal); }
.cited-by-id { font: 400 13px/1.4 var(--serif); overflow-wrap: anywhere; }
.cited-by-id a { color: var(--text); font-style: italic; text-decoration: none; }
.cited-by-id a:hover { color: var(--brass); text-decoration: underline; }
.cited-by-level { font: 600 9px/1 var(--sans); letter-spacing: .06em; text-transform: uppercase; color: var(--text-dim); }
.is-binding .cited-by-level, .is-binding-on-state-law .cited-by-level { color: var(--brass); }
.is-persuasive .cited-by-level { color: var(--signal); }
.cited-by-meta { font: 400 11px/1.45 var(--sans); color: var(--text-dim); }
.cited-by-note { font: 400 11.5px/1.5 var(--sans); color: var(--text-dim); margin: 0; }
.cited-by-note.is-warn { color: var(--warn); }
.cited-by .btn { align-self: flex-start; }

/* What a citing case said, under its row. Set as a QUOTATION and deliberately
   in no colour that grades it: these are the later court's own words, and the
   panel above says in so many words that they are not a statement of what that
   court did with the case. A green or red edge here would make the passage read
   as the treatment signal this product does not have. The only variant is
   `is-apart`, which marks a passage from a dissent or a concurrence — and it
   takes AMBER, the colour this surface uses for something to know about rather
   than something to deal with, because a case relied on only in a dissent is
   exactly the thing a citation check alone reports as clean. */
.cited-by-said { margin: 6px 0 0; padding: 0 0 0 10px; border-left: 2px solid var(--border); display: flex; flex-direction: column; gap: 3px; }
.cited-by-said p { margin: 0; font: 400 12.5px/1.55 var(--serif); color: var(--text-muted); overflow-wrap: anywhere; }
.cited-by-said cite { font: 400 10.5px/1.4 var(--sans); font-style: normal; letter-spacing: .02em; color: var(--text-dim); }
.cited-by-said.is-apart { border-left-color: var(--warn); }
.cited-by-said.is-apart cite { color: var(--warn); }
.cited-by-said.is-none { border-left-style: dashed; }
.cited-by-said.is-none, .cited-by-said.is-none p { font: 400 11.5px/1.5 var(--sans); color: var(--text-dim); }

/* ---------- Table of authorities ---------- */
.toa-line { margin: 4px 0 12px; }
.toa-panel { border: 1px solid var(--border); border-radius: 8px; background: var(--surface); padding: 12px 14px; margin: 0 0 14px; display: flex; flex-direction: column; gap: 8px; }
.toa-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; font: 400 12.5px/1.4 var(--sans); color: var(--text-muted); }
.toa-head b { color: var(--text); font-weight: 600; }
.toa-tools { display: inline-flex; gap: 6px; }
.toa-note { margin: 0; font: 400 11.5px/1.5 var(--sans); color: var(--text-dim); max-width: 72ch; }
/* The preview is the pasted fragment itself, on a white page, because that is
   what it will look like in a word processor. */
.toa-preview { background: #fff; color: #111; border-radius: 4px; padding: 14px 18px; max-height: 360px; overflow: auto; font: 400 13px/1.45 Georgia, 'Times New Roman', serif; }
.toa-preview table { font: inherit; color: inherit; }

/* ---------- Research filters and connector tips ---------- */
.research-filters { display: flex; flex-wrap: wrap; gap: 10px 14px; align-items: flex-end; padding: 12px 14px; margin: -4px 0 12px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface); }
.rf-field { display: flex; flex-direction: column; gap: 4px; font: 400 11.5px/1.3 var(--sans); color: var(--text-muted); min-width: 0; }
.rf-field input { font: 400 13px/1.3 var(--sans); color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 6px 8px; width: 180px; max-width: 100%; }
.rf-court input { width: 280px; }
.rf-year input { width: 72px; font-variant-numeric: tabular-nums; }
.rf-field input:focus-visible { outline: 2px solid var(--brass-ring); outline-offset: 1px; }
.rf-bad { color: var(--bad); font-size: 11px; }
.rf-note { flex-basis: 100%; margin: 0; font: 400 11.5px/1.5 var(--sans); color: var(--text-dim); }
.linkish { background: none; border: 0; padding: 0; font: inherit; color: var(--text-muted); text-decoration: underline; cursor: pointer; }
.linkish:hover { color: var(--text); }
.search-tips { margin: -4px 0 12px; font: 400 12px/1.5 var(--sans); color: var(--text-muted); }
.search-tips summary { cursor: pointer; color: var(--text-dim); width: max-content; }
.search-tips summary:hover { color: var(--text); }
.search-tips dl { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; margin: 8px 0; }
.search-tips dt { white-space: nowrap; }
.search-tips dd { margin: 0; }
.search-tips code { font: 400 12px/1.3 var(--mono); color: var(--text); background: var(--surface-2); border-radius: 3px; padding: 1px 4px; }
@media (max-width: 560px) { .search-tips dl { grid-template-columns: 1fr; } .search-tips dd { margin-bottom: 6px; } }

/* ---------- Citation format ---------- */
.format-check { margin: 0 0 12px; border: 1px solid var(--warn-line); border-left: 2px solid var(--warn); border-radius: 6px; padding: 8px 12px; font: 400 12.5px/1.5 var(--sans); color: var(--text-muted); }
.format-check summary { cursor: pointer; }
.format-check summary b { color: var(--warn); font-weight: 600; }
.format-check ul { list-style: none; margin: 8px 0 4px; padding: 0; }
.format-check li { display: grid; grid-template-columns: 160px 1fr; gap: 2px 12px; padding: 7px 0; border-top: 1px solid var(--border); }
.fc-kind { font: 600 10px/1.6 var(--sans); letter-spacing: .06em; text-transform: uppercase; color: var(--warn); grid-row: span 2; }
.fc-raw { font: 400 12.5px/1.4 var(--mono); color: var(--text); overflow-wrap: anywhere; }
.fc-say { font-size: 12px; }
.fc-sugg code { font: 400 12px/1.3 var(--mono); color: var(--text); }
.fc-note { margin: 4px 0 2px; font-size: 11.5px; color: var(--text-dim); }
@media (max-width: 560px) { .format-check li { grid-template-columns: 1fr; } .fc-kind { grid-row: auto; } }

/* ---------- Pressure-test ----------
   Against is red on its chip only because it is the adversarial search; the
   results themselves carry no red or green — they are things to read. */
.pt-panel { border: 1px solid var(--border); border-radius: 8px; background: var(--surface); padding: 14px 16px; margin: 0 0 14px; display: flex; flex-direction: column; gap: 18px; }
.pt-sec { display: flex; flex-direction: column; gap: 8px; }
.pt-sec h3 { font: 500 15px/1.3 var(--serif); margin: 0; }
.pt-sec h4 { font: 600 10.5px/1.3 var(--sans); letter-spacing: .07em; text-transform: uppercase; color: var(--text-dim); margin: 8px 0 0; }
.pt-note { margin: 0; font: 400 12px/1.55 var(--sans); color: var(--text-muted); max-width: 76ch; }
.pt-sec > .btn { align-self: flex-start; }
.pt-field { display: flex; flex-direction: column; gap: 4px; font: 400 11.5px/1.3 var(--sans); color: var(--text-muted); max-width: 520px; }
.pt-field input, .pt-field select { font: 400 13px/1.3 var(--sans); color: var(--text); background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 6px 8px; }
.pt-list { list-style: none; margin: 0; padding: 0; }
.pt-row { padding: 9px 0 9px 10px; border-top: 1px solid var(--border); border-left: 2px solid var(--text-dim); }
.pt-row.is-binding, .pt-row.is-binding-on-state-law { border-left-color: var(--brass); }
.pt-row.is-persuasive { border-left-color: var(--signal); }
.pt-id { font: 400 13px/1.4 var(--serif); overflow-wrap: anywhere; }
.pt-id a { color: var(--text); font-style: italic; text-decoration: none; }
.pt-id a:hover { color: var(--brass); text-decoration: underline; }
.pt-sent { margin: 6px 0 0; padding: 0 0 0 10px; border-left: 2px solid var(--border); font: 400 12.5px/1.55 var(--serif); color: var(--text-muted); }
.pt-part { font: 400 11px/1 var(--sans); color: var(--text-dim); }
.pt-act { margin-top: 4px; font: 400 11px/1.4 var(--sans); color: var(--text-dim); }
.pt-act button { font: inherit; color: var(--text-dim); background: none; border: 0; padding: 0; cursor: pointer; }
.pt-act button:hover { color: var(--brass); }

/* Text the draft carries and a reader would not see. Amber and never red: see
   hiddenTextHTML() in legal.js for why the colour is a claim in itself. */
.hidden-text { margin-top: 12px; }
.hidden-list {
  font: 400 12px/1.6 var(--sans);
  color: var(--text-muted);
  margin: 6px 0 0 14px;
  max-width: 70ch;
}
.hidden-list summary { cursor: pointer; color: var(--brass); }
.hidden-list ul { list-style: none; margin: 8px 0 0; padding: 0; }
.hidden-list li {
  display: flex;
  gap: 10px;
  align-items: baseline;
  padding: 5px 0;
  border-top: 1px solid var(--border);
  /* A concealed sentence can be long and has no spaces to break on when it is
     a run of control characters. */
  overflow-wrap: anywhere;
}
.hid-kind {
  flex: none;
  font: 600 10.5px/1.6 var(--sans);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--warn);
}
.hid-what { min-width: 0; }
.hid-what code {
  font: 400 11.5px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  background: var(--surface-2);
  border-radius: 4px;
  padding: 1px 5px;
}

/* ---------- Authorities as a table ----------
   A RENDERING OF THE CARDS, NOT A SECOND OPINION ABOUT THEM. Every colour here
   is the one the card already uses for the same finding, so a standing means
   one thing on this surface however it is being looked at — and no cell is
   coloured without a word beside it saying what the colour means, which is the
   rule the authority chips already follow. */

.auth-view { display: inline-flex; gap: 4px; }

.auth-table-wrap { overflow-x: auto; margin-bottom: 9px; }
.auth-table {
  width: 100%; border-collapse: collapse;
  font: 400 12px/1.4 var(--sans); color: var(--text);
}
.auth-table th, .auth-table td {
  text-align: left; vertical-align: top;
  padding: 9px 12px 9px 0; border-bottom: 1px solid var(--border);
}
.auth-table th:last-child, .auth-table td:last-child { padding-right: 0; }
.auth-table thead th { padding-top: 0; white-space: nowrap; }
.auth-table tbody tr:last-child td { border-bottom: 0; }

/* The header BUTTON is the control, not the cell, so it is reachable by
   keyboard and announces itself as something that acts; aria-sort stays on the
   <th>, which is where the spec puts it. */
.auth-table thead button {
  display: inline-flex; align-items: baseline; gap: 4px;
  font: 600 9.5px/1 var(--sans); letter-spacing: .07em; text-transform: uppercase;
  color: var(--text-muted);
}
.auth-table thead button:hover { color: var(--text); }
.auth-table thead button:focus-visible { outline: 2px solid var(--brass-ring); outline-offset: 3px; }
.auth-table th[aria-sort] button { color: var(--brass); }
.at-arrow { font-size: 10px; letter-spacing: 0; }

/* A left edge, the card's own, and nothing else — the standing is in words in
   its own column, and a second statement of it in colour would be a claim
   without a sentence under it. */
.auth-table tbody tr td:first-child { border-left: 2px solid transparent; padding-left: 10px; }
.auth-table tbody tr.is-binding td:first-child,
.auth-table tbody tr.is-binding-on-state-law td:first-child { border-left-color: var(--brass); }
.auth-table tbody tr.is-persuasive td:first-child { border-left-color: var(--signal); }
.auth-table tbody tr.is-law td:first-child,
.auth-table tbody tr.is-unknown td:first-child { border-left-color: var(--text-dim); }
.auth-table tbody tr.is-bad td:first-child { border-left-color: var(--bad); }

/* THE AUTHORITY COLUMN IS STICKY, which is the fix benchmarks.html already
   made for the same shape: seven columns of real legal metadata are wider than
   this pane, so the table scrolls inside its wrapper — and a row of findings
   whose case name has scrolled off the left is not readable. It needs its own
   background or the scrolled columns show through underneath it. */
.at-authority {
  position: sticky; left: 0; z-index: 1;
  min-width: 170px; max-width: 260px; background: var(--bg);
}
.auth-table thead .at-authority { z-index: 2; }
/* A seam on the sticky column's right edge. Without it a half-scrolled cell
   slides straight up against the case name and its own colour reads as a stray
   mark on the page rather than as the next column passing underneath. */
.at-authority::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: -1px; width: 1px;
  background: var(--border);
}
.at-name { display: block; font: 400 13.5px/1.35 var(--serif); font-style: italic; overflow-wrap: anywhere; }
.at-cite { display: block; font: 400 11.5px/1.4 var(--mono); color: var(--text-muted); font-variant-numeric: tabular-nums; }
.at-court { white-space: nowrap; }
.at-year { font-variant-numeric: tabular-nums; white-space: nowrap; }
.at-quotations { white-space: nowrap; }
.at-citedfor { min-width: 170px; }
.at-citedin { min-width: 120px; }

.at-quiet { color: var(--text-muted); }
/* A row with no value for a column says so as a dash rather than as a blank:
   an empty cell reads as a rendering fault, and these absences are facts. */
.at-none { color: var(--text-dim); }

.at-flag { font: 600 9.5px/1.35 var(--sans); letter-spacing: .06em; text-transform: uppercase;
  border-radius: 3px; padding: 4px 7px; display: inline-block; }
/* Every flag but the standing one is two or three words and stays on its line;
   "Names a different case" is the one that would otherwise hold a column open
   at 160px for a single phrase. */
.at-court .at-flag, .at-quotations .at-flag, .at-citedfor .at-flag { white-space: nowrap; }
.at-flag.is-binding, .at-flag.is-binding-on-state-law { background: rgba(176,141,87,.15); color: var(--brass); }
.at-flag.is-persuasive { background: rgba(107,147,181,.15); color: var(--signal); }
.at-flag.is-unknown, .at-flag.is-law, .at-flag.is-dim { background: var(--surface-2); color: var(--text-muted); }
.at-flag.is-bad { background: var(--bad-bg); color: var(--bad); }
.at-flag.is-warn { background: var(--warn-bg); color: var(--warn); }
.at-flag.is-ok { background: rgba(176,141,87,.15); color: var(--brass); }

/* On a phone the table keeps its columns and scrolls inside its own wrapper.
   Folding seven columns into stacked rows would produce the cards again, which
   are one tap away and better at it. */
@media (max-width: 720px) {
  .auth-table { font-size: 11.5px; }
  .auth-table th, .auth-table td { padding-right: 10px; }
  .at-authority { min-width: 145px; max-width: 200px; }
  .at-citedfor { min-width: 140px; }
}
