/* The apparatus face: Archivo, self-hosted (latin subset, 400/600, ~29KB total,
   OFL — licence at fonts/OFL.txt). A grotesque drawn from newsprint lineage, which is
   the genre. Self-hosted because the system stack carried zero identity and a runtime
   fetch from a font CDN is banned (no external assets). font-display: swap — content
   is present on arrival in the fallback, never blanked. */
@font-face {
  font-family: "Fraunces";
  src: url("fonts/fraunces-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("fonts/inter-var.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* Palette: paper + ink + two muted inks + one spot + one data ramp + two poles.
   Every value below was computed, not chosen by eye:
   - `--faint` was 2.89:1 on --bg and failed WCAG 1.4.3 for the small-caps apparatus
     it is used on. It is now 4.54:1.
   - The fit signal is DIVERGING, not categorical: within ←→ outside with "worth
     reviewing" as a genuine midpoint. A hue at a diverging midpoint is wrong, and the
     amber that used to sit there could not be separated from the red pole inside the
     dark-mode lightness band (ΔE 11.5, floor 15). The midpoint is now neutral ink and
     the three states are carried by MARK SHAPE — disc / ring / diamond — so they
     survive greyscale print and colour-vision deficiency, where the two poles have
     nearly identical luminance.
   - Severity is a sequential single-hue ramp with real steps (not opacity), monotone in
     lightness, each step ≥0.06 L apart, light end clearing the surface at ≥2:1.
   Validator: dataviz skill, `scripts/validate_palette.js` — poles pass all six checks
   in light mode and pass with a CVD warning in dark (legal: label + shape encoding);
   both ramps pass all four ordinal checks. */
:root {
  --bg: #fbfaf7;
  --surface: #ffffff;
  --ink: #151515;
  --muted: #555555;
  --faint: #6b6b6b;
  --line: #e9e6df;
  --line-strong: #cfcbc2;
  /* 2026-08-01 visual QA: bronze is not only a mark (focus rings, active rules) — it is
     also resting-state TEXT (.orientation-dismiss, .source-list a, .resource-link a),
     and the old #8a6d3f measured 4.40:1 on --bg, under the 4.5:1 WCAG 1.4.3 floor normal
     text needs (an automated per-page contrast audit caught .orientation-dismiss's "Got
     it" link at 11px). Darkened to clear 4.5:1 on both surfaces; verify's palette check
     now holds bronze to the text floor, not the looser 3:1 mark floor, so this cannot
     regress silently. */
  /* 2026-09-30 REDESIGN — BibleDo law, not taste. DESIGN-DOCTRINE §4: the Brown Ban
     (the old bronze #83683c and its ramp sat in the banned mud zone, hue 25-50 under 60%
     saturation), gold/amber as the brand accent used as LIGHT on true black or clean warm
     white, and "no teal brand law". --bronze keeps its NAME because verify and forty rules
     read it, but it is now ember in light (#b45309, 94% saturation, so not mud; 5.0:1 as
     text) and candle-gold in dark. Severity moved to a NEUTRAL ink ramp: colour is
     reserved for the fit badge and for gold-as-light, so a heavier meter reads as more ink,
     never as a warmer brown. */
  --bronze: #b45309;
  --gold: #f59e0b;          /* fills and highlights only; never text on white */
  --on-gold: #0b0b0b;
  --action: #151515;        /* the one solid control: House Rules, a chosen line */
  --on-action: #ffffff;
  --plate-bg: #f3f1ec;
  --plate-ink: #151515;
  --hover: #f3f1ec;
  --sev-1: #a3a3a3;
  --sev-2: #5c5c5c;
  --sev-3: #151515;
  --good: #15803d;
  --caution: #6b6b6b;
  --poor: #b91c1c;
  /* ---------- type scale ----------
     Derived from the file, not invented: every font-size that survived the audit is one
     of these eighteen steps. Eleven of them already carried three or more rules; the
     rest name a role nothing else plays (the essay body, the review title, the masthead).
     Scale contrast is a charter requirement, so the ends are far apart on purpose:
     9.5px record keys against a 40px masthead.

     RULE FOR ADDING A SIZE: a new size must be added here as a token and referenced by
     name. This is machine-enforced: `verify` fails on any raw px font-size or em
     tracking outside this block, the print block, and the declared exceptions below.

     Deliberately NOT tokenised, and still raw literals below: the print block (pt units),
     the 46px drop cap, and five one-off sizes listed in the refactor notes. */
  --t-nano: 12px;        /* record keys, the smallest small-caps that still reads */
  --t-micro: 12px;      /* the workhorse apparatus caps: table heads, meta, stance */
  --t-label: 12.5px;        /* second caps step: badges, chips, format lines */
  --t-label-lg: 13px;   /* third caps step: section heads, definition terms */
  --t-caption: 13px;      /* caption caps and the footer line */
  --t-ui: 14px;           /* interactive controls: buttons, chips, tabs, selects */
  --t-body-sm: 15px;      /* dense body: table cells, notices, asides */
  --t-body: 16px;       /* default body copy */
  --t-prose-sm: 16px;     /* set prose in a narrow measure */
  --t-prose: 16.5px;      /* page base — the body rule resolves to this */
  --t-prose-lg: 18px;     /* comparison-table titles, empty state */
  --t-essay: 18px;      /* the criticism essay only: longest measure on the page */
  --t-h4: 19px;           /* entry titles inside a panel */
  --t-h3: 24px;           /* the tier-1 verdict */
  --t-h2: 28px;           /* panel headings */
  --t-h1: 32px;           /* stat figures and the modal close glyph */
  --t-title: clamp(30px, 3.4vw, 44px);        /* the review title */
  --t-masthead: 25px;      /* the wordmark; the hero now carries the display type */
  --t-card-title: 21px;    /* card titles, Fraunces */
  --t-hero: clamp(40px, 5.4vw, 76px);
  --t-rules: clamp(23px, 2.6vw, 36px);     /* the house rules, said as a sentence */

  /* ---------- tracking scale ----------
     Small caps need tracking and it scales inversely with size, so these are a ramp, not
     a set of roles: the smaller the caps, the wider the step. --tr-caps-micro is named
     for the size it pairs with (--t-micro), which is why it sits out of the
     tight/wide/wider/widest sequence by name but in order by value. Same rule as above,
     and the same verify check enforces it. */
  --tr-display: -.015em;      /* display type needs almost none */
  --tr-caps-tight: .06em;   /* caps at 12px and up */
  --tr-caps: .08em;         /* control caps at 13px */
  --tr-caps-wide: .1em;     /* caps at 11px */
  --tr-caps-wider: .12em;   /* caps at 11.5px */
  --tr-caps-micro: .13em;   /* the --t-micro apparatus step */
  --tr-caps-widest: .14em;
  --tr-hero: -.03em;        /* display type tightens with size, never uniformly */  /* the rail and section heads */

  /* BibleDo law: Fraunces for titles and His words, Inter for ours. Nothing else. */
  --serif: "Fraunces", Georgia, "Times New Roman", serif;
  --sans: "Inter", -apple-system, "Segoe UI", system-ui, sans-serif;
}
@media (prefers-color-scheme: dark) {
  :root {
    /* True neutral greys — no hue at all, so they can never read brown (the old #16140f
       did) or lavender (the register's 2026-09-05 "purple = ai slop" row). The music app
       is the doctrine's named reference: near-black grounds, amber as the only warmth. */
    --bg: #0b0b0b;
    --surface: #151515;
    --ink: #f5f5f4;
    --muted: #a8a8a8;
    --faint: #8f8f8f;
    --line: #262626;
    --line-strong: #3d3d3d;
    --bronze: #fbbf24;
    --gold: #f59e0b;
    --on-gold: #0b0b0b;
    --action: #fbbf24;
    --on-action: #0b0b0b;
    --plate-bg: #101010;
    --plate-ink: #f59e0b;
    --hover: #1e1e1e;
    /* Heavier = brighter here, because the ground is dark: still one neutral hue, still
       monotone, so it survives greyscale and never borrows the fit badge's colours. */
    --sev-1: #525252;
    --sev-2: #a3a3a3;
    --sev-3: #fafafa;
    --good: #4ade80;
    --caution: #a8a8a8;
    --poor: #f87171;
  }
}
* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
  border-radius: 4px;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  * { transition: none !important; animation: none !important; }
}
body {
  margin: 0;
  font: var(--t-prose)/1.6 var(--sans);
  background: var(--bg);
  color: var(--ink);
  -webkit-font-smoothing: antialiased;
}

/* Skip link: hidden until focused, then a real element at the top — keyboard users
   otherwise tab through the masthead, search, nine filters and two selects to reach
   the first title. */
.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: 10px 18px;
  background: var(--ink);
  color: var(--bg);
  font-family: var(--sans);
  font-size: var(--t-ui);
  letter-spacing: var(--tr-caps);
  text-transform: uppercase;
  text-decoration: none;
}
.skip-link:focus { left: 0; }

/* ---------- prototype note ---------- */
.demo-banner {
  font-size: var(--t-caption);
  color: var(--faint);
  text-align: center;
  padding: 7px 16px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

/* ---------- header ---------- */
.site-header {
  display: flex;
  flex-wrap: wrap;
  gap: 14px 24px;
  align-items: center;
  justify-content: space-between;
  max-width: 1240px;
  margin: 0 auto;
  padding: 20px 32px 16px;
}
.brand { display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; }
/* The masthead is the page's h1 — it was a <span>, so the document had no first-level
   heading at all and a screen-reader outline started at h2. */
.brand-name {
  font-family: var(--serif);
  font-size: var(--t-masthead);
  font-weight: 700;
  letter-spacing: var(--tr-display);
  line-height: 1;
  margin: 0;
}
/* Figures are tabular wherever they can be compared down a column, so digits align. */
.craft-num, .card-year, .summary-meta, .modal-craft, .results-meta {
  font-variant-numeric: tabular-nums;
}
.brand-tag {
  font-size: var(--t-body-sm);
  color: var(--muted);
}
.header-actions { display: flex; gap: 10px; align-items: center; }
#search {
  padding: 10px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: var(--surface);
  color: var(--ink);
  width: min(300px, 58vw);
  font-size: var(--t-body-sm);
  font-family: var(--sans);
  transition: border-color 150ms;
}
/* 2026-08-01 visual QA: this used to suppress the outline entirely (`outline: none`)
   and rely on a 1px border-color change alone, which is a much fainter signal than the
   2px outline every other interactive element on the page uses — a keyboard walk of the
   header found it as the one focus state that reads differently. The border-color
   change is harmless and stays; the global :focus-visible outline (styles.css, top of
   file) is no longer overridden, so the search field matches the rest of the page. */
#search:focus { border-color: var(--bronze); }
#search::placeholder { color: var(--faint); }
.btn {
  padding: 10px 18px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  font-size: var(--t-ui);
  font-weight: 600;
  cursor: pointer;
  font-family: var(--sans);
  transition: background-color 150ms, border-color 150ms, color 150ms;
}
.btn:hover { border-color: var(--ink); }
.btn-accent { background: var(--action); color: var(--on-action); border-color: var(--action); }
.btn-accent:hover { background: var(--gold); color: var(--on-gold); border-color: var(--gold); }

/* ---------- section nav ----------
   A broadsheet's section line: words on a rule. No pills, no buttons, no box — the state
   is carried by ink weight and the 2px rule under the current section, which is the same
   vocabulary the filter chips and the modal tabs already use, so the page has one idea of
   "you are here" rather than three. It WRAPS, like every other control row in this file:
   nothing may sit off an edge behind a fade. */
.site-nav {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.nav-inner {
  display: flex;
  flex-wrap: wrap;
  gap: 0 28px;
  max-width: 1240px;
  margin: 0 auto;
  padding: 0 32px;
}
.nav-link {
  display: inline-block;
  padding: 12px 0 10px;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  color: var(--muted);
  font-size: var(--t-ui);
  font-weight: 500;
  text-decoration: none;
  transition: color 150ms, border-color 150ms;
}
.nav-link:hover { color: var(--ink); }
.nav-link:active { color: var(--bronze); }
.nav-link.active { color: var(--ink); border-bottom-color: var(--gold); }

/* ---------- profile panel ---------- */
.profile-panel { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--surface); }
.profile-inner { max-width: 1200px; margin: 0 auto; padding: 30px 32px 26px; }
.profile-inner h2 { font-family: var(--serif); font-weight: 600; margin: 0 0 6px; font-size: var(--t-h2); }
.muted { color: var(--muted); font-size: var(--t-body-sm); }
.profile-controls {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 18px;
  margin: 22px 0 18px;
}
.profile-control label {
  display: block;
  font-size: var(--t-label-lg);
  color: var(--muted);
  margin-bottom: 7px;
}
.profile-control select {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: var(--bg);
  color: var(--ink);
  font-size: var(--t-body);
  font-family: var(--sans);
}
.profile-footer { display: flex; justify-content: space-between; align-items: center; }

/* ---------- main ---------- */
main { max-width: 1240px; margin: 0 auto; padding: 10px 32px 72px; }   /* the same edge as the header and the front door */

/* ---------- apparatus rail ----------
   A maintained document states what it holds and when it was last touched. Both hairlines
   have a sectioning job: the top rule closes the masthead, the bottom rule separates the
   provenance line from the controls under it, and the filter row keeps its own rule
   separating controls from content. Tabular figures because the date and the counts are
   numerals in an apparatus line, not prose. Wraps to a second line on narrow screens —
   nothing here may sit off an edge. */
.apparatus-rail {
  margin: 0;
  padding: 10px 2px 10px;
  font-size: var(--t-caption);
  line-height: 1.5;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}

/* ---------- first-visit line ----------
   A standing note, not a toast: it arrives with the page, it does not slide, fade or
   float, and it takes one line of the document's own width. The dismiss control is a word
   on a rule for the same reason the nav is — a filled pill here would be the loudest thing
   on a page whose loudest thing should be the masthead. */
.orientation {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 6px 20px;
  margin: 0 0 6px;
  padding: 12px 2px 12px;
  border-bottom: 1px solid var(--line);
}
.orientation-text {
  flex: 1 1 320px;
  font-size: var(--t-body-sm);
  line-height: 1.55;
  color: var(--muted);
}
.orientation-text b { color: var(--ink); font-weight: 600; }
.orientation-dismiss {
  flex: none;
  padding: 0;
  border: none;
  border-bottom: 1px solid currentColor;
  background: none;
  color: var(--bronze);
  font-family: var(--sans);
  font-size: var(--t-caption);
  font-weight: 600;
  cursor: pointer;
}
.orientation-dismiss:hover { color: var(--ink); }

.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 14px;
}
.chip {
  padding: 8px 14px 8px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: transparent;
  color: var(--muted);
  font-size: var(--t-ui);
  font-weight: 500;
  cursor: pointer;
  font-family: var(--sans);
  transition: background-color 150ms, border-color 150ms, color 150ms;
}
.chip:hover { color: var(--ink); border-color: var(--ink); }
.chip.active { color: var(--on-action); background: var(--action); border-color: var(--action); }
/* Weight stays constant between states — the 600 flip used to reflow the whole filter row
   on every click. Colour + the underline carry the state. */
.chip:active, .tab:active, .btn:active, .sort-btn:active, .alt-link:active { color: var(--bronze); }
.card:active { border-color: var(--bronze); }
.record-table tbody tr:active { background: var(--line); }
.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 comparison table ----------
   Density is the point: ~32px rows, tabular figures, hairlines between rows and a heavier
   rule under the header. Two leadings on one page — this is the tight one. */
.table-wrap { overflow-x: auto; }
.record-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-body-sm);
  font-variant-numeric: tabular-nums;
}
.record-table thead th {
  position: sticky;
  top: 0;
  z-index: 2;
  background: var(--bg);
  text-align: left;
  font-family: var(--sans);
  font-size: var(--t-micro);
  letter-spacing: var(--tr-caps-micro);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--muted);
  padding: 10px 10px 8px;
  border-bottom: 1.5px solid var(--line-strong);
  white-space: nowrap;
}
.record-table th.num, .record-table td.num { text-align: center; }
.record-table th abbr { text-decoration: none; border-bottom: 1px dotted var(--line-strong); cursor: help; }
/* Column heads are buttons wearing the th's own apparatus: same 10.5px small caps, same
   --muted, no button chrome, no radius, no lift. The active column goes to --ink; the
   1.5px rule under the header row belongs to the th and is untouched. */
.record-table thead th .sort-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  font: inherit;
  color: inherit;
  letter-spacing: inherit;
  text-transform: inherit;
  text-align: inherit;
  cursor: pointer;
}
.record-table thead th .sort-btn:hover { color: var(--ink); }
.record-table thead th.sorted { color: var(--ink); }
/* Direction is a SHAPE, not a colour: the up triangle is drawn for ascending, the down one
   for descending. Both sit faint on an unsorted column, which is what says the head is
   clickable at all. Built from borders — no glyph, no image, nothing to fetch. */
.sort-mark {
  position: relative;
  display: inline-block;
  width: 8px;
  height: 11px;
  flex: none;
}
.sort-mark::before, .sort-mark::after {
  content: "";
  position: absolute;
  left: 0;
  width: 0;
  height: 0;
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
}
.sort-mark::before { top: 0; border-bottom: 4px solid var(--faint); }
.sort-mark::after { bottom: 0; border-top: 4px solid var(--faint); }
.sort-mark.asc::after, .sort-mark.desc::before { content: none; }
.sort-mark.asc::before { border-bottom-color: var(--ink); }
.sort-mark.desc::after { border-top-color: var(--ink); }
.record-table tbody tr {
  border-bottom: 1px solid var(--line);
  cursor: pointer;
}
.record-table tbody tr:hover { background: var(--surface); }
.record-table tbody tr:hover .t-title { color: var(--bronze); }
.record-table td { padding: 7px 10px; vertical-align: middle; }
.t-title { font-family: var(--serif); font-size: var(--t-prose-lg); font-weight: 600; min-width: 190px; }
.t-format { font-size: var(--t-label); color: var(--muted); white-space: nowrap; }
.t-craft { font-family: var(--serif); font-size: var(--t-prose-lg); font-weight: 600; }
.record-table .sev-meter { gap: 2px; margin: 0 auto; justify-content: center; }
.record-table .sev-seg { width: 9px; }
.record-table td.over { box-shadow: inset 0 -2px 0 var(--poor); }
.over-mark { font-family: var(--serif); font-size: var(--t-ui); color: var(--poor); margin-left: 2px; vertical-align: super; }
.record-table .badge { border-top: none; padding-top: 0; font-size: var(--t-micro); white-space: nowrap; }
.record-table .t-fit { min-width: 90px; }

/* family view: the notice is not decoration — a shortened list must say it is shortened */
.view-notice {
  margin: 0 0 16px;
  padding: 11px 14px;
  border: 1px solid var(--line-strong);
  border-left: 3px solid var(--bronze);
  border-radius: 4px;
  background: var(--surface);
  color: var(--muted);
  font-family: var(--sans);
  font-size: var(--t-body-sm);
  line-height: 1.55;
}

/* a title listed rather than described */
.outside-list { margin-top: 42px; padding-top: 8px; border-top: 1px solid var(--line); }
.outside-head {
  font-family: var(--sans);
  font-size: var(--t-label);
  font-weight: 600;
  color: var(--muted);
  margin: 18px 0 6px;
}
.summary-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 8px 16px;
  width: 100%;
  margin: 0;
  padding: 13px 4px;
  border: none;
  border-bottom: 1px solid var(--line);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.summary-row:hover .summary-title { color: var(--bronze); }
.summary-title { font-family: var(--serif); font-size: var(--t-h4); font-weight: 600; }
.summary-meta { font-size: var(--t-micro); color: var(--faint); }
.summary-row .badge { border-top: none; padding-top: 0; align-self: baseline; margin-left: auto; }

.withheld {
  font-family: var(--sans);
  font-size: var(--t-label);
  color: var(--faint);
}
.withheld-lede {
  font-family: var(--sans);
  font-size: var(--t-h4);
  line-height: 1.55;
  margin: 0 0 18px;
}
.rules-sub {
  font-family: var(--sans);
  font-size: var(--t-label-lg);
  font-weight: 600;
  margin: 26px 0 6px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}

.list-bar {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 20px;
  align-items: baseline;
  justify-content: space-between;
  margin: 2px 2px 22px;
}
.results-meta { color: var(--faint); font-size: var(--t-ui); font-family: var(--sans); }
.sort-control { display: flex; align-items: center; gap: 9px; }
.sort-control label {
  font-size: var(--t-micro);
  color: var(--faint);
}
.sort-control select {
  padding: 5px 8px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: var(--surface);
  color: var(--ink);
  font-size: var(--t-ui);
  font-family: var(--sans);
}

/* ---------- the front door (2026-10-14) ----------
   Tonight's band, then the household's lines said as one sentence. Owner, 2026-10-12: real
   artwork, not drawings made in code, and the opportunity cost beside the rating. The band
   is a screening room, so it is dark in both themes and computed like the rest: #f5f5f4 on
   #0b0b0b is 18.9:1, the muted #c4c4c1 is 11.6:1, gold #fbbf24 is 11.4:1. Colour comes from
   the artwork; gold marks only the one button and the bar for the Word. */
.hero { padding: 0; }
.on {
  --room: #0b0b0b;
  --room-ink: #f5f5f4;
  --room-muted: #c4c4c1;
  --room-gold: #fbbf24;
  --room-good: #4ade80;
  --room-poor: #f87171;
  background: var(--room);
  color: var(--room-ink);
}
.on-in {
  max-width: 1240px;
  margin: 0 auto;
  padding: 40px 32px 26px;
  display: grid;
  grid-template-columns: minmax(0, 340px) minmax(0, 1fr);
  gap: 56px;
  align-items: center;
}
.on-in.wide { grid-template-columns: minmax(0, 540px) minmax(0, 1fr); }
.on-art { width: 100%; justify-self: center; }
.on-art.square, .on-art.icon, .on-art.round { max-width: 320px; }
.on-pic { display: block; width: 100%; padding: 0; margin: 0; border: 0; background: none; cursor: pointer; border-radius: 4px; }
.on-pic img { display: block; width: 100%; height: auto; border-radius: 4px; }
.on-art.round .on-pic, .on-art.round img { border-radius: 50%; }
.on-art.icon img { border-radius: 12px; }
.on-facts { margin: 0; font-size: var(--t-ui); color: var(--room-muted); }
.on-title {
  margin: 6px 0 12px;
  font-family: var(--serif);
  font-size: var(--t-hero);
  font-weight: 600;
  line-height: 1.02;
  letter-spacing: var(--tr-hero);
  text-wrap: balance;
}
.on-hook { margin: 0; font-size: var(--t-prose-lg); line-height: 1.5; max-width: 58ch; }
.pair { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 40px; margin-top: 26px; padding-top: 22px; border-top: 1px solid #3d3d3d; }
.big { display: block; font-size: var(--t-h2); font-weight: 650; line-height: 1.15; letter-spacing: var(--tr-display); font-variant-numeric: tabular-nums; }
.on .fit.good .big { color: var(--room-good); }
.on .fit.poor .big { color: var(--room-poor); }
.on .fit p, .on .fit .card-content { margin: 10px 0 0; font-size: var(--t-body-sm); line-height: 1.5; color: var(--room-muted); }
.on .card-content .quiet { color: var(--room-muted); }
.price p { margin: 12px 0 0; font-size: var(--t-body-sm); line-height: 1.5; }
.bars { display: grid; gap: 12px; margin-top: 14px; max-width: 440px; }
.bar { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 5px 14px; align-items: baseline; font-size: var(--t-ui); line-height: 1.3; }
.bar span { color: var(--muted); }
.bar b { font-weight: 500; font-variant-numeric: tabular-nums; }
.bar i { grid-column: 1 / -1; display: block; height: 10px; }
.bar u { display: block; height: 100%; background: var(--sev-1); }
.bar.me span, .bar.me b { color: var(--ink); font-weight: 600; }
.bar.me u { background: var(--ink); }
.bar.word u { background: var(--gold); }
.on .bar span, .on .bar b { color: var(--room-muted); }
.on .bar.me span, .on .bar.me b { color: var(--room-ink); }
.on .bar u { background: #6b6b6b; }
.on .bar.me u { background: var(--room-ink); }
.on .bar.word u { background: var(--room-gold); }
.on-go { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 22px; margin: 28px 0 0; }
.on .btn-accent { background: var(--room-gold); color: var(--room); border-color: var(--room-gold); font-weight: 650; }
.on .btn-accent:hover { background: var(--room-ink); border-color: var(--room-ink); color: var(--room); }
.plain { background: none; border: 0; margin: 0; padding: 10px 2px; color: inherit; font: inherit; font-size: var(--t-ui); text-decoration: underline; text-underline-offset: 4px; cursor: pointer; }
.on-empty { margin: 0; padding: 40px 0; font-size: var(--t-prose-lg); color: var(--room-muted); }
/* The rest of tonight's lineup. It wraps rather than scrolls (charter §5). */
.strip { max-width: 1240px; margin: 0 auto; padding: 4px 32px 28px; list-style: none; display: flex; flex-wrap: wrap; align-items: flex-end; gap: 12px 14px; }
.strip button { display: block; padding: 0 0 8px; margin: 0; background: none; border: 0; border-bottom: 3px solid transparent; cursor: pointer; opacity: .6; transition: opacity 150ms, border-color 150ms; }
.strip button:hover, .strip button[aria-current] { opacity: 1; }
.strip button[aria-current] { border-bottom-color: var(--room-gold); }
.strip img { display: block; width: auto; height: auto; max-height: 72px; max-width: 128px; border-radius: 4px; }
.strip img.round { border-radius: 50%; }
.on.turn .on-in { animation: stage-fade .5s ease-out; }
@keyframes stage-fade { from { opacity: 0; } to { opacity: 1; } }

/* The household's five lines, as a sentence a parent would say. Each line is a native
   select, sized to its words by sizePicks(), underlined in gold because it can be pressed. */
.rules-board { max-width: 1240px; margin: 0 auto; padding: 56px 32px 6px; }
.rules-line { margin: 0; font-family: var(--serif); font-size: var(--t-rules); line-height: 1.45; letter-spacing: var(--tr-display); max-width: 30em; text-wrap: pretty; }
.line-pick { white-space: nowrap; }
.rules-line select {
  appearance: none;
  -webkit-appearance: none;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  background-color: transparent;
  background-image: linear-gradient(45deg, transparent 50%, var(--gold) 50%), linear-gradient(-45deg, transparent 50%, var(--gold) 50%);
  background-size: 6px 6px, 6px 6px;
  background-position: right 8px top 58%, right 2px top 58%;
  background-repeat: no-repeat;
  border: 0;
  border-bottom: 2px solid var(--gold);
  border-radius: 0;
  margin: 0;
  padding: 0 22px 0 0;
  line-height: 1.15;
  cursor: pointer;
  transition: border-color 150ms;
}
.rules-line select:hover { border-bottom-color: var(--bronze); }
.rules-line option { font-family: var(--sans); font-size: var(--t-body); }
.pick-probe { position: absolute; visibility: hidden; white-space: nowrap; font: inherit; letter-spacing: inherit; }
.rules-foot { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 24px; margin-top: 20px; }
.rules-count { margin: 0; font-size: var(--t-body); color: var(--muted); }
.rules-count b { color: var(--ink); font-weight: 650; font-variant-numeric: tabular-nums; }
.link-btn {
  padding: 0;
  border: 0;
  border-bottom: 1px solid currentColor;
  background: none;
  color: var(--bronze);
  font-family: var(--sans);
  font-size: var(--t-ui);
  font-weight: 600;
  cursor: pointer;
  transition: color 150ms;
}
.link-btn:hover { color: var(--ink); }

/* ---------- the shelf ----------
   Every title in its owner's artwork, at its own shape and about the same area, standing on
   one line; shelfRows() in app.js sizes each row to fill the width exactly. Titles outside
   the household's rules are dimmed, never hidden: hiding is family view's job. */
.shelf-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 30px 0 16px;
  font-family: var(--serif);
  font-size: var(--t-h2);
  font-weight: 650;
  letter-spacing: var(--tr-display);
}
.shelf-head:first-child { margin-top: 4px; }
.shelf-count { font-family: var(--sans); font-size: var(--t-caption); font-weight: 600; color: var(--faint); font-variant-numeric: tabular-nums; }
.shelf-row { display: flex; align-items: flex-end; margin: 0 0 30px; }
.card-content { font-size: var(--t-caption); font-weight: 500; line-height: 1.45; color: var(--ink); }
.card-content .quiet { color: var(--faint); font-weight: 400; }
.grid { display: block; }
.card {
  flex: none;
  display: block;
  min-width: 0;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  appearance: none;
}
.tile-art { display: block; overflow: hidden; border-radius: 4px; background: var(--plate-bg); transition: opacity 150ms; }
.tile-art.round { border-radius: 50%; }
.tile-art.icon { border-radius: 12px; }
.tile-art img { display: block; width: 100%; height: 100%; object-fit: cover; }
.tile-name { display: block; margin-top: 10px; font-size: var(--t-ui); font-weight: 600; line-height: 1.3; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.card:hover .tile-name { text-decoration: underline; text-underline-offset: 3px; }
.tile-fit { display: block; font-size: var(--t-caption); line-height: 1.4; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.tile-fit b { font-weight: 650; color: var(--ink); }
.tile.good .tile-fit b { color: var(--good); }
.tile.poor .tile-fit b { color: var(--poor); }
.tile.poor .tile-art { opacity: .42; }
.tile.poor:hover .tile-art, .tile.poor:focus-visible .tile-art { opacity: 1; }
.craft-num { font-family: var(--serif); font-size: var(--t-h4); font-weight: 600; }
.craft-label { font-size: var(--t-caption); color: var(--faint); }

/* The card record: five categories at the table's scale, the same instrument as a table
   row. Meters come from meterSegments(); the keys are never coloured by severity. */
.card-record {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 4px 6px;
  margin-top: 8px;
  padding-top: 8px;
  border-top: 1px solid var(--line);
}
.rec-cell { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.rec-key {
  font-size: var(--t-nano);
  line-height: 1;
  letter-spacing: var(--tr-caps-wide);
  text-transform: uppercase;
  font-weight: 600;
  color: var(--faint);
}
.card-record .sev-meter { gap: 2px; margin: 0; justify-content: center; }
.card-record .sev-seg { width: 7px; }

/* The review opens on its artwork, with the credit under it and the time beside the fit. */
.modal-top { display: grid; grid-template-columns: minmax(0, 240px) minmax(0, 1fr); gap: 30px; padding: 30px 34px 8px; align-items: start; }
.modal-top.wide { grid-template-columns: minmax(0, 380px) minmax(0, 1fr); }
.modal-art img { display: block; width: 100%; height: auto; border-radius: 4px; }
.modal-art.round img { border-radius: 50%; }
.modal-art.icon img { border-radius: 12px; }
.art-credit { margin: 10px 0 0; font-size: var(--t-caption); line-height: 1.4; color: var(--faint); }
.art-credit a { display: block; width: fit-content; padding: 2px 0; color: inherit; text-underline-offset: 3px; }
.modal-top .modal-head { padding: 0; }
.modal-top .modal-badges { padding: 14px 0 0; }
.modal-main .price { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--line); }
.dial { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 6px 14px; align-items: center; margin-top: 16px; max-width: 340px; font-size: var(--t-ui); }
.dial span { grid-column: 1 / -1; color: var(--muted); }
.dial input { width: 100%; accent-color: var(--gold); }
.dial output { font-variant-numeric: tabular-nums; }
@media (prefers-color-scheme: dark) {
  .modal-backdrop { background: rgba(0, 0, 0, .66); }
  .modal { box-shadow: 0 18px 60px rgba(0, 0, 0, .8), 0 0 0 1px var(--line-strong); }
}

/* fit indicator: dot + small caps, no filled pill */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--t-caption);
  font-weight: 600;
  padding-top: 10px;
  border-top: 1px solid var(--line);
  align-self: stretch;
}
/* The label wears a text token; the MARK carries the state. Three silhouettes, so the
   signal survives greyscale print, colour-vision deficiency, and forced-colors mode:
   filled disc = within · hollow ring = worth reviewing (the neutral midpoint) ·
   filled diamond = outside. */
.badge { color: var(--muted); }
.badge::before { content: ""; width: 8px; height: 8px; flex: none; }
.badge.good { color: var(--ink); }
.badge.good::before { background: var(--good); border-radius: 50%; }
.badge.caution { color: var(--ink); }
.badge.caution::before {
  background: transparent;
  border: 2px solid var(--caution);
  border-radius: 50%;
}
.badge.poor { color: var(--ink); }
.badge.poor::before { background: var(--poor); transform: rotate(45deg); }
.badge.unset { color: var(--faint); }
.badge.unset::before { background: var(--faint); border-radius: 50%; opacity: .55; }

/* ---------- modal ---------- */
.modal-backdrop[hidden] { display: none; }
.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(18, 15, 10, .62); /* dark override below — on a near-black page this composites to nothing */
  display: flex;
  align-items: flex-start;
  justify-content: center;
  overflow-y: auto;
  /* Stop scroll chaining: reaching the end of a long review used to start scrolling the
     grid behind it, and the page kept that offset after the modal closed. body{overflow:
     hidden} alone does not prevent this. */
  overscroll-behavior: contain;
  padding: 48px 16px;
  z-index: 50;
}
.modal {
  background: var(--surface);
  border: 1px solid var(--line);
  /* 3px, not 6: the charter allows 0-3 and the modal is the largest surface in the
     file, so a 6px corner reads as the app vocabulary the genre exists to refuse. */
  border-radius: 12px;
  max-width: 780px;
  width: 100%;
  box-shadow: 0 18px 60px rgba(0, 0, 0, .35);
  overflow: hidden;
}
.modal-head { padding: 30px 34px 12px; display: flex; justify-content: space-between; gap: 14px; }
.modal-head h2 { margin: 0; font-family: var(--serif); font-weight: 600; font-size: var(--t-title); line-height: 1.15; }
.modal-sub { font-family: var(--sans); color: var(--muted); font-size: var(--t-prose-sm); margin-top: 8px; }
.modal-close {
  background: none;
  border: none;
  font-size: var(--t-h1);
  color: var(--faint);
  cursor: pointer;
  line-height: 1;
  padding: 2px 6px;
}
.modal-close:hover { color: var(--ink); }
.modal-badges { padding: 6px 34px 2px; display: flex; gap: 22px; flex-wrap: wrap; align-items: baseline; }
.modal-badges .badge { border-top: none; padding-top: 0; }
.modal-craft { display: flex; align-items: baseline; gap: 7px; }
.modal-craft .craft-num { font-size: var(--t-h2); }

/* Six tabs wrap rather than scroll — see the narrow-viewport note below. Nothing in
   this app may sit off an edge with only a fade to suggest it exists. */
.tabs { display: flex; flex-wrap: wrap; border-bottom: 1px solid var(--line); padding: 0 34px; gap: 2px; margin-top: 16px; }
.tab {
  padding: 11px 16px 10px;
  border: none;
  background: none;
  font-size: var(--t-ui);
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  font-family: var(--sans);
}
.tab:hover { color: var(--ink); }
.tab.active { color: var(--ink); border-bottom-color: var(--bronze); }
.tab-panel { padding: 26px 34px 34px; }

/* content record */
.content-grid { display: flex; flex-direction: column; }
.content-row {
  display: grid;
  grid-template-columns: 140px 130px 1fr;
  gap: 16px;
  align-items: start;
  padding: 13px 0;
  border-bottom: 1px solid var(--line);
}
.content-row:last-child { border-bottom: none; }
.content-cat { font-size: var(--t-label-lg); font-weight: 600; padding-top: 3px; }
.sev-meter { display: flex; gap: 4px; margin-bottom: 6px; }
.sev-seg { width: 22px; height: 4px; border-radius: 0; background: var(--line); }
/* Sequential ramp in one hue — severity is "how much," not "how bad." Real steps rather
   than opacity, so the ramp is monotone in lightness and survives greyscale print. */
.sev-seg.on-1 { background: var(--sev-1); }
.sev-seg.on-2 { background: var(--sev-2); }
.sev-seg.on-3 { background: var(--sev-3); }
.sev-label { font-size: var(--t-caption); color: var(--muted); font-weight: 600; }
.content-note { font-family: var(--sans); color: var(--muted); font-size: var(--t-body); line-height: 1.55; }
/* Stance: how the work TREATS the material — a fact about the work, not a verdict.
   Deliberately NOT colour-coded. The same stance flips valence by category and by
   household: a film that endorses prayer and one that endorses cruelty share a tag
   but not a meaning. Colour would assert a judgment this system cannot justify.
   Precedent: ESRB content descriptors are required to display in black and white.
   Also WCAG 1.4.1 — meaning must not ride on hue alone (~8% of men have red-green
   colour-vision deficiency), and green/red carry conflicting liturgical and
   cross-cultural readings for this audience. */
.stance {
  display: inline-block;
  font-size: var(--t-micro);
  letter-spacing: var(--tr-caps-wide);
  text-transform: uppercase;
  padding: 2px 7px;
  margin-left: 8px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  color: var(--muted);
  vertical-align: 1px;
}
.stance-ambiguous { font-style: italic; letter-spacing: var(--tr-caps-tight); }

.over-flag { display: block; color: var(--poor); font-size: var(--t-label); letter-spacing: var(--tr-caps); text-transform: uppercase; font-weight: 700; margin-top: 4px; }
.record-note { margin-top: 20px; font-family: var(--sans); }

/* criticism */
.discernment p { margin: 0 0 14px; font-family: var(--sans); font-size: var(--t-essay); line-height: 1.7; }
.discernment p:first-of-type::first-letter {
  font-size: 46px;
  float: left;
  line-height: .85;
  padding: 4px 8px 0 0;
  font-weight: 600;
}
.discernment .pull {
  border-top: 1px solid var(--line-strong);
  border-bottom: 1px solid var(--line-strong);
  padding: 14px 4px;
  margin: 20px 0;
  font-family: var(--serif);
  font-style: italic;
  font-size: 18px;
  line-height: 1.5;
  color: var(--ink);
  text-align: center;
}
.themes { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.theme-chip {
  font-size: var(--t-label);
  padding: 5px 12px;
  border: 1px solid var(--line);
  border-radius: 4px;
  color: var(--muted);
}

/* ---------- shared section furniture (tier 2 / tier 3 blocks) ---------- */
.section-head {
  font-family: var(--sans);
  font-size: var(--t-label-lg);
  font-weight: 600;
  color: var(--ink);
  margin: 32px 0 8px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.section-head.first { margin-top: 0; padding-top: 0; border-top: none; }
.section-note { margin: 0 0 16px; font-family: var(--sans); }
.section-note.first { margin-top: 0; }
.micro-label {
  display: inline-block;
  font-size: var(--t-micro);
  font-weight: 600;
  color: var(--faint);
  margin-right: 10px;
}

/* provenance: the reviewer's beat and any title-specific lens caveat */
.beat {
  display: block;
  font-family: var(--sans);
  font-size: var(--t-micro);
  color: var(--faint);
  margin-top: 3px;
}
.lens-note {
  display: block;
  margin-top: 7px;
  padding-left: 12px;
  border-left: 2px solid var(--line-strong);
  color: var(--muted);
  font-size: var(--t-body-sm);
}

.deflist { margin: 0; }
.def-row {
  display: grid;
  grid-template-columns: 168px 1fr;
  gap: 18px;
  padding: 11px 0;
  border-bottom: 1px solid var(--line);
}
.def-row:last-child { border-bottom: none; }
.def-row dt {
  font-size: var(--t-label-lg);
  font-weight: 600;
  color: var(--muted);
  padding-top: 3px;
}
.def-row dd {
  margin: 0;
  font-family: var(--sans);
  font-size: var(--t-prose-sm);
  line-height: 1.6;
  color: var(--ink);
}

/* tier 1 — the fifteen-second answer */
.tier1 .verdict {
  font-family: var(--serif);
  font-size: var(--t-h3);
  line-height: 1.45;
  margin: 0 0 14px;
}
.tier1 .driver {
  font-family: var(--sans);
  font-size: var(--t-prose);
  line-height: 1.6;
  color: var(--muted);
  margin: 0 0 20px;
  padding-bottom: 18px;
  border-bottom: 1px solid var(--line);
}

/* maturity dimensions — same sequential ramp as severity, never a verdict */
.dim-grid { display: flex; flex-direction: column; }
.dim-row {
  display: grid;
  grid-template-columns: 168px 118px 1fr;
  gap: 16px;
  align-items: start;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.dim-row:last-child { border-bottom: none; }
.dim-label { font-size: var(--t-label-lg); font-weight: 600; padding-top: 3px; }
.dim-asks { font-family: var(--sans); font-size: var(--t-body-sm); line-height: 1.55; color: var(--faint); }
.dim-note {
  font-family: var(--sans);
  font-size: var(--t-prose-sm);
  line-height: 1.65;
  margin: 16px 0 0;
  padding-left: 14px;
  border-left: 2px solid var(--line-strong);
  color: var(--muted);
}

/* where Christians differ — two sides, equal weight, no colour verdict */
.differ-q { font-family: var(--serif); font-style: italic; font-size: var(--t-h4); margin: 0 0 16px; }
.two-sides { display: grid; grid-template-columns: 1fr 1fr; gap: 22px; }
.side { border-top: 2px solid var(--line-strong); padding-top: 12px; }
.side p { margin: 6px 0 0; font-family: var(--sans); font-size: var(--t-prose-sm); line-height: 1.6; }
.changes, .watch-for, .already {
  font-family: var(--sans);
  font-size: var(--t-prose);
  line-height: 1.65;
  margin: 0;
}
.watch-for { padding-left: 14px; border-left: 2px solid var(--bronze); }

/* if this is a no, three yeses */
.alts { list-style: none; margin: 0; padding: 0; }
.alt { padding: 13px 0; border-bottom: 1px solid var(--line); }
.alt:last-child { border-bottom: none; }
.alt-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 10px; }
.alt p { margin: 5px 0 0; font-family: var(--sans); font-size: var(--t-body); line-height: 1.6; color: var(--muted); }
.alt-name { font-family: var(--serif); font-size: var(--t-h4); font-weight: 600; }
.alt-link {
  font: inherit;
  font-family: var(--sans);
  font-size: var(--t-h4);
  font-weight: 600;
  color: var(--bronze);
  background: none;
  border: none;
  border-bottom: 1px solid currentColor;
  padding: 0;
  cursor: pointer;
}
.alt-link:hover { color: var(--ink); }
.alt-meta { font-size: var(--t-micro); color: var(--faint); }

/* ---------- talk about it ----------
   A numbered ruled list. The numeral is apparatus, not decoration: small caps scale,
   tabular figures, zero-padded like the recommender's rank, sitting in its own margin
   column so the questions themselves start on one line down the page. No icons, no
   bullets, no quotation ornament — the counter is generated, so there is no glyph in the
   markup and nothing to fetch. */
.talk-list {
  list-style: none;
  margin: 0;
  padding: 0;
  counter-reset: talk;
}
.talk-q {
  display: grid;
  grid-template-columns: 2.4em 1fr;
  gap: 16px;
  padding: 14px 0;
  border-top: 1px solid var(--line);
  font-family: var(--sans);
  font-size: var(--t-prose-sm);
  line-height: 1.65;
}
.talk-q::before {
  counter-increment: talk;
  content: counter(talk, decimal-leading-zero);
  font-family: var(--sans);
  font-size: var(--t-micro);
  letter-spacing: var(--tr-caps-wide);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  padding-top: 5px;
}

/* ---------- episode guide ----------
   Forty episodes and a hundred and forty-four notes set as a ruled column: apparatus in
   small caps on the left, the reading in serif beside it, a hairline between entries and
   nothing else. No cards, no lift, no entrance — the page has to disappear behind the
   text, and at this length any per-entry decoration becomes wallpaper by episode four.

   Colour is deliberately absent from this whole section. The note type is a WORD plus a
   MARK SILHOUETTE, never a hue: "concern" and "highlight" flip valence by household — a
   frank depiction of a betrayal is the reason one family is watching and the reason
   another is not — and colouring them would assert a judgment this system cannot make.
   Same argument as the stance tags, same reason the fidelity grade below is plain text
   rather than a chip. The three silhouettes are the ones the fit badge already uses for
   state, so the vocabulary is one language, and all three survive greyscale print. */
.guide-seasons { margin: 0 0 6px; }
.guide-seasons .chip { padding-left: 0; padding-right: 22px; }
.guide-seasons .chip.active { border-bottom-color: var(--bronze); }
.guide-notice { margin-top: 12px; }
.guide-count {
  margin: 0 0 6px;
  font-size: var(--t-micro);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.ep-list { display: flex; flex-direction: column; }
.ep { padding: 20px 0 18px; border-top: 1px solid var(--line); }
.ep-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 14px;
  margin-bottom: 8px;
}
/* The episode address. Tabular figures so S1·E1 and S5·E8 sit on the same rhythm all
   the way down forty entries — the charter's numeral rule, applied where it earns it. */
.ep-num {
  font-size: var(--t-micro);
  font-weight: 600;
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.ep-sep { padding: 0 5px; color: var(--line-strong); }
.ep-title {
  margin: 0;
  font-family: var(--serif);
  font-size: var(--t-h4);
  font-weight: 600;
  line-height: 1.3;
}
/* The fidelity grade is APPARATUS, not a badge: it is the source project's reading of how
   closely an episode tracks its passage, it feeds no rubric here, and a coloured pill
   would claim otherwise. Text on a hairline, at the apparatus size, in muted ink — the
   same treatment the stance tag gets, for the same reason. */
.ep-grade {
  margin-left: auto;
  font-size: var(--t-micro);
  color: var(--muted);
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  padding: 2px 8px;
  white-space: nowrap;
}
.ep-summary {
  margin: 0 0 8px;
  font-family: var(--sans);
  font-size: var(--t-prose-sm);
  line-height: 1.6;
}
.ep-accuracy {
  margin: 0 0 12px;
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.55;
  color: var(--muted);
}
.ep-notes { list-style: none; margin: 0; padding: 0; }
.ep-note {
  display: grid;
  grid-template-columns: 132px 1fr;
  gap: 16px;
  padding: 9px 0;
  border-top: 1px solid var(--line);
}
.ep-note-type {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-size: var(--t-micro);
  font-weight: 600;
  color: var(--muted);
}
/* Disc / ring / diamond — the same three silhouettes the fit badge uses, in plain ink.
   Shape is the whole distinction: no note type has a colour of its own. */
.note-mark { width: 7px; height: 7px; flex: none; }
.note-mark-disc { background: var(--ink); border-radius: 50%; }
.note-mark-ring { border: 1.5px solid var(--ink); background: transparent; border-radius: 50%; }
.note-mark-diamond { background: var(--ink); transform: rotate(45deg); }
.ep-note-title { font-family: var(--serif); font-size: var(--t-body); font-weight: 600; }
.ep-note-desc {
  margin: 3px 0 0;
  font-family: var(--sans);
  font-size: var(--t-body);
  line-height: 1.55;
  color: var(--muted);
}
/* The quotation is set as a quotation: indented off a rule, with the reference as its
   cite. It is Scripture, not a description of the content, so family view leaves it. */
.ep-scripture {
  margin: 7px 0 0;
  padding-left: 13px;
  border-left: 2px solid var(--line-strong);
  font-family: var(--serif);
  font-size: var(--t-body-sm);
  font-style: italic;
  line-height: 1.55;
  color: var(--ink);
}
.ep-scripture cite, .ep-ref cite {
  display: block;
  margin-top: 4px;
  font-family: var(--sans);
  font-style: normal;
  font-size: var(--t-nano);
  color: var(--faint);
}
.ep-ref { margin: 6px 0 0; }

/* sources */
.source-list { margin: 0; padding-left: 18px; font-family: var(--sans); font-size: var(--t-prose-sm); line-height: 1.7; }
.source-list a { color: var(--bronze); }

/* The community block's stylesheet — community-stats, stat-tile, stat-num, stat-label,
   community-quote and its byline — was DELETED 2026-07-30 with the block itself. It
   styled a vote tally and a testimonial byline for a community that does not exist:
   fabricated social proof, banned by DESIGN-CHARTER §8. Do not restore it — leaving the
   stylesheet in place is an invitation to put the markup back. `verify` fails if any of
   those selectors reappears here, so this is enforced rather than requested. */

/* ---------- about ----------
   The trust page, set as a document rather than a marketing surface: one measure, the
   same section rules and definition rows the reviews use, no new furniture. Its width is
   held to a reading measure — the panel is prose, and prose across 1200px is unreadable. */
.about-panel, .resources-panel { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--surface); }
.about-panel h2, .resources-panel h2 { font-family: var(--serif); font-weight: 600; margin: 0 0 10px; font-size: var(--t-h2); }
.about-inner { max-width: 720px; }
.about-lede {
  font-family: var(--sans);
  font-size: var(--t-h4);
  line-height: 1.6;
  margin: 0;
  padding-bottom: 4px;
}
.about-panel p, .resources-panel p {
  font-family: var(--sans);
  font-size: var(--t-prose-sm);
  line-height: 1.7;
  margin: 0;
  color: var(--ink);
}
.about-panel .def-row dd { line-height: 1.65; }
.about-note {
  margin-top: 14px !important;
  padding-left: 14px;
  border-left: 2px solid var(--line-strong);
  color: var(--muted) !important;
  font-size: var(--t-body-sm) !important;
}

/* ---------- resources ----------
   A ruled list grouped by category — ink and rules, no cards, no favicons, radius 0.
   Each row is a def-row-shaped block: name, one-line description, the why-trusted line
   (same micro-label apparatus the tier-1 "Why" line uses), and a link whose visible text
   is the domain rather than the site's own name for itself or the bare URL. Hairlines
   only; the group head reuses .section-head so the page does not invent a second
   heading style for what is, structurally, the same kind of section break. */
.resource-group-head { margin-top: 28px; }
.resource-list { margin: 0; }
.resource-row {
  padding: 16px 0;
  border-bottom: 1px solid var(--line);
}
.resource-row:last-child { border-bottom: none; }
.resource-name {
  font-family: var(--serif);
  font-weight: 600;
  font-size: var(--t-h4);
  margin: 0 0 4px !important;
  color: var(--ink);
}
.resource-author {
  display: block;
  font-family: var(--sans);
  font-size: var(--t-micro);
  font-weight: 600;
  color: var(--faint);
  margin-top: 3px;
}
.resource-desc { margin: 0 0 8px !important; }
.resource-why { margin: 0 0 8px !important; color: var(--muted) !important; }
.resource-link { margin: 0 !important; }
.resource-link a {
  font-family: var(--sans);
  font-size: var(--t-label);
  color: var(--bronze);
  overflow-wrap: anywhere;
}

/* footer */
.site-footer {
  border-top: 1px solid var(--line);
  padding: 22px 32px 28px;
  color: var(--faint);
  font-size: var(--t-caption);
  letter-spacing: .04em;
  text-align: center;
}
.site-footer code { font-family: inherit; }
/* The nav repeats here because a catalogue page ends a long way from its masthead. Same
   words, same rule, one step quieter — it is a way back, not a second masthead. */
.footer-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 26px;
  padding-bottom: 12px;
  margin-bottom: 12px;
  border-bottom: 1px solid var(--line);
}
.footer-nav .nav-link { padding: 0; border-bottom: none; font-size: var(--t-label); letter-spacing: var(--tr-caps-wide); }
.footer-nav .nav-link.active { border-bottom: none; }
/* Provenance and the pilot disclosure. Not chrome: they are the two claims that have to
   travel with the product wherever a page of it is opened, so they also print. */
.footer-line {
  max-width: 760px;
  margin: 0 auto;
  font-family: var(--sans);
  font-size: var(--t-body-sm);
  line-height: 1.55;
  letter-spacing: normal;
}
.footer-line + .footer-line {
  margin-top: 8px;
  font-family: var(--sans);
  font-size: var(--t-label);
}
.empty { color: var(--muted); padding: 48px 0; text-align: center; font-family: var(--sans); font-size: var(--t-prose-lg); grid-column: 1 / -1; }

/* ---------- the guided recommender ----------
   A questionnaire is where a broadsheet is most likely to turn into an app: numbered
   circles, a progress bar, big rounded option tiles, a hover lift on every result. None
   of that is here. A question is a ruled section with a small-caps address ("Question 1
   of 3"), its options are the catalogue's own chip row, and a result is a ruled entry
   carrying the same five-category record at the same 9px scale as a card and a table row
   — so a recommendation and a browse are visibly the same instrument.

   Colour: none of it. Every rule below uses ink, muted ink, the hairline and the single
   bronze spot. The one coloured thing on a result is the fit badge, which is the only
   place this project spends valence colour at all — and it comes from `.badge`, unchanged,
   so the recommender cannot invent a second fit vocabulary. `verify` fails on any
   `.find-` rule that reaches for --good / --poor / --caution / the severity ramp.

   The option rows and the answer summary WRAP. `verify` checks both by name alongside
   .filters and .tabs: the questions produce up to nine chips in a row, and at 375px a row
   that does not wrap puts an answer off the edge behind nothing at all. */
.find-panel { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); background: var(--surface); }
.find-panel h2 { font-family: var(--serif); font-weight: 600; margin: 0 0 6px; font-size: var(--t-h2); }
.find-step {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 14px;
  margin: 24px 0 6px;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}
/* Tabular, because "Question 1 of 3" is an address that changes under the reader. */
.find-step-count {
  font-size: var(--t-micro);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.find-question { font-family: var(--serif); font-weight: 600; font-size: var(--t-h3); margin: 0; line-height: 1.25; }
.find-note { margin: 0 0 2px; font-family: var(--sans); color: var(--muted); font-size: var(--t-body-sm); line-height: 1.55; }
/* The recommender's answers are the catalogue's own chips: one control vocabulary across
   the page. The old underline-tab overrides (zero gap, zero left padding) are gone; left
   in place over the new bordered chip they produced uneven, borderless cells. */
.find-options { display: flex; flex-wrap: wrap; gap: 8px; margin: 4px 0 16px; }
.find-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-top: 18px;
}
/* Disabled reads as inert, never as a faded primary: a pale gold 'Next' looked maybe-clickable. */
.btn[disabled], .find-nav .btn[disabled] { background: transparent; color: var(--faint); border-color: var(--line); cursor: not-allowed; }

/* the answers, restated on the results screen — the conditions the ranking was run under */
.find-conditions {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 6px 22px;
  margin: 22px 0 12px;
  padding: 12px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.find-condition {
  font-size: var(--t-label);
  color: var(--faint);
}
.find-condition b { font-weight: 600; color: var(--ink); }
.find-count {
  margin: 0 0 4px;
  font-size: var(--t-micro);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.find-order { margin: 0 0 6px; font-family: var(--sans); color: var(--muted); font-size: var(--t-body-sm); line-height: 1.55; }
.find-empty { padding: 34px 0; }

.find-list { display: flex; flex-direction: column; }
.find-entry {
  display: grid;
  grid-template-columns: 2.4em minmax(0, 1fr) auto;
  align-items: start;
  gap: 4px 20px;
  width: 100%;
  margin: 0;
  padding: 17px 4px;
  border: none;
  border-top: 1px solid var(--line);
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}
.find-entry:hover .find-title { color: var(--bronze); }
.find-rank {
  font-size: var(--t-micro);
  letter-spacing: var(--tr-caps-wide);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
  padding-top: 5px;
}
.find-title-row { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; }
.find-title { font-family: var(--serif); font-size: var(--t-h4); font-weight: 600; }
.find-meta {
  font-size: var(--t-micro);
  color: var(--faint);
  font-variant-numeric: tabular-nums;
}
.find-hook { display: block; margin-top: 4px; font-family: var(--sans); font-size: var(--t-body-sm); color: var(--muted); line-height: 1.55; }
/* The two axes that must never reach the ranking, printed and SAID to be description. */
.find-axes { display: block; margin-top: 7px; font-size: var(--t-label); color: var(--faint); line-height: 1.6; }
.find-axes-note { font-family: var(--sans); letter-spacing: var(--tr-display); text-transform: none; }
.find-figures { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; min-width: 190px; }
.find-figures .card-record { width: 100%; border-top: none; padding-top: 0; }
.find-craft { display: flex; align-items: baseline; gap: 6px; font-variant-numeric: tabular-nums; }
.find-figures .badge { border-top: none; padding-top: 0; }
.find-outside-head { margin-top: 34px; padding-top: 18px; border-top: 1px solid var(--line); }
.find-save-note { margin: 10px 0 0; }

/* The front door at tablet widths (2026-10-23, seen live at 780px): the desktop's two columns
   left the picture centred far below the title and squeezed the fit and the time side by side
   into a narrow column. Here the picture sits at the top, a wide picture goes above the text,
   and the fit and the time stack. */
@media (min-width: 761px) and (max-width: 1080px) {
  .on-in { grid-template-columns: minmax(0, 280px) minmax(0, 1fr); gap: 36px; align-items: start; }
  .on-in.wide { grid-template-columns: minmax(0, 1fr); }
  .on-in.wide .on-art { max-width: 560px; justify-self: start; }
  .pair { grid-template-columns: minmax(0, 1fr); gap: 20px; }
}

@media (max-width: 760px) {
  /* Density defect (measured 2026-08-01): at 375px the first catalogue card sat at
     y=825 — a parent deciding tonight had to scroll a full screen before seeing one
     title. Nothing below drops a rule, a disclosure or the masthead/apparatus scale
     contrast (§4 stays: the h1 is untouched at --t-masthead, apparatus stays the small
     tokens it already used) — every line here is vertical RHYTHM: padding, gap and
     line-height compressed on the rows that were carrying whitespace no reader asked
     for. Measured result: first card at y=504 with the orientation line dismissed
     (was ~669) and y=617 with it present (was 825). Desktop (>760px) is untouched. */
  .demo-banner { padding: 5px 16px; line-height: 1.3; }

  .site-header { padding: 14px 18px 8px; gap: 10px; }
  .brand { gap: 2px 12px; }
  .brand-tag { line-height: 1.25; }
  .header-actions { gap: 8px; width: 100%; }
  #search { flex: 1; width: auto; min-width: 0; }

  main { padding: 8px 18px 56px; }
  .nav-inner { padding: 0 18px; gap: 2px 18px; }
  .nav-link { padding: 7px 0 5px; }

  /* The rail wraps to two lines here rather than scrolling or clipping; slightly less
     tracking so the wrap happens later. */
  .apparatus-rail { font-size: var(--t-micro); padding: 5px 0 4px; line-height: 1.3; }

  /* The first-visit line is a standing note, not a toast (§ orientation in this file) —
     it still gets its own row and rule, just fewer of them: tighter padding and prose
     leading, and the text's flex-basis trimmed so the "Got it" control keeps sitting on
     the baseline instead of forcing an extra wrap. */
  .orientation { padding: 6px 2px 7px; margin: 0 0 1px; gap: 4px 14px; }
  .orientation-text { flex-basis: 250px; line-height: 1.35; }

  /* Filter chips: padding compressed so 9 chips (All + 8 formats) wrap to 3 rows
     instead of 4 at 375px — still comfortably tappable text, still wrapping (never
     nowrap, never a scroller — see the off-edge rule below), just less air around each
     chip's label. */
  .filters { margin-bottom: 8px; }
  .chip { padding: 7px 11px 7px; }

  /* The front door on a phone: the artwork first, then the title, the verdict and the
     time stacked, then the lineup; the house sentence keeps thumb-height lines. */
  .on-in, .on-in.wide { grid-template-columns: minmax(0, 1fr); gap: 20px; padding: 22px 18px 20px; }
  .on-art { max-width: 200px; justify-self: start; }
  .on-in.wide .on-art { max-width: none; }
  .pair { grid-template-columns: minmax(0, 1fr); gap: 20px; margin-top: 20px; padding-top: 18px; }
  .on-go { margin-top: 22px; }
  .strip { padding: 0 18px 22px; gap: 10px; }
  .strip img { max-height: 60px; max-width: 104px; }
  .rules-board { padding: 36px 18px 4px; }
  .rules-line { line-height: 1.75; }
  .shelf-row { margin-bottom: 22px; }
  .tile-name { margin-top: 8px; }
  .card .card-record { display: none; }
  .modal-top, .modal-top.wide { grid-template-columns: minmax(0, 1fr); gap: 18px; padding: 22px 20px 6px; }
  .modal-art { max-width: 200px; }
  .modal-top.wide .modal-art { max-width: none; }

  .list-bar { margin: 2px 2px 8px; gap: 8px 14px; }

  .modal-backdrop { padding: 20px 10px; }
  .modal-head, .modal-badges, .tabs, .tab-panel { padding-left: 20px; padding-right: 20px; }
  .modal-head { padding-top: 24px; }
  .modal-head h2 { font-size: 25px; }

  /* Filters and tabs WRAP. They used to scroll sideways behind a fade, which put
     Podcasts and Apps off the right edge with no visible way to reach them: a mouse
     cannot scroll a horizontal strip, and a fade is a hint, not an affordance.
     Wrapping costs one row of height and makes every control clickable. */
  .filters, .tabs { flex-wrap: wrap; overflow: visible; }
  .chip, .tab { white-space: nowrap; }
  .tab { padding-left: 12px; padding-right: 12px; }

  /* content record: stack instead of squeezing three columns into 375px */
  .content-row {
    grid-template-columns: 1fr;
    gap: 7px;
    padding: 15px 0;
  }
  .content-cat { padding-top: 0; }
  .sev-meter { margin-bottom: 4px; }
  .sev-label { display: inline; }

.over-flag { display: inline; margin-left: 10px; }
  .content-note { font-size: var(--t-prose-sm); }

  .discernment p { font-size: var(--t-prose-lg); }
  .discernment .pull { font-size: var(--t-h4); text-align: left; }

  /* tier-2/3 blocks stack rather than squeezing label columns into 375px */
  .def-row, .dim-row { grid-template-columns: 1fr; gap: 6px; }
  .def-row { padding: 13px 0; }
  .def-row dt { padding-top: 0; }
  .dim-label { padding-top: 0; }
  .dim-asks { font-size: var(--t-ui); }
  .two-sides { grid-template-columns: 1fr; gap: 18px; }
  .tier1 .verdict { font-size: 19px; }

  /* The question keeps its numeral, but the two columns become one: a 2.4em margin
     column and a serif sentence cannot share 375px. */
  .talk-q { grid-template-columns: 1fr; gap: 2px; }
  .talk-q::before { padding-top: 0; }

  /* Episode notes stack for the same reason def/dim rows do: a 132px label column and a
     serif paragraph cannot share 375px without one of them becoming a column of syllables. */
  .ep-note { grid-template-columns: 1fr; gap: 5px; }
  .ep-grade { margin-left: 0; }
  .guide-seasons .chip { padding-right: 16px; }

  /* A recommendation stacks rather than squeezing a rank column, a title and a 190px
     figure stack into 375px — same reason the def/dim rows above do. The record keeps
     its five columns, which already fit at 320px. */
  .find-entry { grid-template-columns: 1fr; gap: 10px; }
  .find-rank { padding-top: 0; }
  .find-figures { align-items: flex-start; min-width: 0; width: 100%; }
  .find-options .chip { padding-right: 18px; }
}

/* ---------- print ----------
   Someone will print a review: a parent deciding away from the device, or the concierge
   test handing an answer to a spouse. Without this, printing a modal produces a page of
   backdrop. The severity ramp is monotone in lightness precisely so it survives here,
   and the fit mark is a shape, so greyscale keeps the signal. */
@media print {
  .demo-banner, .header-actions, .filters, .list-bar, .profile-panel,
  .view-notice, .modal-close, .tabs, .site-nav, .footer-nav, .orientation { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .site-header { padding: 0 0 8pt; border-bottom: 1.5pt solid #000; }
  .brand-name { font-size: 18pt; }
  .brand-tag { font-size: 9pt; }
  main { padding: 0; max-width: none; }

  /* Print the open review, not the catalogue behind it. 2026-08-01 visual QA found this
     comment was only half true: the line below stops the backdrop printing as a solid
     overlay, but `main#catalogue` (id="catalogue", panel:null in app.js — it is the page
     itself and stays in the DOM under every section) was never hidden, and #grid holds
     all 52 cards. Printing an open review, or the recommender's results, printed the
     entire catalogue as well — many pages of cards before or after the one thing the
     reader actually asked to print. `:has()` conditions the hide on the SAME `hidden`
     attribute openModal()/showSection() already toggle, so no new JS state is needed;
     it has shipped in every evergreen engine (Chrome 105+, Safari 15.4+, Firefox 121+)
     well before this project's browser floor. */
  /* 2026-10-23 (Cursor PR 9, confirmed here): a review opened from About, Resources or What to
     watch printed that panel, the front door and the footer too. With a review open, print the
     masthead and the review and nothing else; with a panel open, leave the front door and the
     catalogue off its sheet. */
  body:has(#modal-backdrop:not([hidden])) > :not(#modal-backdrop):not(.site-header):not(script) { display: none !important; }
  body:has(#about:not([hidden])) #hero, body:has(#about:not([hidden])) #catalogue,
  body:has(#resources:not([hidden])) #hero, body:has(#resources:not([hidden])) #catalogue,
  body:has(#find-panel:not([hidden])) #hero { display: none !important; }
  body:has(#modal-backdrop:not([hidden])) #grid,
  body:has(#modal-backdrop:not([hidden])) #outside-list,
  body:has(#find-panel:not([hidden])) #grid,
  body:has(#find-panel:not([hidden])) #outside-list { display: none !important; }
  .modal-backdrop { position: static; background: none; padding: 0; overflow: visible; display: block; }
  .modal { box-shadow: none; border: none; max-width: none; }
  .modal-head { padding: 12pt 0 6pt; }
  .modal-head h2 { font-size: 20pt; }
  .modal-badges { padding: 0 0 6pt; }
  .tab-panel { padding: 0; }
  /* A printed sheet has no tabs, so every panel prints in charter order. */
  .section-head { break-after: avoid; page-break-after: avoid; }

  /* Ink economy: rules instead of tints, and the grid collapses to one column. */
  .grid { display: block; }
  .card { border: none; border-bottom: 0.5pt solid #999; break-inside: avoid; page-break-inside: avoid; }
  .sev-seg { border: 0.4pt solid #000; }
  /* The rail is provenance, so it prints — it is not in the hidden list above. It only
     needs its screen greys converted to ink: --faint resolves to a light grey (and to the
     dark-theme grey if the OS is in dark mode), which is unreadable on paper. */
  .apparatus-rail { color: #000; border-color: #000; font-size: 8pt; letter-spacing: .1em; }
  .rec-key { color: #000; }
  /* The withheld-notes count is provenance about the sheet in your hand, not chrome. The
     blanket .view-notice hide above would drop it, and a printout that silently omits a
     third of its sentences is the same lie on paper that it would be on screen. */
  .guide-notice { display: block !important; color: #000; border-color: #000; }
  .ep { break-inside: avoid; page-break-inside: avoid; }
  .ep-num, .ep-grade, .ep-note-type, .ep-scripture cite { color: #000; }
  .ep-grade { border-color: #000; }
  .note-mark-disc, .note-mark-diamond { background: #000 !important; }
  .note-mark-ring { border-color: #000 !important; }
  .badge::before { border-color: #000 !important; }
  .badge.good::before, .badge.poor::before { background: #000 !important; }
  a[href]::after { content: ""; }

  /* The questions print with the review — they are the thing a parent carries away from
     the screen to use later, which is the whole case for a print stylesheet here. */
  .talk-q { border-color: #999; break-inside: avoid; page-break-inside: avoid; }
  .talk-q::before { color: #000; }

  /* ---------- the recommender's results ----------
     Reported unprintable, and it was: `.find-panel` sat in the blanket hide above, so
     printing from a results screen produced the catalogue behind it and none of the
     answer. A ranked list IS a printable answer — the same job the open review does — so
     it prints as a ruled list with the conditions it was run under at the top, which is
     what makes the sheet readable a day later. Controls drop out; the ordering note and
     the honesty counts stay, because a printed list that does not say what it was ranked
     against or how many titles it left out is the same lie on paper as on screen.
     A hidden panel keeps its `hidden` attribute, so none of this prints unless the
     results are actually on the screen being printed. */
  .find-panel { border: none; background: none; }
  .find-panel .profile-inner { padding: 0; }
  .find-nav, .find-options, .find-save-note, .find-step { display: none !important; }
  .find-panel h2 { font-size: 15pt; margin-bottom: 4pt; }
  .find-conditions, .find-count, .find-order, .find-condition, .find-rank, .find-meta,
  .find-axes, .find-hook, .find-outside-head, .summary-meta { color: #000; }
  .find-conditions { border-color: #000; margin-top: 6pt; }
  .find-entry, .summary-row {
    border-color: #999;
    break-inside: avoid;
    page-break-inside: avoid;
  }
  .find-entry { border-top-width: 0.5pt; padding: 8pt 0; }
  .find-figures { min-width: 34mm; }
  .find-outside-head { border-color: #000; }

  /* Provenance and the pilot line travel with the sheet. The nav does not — a printed
     page has no sections to move between. */
  .site-footer { color: #000; border-color: #000; padding: 10pt 0 0; margin-top: 12pt; }
  .footer-line { font-size: 8pt; }

  /* ---------- resources ----------
     A parent who prints House Rules or a review is exactly the reader who would also
     print "where do I go to study this myself" — same use case as the recommender's
     results, and the same rule applies: a section is only unprintable if nobody thought
     about it. Each row stays on one page rather than splitting a name from its link, and
     the external-sites note travels with the list the way the footer's provenance line
     travels with the page. */
  .resource-row { break-inside: avoid; page-break-inside: avoid; }
  .resource-group-head { break-after: avoid; page-break-after: avoid; }
}

@media (max-width: 420px) {
  .brand-name { font-size: 29px; }

  /* Segment width stays at 9px — one scale across cards and table — and the column gap
     absorbs the narrower card instead. Even at 320px the five meters need 155px of a
     ~248px body. */
  .card-record { gap: 4px; }
  #search { width: 100%; }
  .header-actions { width: 100%; flex-wrap: wrap; }
}

/* ---------- money: store links, gifts, guides, the weekly email (DECISIONS.md § Money) ----------
   Store links sit under the short answer as a plain row of words, the same weight as the
   record around them: they are a convenience, not the point of the page. "paid link" is set
   beside each paid link in the apparatus caps, never smaller than the record keys, so the
   disclosure is as easy to read as the link (FTC: hard to miss). Gift, guides and sign-up are
   written into About only when switched on in app/money.js, and never in family view. */
.stores {
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px solid var(--line);
}
.store-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 22px;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-ui);
}
.store-links a { color: var(--ink); font-weight: 600; text-decoration: underline; text-underline-offset: 3px; }
.store-links a:hover { color: var(--muted); }
.store-links .paid {
  margin-left: 8px;
  font-size: var(--t-nano);
  font-weight: 600;
  letter-spacing: var(--tr-caps-tight);
  text-transform: uppercase;
  color: var(--muted);
}
.paid-note {
  margin: 10px 0 0;
  font-size: var(--t-body-sm);
  color: var(--muted);
  max-width: 62ch;
}
.money-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px 28px;
  margin-top: 10px;
}
.money-item h4 {
  margin: 0 0 6px;
  font-family: var(--serif);
  font-size: var(--t-h4);
  font-weight: 600;
}
.money-item p { margin: 0 0 10px; }
.email-form { display: flex; flex-wrap: wrap; gap: 8px; }
.email-form input {
  flex: 1 1 200px;
  min-width: 0;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 4px;
  background: var(--surface);
  color: var(--ink);
  font-size: var(--t-ui);
}
.money-item a.btn { display: inline-block; text-decoration: none; }
