/* Bill of Health — brand system. Tokens are the source of truth from docs/design/brand.md.
   Palette is drawn from medical billing paperwork (EOB form stock, carbon ink, ledger rules)
   rather than healthcare's default soft blue. `signal` is reserved for money the reader could
   keep — never decoration. */

:root {
  --paper: #F6F8F4;
  --paper-2: #EDF1EA;
  --rule: #D3DBCF;
  --ink: #14181A;
  --ink-2: #4A5551;
  /* 4.97:1 on --paper and 4.65:1 on --paper-2. The muted tier carries real content — source
     attributions, rate kinds, plan line items — not decoration, so it is held to the 4.5:1 body
     minimum on both grounds rather than the 3:1 large-text allowance. The previous #77837E read
     as a pleasant grey and measured 3.69:1. */
  --ink-3: #5C6863;
  --ledger: #1C5546;
  --ledger-soft: #E2EDE6;
  --signal: #C0432A;
  --signal-soft: #F7E5E0;

  /* The map's heat ramp (issue #88): six stops, lowest price (green) to highest price (red),
     used ONLY on the map page's pills and their legend — never anywhere else. This is a new,
     scoped family on purpose: `signal` stays reserved for money the reader could keep, and a
     dear-price tint is a different claim entirely. Every stop is a GROUND the full `ink` token
     sits on, swept by scripts/check-contrast.py (which discovers --heat-N from this file), so a
     new or changed stop cannot dodge the 4.5:1 body minimum in either theme. The colour only
     repeats the figure each pill already prints (FR-028). */
  --heat-1: #63BE7B;
  --heat-2: #A8CE7F;
  --heat-3: #E7DC84;
  --heat-4: #FCC57C;
  --heat-5: #FA9473;
  --heat-6: #F8696B;

  --display: ui-serif, Georgia, "Iowan Old Style", "Times New Roman", serif;
  --sans: ui-sans-serif, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;

  --shell: 1060px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #101413; --paper-2: #171D1B; --rule: #2A3532;
    --ink: #EDF2EE; --ink-2: #A8B5B0; --ink-3: #8A9793;
    --ledger: #6FBFA3; --ledger-soft: #172C26;
    --signal: #E8785C; --signal-soft: #2B1A16;
    --heat-1: #2B7049; --heat-2: #4D6B35; --heat-3: #6B662C;
    --heat-4: #7E5A2B; --heat-5: #8A4A2E; --heat-6: #96383C;
  }
}
:root[data-theme="dark"] {
  --paper: #101413; --paper-2: #171D1B; --rule: #2A3532;
  --ink: #EDF2EE; --ink-2: #A8B5B0; --ink-3: #8A9793;
  --ledger: #6FBFA3; --ledger-soft: #172C26;
  --signal: #E8785C; --signal-soft: #2B1A16;
  --heat-1: #2B7049; --heat-2: #4D6B35; --heat-3: #6B662C;
  --heat-4: #7E5A2B; --heat-5: #8A4A2E; --heat-6: #96383C;
}
:root[data-theme="light"] {
  --paper: #F6F8F4; --paper-2: #EDF1EA; --rule: #D3DBCF;
  --ink: #14181A; --ink-2: #4A5551; --ink-3: #5C6863;
  --ledger: #1C5546; --ledger-soft: #E2EDE6;
  --signal: #C0432A; --signal-soft: #F7E5E0;
  --heat-1: #63BE7B; --heat-2: #A8CE7F; --heat-3: #E7DC84;
  --heat-4: #FCC57C; --heat-5: #FA9473; --heat-6: #F8696B;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font-family: var(--sans); font-size: 17px; line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
.shell { max-width: var(--shell); margin: 0 auto; padding: 0 24px; }

a { color: var(--ledger); text-underline-offset: 3px; }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--ledger); outline-offset: 3px; border-radius: 3px;
}
.skip {
  position: absolute; left: -9999px; top: 0; background: var(--ledger); color: var(--paper);
  padding: 10px 16px; z-index: 10;
}
.skip:focus { left: 0; }

/* ── chrome ───────────────────────────────────────────── */
header.site { border-bottom: 1px solid var(--rule); background: var(--paper); }
.bar { display: flex; align-items: baseline; justify-content: space-between; gap: 20px; padding-top: 18px; padding-bottom: 18px; }
.mark { font-family: var(--display); font-size: 20px; font-weight: 600; letter-spacing: -.01em; color: var(--ink); text-decoration: none; }
header.site nav a { font-size: 14.5px; }

/* The public-beta marker (014-deployment FR-018). Existing tokens only: ink on ledger-soft and
   ledger on ledger-soft are both already-swept pairings (scripts/check-contrast.py GROUNDS). */
aside.beta { background: var(--ledger-soft); border-bottom: 1px solid var(--rule); }
aside.beta p { font-size: 14px; color: var(--ink); max-width: 90ch; margin: 0; padding: 9px 0; }
aside.beta strong { color: var(--ledger); font-weight: 650; }

footer.site { border-top: 1px solid var(--rule); margin-top: 72px; padding: 26px 0 44px; }
.fine { font-size: 13.5px; color: var(--ink-2); max-width: 74ch; margin: 0 0 8px; }
.fine.muted { color: var(--ink-3); }

/* ── type ─────────────────────────────────────────────── */
h1 { font-family: var(--display); font-weight: 600; font-size: clamp(32px, 4.6vw, 52px); line-height: 1.06; letter-spacing: -.022em; margin: 0 0 16px; text-wrap: balance; }
h1 em { font-style: normal; color: var(--signal); }
h2 { font-family: var(--display); font-weight: 600; font-size: clamp(22px, 2.6vw, 29px); line-height: 1.15; letter-spacing: -.015em; margin: 0 0 12px; text-wrap: balance; }
h3 { font-size: 17px; font-weight: 650; margin: 0 0 6px; }
.lede { font-size: 19px; line-height: 1.5; color: var(--ink-2); max-width: 54ch; margin: 0 0 30px; }
.eyebrow { font-family: var(--mono); font-size: 11.5px; letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3); margin: 0 0 12px; }
section { margin-top: 52px; }

/* ── search form ──────────────────────────────────────── */
.finder { display: flex; gap: 10px; flex-wrap: wrap; align-items: stretch; margin-bottom: 14px; }
.finder .grow { flex: 1 1 280px; }
.finder .narrow { flex: 0 1 150px; }
.finder input, .finder select {
  width: 100%; font: inherit; font-size: 16px; color: var(--ink);
  background: var(--paper-2); border: 1.5px solid var(--rule); border-radius: 3px; padding: 13px 15px;
}
.finder input::placeholder { color: var(--ink-3); }
.finder button {
  font: inherit; font-size: 16px; font-weight: 600; border: 0; cursor: pointer;
  background: var(--ledger); color: var(--paper); padding: 13px 28px; border-radius: 3px;
}
.finder button:hover { filter: brightness(1.08); }
fieldset.who { border: 0; margin: 0 0 14px; padding: 0; display: flex; gap: 18px; flex-wrap: wrap; align-items: center; }
fieldset.who legend { float: left; font-size: 14px; color: var(--ink-2); margin-right: 14px; padding: 0; }
fieldset.who label { font-size: 14.5px; display: inline-flex; align-items: center; gap: 7px; }

.suggests { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin-top: 4px; }
.suggests .lbl { font-size: 13.5px; color: var(--ink-3); }
.suggests a {
  font-size: 13.5px; padding: 5px 12px; border: 1px solid var(--rule); border-radius: 100px;
  background: var(--paper-2); color: var(--ink-2); text-decoration: none;
}
.suggests a:hover { border-color: var(--ledger); color: var(--ledger); }

/* ── coverage selector ────────────────────────────────
   A filter, not navigation: it gets a heading like any other control group, and
   the current choice is unmistakable. Without a selected state the page silently
   changed what it was showing with nothing to point at. */
.coverage { margin: 26px 0 30px; }
.chips { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; }
.chip {
  font-size: 14px; padding: 7px 15px; border: 1px solid var(--rule); border-radius: 100px;
  background: var(--paper-2); color: var(--ink-2); text-decoration: none; line-height: 1.35;
}
.chip:hover { border-color: var(--ledger); color: var(--ledger); }
.chip[aria-current="true"] {
  background: var(--ledger); border-color: var(--ledger); color: var(--paper); font-weight: 600;
}
.chip[aria-current="true"]:hover { color: var(--paper); filter: brightness(1.08); }
.coverage .said {
  margin: 12px 0 0; font-size: 14.5px; color: var(--ink-2); max-width: 72ch;
}
.coverage .said strong { color: var(--ink); }

/* ── proof panel ──────────────────────────────────────── */
.proof { border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2); overflow: hidden; margin-bottom: 34px; }
.proof-head { padding: 15px 20px; border-bottom: 1px solid var(--rule); display: flex; justify-content: space-between; gap: 12px; flex-wrap: wrap; align-items: baseline; }
.proof-head .what { font-size: 14.5px; font-weight: 600; }
.proof-head .who { font-family: var(--mono); font-size: 11.5px; color: var(--ink-3); }
.prow { display: grid; grid-template-columns: 1fr 120px; gap: 16px; align-items: center; padding: 15px 20px; border-bottom: 1px solid var(--rule); }
.prow:last-of-type { border-bottom: 0; }
.prow .h { font-size: 15px; font-weight: 600; line-height: 1.25; }
.prow .p { font-size: 12.5px; color: var(--ink-3); margin-top: 3px; }
.prow .amt { font-family: var(--mono); font-size: 22px; text-align: right; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.prow.low { background: var(--ledger-soft); }
.prow.low .amt { color: var(--ledger); font-weight: 700; }
.prow.high .amt { color: var(--signal); font-weight: 700; }
.proof-foot { padding: 14px 20px; background: var(--paper); border-top: 1px solid var(--rule); font-size: 14.5px; }
.proof-foot strong { font-family: var(--mono); }

/* ── payer/plan breakdown ─────────────────────────────
   The point of this component is that one insurer is not one price. Plans are
   listed individually with the spread called out, because a collapsed average
   is what makes a hospital's range look arbitrary. */
.payergroup { border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2); overflow: hidden; }
/* Rates belonging to someone other than the visitor recede without disappearing. A page that hid
   them would be easier to read and impossible to check. */
.payergroup.aside { background: var(--paper); }
.payergroup.aside .payerhead { background: transparent; }
.payergroup.aside .payerhead .pname { font-weight: 600; color: var(--ink-2); }
.payerhead {
  display: flex; justify-content: space-between; align-items: baseline; gap: 14px; flex-wrap: wrap;
  padding: 13px 17px; border-bottom: 1px solid var(--rule); background: var(--paper);
}
.payerhead .pname { font-size: 15px; font-weight: 650; }
.payerhead .prange { font-family: var(--mono); font-size: 14.5px; font-variant-numeric: tabular-nums; display: flex; align-items: center; gap: 10px; }
table.plans { width: 100%; border-collapse: collapse; }
table.plans td { padding: 9px 17px; border-bottom: 1px solid var(--rule); font-size: 14.5px; }
table.plans tr:last-child td { border-bottom: 0; }
table.plans td.plan { color: var(--ink-2); }
table.plans td.amt { font-family: var(--mono); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Plan named once, the hospital's own line items indented beneath it. The line item is the
   discriminator: one plan can carry several prices, and until its description sat beside each rate
   the repetition read as a fault in our data rather than a fact about the hospital's file. */
table.plans td.plan .pn { display: block; color: var(--ink); font-weight: 600; }
table.plans td.plan .item { display: block; padding-left: 14px; }
table.plans td.plan .pn + .item { margin-top: 3px; }
/* Line items the hospital priced identically collapse to one row. Their names stay, smaller, so
   the collapse is checkable rather than something the reader has to take on trust. */
table.plans td.plan .names { display: block; padding-left: 14px; margin-top: 2px; font-size: 12.5px; color: var(--ink-3); }
.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* ── results ──────────────────────────────────────────── */
.resulthead { display: flex; justify-content: space-between; gap: 16px; flex-wrap: wrap; align-items: baseline; margin-bottom: 6px; }
.count { font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); }
.rows { display: grid; gap: 9px; margin-top: 20px; }
.row {
  display: grid; grid-template-columns: 1fr auto; gap: 18px; align-items: center;
  border: 1px solid var(--rule); border-radius: 4px; padding: 15px 18px; background: var(--paper-2);
}
.row.best { border-color: var(--ledger); border-width: 1.5px; }
a.rowlink { text-decoration: none; color: inherit; }
a.rowlink:hover { border-color: var(--ledger); }
a.rowlink .name { text-decoration: underline; text-decoration-color: var(--rule); text-underline-offset: 3px; }
a.rowlink:hover .name { text-decoration-color: var(--ledger); }
.row .name { font-size: 16px; font-weight: 650; line-height: 1.25; }
.row .meta { font-size: 13px; color: var(--ink-3); margin-top: 4px; display: flex; gap: 12px; flex-wrap: wrap; }
.row .price { text-align: right; }
.row .price .val { font-family: var(--mono); font-size: 21px; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.row.best .price .val { color: var(--ledger); font-weight: 700; }
.row .price .kind { font-size: 11.5px; color: var(--ink-3); margin-top: 2px; }
.badge { display: inline-block; font-family: var(--mono); font-size: 10.5px; letter-spacing: .08em; text-transform: uppercase; padding: 2px 8px; border-radius: 100px; border: 1px solid var(--rule); }
/* `.yours` marks the one figure the visitor said applies to them. It shares `.best`'s ledger
   outline because both mean "this is the row to read", not "this is a saving". */
.badge.best, .badge.yours { border-color: var(--ledger); color: var(--ledger); }
.badge.thin { border-color: var(--signal); color: var(--signal); }

.notice { border: 1px solid var(--rule); border-left: 3px solid var(--ledger); border-radius: 3px; padding: 16px 20px; background: var(--paper-2); margin: 22px 0; }
.notice.warn { border-left-color: var(--signal); }
.notice p { margin: 0; font-size: 15px; color: var(--ink-2); }
.notice p + p { margin-top: 8px; }

.withheld { margin-top: 34px; padding-top: 22px; border-top: 1px dashed var(--rule); }
.withheld h3 { font-family: var(--display); font-size: 19px; font-weight: 600; }

.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 12px; margin-top: 18px; }
.card { border: 1px solid var(--rule); border-radius: 4px; padding: 15px 17px; background: var(--paper-2); text-decoration: none; color: inherit; display: block; }
.card:hover { border-color: var(--ledger); }
.card .t { font-size: 15.5px; font-weight: 650; }
.card .d { font-size: 13px; color: var(--ink-3); margin-top: 5px; }

/* ── disclosure gate ──────────────────────────────────
   Everything in this block describes how complete a hospital's *published file* is.
   It never describes care, and the treatment is chosen so a glance cannot suggest
   otherwise: no `signal`, which this system reserves for money the reader could keep
   and which would misread as either danger or a saving; no `ledger`, which reads as a
   recommendation the score does not make. Neutral ink and a dashed rule instead — the
   look of an annotation on a form, which is what it is.

   Colour also carries no meaning alone here (WCAG 2.1 AA): the meter is narrated in
   text, and every component prints its own value next to a word for that value. */
.gate { margin-top: 52px; }
.gate-score { display: flex; align-items: baseline; gap: 18px; flex-wrap: wrap; margin-bottom: 14px; }
.gate-num { margin: 0; font-family: var(--mono); font-variant-numeric: tabular-nums; letter-spacing: -.02em; white-space: nowrap; }
.gate-num .v { font-size: 34px; font-weight: 700; }
.gate-num .d { font-size: 15px; color: var(--ink-2); margin-left: 6px; }
.gate-state { margin: 0; font-size: 14.5px; color: var(--ink-2); max-width: 62ch; }
.gate-state .flag {
  display: block; font-family: var(--mono); font-size: 11.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink); margin-bottom: 4px;
}

/* The fill is hatched rather than solid so it reads as a measurement taken, not a grade awarded. */
.meter { position: relative; height: 14px; background: var(--paper-2); border: 1px solid var(--rule); border-radius: 2px; overflow: hidden; }
.meter .fill {
  height: 100%;
  background: repeating-linear-gradient(135deg, var(--ink-2) 0 2px, transparent 2px 5px), var(--paper-2);
}
.meter .threshold { position: absolute; top: -1px; bottom: -1px; width: 2px; background: var(--ink); }
.meterkey {
  display: flex; justify-content: space-between; gap: 10px; margin: 6px 0 0;
  font-family: var(--mono); font-size: 11.5px; color: var(--ink-2);
}

/* The scoring block's own frame (issue #10). Wide content scrolls in here; the page body never
   moves. `position: relative` is not decoration — it makes this box the containing block for any
   absolutely positioned descendant (an .sr-only caption, say), which would otherwise be laid out
   against the page, escape the clip, and widen the document by exactly the amount the reader then
   has to scroll back. That is the bug this pattern exists to prevent, and it is invisible unless
   you try the scroll. */
.gate-scroller { position: relative; overflow-x: auto; }
.gate-table { width: 100%; border-collapse: collapse; margin-top: 26px; }
.gate-table th, .gate-table td { border-bottom: 1px solid var(--rule); padding: 12px 10px; text-align: left; vertical-align: top; }
.gate-table thead th { font-family: var(--mono); font-size: 11px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-2); font-weight: 500; }
.gate-table tbody th { font-weight: 400; }
.gate-table .num { text-align: right; font-family: var(--mono); font-variant-numeric: tabular-nums; white-space: nowrap; }
.gate-table .num.strong { font-weight: 700; }
.gate-table .part { display: block; font-size: 15px; font-weight: 650; }
.gate-table .band { display: block; font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); margin-top: 3px; }
.gate-table .why { display: block; font-size: 13px; color: var(--ink-2); margin-top: 5px; max-width: 60ch; }
.gate-table tfoot th, .gate-table tfoot td { border-bottom: 0; font-weight: 650; }

/* Neutral counterpart to .badge.thin: same shape, none of red's claim. */
.badge.gate { border-style: dashed; border-color: var(--ink-3); color: var(--ink-2); }

/* The caveat travels with the price. Spans the row so the sentence has room to be a
   sentence — a truncated warning is a warning nobody acts on. */
.caution {
  grid-column: 1 / -1; display: block; margin-top: 10px; padding: 9px 0 2px 12px;
  border-left: 2px dashed var(--ink-3); color: var(--ink-2);
}
.caution-head { display: block; font-family: var(--mono); font-size: 11px; letter-spacing: .09em; text-transform: uppercase; color: var(--ink); }
.caution-detail { display: block; font-size: 13px; margin-top: 4px; max-width: 68ch; }
.notice.gate { border-left-style: dashed; border-left-color: var(--ink-3); }

@media (max-width: 640px) {
  body { font-size: 16px; }
  .row { grid-template-columns: 1fr; gap: 10px; }
  .row .price { text-align: left; }
  .prow { grid-template-columns: 1fr 100px; }
  .gate-table th, .gate-table td { padding: 10px 6px; }
  .gate-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}

/* ── shortlist & comparison (US4) ─────────────────────
   The pick control is a footer strip on the result row rather than something inside it: the row
   is a link, and a link may not contain a form. Ledger green marks the row already chosen — this
   is structure ("you picked this"), not a saving, so it never reaches for `signal`. */
.pickable { display: grid; }
.pickable > .row { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.pickform {
  margin: 0; padding: 8px 18px 10px; background: var(--paper);
  border: 1px solid var(--rule); border-top: 0; border-radius: 0 0 4px 4px;
}
.pickable.best .pickform { border-color: var(--ledger); border-width: 1.5px; border-top: 0; }
button.pick {
  font: inherit; font-size: 13.5px; line-height: 1.2; cursor: pointer; min-height: 40px;
  padding: 8px 16px; border-radius: 100px; border: 1px solid var(--rule);
  background: var(--paper-2); color: var(--ink-2);
}
button.pick:hover { border-color: var(--ledger); color: var(--ledger); }
button.pick.on { border-color: var(--ledger); background: var(--ledger-soft); color: var(--ledger); font-weight: 650; }
.pickfull { display: inline-block; font-size: 13px; color: var(--ink-3); padding: 9px 0; }

.tray {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  margin-top: 18px; padding: 12px 16px; border: 1px solid var(--ledger); border-radius: 4px;
  background: var(--ledger-soft);
}
.tray .names { margin: 0; font-size: 14px; color: var(--ink-2); }
.tray .names strong { color: var(--ink); }
.tray .go {
  font-size: 14.5px; font-weight: 650; text-decoration: none; white-space: nowrap;
  background: var(--ledger); color: var(--paper); padding: 10px 18px; border-radius: 3px;
}
.tray .go:hover { filter: brightness(1.08); }

/* One column per hospital is wider than a phone by definition, so the width lives here and never
   on the page (SC-006): this box scrolls, the body does not. The measure column stays put while
   it scrolls, or the numbers arrive with nothing to label them. */
.cmp-scroll {
  max-width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch;
  /* Containing block for the shortlist buttons' .sr-only labels. Without it those absolutely
     positioned 1px spans are placed against the page rather than this box, so they are neither
     clipped nor scrolled by it: at 320–420px the document itself grew to 430px and the comparison
     page slid sideways to reveal nothing. Mobile emulation hides this (it shrinks the layout to
     fit), which is why every phone journey passed over it. */
  position: relative;
  border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2);
  /* Columns come to rest against the measure column instead of half-off the edge — a comparison
     read through a 170px window only works if the column you land on is whole. */
  scroll-snap-type: x proximity; scroll-padding-left: 136px;
}
table.cmp th[scope="col"], table.cmp tbody td { scroll-snap-align: start; }
.cmp-scroll:focus-visible { outline: 2px solid var(--ledger); outline-offset: 2px; }
/* Fixed layout and stated column widths, not `min-width`: left to the automatic algorithm the
   table honours `width: 100%` first and crushes four columns into a phone, which is legible to
   nobody. Columns keep their width and the box above scrolls instead. `min-width: 100%` keeps a
   one- or two-hospital comparison filling the space rather than huddling on the left. */
table.cmp { border-collapse: collapse; table-layout: fixed; width: max-content; min-width: 100%; }
table.cmp th, table.cmp td {
  width: 208px; padding: 13px 15px; text-align: left; vertical-align: top; overflow-wrap: break-word;
  border-bottom: 1px solid var(--rule); border-left: 1px solid var(--rule);
}
table.cmp tr > *:first-child { border-left: 0; }
table.cmp tbody tr:last-child th, table.cmp tbody tr:last-child td { border-bottom: 0; }
table.cmp thead th { vertical-align: bottom; background: var(--paper-2); }
table.cmp tbody th[scope="row"], table.cmp thead td.corner {
  position: sticky; left: 0; z-index: 1; width: 136px;
  background: var(--paper); box-shadow: 1px 0 0 var(--rule);
  font-family: var(--mono); font-size: 11px; letter-spacing: .09em; text-transform: uppercase;
  font-weight: 500; color: var(--ink-2);
}
.cmp .hname { display: block; font-family: var(--sans); font-size: 15.5px; font-weight: 650; line-height: 1.25; letter-spacing: 0; text-transform: none; }
.cmp .hplace { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 3px; }
.cmp thead .badge { margin-top: 8px; }
.cmp .amt { display: block; font-family: var(--mono); font-size: 20px; font-variant-numeric: tabular-nums; letter-spacing: -.02em; }
.cmp .kind { display: block; font-size: 12px; color: var(--ink-3); margin-top: 3px; }
.cmp .none { display: block; font-size: 13px; color: var(--ink-3); }
.cmp td.low, .cmp th.low { background: var(--ledger-soft); }
.cmp td.low .amt { color: var(--ledger); font-weight: 700; }
.cmp .pickform { border: 0; padding: 0; background: transparent; }

.cmp-cautions { margin-top: 18px; display: grid; gap: 14px; }
/* `.caution` is written for a grid row; standing on its own it just needs its own left rule. */
.cmp-cautions .caution { margin-top: 0; }

/* The one figure on the site that is ours rather than a hospital's, so it says so in words beside
   it. `signal` is right here and nowhere else on this page: it is the money in play. */
.gapline { margin: 22px 0 20px; font-size: 15.5px; color: var(--ink-2); max-width: 68ch; }
.gapline strong { color: var(--ink); }
.gapline .amount { font-family: var(--mono); font-weight: 700; color: var(--signal); font-variant-numeric: tabular-nums; }

@media (max-width: 640px) {
  .cmp-scroll { scroll-padding-left: 108px; }
  table.cmp th, table.cmp td { width: 174px; padding: 12px 12px; }
  table.cmp tbody th[scope="row"], table.cmp thead td.corner { width: 108px; padding: 12px 10px; }
  .tray .go { width: 100%; text-align: center; }
}

/* ── price map ────────────────────────────────────────
   Interactive Leaflet over OpenStreetMap tiles since ADR-0009; price pills since issue #88. Every
   marker is a pill — paper body, ink figure, in both themes — printing its rank and the hospital's
   own published figure, so the price itself is the highest-contrast thing on the map whatever tile
   it sits under. The figure on the pill is what makes the markers legible in greyscale and to a
   colour-blind reader (FR-028): the retired size/silhouette/weight scale encoded the price; the
   pill just says it. The tile layer is the standard OSM raster in both themes: a basemap is
   reference material, and recolouring it would spend effort making the one third-party element
   look owned.

   No `signal` here — red stays reserved for money the reader could keep. The OPT-IN heat ramp
   (issue #88, owner decision) tints pills from green (lowest price) to red (highest price) on its
   own scoped token family, --heat-1..6, used only on this page's pills and legend; it is not
   `signal` and must never borrow it. Colour-blind safety is the printed figure, not the hue: the
   ramp repeats what every pill already says, and the default view carries no ramp at all. The pill
   text stays full `ink` over every stop in both themes, and scripts/check-contrast.py sweeps every
   stop as a ground under `ink`. `ledger` appears once, on the lowest-priced pill, where it means
   what it means on the results list — "this is the row to read", not "this is the hospital to
   choose". */
/* Issue #69. This was `margin: -18px 0 22px` — a negative top margin, tuned for whatever happened
   to sit above it on the page it was written for, which pulled the link up into its predecessor
   everywhere else. On /search the `plausibleOnly` chips row (T021) was added above it later and
   nothing connected the two, so "See these on a map →" rendered *underneath* the chips and was
   unclickable at its left end; /prices had been overriding the rule inline since it was written.
   A negative margin that assumes a particular predecessor is a coupling nothing enforces, and the
   fix is the spacing this element actually wants, stated once and used by all three callers. */
.mapswitch { margin: 20px 0 22px; font-size: 14.5px; }

.pricemap { margin: 0 0 30px; padding: 0; }
/* The Leaflet host. A fixed height rather than an aspect ratio: tiles fill whatever box they are
   given, and fitBounds decides what the box shows, so the height is purely a reading decision —
   tall enough that the metro's north–south spread is not a letterbox. `position: relative` is what
   Leaflet requires of its container anyway (it positions every pane absolutely inside it), and it
   keeps those panes clipped to this box rather than laid out against the page (issue #15's shape). */
.pricemap .plot {
  position: relative; height: 520px; border: 1px solid var(--rule); border-radius: 4px;
  background: var(--paper-2); isolation: isolate; z-index: 0;
}
.pricemap .plot:focus-visible { outline: 2px solid var(--ledger); outline-offset: 2px; }
.pricemap figcaption { margin-top: 12px; }
.pricemap figcaption p { font-size: 13.5px; color: var(--ink-2); max-width: 74ch; margin: 0 0 6px; }
.pricemap figcaption a { color: var(--ink-2); text-underline-offset: 3px; }
.pricemap noscript p { margin-top: 10px; }

/* The mode toggle (issue #88): plain links above the map — keyboard-reachable because they are
   HTML, honest without JavaScript because the server renders the chosen mode. The active mode
   carries aria-current and the filled treatment the search button already uses. */
.mapmode { display: flex; gap: 8px; margin: 0 0 12px; }
.mapmode a {
  font-size: 13.5px; padding: 6px 16px; border: 1px solid var(--rule); border-radius: 100px;
  background: var(--paper-2); color: var(--ink-2); text-decoration: none;
}
.mapmode a:hover { border-color: var(--ledger); color: var(--ledger); }
.mapmode a[aria-current="true"] { background: var(--ledger); color: var(--paper); border-color: var(--ledger); }

/* The marker: a Leaflet divIcon price pill (issue #88) — paper body, the rank in the margin face,
   the figure in the receipt face, over any tile. The outer .leafpill is Leaflet's positioning box
   and stays unstyled (iconSize is null, so the pill sizes itself to its own figure); the body
   centres itself on the point. The figure IS the non-colour channel (FR-028). */
.leafpill { background: none; border: none; }
.leafpill-body {
  position: absolute; transform: translate(-50%, -50%); white-space: nowrap;
  display: inline-flex; align-items: baseline; gap: 6px;
  background: var(--paper); border: 1.5px solid var(--ink-2); border-radius: 100px;
  padding: 3px 11px 4px; box-shadow: 0 1px 3px var(--rule);
  cursor: pointer;
}
.leafpill-rank {
  font-family: var(--mono); font-size: 10.5px; color: var(--ink-2); line-height: 1;
}
.leafpill-price {
  font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 650;
  font-size: 12.5px; color: var(--ink); line-height: 1.2;
}
/* A hospital whose paperwork carries a caveat, and one we have withheld from the ranking, are both
   drawn as a broken outline — the same dashed-margin-note language the results list uses. FR-029:
   a cheap hospital with a thin disclosure must never come out looking like an endorsement. */
.leafpill-body.cautioned { border-style: dashed; border-color: var(--ink-3); }
.leafpill-body.withheld {
  background: var(--paper-2); border: 1.4px dashed var(--ink-3);
}
.leafpill-body.withheld .leafpill-price { color: var(--ink-2); font-weight: 500; }
/* FR-029's ring: concentric paper-then-ledger, so the emphasis survives greyscale as a ring rather
   than depending on the colour it also carries. */
.leafpill-body.lowest {
  border-color: var(--ledger);
  box-shadow: 0 0 0 2px var(--paper), 0 0 0 3.5px var(--ledger);
}
.leafpill:hover .leafpill-body { border-color: var(--ink); }
/* Heat mode (issue #88): the pill's ground moves along the scoped ramp; the figure stays full ink
   on every stop, in both themes — swept, not hoped (scripts/check-contrast.py). The rank span
   lifts to full ink too: ink-2 was tuned for paper, not for the stops. */
.leafpill-body.heat .leafpill-rank { color: var(--ink); }
.leafpill-body.heat-1 { background: var(--heat-1); }
.leafpill-body.heat-2 { background: var(--heat-2); }
.leafpill-body.heat-3 { background: var(--heat-3); }
.leafpill-body.heat-4 { background: var(--heat-4); }
.leafpill-body.heat-5 { background: var(--heat-5); }
.leafpill-body.heat-6 { background: var(--heat-6); }

/* The ramp's legend swatches, inline before the counted words in the figcaption — the paragraph
   stays a paragraph (a flexed <p> would shatter the sentence into columns). aria-hidden: the
   sentence carries the claim; the swatches illustrate it. */
.heatswatches { display: inline-flex; vertical-align: middle; margin-right: 6px; border: 1px solid var(--rule); border-radius: 2px; overflow: hidden; }
.heatswatches span { width: 18px; height: 11px; display: inline-block; }
.heatswatches .hs-1 { background: var(--heat-1); }
.heatswatches .hs-2 { background: var(--heat-2); }
.heatswatches .hs-3 { background: var(--heat-3); }
.heatswatches .hs-4 { background: var(--heat-4); }
.heatswatches .hs-5 { background: var(--heat-5); }
.heatswatches .hs-6 { background: var(--heat-6); }

/* Leaflet's own chrome, in the site's tokens so both themes hold. The popup repeats the row a
   visitor would find in the list: name as the link, the price in the receipt face, the distance. */
.pricemap .leaflet-popup-content-wrapper, .pricemap .leaflet-popup-tip {
  background: var(--paper); color: var(--ink); box-shadow: 0 1px 4px var(--rule);
}
.pricemap .leaflet-popup-content-wrapper { border: 1px solid var(--rule); border-radius: 4px; }
.pricemap .leaflet-popup-content { margin: 12px 16px; font-family: inherit; font-size: 13.5px; line-height: 1.45; }
.pricemap a.leaflet-popup-close-button { color: var(--ink-2); }
.leafpill-pop p { margin: 0 0 4px; }
.leafpill-pop-name a { color: var(--ink); font-weight: 600; text-underline-offset: 3px; }
.leafpill-pop-price .val { font-family: var(--mono); font-variant-numeric: tabular-nums; font-weight: 600; }
.leafpill-pop-price .kind { color: var(--ink-2); font-size: 12.5px; }
.leafpill-pop-meta { color: var(--ink-2); font-size: 12.5px; }
.pricemap .leaflet-bar { border-color: var(--rule); }
.pricemap .leaflet-bar a {
  background: var(--paper); color: var(--ink); border-bottom-color: var(--rule);
}
.pricemap .leaflet-bar a:hover, .pricemap .leaflet-bar a:focus { background: var(--paper-2); color: var(--ink); }
/* The in-map attribution, on tokens: the default rgba-white strip under a token-dark theme would
   be the one unreadable corner of the page (gotcha 21's lesson — check every ground it sits on). */
.pricemap .leaflet-container .leaflet-control-attribution {
  background: var(--paper); color: var(--ink-2); font-size: 11px;
}
.pricemap .leaflet-container .leaflet-control-attribution a { color: var(--ink-2); }

.mapkey { border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2); padding: 16px 20px; margin-bottom: 30px; }
.mapkey ul { margin: 0; padding-left: 20px; }
.mapkey li { font-size: 14px; color: var(--ink-2); margin-bottom: 6px; max-width: 74ch; }
.mapkey li:last-child { margin-bottom: 0; }

.unplaced { margin-top: 30px; padding-top: 20px; border-top: 1px dashed var(--rule); }
.unplaced h3 { font-family: var(--display); font-size: 18px; font-weight: 600; }

.maplist { margin-top: 34px; }
.maplist h3 { font-family: var(--display); font-size: 18px; font-weight: 600; margin-bottom: 14px; }
.maplist ol { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
/* The same handle the marker prints, so the plot and the list can be read against each other
   without either one having to be seen first. */
.mapglyph {
  display: inline-block; min-width: 22px; text-align: center; font-family: var(--mono);
  font-size: 12px; padding: 1px 5px; margin-right: 7px; border: 1px solid var(--rule);
  border-radius: 3px; color: var(--ink-2); background: var(--paper);
}
.maplist .withheld-item .mapglyph { border-style: dashed; border-color: var(--ink-3); }

@media (max-width: 640px) {
  /* A shorter box on a phone, so the list below stays within a thumb's reach — the map pans and
     zooms, so nothing is lost to the smaller window. The markers keep their full size: a marker
     squeezed down is not a smaller map, it is an unreadable one. */
  .pricemap .plot { height: 380px; }
}

/* ── findability: the measured lead, the addressable answer, the share block ─────────── */

/* A price set in the display face would read as a headline; set in the receipt face it reads as a
   figure someone can check. Applies wherever money appears inside a heading. */
h1 .fig { font-family: var(--mono); font-size: .9em; font-variant-numeric: tabular-nums; letter-spacing: -.03em; }

/* The provenance stamp under the headline: how much we hold and when we last looked. Small,
   unglamorous, and the first thing a sceptical reader wants. */
.stamp { font-family: var(--mono); font-size: 12.5px; color: var(--ink-2); margin: -6px 0 26px; }
.stamp a { color: var(--ink-2); text-underline-offset: 3px; }

/* The measured range, rendered by the server into the markup so a shared link carries it. */
.spread { border: 1px solid var(--rule); border-left: 3px solid var(--ledger); border-radius: 4px; background: var(--paper-2); padding: 18px 22px; margin: 0 0 22px; }
.spread .figure {
  font-family: var(--mono); font-size: clamp(26px, 4vw, 38px); font-variant-numeric: tabular-nums;
  letter-spacing: -.03em; margin: 0 0 8px; line-height: 1.1;
}
.spread .says { margin: 0; font-size: 14.5px; color: var(--ink-2); max-width: 74ch; }
.spread .says strong { color: var(--ink); }

/* "What this is and why you can believe it" — counted at render time, never typed in. */
.believe .facts { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 14px; margin-bottom: 8px; }
.believe .fact { border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2); padding: 16px 18px; }
.believe .fact .n { font-family: var(--mono); font-size: 30px; font-variant-numeric: tabular-nums; letter-spacing: -.03em; color: var(--ledger); line-height: 1.1; }
.believe .fact .d { font-size: 13.5px; color: var(--ink-2); margin-top: 7px; }

.share { margin-top: 30px; padding-top: 20px; border-top: 1px dashed var(--rule); }
.sharelink {
  display: inline-block; font-family: var(--mono); font-size: 13.5px; word-break: break-all;
  border: 1px solid var(--rule); border-radius: 3px; background: var(--paper-2);
  padding: 9px 12px; color: var(--ink-2); text-decoration: none;
}
.sharelink:hover { border-color: var(--ledger); color: var(--ledger); }

/* ── admin shell (/admin, Bucket 3) ───────────────────
   Operator chrome only. Reuses the brand tokens above unchanged — no new palette, no new
   meanings: `signal` still means money, so nothing here reaches for it. Operator surfaces are
   information-dense: smaller type, tables first, no hero treatment. */
body.admin { font-size: 15px; }
body.admin h1 { font-size: 26px; letter-spacing: -.015em; margin: 26px 0 10px; }
body.admin h2 { font-size: 19px; }
.admin-note { font-size: 14px; color: var(--ink-2); max-width: 74ch; margin: 0 0 18px; }

.admin-bar { display: flex; align-items: baseline; justify-content: space-between; gap: 16px; padding-top: 14px; padding-bottom: 10px; }
.admin-bar .mark .ops { font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase; color: var(--ink-3); margin-left: 8px; }
.admin-operator { display: flex; align-items: baseline; gap: 12px; font-size: 13.5px; }
.admin-operator .who { font-family: var(--mono); color: var(--ink-2); }
.admin-operator form { margin: 0; display: inline; }
.admin-operator button {
  font: inherit; font-size: 13px; cursor: pointer; padding: 5px 12px; border-radius: 3px;
  border: 1px solid var(--rule); background: var(--paper-2); color: var(--ink-2);
}
.admin-operator button:hover { border-color: var(--ledger); color: var(--ledger); }

nav.admin-nav { display: flex; gap: 4px 16px; flex-wrap: wrap; padding-bottom: 12px; font-size: 13.5px; }
nav.admin-nav a { text-decoration: none; color: var(--ink-2); }
nav.admin-nav a:hover { color: var(--ledger); text-decoration: underline; text-underline-offset: 3px; }
/* Queue slots that land in later phases: present so the shell's shape is stable, visibly inert. */
nav.admin-nav a.soon { color: var(--ink-3); cursor: default; }
nav.admin-nav a.soon:hover { color: var(--ink-3); text-decoration: none; }

.admin-login { max-width: 420px; margin: 48px auto 0; }
.admin-form { display: grid; gap: 14px; margin-top: 18px; }
.admin-form label { font-size: 14px; color: var(--ink-2); display: grid; gap: 6px; }
.admin-form input {
  font: inherit; font-size: 16px; color: var(--ink); background: var(--paper-2);
  border: 1.5px solid var(--rule); border-radius: 3px; padding: 11px 13px;
}
.admin-form button {
  font: inherit; font-size: 15px; font-weight: 600; border: 0; cursor: pointer;
  background: var(--ledger); color: var(--paper); padding: 12px 24px; border-radius: 3px;
  justify-self: start;
}
.admin-form button:hover { filter: brightness(1.08); }
/* A second-rank action inside a form (the address lookup): unmistakably a button, unmistakably
   not the one that commits the record. */
.admin-form button.secondary {
  background: transparent; color: var(--ink-2); border: 1px solid var(--rule);
  font-weight: 500; font-size: 14px; padding: 9px 16px;
}
.admin-form button.secondary:hover { border-color: var(--ledger); color: var(--ledger); filter: none; }

/* Selects carried the browser's default chrome — a white slab on the operator's dark ground, and
   the one thing on the page that did not belong to the palette (owner feedback). The native
   control is switched off and rebuilt from the same tokens the inputs use, so it matches in both
   themes; the chevron is drawn in CSS from --ink-3 rather than an image, so it follows the theme
   too. The wrapper exists only to hang the chevron on. */
.selectwrap { position: relative; display: block; }
.selectwrap::after {
  content: ""; position: absolute; right: 14px; top: 50%; margin-top: -2px;
  width: 0; height: 0; pointer-events: none;
  border-left: 5px solid transparent; border-right: 5px solid transparent;
  border-top: 6px solid var(--ink-3);
}
.admin-form select {
  width: 100%; font: inherit; font-size: 15px; color: var(--ink); background: var(--paper-2);
  border: 1.5px solid var(--rule); border-radius: 3px; padding: 10px 38px 10px 12px;
  appearance: none; -webkit-appearance: none;
}
.admin-form select:hover { border-color: var(--ledger); }
.admin-form option { background: var(--paper-2); color: var(--ink); }

/* ── admin: operator tables ───────────────────────────
   The list is scanned, not read: fixed columns so every row starts in the same place, hairline
   rules instead of boxes, labels in the receipt face, and no cell allowed to set its own width.
   Wide tables scroll inside their own scroller — the page itself never moves sideways. */
.admin-scroller { position: relative; overflow-x: auto; margin: 0 0 20px; }
.admin-table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
.admin-table th, .admin-table td {
  text-align: left; vertical-align: top; padding: 10px 16px 10px 0;
  border-bottom: 1px solid var(--rule);
}
.admin-table th:last-child, .admin-table td:last-child { padding-right: 0; }
.admin-table thead th {
  font-family: var(--mono); font-size: 11px; font-weight: 500; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3); white-space: nowrap;
  padding-top: 0; padding-bottom: 8px; border-bottom: 1.5px solid var(--rule);
}
.admin-table tbody tr:hover { background: var(--paper-2); }
.admin-table td.dim { color: var(--ink-2); }
body.admin .mono { font-family: var(--mono); font-variant-numeric: tabular-nums; }

.admin-candidates { table-layout: fixed; min-width: 760px; }
.admin-candidates .c-name { width: 32%; }
.admin-candidates .c-system { width: 18%; }
.admin-candidates .c-reason { width: 38%; }
.admin-candidates .c-source { width: 12%; }
.admin-candidates td.reason { color: var(--ink-2); }
.admin-candidates a.row-open { font-weight: 600; text-decoration: none; }
.admin-candidates a.row-open:hover { text-decoration: underline; }

/* The registry list carries six facts per row, so the columns are pinned and the secondary fact in
   a cell (the system, a status reason) drops under the primary one rather than widening it. Same
   table, same rules, same face as the candidate queue — only the column plan differs. */
.admin-sources { table-layout: fixed; min-width: 900px; }
.admin-sources .c-where { width: 27%; }
.admin-sources .c-state { width: 16%; }
.admin-sources .c-fresh { width: 17%; }
.admin-sources .c-fail { width: 8%; }
.admin-sources .c-cadence { width: 12%; }
.admin-sources .c-act { width: 20%; }
.admin-sources a.row-open { font-weight: 600; text-decoration: none; }
.admin-sources a.row-open:hover { text-decoration: underline; }
.admin-sources .sub { display: block; font-size: 12.5px; color: var(--ink-3); margin-top: 2px; }
/* A per-row action is a button, not a link dressed as one, because it posts. Sized and coloured
   like the sign-out control in the bar — the same rank of action, so the same weight. */
.admin-rowform { display: inline; margin: 0 0 0 8px; }
.admin-rowform button {
  font: inherit; font-size: 12px; cursor: pointer; padding: 4px 10px; border-radius: 3px;
  border: 1px solid var(--rule); background: var(--paper-2); color: var(--ink-2);
}
.admin-rowform button:hover { border-color: var(--ledger); color: var(--ledger); }

/* The source URL was 140 characters of monospace setting the width of the whole table. Reduced to
   a handle that still opens the file; the full URL is the link target, the tooltip, and is printed
   in full on the detail page. Provenance is not hidden, it just stops shouting. */
.urlchip {
  display: inline-flex; align-items: baseline; gap: 6px; max-width: 100%;
  font-family: var(--mono); font-size: 12px; text-decoration: none;
  border: 1px solid var(--rule); border-radius: 3px; background: var(--paper-2);
  color: var(--ink-2); padding: 4px 9px;
}
.urlchip .name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.urlchip .glyph { flex: none; }
.urlchip:hover { border-color: var(--ledger); color: var(--ledger); }
.urlfull { font-family: var(--mono); font-size: 13px; overflow-wrap: anywhere; }

.admin-count { font-family: var(--mono); font-size: 12.5px; color: var(--ink-3); margin: 0 0 12px; }
.admin-pager { display: flex; gap: 20px; font-size: 13.5px; margin: 0 0 10px; }
.admin-back { font-size: 13.5px; margin: 18px 0 0; }

/* ── admin: sections and facts ────────────────────────
   Generous between sections, tight within them. A section announces itself with a ruled heading so
   the eye can find where one decision ends and the next begins. */
.admin-panel { margin-top: 40px; }
.admin-panel > h2 { margin-bottom: 10px; padding-bottom: 8px; border-bottom: 1px solid var(--rule); }
.admin-panel > h2 + .admin-note { margin-top: 0; }

/* Evidence: one fact per line, label column fixed, value never hunted for. The discovery attempt
   is several facts, not one sentence — an operator looks for the status code, they do not read. */
.admin-facts { margin: 0; }
.admin-facts .fact {
  display: grid; grid-template-columns: 200px minmax(0, 1fr); gap: 4px 22px;
  align-items: baseline; padding: 12px 0; border-bottom: 1px solid var(--rule);
}
.admin-facts dt {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-3);
}
.admin-facts dd { margin: 0; font-size: 14.5px; color: var(--ink); min-width: 0; overflow-wrap: anywhere; }
.admin-facts .tag {
  display: inline-block; font-family: var(--mono); font-size: 12px; padding: 2px 8px;
  border: 1px solid var(--rule); border-radius: 3px; background: var(--paper-2); color: var(--ink-2);
}
.admin-facts .because { color: var(--ink-2); font-size: 13.5px; margin-left: 8px; }

/* ── admin: form grouping ─────────────────────────── */
.admin-inline { display: flex; flex-wrap: wrap; align-items: end; gap: 12px; }
.admin-inline label { flex: 1 1 340px; max-width: 520px; }
.admin-filter { display: flex; flex-wrap: wrap; align-items: end; gap: 12px; margin: 0 0 22px; }
.admin-filter label { flex: 1 1 320px; max-width: 460px; }
.admin-filter button { font-size: 14px; padding: 10px 20px; }

.admin-fieldset {
  border: 1px solid var(--rule); border-radius: 4px; margin: 0;
  padding: 6px 20px 22px; display: grid; gap: 16px;
}
.admin-fieldset legend {
  font-family: var(--mono); font-size: 11.5px; letter-spacing: .09em; text-transform: uppercase;
  color: var(--ink-3); padding: 0 8px; margin-left: -8px;
}
.admin-row3 { display: grid; grid-template-columns: 2.2fr .8fr 1fr; gap: 14px; }
.admin-subhead { margin-top: 6px; padding-top: 18px; border-top: 1px solid var(--rule); }
.admin-subhead h3 {
  font-family: var(--mono); font-size: 11.5px; font-weight: 500; letter-spacing: .1em;
  text-transform: uppercase; color: var(--ink-3); margin: 0 0 8px;
}
.admin-subhead .hint { font-size: 13px; color: var(--ink-2); margin: 0; max-width: 72ch; }

/* "or" between two forms that do the same job different ways. */
.admin-or {
  display: flex; align-items: center; gap: 14px; margin: 26px 0;
  font-family: var(--mono); font-size: 11px; letter-spacing: .12em; text-transform: uppercase;
  color: var(--ink-3);
}
.admin-or::before, .admin-or::after { content: ""; flex: 1; height: 1px; background: var(--rule); }

/* A checkbox is a statement, not a stray control: the box sits beside its statement, and the
   statement can carry the line explaining what the flag decides. */
.admin-check {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0 11px; align-items: start;
  font-size: 14px; color: var(--ink);
}
.admin-check input { margin: 2px 0 0; width: 16px; height: 16px; accent-color: var(--ledger); }
.admin-check .what { display: block; font-weight: 600; }
.admin-check .what .hint {
  display: block; font-weight: 400; font-size: 13px; color: var(--ink-2); margin-top: 6px;
  max-width: 64ch; letter-spacing: 0; text-transform: none;
}
.admin-check.boxed { border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2); padding: 14px 16px; }

/* Button first, then the answer on its own line: a result squeezed into the column beside the
   button wraps to four short lines and reads worse than the thing it is explaining. */
.admin-lookup { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 16px; }
.admin-lookup p { flex: 1 1 100%; margin: 0; font-size: 13px; max-width: 78ch; }
.admin-lookup .found { color: var(--ink-2); }
.admin-lookup .unavailable { color: var(--ink-3); }
.admin-choices {
  border: 1px dashed var(--rule); border-radius: 4px; margin: 0; padding: 6px 16px 16px;
  display: grid; gap: 12px;
}
.admin-choices legend { font-size: 12.5px; color: var(--ink-2); padding: 0 6px; margin-left: -6px; }

/* Terminal actions. Set apart and softened rather than reddened: `signal` means money the reader
   could keep, and nothing else is allowed to borrow it. */
.admin-panel.admin-danger {
  border: 1px dashed var(--rule); border-radius: 4px; background: var(--paper-2);
  padding: 18px 22px 24px; margin-top: 46px;
}
.admin-panel.admin-danger > h2 { border-bottom: 0; padding-bottom: 0; margin-bottom: 6px; }
.admin-danger .admin-form input, .admin-danger .admin-form select { background: var(--paper); }

@media (max-width: 640px) {
  .admin-facts .fact { grid-template-columns: 1fr; gap: 3px; }
  .admin-row3 { grid-template-columns: 1fr; }
  .admin-fieldset { padding-left: 14px; padding-right: 14px; }
  .admin-panel.admin-danger { padding-left: 14px; padding-right: 14px; }
}

/* ── The integrator's page (/docs) ────────────────────────────────────────────
   No new colour tokens: every rule below reuses the palette the rest of the site
   is swept for, so `scripts/check-contrast.py` continues to cover this page by
   already covering the tokens. A documentation page that needed its own ink
   would be a documentation page nobody had checked. */
.docs { padding-bottom: 20px; }
.docs p { font-size: 16px; line-height: 1.62; color: var(--ink-2); max-width: 72ch; margin: 0 0 16px; }
.docs p strong, .docs li strong { color: var(--ink); }
.docs section { margin-top: 46px; }
.docs h2 { margin-bottom: 14px; }
.docs h3 { font-size: 16.5px; margin-bottom: 4px; }
.docs em { font-style: italic; }

.docs-toc { border: 1px solid var(--rule); border-radius: 4px; background: var(--paper-2); padding: 16px 22px; margin: 26px 0 0; }
.docs-toc ol { margin: 0; padding-left: 20px; columns: 2; column-gap: 30px; }
.docs-toc li { font-size: 14.5px; margin-bottom: 6px; break-inside: avoid; }

.docs-list { max-width: 72ch; margin: 0 0 16px; padding-left: 22px; }
.docs-list li { font-size: 16px; line-height: 1.6; color: var(--ink-2); margin-bottom: 10px; }

.docs code {
  font-family: var(--mono); font-size: .88em; color: var(--ink);
  background: var(--paper-2); border: 1px solid var(--rule); border-radius: 3px; padding: 1px 5px;
}
.docs th code, .docs pre code { background: transparent; border: 0; padding: 0; }

/* The command a reader copies. Its own scroller so a long URL scrolls inside the
   block instead of widening the page — and a containing block, per the rule every
   horizontal scroller here follows. */
.docs-code {
  position: relative; overflow-x: auto; margin: 0 0 10px;
  border: 1px solid var(--rule); border-left: 3px solid var(--ledger); border-radius: 3px;
  background: var(--paper-2); padding: 13px 16px;
  font-family: var(--mono); font-size: 13px; line-height: 1.5; color: var(--ink);
}
.docs-code:focus-visible { outline: 2px solid var(--ledger); outline-offset: 2px; }

.docs-example { margin: 0 0 26px; padding-top: 20px; border-top: 1px dashed var(--rule); }
.docs-example .docs-purpose { font-size: 14.5px; margin-bottom: 12px; max-width: 72ch; }
.docs-example .docs-claim { font-size: 14px; color: var(--ink-2); max-width: 72ch; margin: 0; }
.docs-expect {
  font-family: var(--mono); font-size: 11px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ledger); border: 1px solid var(--ledger); border-radius: 100px;
  padding: 2px 8px; margin-right: 8px; white-space: nowrap;
}

.docs-table { margin-top: 0; }
.docs-table td { font-size: 14.5px; color: var(--ink-2); }
.docs-table tbody th { font-family: var(--mono); font-size: 13px; white-space: nowrap; }

@media (max-width: 640px) {
  .docs-toc ol { columns: 1; }
}
