/* =========================================================================
   GEBible — base styles
   Theming system per docs/THEME.md. Dark is the unconditional default; light
   and sepia are opt-in. The OS preference only applies when the user explicitly
   selects "System" (resolved by the pre-paint JS in head.ejs, which then sets
   data-theme to light/dark). We deliberately do NOT use a prefers-color-scheme
   media query to pick the default — dark is default regardless of OS.

   Reading-surface discipline (THEME.md §0/§2): the verse/reading column paints
   ONLY with --surface, --text-primary, and --text-secondary. Brand red never
   appears in the verse column.

   Reserved THEME.md design-palette tokens — defined centrally so they re-skin
   per theme even though no UI wires them up yet (so they are NOT orphans):
   the semantic-routing set (--cross-ref, --diff, --woc, --quoted-ot, --note)
   plus --danger, the highlight set (--hl-yellow/green/blue/pink/purple/orange),
   --brand-core, --font-fallback-classical, and the spacing steps
   (--space-1/2/3/4/6/8). All are documented in THEME.md and held for upcoming
   reading features (cross-refs, translation diff, highlights, etc.).

   RD6 (Pass 2): the OFL reading/UI/mono faces are now self-hosted as same-origin
   woff2 (public/fonts/, all SIL OFL — see public/fonts/LICENSE.txt) with
   font-display: swap. The reading-body regular is preloaded in head.ejs; CLS on
   swap is minimised by metric-matched fallback faces — Georgia-based for the
   reading body, Segoe-UI-based for the UI face (#138) — carrying metric overrides
   (RD23, see the @font-face block below). No CDN / no CSP change — fonts are
   static assets served from this origin (CSP fontSrc already allows 'self').
   ========================================================================= */

/* =========================================================================
   RD6 — Self-hosted OFL fonts (woff2, Latin subset). font-display: swap so the
   fallback paints immediately and text is readable before the face loads
   (progressive enhancement: the page is correct with fonts blocked).

   Subset scope: Latin + basic punctuation/quotes only (THEME.md §6). Greek/
   Hebrew/Cyrillic ranges are deliberately NOT shipped yet — no non-Latin
   translations ship, so the bytes would be dead weight. When such a translation
   lands, add the matching subset face(s) per THEME.md §5.

   Reading body — Gentium Book Plus (SHIPPED after the gold-on-navy retheme):
   The gold-on-navy "Lemma" identity (docs/theming-guidelines.md §3) makes Gentium
   the scholarly reading serif shared across the sibling apps, so it is now the
   shipped body here too — giving the family one typographic voice. Gentium Book
   Plus has moderate-to-high stroke contrast (measured x-height 0.454em); the
   0.01em letter-spacing on .scripture quiets any halation on the dark navy ground
   at 19px (the contrast/halation note lives on the .scripture rule). NOTE: live
   in-browser legibility on the navy ground could not be verified headlessly.
   LITERATA — the prior default, commissioned as a screen reading face (Google
   Play Books), lower/even stroke contrast, larger x-height (measured 0.507em) —
   stays self-hosted as the DOCUMENTED ALTERNATE: reorder --font-reading back to
   "Literata", "Literata Fallback", Georgia, serif to revert in one line. Both
   are OFL; both @font-face + metric-matched fallback faces are defined below.
   ========================================================================= */

/* ---- Reading body: Literata (SHIPPED default) ---- */
@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 400 700;            /* variable woff2 covers the weight axis */
  font-display: swap;
  src: url("/fonts/literata-latin-400.woff2") format("woff2");
}
@font-face {
  font-family: "Literata";
  font-style: italic;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/literata-latin-400-italic.woff2") format("woff2");
}

/* ---- Reading body: Gentium Book Plus (self-hosted ALTERNATE, not default) ---- */
@font-face {
  font-family: "Gentium Book Plus";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/gentium-book-plus-latin-400.woff2") format("woff2");
}
@font-face {
  font-family: "Gentium Book Plus";
  font-style: italic;
  font-weight: 400;
  font-display: swap;
  src: url("/fonts/gentium-book-plus-latin-400-italic.woff2") format("woff2");
}
@font-face {
  font-family: "Gentium Book Plus";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/fonts/gentium-book-plus-latin-700.woff2") format("woff2");
}

/* ---- UI: Inter (variable woff2 covers 400/600/700) ---- */
@font-face {
  font-family: "Inter";
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url("/fonts/inter-latin-variable.woff2") format("woff2");
}

/* ---- Codes/refs: JetBrains Mono (variable woff2 covers 400/500) ---- */
@font-face {
  font-family: "JetBrains Mono";
  font-style: normal;
  font-weight: 400 500;
  font-display: swap;
  src: url("/fonts/jetbrains-mono-latin-variable.woff2") format("woff2");
}

/* =========================================================================
   RD23 — Font-loading CLS discipline.
   Self-hosting fonts is the redesign's main CLS risk: when a web font swaps in
   (font-display: swap), a difference in metrics vs the fallback reflows the
   text. We minimise that reflow for the READING BODY (the largest run of text,
   so the biggest CLS lever) by giving its fallback a metric-matched cut: a
   @font-face that wraps the local serif fallback (Georgia, then Times New Roman)
   and carries size-adjust + ascent/descent/line-gap overrides tuned so the
   fallback occupies almost exactly the same line box and x-height as the web
   font. The web-font @font-face above ships UNMODIFIED (renders as designed);
   only these fallback faces are reshaped. The adjusted family is inserted ahead
   of bare Georgia in --font-reading below.

   #138 CORRECTION — the UI face needed one too. This block used to claim
   "UI/mono fall back to system faces whose metrics are already close and which
   carry far less text, so they do not get a tuned fallback". THE MEASUREMENT
   CONTRADICTS THAT, so the claim is retired. Request-blocking one face at a time
   on /v/john/3/16 (mobile 412x823 DPR 1.75, cold cache) attributes effectively
   ALL of that page's CLS to Inter: block Inter and CLS goes 0.0886 -> 0.0000,
   while blocking Gentium (0.0886) or JetBrains (0.0885) changes nothing.
   "Carries far less text" was the wrong model. UI text sits in boxes that
   RE-WRAP, and one extra wrapped row displaces every pixel below it: on swap the
   .study-toolbar-shelf button row measures 109px -> 161px (+52px, one row), and
   .pager-prev / .share-permalink each go from one line to two. Inter runs ~9%
   wider than Segoe UI at the same size, which is what tips those rows over. So
   the UI face now gets the same treatment the reading body already had — see
   "Inter Fallback" below. MONO still has no tuned fallback, and that is measured
   rather than assumed: blocking JetBrains moved CLS by 0.0001.

   Override values are DERIVED from the real font metrics (fontTools on the
   shipped woff2), not guessed. Method, so this stays re-derivable:
     size-adjust      = webfont x-height / fallback x-height
     ascent-override  = webfont ascent  / that size-adjust
     descent-override = webfont descent / that size-adjust   (line-gap likewise)
   "line asc/desc" is the metric pair the browser ACTUALLY uses: hhea/usWin*,
   EXCEPT when OS/2 fsSelection bit 7 (USE_TYPO_METRICS) is set, in which case it
   is sTypoAscender/sTypoDescender. Georgia and Segoe UI have bit 7 CLEAR (usWin);
   Literata, Gentium and Inter have it SET (sTypo). For Inter that distinction is
   load-bearing — its usWin pair is 1.1079/0.3223 and would give wrong overrides.
     Georgia natural x-height = 0.4814em; line asc/desc = 0.917 / 0.219.
     Literata x-height = 0.507em; line asc/desc = 1.177 / 0.308.
       -> size-adjust 105.31%, ascent 111.77%, descent 29.25%, line-gap 0%.
     Gentium x-height = 0.454em; line asc/desc = 1.099 / 0.366.
       -> size-adjust 94.32%, ascent 116.48%, descent 38.83%, line-gap 0%.
     Segoe UI natural x-height = 0.5000em; line asc/desc = 1.0791 / 0.2510.
     Inter x-height = 0.5459em; line asc/desc = 0.9688 / 0.2412.
       -> size-adjust 109.18%, ascent 88.73%, descent 22.09%, line-gap 0%.

   Why Segoe UI is the basis for the Inter cut: --font-ui's first fallback is
   `system-ui`, which on the reference platform (Chrome/Windows) resolves to
   Segoe UI — confirmed by canvas metric equality against the named family, not
   assumed. Matching x-height also matches WIDTH here, which is the property that
   actually governs re-wrap: the measured corpus advance-width ratio Inter/Segoe
   UI is 1.0905, within 0.12% of the 1.0918 x-height ratio. The local() list
   carries Roboto then Arial for platforms where system-ui is not Segoe UI; both
   were measured against the shipped Inter and both are IMPROVED by these
   overrides (residual advance-width error: Segoe UI 0.12%, Arial 3.10%, Roboto
   3.58% — against 8.30% / 5.57% / 5.13% with no adjusted fallback at all).
   Verdana is deliberately NOT in that list: it is wider than Inter, so these
   overrides would make it worse (15.29% vs 5.60% unadjusted).
   ========================================================================= */
@font-face {
  font-family: "Literata Fallback";
  src: local("Georgia"), local("Times New Roman");
  size-adjust: 105.31%;
  ascent-override: 111.77%;
  descent-override: 29.25%;
  line-gap-override: 0%;
}
@font-face {
  font-family: "Gentium Fallback";
  src: local("Georgia"), local("Times New Roman");
  size-adjust: 94.32%;
  ascent-override: 116.48%;
  descent-override: 38.83%;
  line-gap-override: 0%;
}
/* #138 — the UI fallback. Same discipline as the two reading cuts above, applied
   to the face that measurement showed owns the /v/* CLS. If none of these local
   faces exist the family simply does not resolve and --font-ui falls through to
   bare `system-ui` exactly as before, so this can only help. */
@font-face {
  font-family: "Inter Fallback";
  src: local("Segoe UI"), local("Roboto"), local("Arial");
  size-adjust: 109.18%;
  ascent-override: 88.73%;
  descent-override: 22.09%;
  line-gap-override: 0%;
}

:root {
  /* ---- shared (THEME.md §2 + §3 + §4) ---- */
  /* GOLD-ON-NAVY "Lemma" identity (docs/theming-guidelines.md is the canonical
     authority). The single chromatic accent is gold #c8a13b; the old brand red
     has retired. --brand-core anchors the gold so any chrome that referenced the
     old identity hue now resolves to the gold mark. */
  --brand-core: #c8a13b;             /* identity gold (the single accent) */
  --radius: 10px;                    /* Lemma base radius (was 6px) */
  --focus-ring: 2px solid var(--brand);
  --measure: 66ch;                   /* reading column; clamp 60–72ch */

  /* ---- Lemma accent alphas (theme-invariant: gold alphas + dark navy) ----
     GEBible lacks these; they are defined ONCE here (gold is the same hue on
     every theme, and the on-accent navy is constant) so the Lemma component
     idioms — soft-button inversion, icon badges, input focus halo, selected
     rings — work across dark/light/sepia without per-theme overrides. */
  --accent-soft: rgba(200, 161, 59, 0.12);   /* 12% gold fill (soft buttons, icon badges, halos) */
  --accent-border: rgba(200, 161, 59, 0.35); /* 35% gold border (outlines, hairlines, rings) */
  --on-accent: #0a1530;                       /* dark navy text on ANY solid-gold fill */

  /* color-blind-safe highlight set (bg tint + optional underline; never spectral) */
  --hl-yellow: #E6D072; --hl-green: #8FCFA0; --hl-blue: #8FBEE0;
  --hl-pink: #E3A6C0;   --hl-purple: #B6A6E0; --hl-orange: #E6B584;

  /* font stacks (THEME.md §3 + docs/theming-guidelines.md §3).
     Reading body ships GENTIUM BOOK PLUS (the Lemma identity reading face), with
     the metric-matched "Gentium Fallback" (Georgia + overrides) ahead of bare
     Georgia so a font-swap reflow is negligible (RD23). This adopts the Lemma
     gold-on-navy retheme: the scholarly serif of the sibling apps is now the
     SHIPPED body here too, so the family reads as one voice.
     LITERATA stays self-hosted as the documented alternate (screen-tuned; the
     prior default) — to revert the body to Literata, reorder this stack to
       "Literata", "Literata Fallback", Georgia, serif;
     (its @font-face + "Literata Fallback" metric face are still defined above,
     so the revert is a one-line change). */
  --font-reading: "Gentium Book Plus", "Gentium Fallback", Georgia, serif;
  --font-ui: "Inter", "Inter Fallback", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  --font-fallback-classical: "Noto Serif", serif;

  /* spacing scale + density (THEME.md §4) */
  --space-1: 4px; --space-2: 8px; --space-3: 12px; --space-4: 16px;
  --space-5: 24px; --space-6: 32px; --space-7: 40px; --space-8: 48px;
  --density: 1;                      /* comfortable */

  /* Label color on solid-gold fills. INVERTED from the old white-on-red: a solid
     gold fill is light, so it takes DARK NAVY text. Equal to --on-accent. */
  --brand-on-fill: #0a1530;

  /* Optional hairline a hair softer than --pane-border (Lemma --border-soft). */
  --pane-border-soft: #232c4d;

  /* Patreon's CURRENT brand pair, for the one third-party sign-in control
     (.patron-signin-btn). Theme-invariant on purpose — a brand colour is not
     ours to re-theme. White on this near-black measures 19.3:1. The retired
     coral #FF424D is deliberately NOT tokenised here: white on it measures
     3.42:1 and fails WCAG AA for normal text, and an unused token invites use. */
  --patreon-black: #0e0e10;
  --patreon-on-black: #ffffff;

  /* ---- DARK is the unconditional default: the bare :root resolves to the
         gold-on-navy Lemma dark theme. ---- */
  --surface: #0a1530; --surface-raised: #1a2547; --surface-sunken: #070f24;
  --text-primary: #e6edf3;           /* 15.3:1 on --surface (AAA) */
  --text-secondary: #9aa7c4;         /* 7.5:1 on --surface (AAA) — verse numbers, labels */
  --text-faint: #909dbe;             /* tertiary: captions, meta, placeholders (5.5:1 on card) */
  --brand: #c8a13b;                  /* THE gold accent: links, active, focus, icons (7.4:1 on --surface) */
  --brand-fill: #c8a13b;             /* solid primary-button fill (dark navy label via --brand-on-fill) */
  --cross-ref: #8AB4F8; --quoted-ot: #6FB8C9; --diff: #D9A441;
  --note: #5FB89A;     --woc: #D98078; --danger: #FF7A45;
  --search-match: #2a3320;           /* subtle warm tint behind matched terms (navy-warm) */
  --pane-border: #2a3559;
  --shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
  /* Spotlight warmth wash: a very soft gold glow seated in the top-right of the
     study-spotlight card, fading to transparent so the card surface (and the
     .scripture reading text on it) is untouched at the reading line. Built from
     the same 12%-gold alpha family as --accent-soft so it is theme-invariant and
     subordinate. See .study-spotlight-card. */
  --spotlight-glow: rgba(200, 161, 59, 0.10);
}

/* ---- DARK (default — gold-on-navy Lemma identity) ---- */
[data-theme="dark"] {
  --surface: #0a1530; --surface-raised: #1a2547; --surface-sunken: #070f24;
  --text-primary: #e6edf3;
  --text-secondary: #9aa7c4;
  --text-faint: #909dbe;
  --brand: #c8a13b;
  --brand-fill: #c8a13b;
  --cross-ref: #8AB4F8; --quoted-ot: #6FB8C9; --diff: #D9A441;
  --note: #5FB89A;     --woc: #D98078; --danger: #FF7A45;
  --search-match: #2a3320;
  --pane-border: #2a3559;
  --pane-border-soft: #232c4d;
  --shadow: 0 8px 30px rgba(0, 0, 0, 0.35);
  --spotlight-glow: rgba(200, 161, 59, 0.10);
}

/* ---- LIGHT (opt-in — shares the gold accent) ----
   Surfaces + text are unchanged (AA-verified). The accent is the SAME gold family
   as dark, but bright gold #c8a13b on a light surface is only ~2.4:1 and FAILS AA
   for text/links, so --brand uses a darker "gold-ink" (#8a6510) that holds AA on
   every light surface: 5.13:1 on --surface, 5.32:1 on --surface-raised, 4.74:1 on
   --surface-sunken. The SOLID button fill stays BRIGHT gold (#c8a13b) with dark
   navy text (--brand-on-fill) because the fill is its own surface (7.41:1). */
[data-theme="light"] {
  --surface: #FBFBF9;                /* warm off-white reduces glare vs #FFF */
  --surface-raised: #FFFFFF; --surface-sunken: #F2F2EF;
  --text-primary: #1B1B1F;           /* 16.6:1 — crisp, not glaring */
  --text-secondary: #54545C;         /* 7.2:1 (AAA) */
  --text-faint: #646470;             /* tertiary captions/placeholders (5.63:1 on --surface) */
  --brand: #8a6510;                  /* AA-safe gold-ink: 5.13:1 on --surface */
  --brand-fill: #c8a13b;             /* solid fill stays bright gold (dark navy label) */
  --cross-ref: #2E5AAC; --quoted-ot: #2C7A8C; --diff: #8A5A00;
  --note: #2E7D64;     --woc: #A23329; --danger: #C2410C;
  --search-match: #FFF1B8;
  --pane-border: #E4E4E1;
  --pane-border-soft: #ECECEA;
  --shadow: 0 8px 30px rgba(27, 31, 36, 0.12), 0 1px 2px rgba(27, 31, 36, 0.06);
  /* On the near-white light ground a 10% gold reads as muddy; a lighter 7% warm
     gold keeps the wash a barely-there warmth without dulling the surface. */
  --spotlight-glow: rgba(200, 161, 59, 0.07);
}

/* ---- SEPIA (optional, recommended — shares the gold accent) ----
   Warm reading ground unchanged. The accent is the SAME gold family; on the
   warmer sepia ground a darker gold-ink is required for AA than on light (the
   ground sits closer to the gold in luminance), so --brand uses #7a5e16: 5.07:1
   on --surface, 5.52:1 on --surface-raised, 4.50:1 on --surface-sunken. Solid
   fill stays bright gold (#c8a13b) with dark navy text. */
[data-theme="sepia"] {
  --surface: #F3E9D6; --surface-raised: #FAF3E3; --surface-sunken: #E9DCC2;
  --text-primary: #2E2519;           /* warm near-black 12.5:1 */
  --text-secondary: #6B5B43;
  --text-faint: #6B5840;             /* tertiary captions/placeholders (5.63:1 on --surface) */
  --brand: #7a5e16;                  /* AA-safe gold-ink: 5.07:1 on --surface */
  --brand-fill: #c8a13b;             /* solid fill stays bright gold (dark navy label) */
  --cross-ref: #2B5C7A; --quoted-ot: #2C6F66; --diff: #7A5400;
  --note: #3E6B4E;     --woc: #8C2E22; --danger: #B5502A;
  --search-match: #EBD9A8;
  --pane-border: #DCC9A6;
  --pane-border-soft: #E6D8BC;
  --shadow: 0 8px 30px rgba(74, 60, 38, 0.16), 0 1px 2px rgba(74, 60, 38, 0.08);
  /* The sepia ground is already warm; a touch more gold than light reads as a
     natural deepening of the paper rather than a separate tint. */
  --spotlight-glow: rgba(200, 161, 59, 0.12);
}

/* ---- density: scales margins/padding only, never reading-body line-height ---- */
[data-density="compact"] { --density: 0.8; }

* { box-sizing: border-box; }

/* Gold focus ring on all interactive elements (THEME.md §7 / Lemma §6.3).
   --focus-ring resolves to 2px solid var(--brand), so it is gold on every theme. */
:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

/* Input focus HALO (Lemma §5.11 / §6.3): text inputs, search fields, selects and
   textareas use a softer 3px --accent-soft halo + a 35%-gold border on focus
   instead of the hard 2px ring. Property-scoped transition (Lemma §6.1). The
   halo is theme-invariant (gold alpha), so it reads the same on dark/light/sepia.
   We zero the outline on BOTH :focus and :focus-visible for these field types
   (the global :focus-visible rule above would otherwise re-add the 2px ring for
   keyboard focus) and replace it with the halo. Every other control keeps the
   2px ring. The halo is visible focus feedback, so a11y focus-visibility is
   preserved. Checkboxes/radios/submit/reset/button inputs keep the ring. */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):focus,
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="reset"]):focus-visible,
select:focus,
select:focus-visible,
textarea:focus,
textarea:focus-visible {
  outline: none;
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Motion is functional only; honor reduced-motion (THEME.md §4/§7). */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  /* Neutralize the global anchor-jump smooth-scroll on `html` (set below) for a
     motion-averse reader: an in-page jump (e.g. the study jump-nav) snaps with no
     pan. The `*` rule above already matches `html`; this is the explicit, self-
     documenting fold the jump-nav relies on (so it survives if `*` is ever
     narrowed). No second reduced-motion block is introduced. */
  html { scroll-behavior: auto !important; }
}

/* Smooth in-page anchor jumps (the study "On this page" jump-nav's pure-CSS
   "auto-pan" — no JS smooth-scroll). Neutralized under prefers-reduced-motion
   above. Scoped to `html` so it governs every same-page #id jump. */
html { scroll-behavior: smooth; }

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  font-family: var(--font-ui);
  /* Dark-theme background WASH (Lemma §2.4): a large soft radial gradient lifts a
     slightly brighter navy into the top-right and fades to --surface by 55%,
     giving the dark page depth without a visible seam. The :root default is the
     dark theme, so the wash is the default; light/sepia override to FLAT below
     (a navy wash would muddy their warm reading grounds). Sticky bars stay FLAT
     var(--surface) so content scrolls under them fully occluded. */
  background: radial-gradient(1200px 600px at 70% -10%, #1a3568 0%, var(--surface) 55%);
  background-color: var(--surface);
  color: var(--text-primary);
  line-height: 1.6;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}
/* Light + sepia keep a FLAT reading ground (no navy wash). */
[data-theme="light"] body,
[data-theme="sepia"] body { background: var(--surface); }

a { color: var(--brand); text-decoration: none; }
a:hover { text-decoration: underline; }

.container {
  width: 100%;
  max-width: 76rem;
  margin: 0 auto;
  /* Density wires into the main container padding (THEME.md §4). */
  padding: calc(var(--space-5) * var(--density));
  flex: 1 0 auto;
}
.container.narrow { max-width: 40rem; }
.text-center { text-align: center; }
.muted { color: var(--text-secondary); }
.small { font-size: 0.85rem; }
.empty { color: var(--text-secondary); font-style: italic; }

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

/* --- Buttons --- */
/* Primary button (Lemma §5.1): a 135deg gold gradient with dark navy text. The
   gold fill is its own surface, so --brand-on-fill (= --on-accent, dark navy)
   holds AA across all three themes (≥5.5:1). Hover adds the signature gold glow;
   :active presses 1px. */
.btn {
  display: inline-block;
  padding: 0.55rem 1rem;
  border-radius: var(--radius);
  background: linear-gradient(135deg, #d4a839 0%, #b8852a 100%);
  color: var(--brand-on-fill);
  border: 1px solid transparent;
  font-weight: 700;
  cursor: pointer;
  text-decoration: none;
  transition: box-shadow 120ms ease, transform 0.08s ease;
}
.btn:hover { box-shadow: 0 6px 18px rgba(200, 161, 59, 0.3); text-decoration: none; }
.btn:active { transform: translateY(1px); }
/* Soft / outline button (Lemma §5.1 — the dominant secondary idiom): gold text on
   a 12% gold fill with a 35% gold border, INVERTING to solid BRIGHT gold + dark
   navy text on hover/focus. The inversion fills with --brand-fill (bright gold
   #c8a13b on every theme) rather than --brand, so the dark-navy --on-accent label
   holds AA (7.41:1) on all three themes — on light/sepia --brand is a dark
   gold-ink that would fail under navy text. */
.btn-ghost {
  background: var(--accent-soft);
  color: var(--brand);
  border-color: var(--accent-border);
  font-weight: 600;
  transition: color 120ms, border-color 120ms, background 120ms;
}
.btn-ghost:hover,
.btn-ghost:focus-visible {
  background: var(--brand-fill);
  color: var(--on-accent);
  border-color: var(--brand-fill);
  box-shadow: none;
  text-decoration: none;
}

.pill {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 600;
  background: var(--surface-sunken);
  border: 1px solid var(--pane-border);
}
/* `.pill-subscriber` (the solid-gold fill) was REMOVED with the header's Ad-free
   pill, which was its only consumer — the ★ Supporter menu replaced it. It is
   not dead-but-kept: an unused gold-fill class is exactly the kind of rule a
   later surface picks up by accident, and gold is chrome-only here. */
.pill-soon { color: var(--text-secondary); }
.badge {
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}

/* --- Header / nav (chrome — the gold accent is correct for active/CTA) --- */
.site-header {
  background: var(--surface-raised);
  border-bottom: 1px solid var(--pane-border);
  position: sticky;
  top: 0;
  z-index: 50;
}
.header-inner {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  padding: 0.6rem 1.25rem;
  max-width: 76rem;
  margin: 0 auto;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  /* RD1/RD18: the wordmark is NOT all-accent. The link is neutral text; the gold
     accent is reserved for the single .brand-mark ("GE"), keeping the chrome calm
     and editorial. */
  color: var(--text-primary);
}
.brand:hover { text-decoration: none; }
.brand-logo { border-radius: 6px; }

/* RD1 — GEBible wordmark. The gold accent touches ONLY the "GE" (the
   .brand-mark), never the whole word (THEME.md §0/§1). The reading column is
   unaffected — this is chrome. */
.brand-name {
  /* Closed "GEBible" wordmark set in the READING SERIF (--font-reading, the
     shipped Gentium Book Plus) rather than the UI sans, to read as a well-set
     edition's title rather than app chrome. Reuses the existing reading-serif
     token — NO new font file. The gold-"GE" / neutral-"Bible" carve-out
     (.brand-mark / .brand-rest) is unchanged, so the single-accent discipline
     and AA contrast of the gold mark (the --brand token) hold on all three
     themes. Applied to both header brand and the hero wordmark below. */
  font-family: var(--font-reading);
  font-weight: 700;
  letter-spacing: -0.01em;
  /* Snap to the smaller of the surrounding context; header/footer set sizes. */
  line-height: 1;
}
.brand-mark { color: var(--brand); }
.brand-rest { color: var(--text-primary); }
/* In the footer the brand line is a heading-weight wordmark; keep the same
   carve-out (mark gold, rest neutral). The display size is set on .footer-brand
   in the Footer section (1.3rem for the fat-footer brand column). */

.nav-toggle {
  margin-inline-start: auto;
  display: none;
  width: 40px; height: 36px;
  background: transparent;
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  cursor: pointer;
}
.nav-toggle-bar,
.nav-toggle-bar::before,
.nav-toggle-bar::after {
  display: block;
  width: 18px; height: 2px;
  margin: 0 auto;
  background: var(--text-primary);
  position: relative;
}
.nav-toggle-bar::before { content: ""; position: absolute; top: -6px; inset-inline-start: 0; width: 18px; height: 2px; background: var(--text-primary); }
.nav-toggle-bar::after { content: ""; position: absolute; top: 6px; inset-inline-start: 0; width: 18px; height: 2px; background: var(--text-primary); }

.primary-nav {
  display: flex;
  align-items: center;
  gap: 1rem;
  flex: 1;
  flex-wrap: wrap;
}
.nav-list {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-list-end { margin-inline-start: auto; }
.nav-list a,
.nav-dropdown-toggle {
  display: inline-block;
  padding: 0.4rem 0.7rem;
  border-radius: 8px;
  color: var(--text-primary);
  background: transparent;
  border: none;
  font: inherit;
  cursor: pointer;
}
.nav-list a:hover,
.nav-dropdown-toggle:hover { background: var(--surface-sunken); color: var(--brand); text-decoration: none; }
.nav-cta { color: var(--brand) !important; font-weight: 600; }

/* Dropdown */
.nav-dropdown { position: relative; }
.nav-dropdown-menu {
  position: absolute;
  top: 100%;
  inset-inline-start: 0;
  min-width: 13rem;
  margin: 0.25rem 0 0;
  padding: 0.35rem;
  list-style: none;
  background: var(--surface-raised);
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  display: none;
}
.nav-dropdown.open .nav-dropdown-menu { display: block; }
.nav-dropdown-menu a,
.nav-dropdown-menu .is-coming-soon {
  display: block;
  padding: 0.45rem 0.6rem;
  border-radius: 6px;
}
.nav-dropdown-menu a:hover { background: var(--surface-sunken); }
/* Inert "soon" rows (Analysis dropdown): a non-link <span aria-disabled> that
   sits exactly like the anchor rows but is recessive and not interactive. The
   section name stays reading-adjacent (--text-secondary, NOT gold); only the
   .badge carries the existing recessive treatment. */
.nav-dropdown-menu .is-coming-soon {
  color: var(--text-secondary);
  cursor: default;
}
.nav-dropdown-divider { border-top: 1px solid var(--pane-border); margin-top: 0.25rem; padding-top: 0.25rem; }
.caret { font-size: 0.7em; }

/* --- Hero / home ---
   Centered, search-first single column at ALL widths: app icon, GE/Bible
   wordmark, the paramount (enlarged) search with its examples folded into the
   placeholder, a recessive trust echo, and one subordinate browse link. The
   search is the visual focal point; everything else is calmer chrome. The
   reading specimen moved to the "passage worth studying" spotlight further
   down. */
.hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.85rem;
  padding: 2.5rem 0 1.5rem;
}

/* Decorative app icon. Rounded container, NO gold .icon-badge halo (the badge is
   a button-like chrome primitive; doubling the gold here would read as a CTA).
   Sized by clamp; explicit width/height attrs in the markup reserve the box. */
.hero-icon {
  inline-size: clamp(72px, 10vw, 88px);
  block-size: clamp(72px, 10vw, 88px);
  border-radius: 18px;
  margin: 0;
}

/* Wordmark — same carve-out as the header brand (.brand-mark gold "GE",
   .brand-rest neutral). Larger here, and resets the <h1> default margins. */
.hero-wordmark {
  margin: 0;
  font-size: clamp(2rem, 6vw, 3rem);
}

/* Hero line — "Read. Study. Question." Subordinate to the wordmark above it and
   to the search below it, so it takes the secondary ink and stays well under the
   wordmark's size. NOT gold: gold is chrome-only here, and this is content. The
   open letter-spacing is doing the real work — it separates the three beats so
   they read as a deliberate stack rather than a cramped sentence. Vertical
   rhythm comes from the .hero flex `gap`, so margin is only reset. */
.hero-tagline {
  margin: 0;
  color: var(--text-secondary);
  font-size: clamp(0.95rem, 2.4vw, 1.15rem);
  letter-spacing: 0.08em;
}

/* Decorative scholarly flourish: a thin hairline rule split by a small centered
   gold ornament, echoing a well-set edition's title rule. A quiet accent
   subordinate to the search — NOT a box around the hero. Theme-aware via tokens
   ONLY (no hardcoded hex): the rule fades to a soft hairline (--pane-border-soft)
   away from center, and the central gold uses --accent-border so it resolves to
   the AA-safe gold-ink on light/sepia. aria-hidden in the markup, so it is never
   announced; this is pure chrome. The rule itself is the row; the ::before/::after
   draw the two hairline segments flanking the centered .hero-flourish glyph. */
.hero-rule {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  width: 100%;
  max-width: 18rem;
  margin: 0.15rem 0;
}
.hero-rule::before,
.hero-rule::after {
  content: "";
  flex: 1 1 auto;
  block-size: 1px;
}
.hero-rule::before {
  background: linear-gradient(to right, transparent, var(--pane-border-soft) 35%, var(--accent-border));
}
.hero-rule::after {
  background: linear-gradient(to left, transparent, var(--pane-border-soft) 35%, var(--accent-border));
}

/* The flourish glyph itself — a small symmetric four-point star. Colored gold via
   currentColor + the --brand token, so it resolves to bright gold on dark and the
   AA-safe gold-ink on light/sepia. Sized small so it reads as a quiet ornament. */
.hero-flourish {
  flex: 0 0 auto;
  inline-size: 0.85rem;
  block-size: 0.85rem;
  color: var(--brand);
}

/* The paramount search — ONE integrated rounded "pill". The .hero-search element
   is the pill: a subtle raised surface (--surface-raised) with a thin border
   (--pane-border), fully rounded, holding a leading magnifier, a borderless
   transparent input filling the middle, and a solid-gold "Search" button inset on
   the right. Full width up to a generous cap, centered; stays fluid on small
   screens (the button stays inset, the input shrinks). The whole pill lights up
   with the standard gold focus halo on :focus-within (replacing the per-input
   global :focus halo, which is suppressed below so it does not double inside the
   pill). Token-only color — CSP-safe (no inline style). */
.hero-search {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  width: 100%;
  max-width: 56rem;
  margin-inline: auto;
  margin-block: 0.25rem 0;
  padding: 0.35rem 0.4rem 0.35rem 0.9rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  box-shadow: var(--shadow);
}
/* The pill (not the input) owns the focus halo. */
.hero-search:focus-within {
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Leading magnifier — decorative, muted gold; sized/colored here, not inline. */
.hero-search-icon {
  flex: 0 0 auto;
  inline-size: 1.25rem;
  block-size: 1.25rem;
  color: var(--brand);
  opacity: 0.75;
}
/* The input is borderless/transparent WITHIN the pill (the pill draws the chrome).
   Its own focus outline is removed because :focus-within lights the whole pill. */
.hero-search input {
  flex: 1;
  min-width: 0;
  padding: 0.55rem 0.5rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text-primary);
  font-size: 1.05rem;
}
/* The pill owns the focus halo (:focus-within above), so suppress the per-input
   global halo (Lemma §5.11) here — otherwise the input would draw a SECOND halo
   inside the pill. The #hero-q id selector clears the global field-focus rule's
   specificity for both :focus and :focus-visible. */
#hero-q:focus,
#hero-q:focus-visible {
  outline: none;
  border: 0;
  box-shadow: none;
}
.hero-search input::placeholder {
  color: var(--text-faint);
}
/* The inset gold button — solid --brand-fill with dark-navy --on-accent text
   (AA on the fill in every theme), rounded to sit inside the pill. */
.hero-search button {
  flex: 0 0 auto;
  padding: 0.6rem 1.4rem;
  border: 1px solid var(--brand-fill);
  border-radius: 999px;
  background: var(--brand-fill);
  color: var(--on-accent);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
}
.hero-search button:hover {
  filter: brightness(1.05);
}
/* On very narrow screens drop the leading icon and tighten padding so the input
   keeps usable room and the button stays inset (no overflow). */
@media (max-width: 30rem) {
  .hero-search {
    padding-inline-start: 0.6rem;
  }
  .hero-search-icon {
    display: none;
  }
  .hero-search button {
    padding-inline: 1rem;
  }
}

/* Trust echo: one recessive line (the full contract strip is its own section). */
.hero-trust {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.9rem;
}

/* (The former subordinate .hero-browse link was folded into the lower 3-up panel
   grid's "Browse all books" card; its orphaned rules were removed.) */

/* --- Reusable gold icon-badge (theming-guidelines §1.3/§5.4) ---
   Circular --accent-soft fill, 35%-gold border, gold glyph; fully round (999px).
   Chrome primitive — the gold accent is the documented treatment here. Used by
   the lower 3-up .home-panel grid (Browse / Tools / From the blog). (The contract
   strip now uses the ring-only .contract-icon instead — see Section 2.) The glyph
   is decorative (aria-hidden in the markup), so its meaning never depends on color
   alone. */
.icon-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border-radius: 999px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--brand);
  font-family: var(--font-ui);
  font-size: 1.1rem;
  line-height: 1;
}

/* --- Section 2: primary-source contract strip ---
   The four trust claims under the hero. Each claim: a circular gold-RING icon
   (thin outlined circle, transparent fill, gold glyph centered) on the left, then
   a bold label + two-line description stacked to the right. Faint vertical hairline
   dividers separate the four columns.

   The grid collapses 4 -> 2 -> 1 via explicit breakpoints (NOT auto-fit) so we
   know exactly which items begin a row and can hide the divider on each row's
   leading column — auto-fit would leave dangling/orphan dividers when it wraps. */
.contract-strip { margin: 1.75rem 0; }
.contract-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
/* Each column: icon + body, with a leading vertical hairline divider drawn by
   ::before. column-gap is 0 so the divider sits in the padded gutter. */
.contract-item {
  position: relative;
  display: flex;
  gap: 0.75rem;
  align-items: flex-start;
  padding-inline: 1.25rem;
}
/* Faint vertical hairline between same-row siblings. Hidden on the leading column
   of each row (overridden per breakpoint below) so wrapping never orphans a line. */
.contract-item::before {
  content: "";
  position: absolute;
  inset-block: 0.1rem;
  inset-inline-start: 0;
  inline-size: 1px;
  background: var(--pane-border-soft);
}
/* 4-up (default, wide): only the first column has no left divider. */
.contract-item:first-child::before { display: none; }

/* The circular gold badge: --accent-soft (12% gold) fill, thin --accent-border
   ring, gold glyph centered (the glyph inherits color via currentColor). This is
   the app's signature icon-badge treatment (theming-guidelines §5.4) — the same
   fill the .icon-badge containers and panel/stat badges carry — so the contract
   strip's four icons read with the same weight as every other gold badge on the
   page instead of as hollow rings. */
.contract-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  inline-size: 3.5rem;
  block-size: 3.5rem;
  border-radius: 999px;
  border: 1px solid var(--accent-border);
  background: var(--accent-soft);
  color: var(--brand);
}
.contract-glyph {
  inline-size: 1.8rem;
  block-size: 1.8rem;
}
.contract-body { min-width: 0; }
.contract-label {
  margin: 0 0 0.15rem;
  font-family: var(--font-ui);
  font-weight: 600;
}
.contract-line {
  margin: 0;
  font-size: 0.9rem;
  color: var(--text-secondary);
}

/* 2-up (medium): items 1 and 3 begin a row, so they carry no left divider.
   Vertical gutter padding keeps the two rows breathing. */
@media (max-width: 52rem) {
  .contract-list {
    grid-template-columns: repeat(2, 1fr);
    row-gap: 1.5rem;
  }
  /* Items 1 and 3 begin a row at 2-up — no left divider. */
  .contract-item:nth-child(odd)::before { display: none; }
}

/* 1-up (narrow): single column — every vertical divider would be an orphan, so
   drop them all and switch to a horizontal hairline above each item after the
   first (a clean horizontal rule instead of dangling vertical lines). */
@media (max-width: 32rem) {
  .contract-list {
    grid-template-columns: 1fr;
    row-gap: 0;
  }
  .contract-item {
    padding-block: 1rem;
    padding-inline: 0;
  }
  .contract-item::before {
    inset: 0 auto auto 0;
    inline-size: 100%;
    block-size: 1px;
  }
  /* Re-show the divider on odd items (the wider 2-up rule hid them); matched
     specificity + later source order so it wins. At 1-up every item except the
     first needs its horizontal hairline back. */
  .contract-item:nth-child(odd)::before { display: block; }
  .contract-item:first-child::before { display: none; }
}
/* The framing line ("Presented as a primary source...") reuses the recessive,
   italic .source-framing-note token; just give it the strip's top spacing. */
.contract-framing { margin-block-start: 1rem; }

/* --- Section 5: "A passage worth studying" spotlight ---
   The daily verse as a primary-source specimen, not a devotional card. Reading
   surface for the verse text; recessive reference; cross-ref count + translation
   chips + a study-page CTA. */
.study-spotlight { margin: 1.75rem 0; }
/* Heading row: the section <h2> with a quiet "A new passage each day" rotation
   microlabel beside it (P2 — accurate: the daily verse rotates daily from a
   curated table). The microlabel is recessive chrome. */
.study-spotlight-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 0.75rem;
}
.study-spotlight-rotation {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  color: var(--text-secondary);
}
/* The card carries a soft, theme-aware warmth wash INSTEAD of the rejected
   raster sunrise: a single radial gold glow (--spotlight-glow, per-theme) seated
   in the top-right and fading to transparent well before the reading line, layered
   OVER the flat --surface-raised fill. Because the glow is a low-alpha gold that
   dissolves to nothing, it warms the card chrome without sitting behind — or
   lowering the contrast of — the .scripture verse text, and it never colors the
   verse body gold (the text keeps --text-primary). Reads correctly on all three
   themes via the per-theme token; no hardcoded hex here.

   TWO-COLUMN at >=52rem: the verse specimen (FIRST in DOM source order) and the
   "Explore deeper" panel (SECOND) split into a grid with a vertical divider
   between them. Below 52rem it STACKS to one column, verse-first — achieved by
   the default single-column flow over the unchanged source order, NOT a CSS
   `order` swap, so tab order always equals visual order. */
.study-spotlight-card {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.1rem;
  background:
    radial-gradient(120% 90% at 100% 0%, var(--spotlight-glow) 0%, transparent 55%),
    var(--surface-raised);
  border: 1px solid var(--pane-border-soft);
  border-radius: 12px;
  padding: 1.25rem 1.35rem;
}
@media (min-width: 52rem) {
  .study-spotlight-card {
    grid-template-columns: minmax(0, 1fr) minmax(0, 16rem);
    gap: 1.6rem;
    align-items: stretch;
  }
  /* Vertical divider drawn on the Explore-deeper column's leading edge. */
  .study-spotlight-explore {
    border-inline-start: 1px solid var(--pane-border-soft);
    padding-inline-start: 1.6rem;
  }
}
/* Decorative sunrise/rays ornament — a minimal token-only glyph echoing the
   .hero-flourish pattern, NOT a raster. It sits as a small quiet mark above the
   verse, colored gold via currentColor + --brand (resolves to the AA-safe
   gold-ink on light/sepia), sized small so it stays subordinate to the verse.
   aria-hidden + focusable="false" in the markup; presentation attrs only there,
   all sizing/color here (CSP-safe). */
.study-spotlight-ornament {
  display: block;
  /* Sized off the 48:27 viewBox so the rays keep their proportions. Kept
     subordinate to the verse, but enlarged from the original 1.5rem so the
     glyph reads as an intentional motif rather than a stray mark. */
  inline-size: 2.5rem;
  block-size: 1.4rem;
  margin: 0 0 0.6rem;
  color: var(--brand);
  opacity: 0.85;
}
/* Reading surface: text tokens + reading font only (no brand). .scripture sets
   the face/size; reset the blockquote chrome and the constrained measure. */
.study-spotlight-text {
  margin: 0 0 0.85rem;
  border: none;
  padding: 0;
  max-width: none;
}
.study-spotlight-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
}
.study-spotlight-ref { margin: 0; }
/* The reference is now a passage-view link. It keeps the .reference-label
   mono/meta type but takes the citation-link token (--cross-ref) — never brand
   red — with an underline affordance on hover/focus. Mirrors .search-hit-ref so
   reference links read consistently and no brand color leaks near the reading
   surface (THEME.md: brand color is chrome-only and never in/around reading text). */
.study-spotlight-ref a { color: var(--cross-ref); }
.study-spotlight-ref a:hover, .study-spotlight-ref a:focus-visible { text-decoration: underline; }
.study-spotlight-refcount { margin: 0; font-family: var(--font-ui); font-size: 0.9rem; }
.study-spotlight-chips {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin: 0;
  padding: 0;
}

/* Left column wrapper — keeps the verse + meta as one flow so the grid can split
   it from the Explore-deeper panel. */
.study-spotlight-verse { min-width: 0; }

/* Diamond-divider hairline: a thin token-only rule split by a small gold gem,
   between the verse specimen and its meta line. Purely decorative (aria-hidden in
   the markup). The gold gem sits over a faint rule drawn with two flanking lines. */
.study-spotlight-rule {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0 0 0.85rem;
  color: var(--brand);
}
.study-spotlight-rule::before,
.study-spotlight-rule::after {
  content: "";
  flex: 1 1 auto;
  block-size: 1px;
  background: var(--pane-border-soft);
}
.study-spotlight-diamond { display: block; flex: 0 0 auto; opacity: 0.9; }

/* Right column — the "Explore deeper" panel. A compass icon badge, a heading, the
   warm/plain copy, a divider, then ONE gold-outlined primary CTA. The vertical
   divider between the columns is drawn on this element's inline-start at >=52rem
   (see the grid rule above). */
.study-spotlight-explore {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.7rem;
  min-width: 0;
}
/* Compass icon badge (the signature gold-ring icon, Lemma §5.4). */
.study-spotlight-explore-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border-radius: 999px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--brand);
}
.study-spotlight-explore-glyph { display: block; }
.study-spotlight-explore-title {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
}
.study-spotlight-explore-copy {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.92rem;
  line-height: 1.55;
  color: var(--text-secondary);
}
.study-spotlight-explore-divider {
  inline-size: 100%;
  block-size: 1px;
  background: var(--pane-border-soft);
  margin: 0.15rem 0;
}
/* The single primary CTA — the gold-outlined .btn.btn-ghost idiom (inverts to a
   solid bright-gold fill on hover/focus). Spans the panel width. */
.study-spotlight-explore-cta {
  align-self: stretch;
  text-align: center;
  /* Property-scoped transition so the .btn gold-glow eases in TOGETHER with the
     .btn-ghost colour invert. The base .btn-ghost transition omits box-shadow,
     which would otherwise pop the glow in instantly while the colour fades — a
     subtle but cheap-feeling mismatch. Functional only; the global
     prefers-reduced-motion clamp (THEME.md §4) neutralises it. */
  transition: color 120ms ease, background 120ms ease, border-color 120ms ease,
              box-shadow 120ms ease;
}
/* Keyboard focus earns the same gold glow as pointer hover (the base .btn adds
   the glow on :hover only), so tabbing to the CTA feels identical to pointing at
   it. The global gold focus ring still sits outside the glow for a11y. */
.study-spotlight-explore-cta:focus-visible {
  box-shadow: 0 6px 18px rgba(200, 161, 59, 0.3);
}

/* --- Section 6: lower-content 3-up panel grid ---
   Browse all books / Tools / From the blog, consolidating the former tools band +
   blog sections into one cohesive grid that sits BELOW the study-spotlight (the
   spotlight is the only live reading specimen and stays above). Auto-fit 3->2->1;
   each panel reuses the card idiom (--surface-raised + --pane-border + 12px
   radius) shared with .verse-card / .study-spotlight-card. Token-only; no new
   surface look invented. */
.home-panels { margin: 1.75rem 0; }
.home-panel-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 1rem;
}
.home-panel {
  border: 1px solid var(--pane-border-soft);
  border-radius: 12px;
  background: var(--surface-raised);
  padding: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
.home-panel-title { margin: 0; font-size: 1.1rem; }
.home-panel-line { margin: 0; color: var(--text-secondary); font-size: 0.9rem; }
/* Tool / post lists inside a panel: plain stacked rows, recessive supporting
   copy in --text-secondary; the link itself stays the gold --brand accent. */
.home-panel-tools,
.home-panel-posts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.45rem;
}
.home-panel-tools li,
.home-panel-posts li { color: var(--text-secondary); font-size: 0.9rem; }
/* The "Browse now ->" / "All tools ->" / "View all posts ->" footer link of each
   panel sits at the card foot; margin-top:auto keeps it bottom-aligned so the
   uneven-height panels read as a tidy row. */
.home-panel-link { margin: auto 0 0; font-size: 0.9rem; }

/* --- Section 4: Scripture Analysis band ---
   Surfaces the family of content sections that are LIVE (the roster's forthcoming
   members are deliberately not advertised on the front door).
   Matches the 1.75rem block rhythm of the neighboring sections. Each tile is a
   block-level <a> wearing the .home-panel card recipe (raised surface + soft
   border + 12px radius). Tokens-only color; the ONLY gold is the glyph (it
   inherits --brand from .icon-badge) — the tile's name/line read as normal text,
   never gold. */
.scripture-analysis { margin: 1.75rem 0; }
/* Header ornament — the centered open-book glyph flanked by gold hairline rules,
   reusing the home .hero-rule / .hero-flourish idiom. Centered above the display
   <h2>; the <h2> and subhead center under it so the band reads as a titled
   section, not a left-aligned list. Chrome only — no layout role. */
.analysis-rule { margin-inline: auto; margin-block: 0 0.5rem; }
.scripture-analysis > h2 {
  margin: 0 0 0.35rem;
  text-align: center;
}
.analysis-subhead {
  margin: 0 auto 1rem;
  color: var(--text-secondary);
  font-size: 0.95rem;
  max-inline-size: 60ch;
  text-align: center;
}
/* Auto-fit grid mirroring .home-panel-grid so 2-3 tiles "just work" when more
   sections go live. At N=1 the single column would stretch full-width; capping
   each item's inline-size and centering the track keeps the lone tile deliberate
   rather than a stretched lonely card. The track is centered (justify-content)
   so the lone capped tile sits under the centered header ornament. */
.analysis-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 1rem;
  justify-content: center;
}
.analysis-item { max-inline-size: 30rem; }
/* ICON-LEFT horizontal tile: the .icon-badge glyph at the inline-start, the
   title + line stacked to its right in .analysis-body. The whole tile is the
   link — one large tap target (>=44px naturally), one focus stop. Reading text
   inherits normal --text color; only the badge glyph is gold. align-items:start
   keeps the badge top-aligned with the title rather than vertically centered on
   the taller text block. */
.analysis-tile {
  display: flex;
  flex-direction: row;
  align-items: start;
  gap: 0.85rem;
  block-size: 100%;
  border: 1px solid var(--pane-border-soft);
  border-radius: 12px;
  background: var(--surface-raised);
  padding: 1.1rem;
  color: inherit;
  text-decoration: none;
}
/* The text column to the right of the badge. */
.analysis-body {
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
  min-inline-size: 0;
}
.analysis-badge { flex: 0 0 auto; }
.analysis-glyph {
  inline-size: 1.4rem;
  block-size: 1.4rem;
}
/* Capped tile title — serif display face, ~1.1rem, medium weight (500), so a row
   of tiles never out-shouts the hero search above the band. (The band <h2> stays
   large; only these per-tile <h3> titles are capped.) text-align:start keeps the
   tile copy left-aligned even though the header ornament/heading are centered. */
.analysis-name {
  margin: 0;
  font-family: var(--font-reading);
  font-size: 1.1rem;
  font-weight: 500;
  color: var(--text-primary);
  text-align: start;
}
.analysis-line {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.9rem;
  text-align: start;
}
/* Hover affordance, reduced-motion-safe: a quiet border lift only — NO gold
   bottom-glow / underline and NO standing gold arrow (every tile is an equal
   destination, and the whole tile is already the link). The transition is gated
   behind the motion-OK media query so reduced-motion users get the instant state
   change with no animation. */
.analysis-tile:hover { border-color: var(--accent-border); }
.analysis-tile:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: no-preference) {
  .analysis-tile { transition: border-color 0.15s ease; }
}
/* #132(b) — the band's closing provenance line. A NEW class: .analysis-subhead,
   .home-panel-link, .analysis-all, .source-framing-note and every .nav-* rule stay
   byte-untouched. Centered under the tiles, recessive, reading-measure capped. */
.analysis-provenance {
  margin: 0.9rem auto 0;
  max-inline-size: 62ch;
  text-align: center;
  font-size: 0.88rem;
  color: var(--text-secondary);
}

/* === Scripture Analysis HUB (/analysis) ================================== *
 * The umbrella front door. Composes the shipped .analysis-grid / .analysis-tile
 * recipe (above) + the section .analysis-search pill + the .rail-card .analysis-howto
 * explainer chrome. Only TWO genuinely-new tile bits are justified — .analysis-tile-stat
 * (the live meta line) and .analysis-tile--soon (the recessed soon modifier); the
 * rest here is minimal hub-LAYOUT + search-GROUP scaffolding (no shipped class fit a
 * single content column hero / a grouped-results header). Gold is CHROME-ONLY. */

/* Single content column, centered hero zone (no content+rail split — the hub has
   no rail content). */
.analysis-hub { padding-block: 1.5rem 2.5rem; }
.analysis-hub-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 0.75rem;
  margin-block-end: 2rem;
}
/* The hero magnifier badge — the gold-ring .icon-badge idiom, slightly larger to
   anchor the hero. */
.analysis-hub-hero-badge { margin-block-end: 0.25rem; }
.analysis-hub-title { margin: 0; }
.analysis-hub-mission {
  margin: 0 auto;
  max-inline-size: 60ch;
  color: var(--text-secondary);
  font-size: 1rem;
}
/* NEW (justified) — the hub at-a-glance meta strip: a single quiet reading-ink line
   beneath the mission (live-of-total scope · distinct-book reach). Smaller than the
   mission, same reading ink (--text-secondary, NOT gold — gold is chrome-only on this
   hub). tabular-nums keeps the derived counts steady. Mirrors the .analysis-tile-stat
   spirit (a calm meta line), at the hub level. */
.analysis-hub-meta {
  margin: 0 auto;
  color: var(--text-secondary);
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}
/* The hub search pill spans the FULL content column (no inline-size cap) so it reads
   as the hub's primary CTA across the same measure as the roster grid below it,
   matching the full-width /analysis/search results-page pill (.science-theme-search).
   The inner .analysis-search-form is already full-width (inline-size: 100%, no cap),
   so lifting the wrapper cap is sufficient — no form-level override needed. */
.analysis-hub-search {
  inline-size: 100%;
  margin-block-start: 0.5rem;
}
/* The roster grid spans the content column (the homepage band caps each tile; here
   we let the auto-fit grid breathe across the full width). */
.analysis-hub-grid { margin-block-end: 2.25rem; }
.analysis-hub-grid .analysis-item { max-inline-size: none; }

/* NEW (justified #1) — the live-tile stat: a quiet reading-ink meta line, NOT a
   gold-ring landing stat badge. Reading ink (--text-secondary), small, never gold. */
.analysis-tile-stat {
  margin: 0.15rem 0 0;
  color: var(--text-secondary);
  font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}

/* NEW (justified #2) — the SOON tile modifier: a RECESSED, INERT card. Recession is
   via a SUNKEN surface + a softened border + a dimmed NAME — deliberately NOT via
   opacity (opacity would drag the .analysis-line's --text-secondary below WCAG AA).
   The .analysis-line body text stays at full --text-secondary. On --surface-sunken it
   measures 7.89:1 (dark), 6.69:1 (light), 4.83:1 (sepia) — all clear WCAG AA (4.5:1).
   Note: in the light/sepia themes the sunken surface is slightly darker than --surface,
   so contrast DECREASES vs --surface (7.24/5.44:1) but stays above AA; the recession is
   intentionally NOT via opacity (which would drag it below). The cursor + no-hover make
   the inert state pre-attentive alongside the badge. */
.analysis-tile--soon {
  background: var(--surface-sunken);
  border-color: var(--pane-border-soft);
  cursor: default;
}
.analysis-tile--soon .analysis-name { color: var(--text-secondary); }
/* No hover lift on an inert tile (it is not a link). */
.analysis-tile--soon:hover { border-color: var(--pane-border-soft); }

/* NEW (justified) — the FEATURED STRIP: one deterministic daily example per live
   section, side by side, BETWEEN the hero and the roster grid. It reuses the shipped
   .analysis-grid auto-fit recipe (2->1 responsive, same as the roster) and the
   .analysis-tile chrome (icon-left card), so the strip reads as one family with the
   roster below it. Reading-ink only — gold stays CHROME-ONLY on the hub (the search
   submit is the sole gold CTA); these cards get NO gold ring / trophy treatment. */
.analysis-featured { margin-block-end: 2.25rem; }
/* The strip heading — descriptive, not a hook; sized like the section landings'
   secondary headings, calm and centered above the cards. */
.analysis-featured-heading {
  margin: 0 0 1rem;
  text-align: center;
  font-family: var(--font-reading);
  font-weight: 600;
  font-size: 1.15rem;
  color: var(--text-primary);
}
/* The card track caps at two columns (one per live section) on wide viewports and
   collapses to one on narrow — matching the roster's responsive behavior. */
.analysis-featured-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 20rem), 1fr));
  max-inline-size: 52rem;
  margin-inline: auto;
}
/* The featured card is a non-link <article> (the TITLE is the link, plus a quiet
   "in {Section}" link), so it carries no whole-tile hover lift; the inner links own
   their own focus/hover. */
.analysis-featured-card { cursor: default; }
.analysis-featured-card:hover { border-color: var(--pane-border-soft); }
/* The section label above the entry lead — quiet reading-ink, slightly raised so the
   reader sees the SECTION before the example. */
.analysis-featured-label {
  margin: 0;
  color: var(--text-secondary);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
/* The entry lead (a claim / a question) — inherits the .analysis-name serif tile
   title; the link is reading-ink (not gold) with a quiet underline-on-hover. */
.analysis-featured-title { margin: 0; }
.analysis-featured-link {
  color: var(--text-primary);
  text-decoration: none;
}
.analysis-featured-link:hover { text-decoration: underline; }
.analysis-featured-link:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
/* The neutral sub-line (a citation / a summary teaser) — reading-ink body text. */
.analysis-featured-meta { margin: 0; }
/* The quiet "in {Section} ->" affordance — small reading-ink link, not a gold CTA. */
.analysis-featured-more { margin: 0.15rem 0 0; }
.analysis-featured-section {
  color: var(--text-secondary);
  font-size: 0.85rem;
  text-decoration: none;
}
.analysis-featured-section:hover { text-decoration: underline; }
.analysis-featured-section:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}

/* The shared explainer panel below the grid — caps its measure so the family-level
   method reads as a calm closing note, centered under the grid. */
.analysis-hub-howto {
  max-inline-size: 46rem;
  margin-inline: auto;
}

/* --- Federated search results (grouped by section) --- */
/* Each group is a section block: a header (glyph + plain name + honest count) and
   the section's OWN reused result cards. Minimal group scaffolding only — the cards
   reuse .science-statement-card; only the group header + the "see all" row are new. */
.analysis-hub-results { padding-block-end: 2.5rem; }
.analysis-result-group { margin-block: 2rem 0; }
.analysis-result-group-header {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-block-end: 0.75rem;
  padding-block-end: 0.5rem;
  border-block-end: 1px solid var(--pane-border-soft);
}
/* The group glyph — gold chrome, inheriting the .analysis-glyph badge size. */
.analysis-result-group-icon { color: var(--brand); flex: 0 0 auto; display: inline-flex; }
.analysis-result-group-title {
  margin: 0;
  font-size: 1.15rem;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
}
/* The honest full count — reading-ink meta, never gold. */
.analysis-result-group-count { font-size: 0.85rem; font-weight: 400; }
.analysis-result-list { margin-block-start: 0; }
/* The "See all N in {Section} →" deep link row — a quiet link, not a gold button. */
.analysis-result-group-more { margin-block: 0.75rem 0; font-size: 0.9rem; }

/* #93 — the Scripture Analysis "Related by meaning" (entry-semantic) band. The ONLY
   genuinely new CSS this build adds: a quiet top separator that sets the subordinate
   band apart from the keyword content above it (every other class the band uses —
   .bible-search-fuzzy-head/-disclosure/-provenance, .science-statement-*,
   .analysis-featured-meaning* — is reused byte-untouched). */
.analysis-semantic-band {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border);
}
/* Intentionally rule-less: a test-scoping marker only (mirrors .search-hit--fuzzy), so a
   test can count semantic-band rows without colliding with the shared
   .science-statement-card count regex. */
.science-statement-card--semantic {}

/* --- Verse card --- */
/* Lemma card recipe (§5.3): raised surface + 1px border + 12px radius + padding,
   and NO drop shadow (the design leans on borders/fills, not shadows; shadows are
   reserved for menus/dialogs/button-hover glow). */
.verse-card {
  background: var(--surface-raised);
  border: 1px solid var(--pane-border-soft);
  border-radius: 12px;
  padding: 1rem 1.1rem;
}
/* Reading surface: text tokens + reading font only (no brand red). */
.verse-card-text {
  font-family: var(--font-reading);
  font-size: 1.1rem;
  margin: 0 0 0.6rem;
  border: none;
  padding: 0;
}
.verse-card-missing { font-family: var(--font-ui); font-size: 0.95rem; color: var(--text-secondary); }
.verse-card-meta { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: baseline; }
.verse-card-ref { font-weight: 700; }
.verse-card-blurb { color: var(--text-secondary); font-size: 0.9rem; }

.post-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 1rem; }
.post-title { font-weight: 700; font-size: 1.1rem; }
.post-excerpt { margin: 0.25rem 0 0; color: var(--text-secondary); }
.post-date { display: block; font-size: 0.85rem; }

/* --- TOC --- */
.toc-section { margin: 1.5rem 0; }
.book-grid {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(8.5rem, 1fr));
  gap: 0.4rem;
}
.book-grid a {
  display: block;
  padding: 0.5rem 0.65rem;
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  background: var(--surface-raised);
  color: var(--text-primary);
}
/* Catalog/navigation chrome — brand accent on hover is allowed here. */
.book-grid a:hover { border-color: var(--brand); text-decoration: none; }
.toc-other { border-top: 1px solid var(--pane-border); padding-top: 1.25rem; }

/* --- Reader --- */
/* Shared reader chrome still used by the compare (parallel.ejs) and study
   (verse.ejs) views. The CHAPTER reader (reader.ejs) folds these into the RD5
   toolbar, but the sibling views keep the classic header, so the tokens stay. */
.reader-breadcrumb { color: var(--text-secondary); font-size: 0.9rem; margin-bottom: 0.5rem; }
.reader-header { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.75rem; }
.reader-header h1 { margin: 0; }
.reader-compare-link { margin: 0 0 0.75rem; font-family: var(--font-ui); font-size: 0.9rem; }
.chapter-jump { display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem; }
.chapter-jump label { font-family: var(--font-ui); font-size: 0.85rem; color: var(--text-secondary); }
.chapter-jump select { padding: 0.35rem 0.5rem; border: 1px solid var(--pane-border); border-radius: 8px; background: var(--surface); color: var(--text-primary); }

/* --- RD5: compact, sticky reader toolbar ---
   Replaces the four stacked pre-text rows with one row. Chrome (THEME.md §0):
   brand accents on the active version chip / focus are allowed; the reading
   column below stays calm. Logical properties throughout for RTL (THEME.md §5).

   CLS (THEME.md §6): the toolbar reserves a fixed min height so it never shifts
   the scripture when it becomes sticky. It sticks just under the site header
   (which is itself sticky at top:0). */
.reader-toolbar {
  position: sticky;
  inset-block-start: 0;
  z-index: 40;
  margin-block-end: 0.5rem;
  background: var(--surface);
  border-block-end: 1px solid var(--pane-border);
  /* Reserve height to avoid layout shift on stick (CLS). */
  min-block-size: 3rem;
}
.reader-toolbar-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  padding-block: 0.5rem;
  min-block-size: 3rem;
}

/* Book/chapter control (the breadcrumb + h1 fold into this). A native <details>
   so it opens with no JS; app.js adds click-away/single-open. */
.reader-loc { position: relative; }
.reader-loc-summary {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-family: var(--font-ui);
  cursor: pointer;
  list-style: none;
  /* Tap target ≥44px (RD20 a11y). */
  min-block-size: 2.75rem;
}
.reader-loc-summary::-webkit-details-marker { display: none; }
.reader-loc-summary:hover { border-color: var(--brand); }
.reader-loc-book { font-weight: 600; }
.reader-loc-chapter { font-weight: 600; }
.reader-loc-caret { color: var(--text-secondary); font-size: 0.8em; }
/* Item 4 (this UX pass) — the LEADING book glyph is rendered in the shared summary
   markup but shown ONLY on the study page (the chapter reader's picker is untouched).
   Hidden by default; revealed + sized under .study-page below. */
.reader-loc-glyph { display: none; }

/* Item 2 — STUDY-PAGE book/chapter picker affordance. Scoped under .study-page so
   the chapter reader/compare keep their existing toolbar look. A clearer
   button/pill affordance matching the mockup: a defined border, a visible
   hover/focus-visible ring, and a caret that nudges on open — so it reads as a
   tappable control, not just a label. Tokens only; the ≥44px target is inherited
   from .reader-loc-summary above. Chrome, so the brand accent on hover/focus is
   allowed (THEME.md §0); the reading column is untouched. */
.study-page .reader-loc-summary {
  gap: 0.5rem;
  padding: 0.5rem 0.9rem;
  background: var(--surface-raised);
  font-weight: 600;
  /* Center-align so the leading glyph + book/chapter labels + caret share a baseline
     row cleanly (the base picker uses baseline alignment without a glyph). */
  align-items: center;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
/* Item 4 — reveal the leading book glyph on the study-page picker (recessive at rest,
   brightening to the accent on hover/open for parity with the version dropdown). */
.study-page .reader-loc-glyph {
  display: inline-flex;
  inline-size: 1.1em;
  block-size: 1.1em;
  flex: 0 0 auto;
  color: var(--text-secondary);
}
.study-page .reader-loc-summary:hover .reader-loc-glyph,
.study-page .reader-loc[open] > .reader-loc-summary .reader-loc-glyph {
  color: var(--brand);
}
.study-page .reader-loc-summary:hover {
  border-color: var(--brand);
  background: var(--surface-sunken);
}
.study-page .reader-loc-summary:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 2px;
  border-color: var(--brand);
}
.study-page .reader-loc[open] > .reader-loc-summary { border-color: var(--brand); }
.study-page .reader-loc-caret { transition: transform 0.15s ease; }
.study-page .reader-loc[open] > .reader-loc-summary .reader-loc-caret {
  transform: rotate(180deg);
}
.reader-loc-panel {
  position: absolute;
  inset-block-start: calc(100% + 0.35rem);
  inset-inline-start: 0;
  z-index: 5;
  min-inline-size: 14rem;
  padding: 0.75rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
}
.reader-loc-links { display: flex; flex-wrap: wrap; gap: 0.75rem; margin: 0.6rem 0 0; font-family: var(--font-ui); font-size: 0.9rem; }

/* RD11 — global picker inside the toolbar location panel. The panel can hold the
   whole canon (two collapsible testaments, each a book list whose chapter grids
   are lazy-built by app.js), so cap its height and scroll rather than pushing the
   page. Logical properties for RTL (THEME.md §5). */
.reader-loc-panel { max-block-size: min(70vh, 32rem); overflow-y: auto; }
.reader-loc-picker { margin-block-start: 0.6rem; }
.reader-loc-testament { border-block-start: 1px solid var(--pane-border); }
.reader-loc-testament:first-child { border-block-start: none; }
.reader-loc-testament-summary {
  cursor: pointer;
  padding-block: 0.5rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text-secondary);
  list-style-position: inside;
}
.reader-loc-testament-summary:hover { color: var(--brand); }
/* The toolbar picker reuses the .book-picker-* tokens (defined in the /bible TOC
   section) but in a denser context: tighten the rows so a long book list scans. */
.reader-loc-picker .book-picker-list { gap: 0.25rem; padding-block-end: 0.4rem; }
.reader-loc-picker .book-picker-summary { padding: 0.45rem 0.6rem; min-block-size: 2.5rem; }

/* ===========================================================================
   P1-7 (this UX pass) — RESTYLE the OPEN book/chapter picker panel ON-BRAND.
   The closed summary pills are already good; the open panel was a plain dropdown.
   Token-only polish; the native <details> mechanism is UNTOUCHED (no-JS still opens
   it). SCOPED under .study-page so the chapter reader / compare picker is unaffected
   (the spec: study-page-specific styling stays under .study-page). Gold appears only
   as the chrome accent border (a control frame, not reading text), per the gold policy.
   =========================================================================== */
/* The open panel reads as the SAME on-brand control as its gold-hover pill: soften
   the harder --pane-border to --pane-border-soft and add a thin gold top accent that
   ties it to the summary it dropped from. */
.study-page .reader-loc-panel {
  border-color: var(--pane-border-soft);
  border-block-start: 2px solid var(--accent-border);
}
/* The quick-jump reads as an INSET strip: a sunken ground + radius groups label+select
   as a distinct band at the top of the panel. */
.study-page .chapter-jump {
  padding: var(--space-2);
  background: var(--surface-sunken);
  border-radius: var(--radius);
}
/* Soften the quick-jump <select> border to the pill family + guarantee a ≥44px target. */
.study-page .chapter-jump select {
  border-color: var(--pane-border-soft);
  min-block-size: 2.75rem;
}
/* Each testament header reads as a pressable row: a radius + a sunken hover/focus
   ground (the gold-on-hover TEXT color is kept from the base rule above). */
.study-page .reader-loc-testament-summary {
  border-radius: var(--radius);
  padding-inline: var(--space-2);
}
.study-page .reader-loc-testament-summary:hover,
.study-page .reader-loc-testament-summary:focus-visible {
  background: var(--surface-sunken);
}
/* Book rows: soften the dense-panel card border + a sunken hover/focus ground for
   affordance. The book NAME stays --text-primary (a title, not a gold link). */
.study-page .reader-loc-picker .book-picker-details {
  border-color: var(--pane-border-soft);
}
.study-page .reader-loc-picker .book-picker-summary:hover,
.study-page .reader-loc-picker .book-picker-summary:focus-within {
  background: var(--surface-sunken);
}
/* "You are here": the CURRENT book's open row gets a left accent rule (logical
   property keeps it on the inline-start edge in RTL). */
.study-page .reader-loc-picker .book-picker-details[open] {
  border-inline-start: 3px solid var(--accent-border);
}
/* The "All books & chapters →" no-JS escape hatch is a QUIET-BLUE --cross-ref link,
   NOT gold — so the open panel's ONLY gold is the chrome accent border + the testament
   hover. (The default `a` color is --brand/gold, so this is an explicit override.)
   Scoped to .study-page so the chapter reader's picker keeps its existing styling. */
.study-page .reader-loc-links a { color: var(--cross-ref); }

/* ===========================================================================
   P1 — TWO-PANE toolbar book/chapter picker (JS enhancement).
   app.js reveals .loc-twopane (hidden by default) and hides the no-JS accordion +
   the chapter-jump <select>. Works in BOTH the chapter reader / compare context and
   under .study-page, so these rules are NOT scoped to .study-page. Gold (--brand /
   --accent-border / --accent-soft) is CHROME ONLY here: the active tab, the selected
   book row accent, the selected chapter tile, control hover/focus rings. Book names
   stay --text-primary (titles, not gold links). Logical properties for RTL; ≥44px
   touch targets; visible focus-visible rings; reduced-motion respected.
   =========================================================================== */
/* When the two-pane is live the panel needs room for two comfortable columns: give it
   an explicit width (viewport-capped so it never overflows the screen) and a taller
   scroll cap than the base panel. app.js adds .reader-loc-panel--twopane when it
   reveals the two-pane (no :has() dependency). */
.reader-loc-panel--twopane {
  inline-size: 34rem;
  max-inline-size: calc(100vw - 2rem);
  max-block-size: min(82vh, 44rem);
  /* Flex column so the filter / recents / section group stay PINNED and only the
     book+chapter content scrolls — no second (outer-panel) scrollbar stacked on top of
     the book list. overflow:hidden makes the inner .loc-twopane-body the lone scroll. */
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
/* Pass the panel height down to the body: the picker + two-pane wrappers fill the
   remaining space; the chapter-jump (hidden when two-pane) + the /bible link don't grow. */
.reader-loc-panel--twopane > .chapter-jump,
.reader-loc-panel--twopane > .reader-loc-links { flex: 0 0 auto; }
.reader-loc-panel--twopane > .reader-loc-picker {
  flex: 1 1 auto;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
}
.reader-loc-panel--twopane .loc-twopane {
  flex: 1 1 auto;
  min-block-size: 0;
  display: flex;
  flex-direction: column;
}
.loc-twopane-filter,
.loc-twopane-recents,
.loc-twopane-tabs { flex: 0 0 auto; }
.loc-twopane { margin-block-start: 0.6rem; }
.loc-twopane-filter { margin-block-end: 0.5rem; }
.loc-twopane-search {
  inline-size: 100%;
  min-block-size: 2.75rem;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.9rem;
}
.loc-twopane-search:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
  border-color: var(--brand);
}
.loc-twopane-recents { margin-block-end: 0.5rem; }
/* The picker's recents chips reuse the global .recents-link pill but, as a primary
   touch target in this control, get the ≥44px tap height (scoped so the global chip
   used elsewhere is unchanged). */
.loc-twopane-recents .recents-link { min-block-size: 2.75rem; }

/* Segmented OT/DC/NT control (a group of toggle buttons). Sunken track; the active
   button is the only gold chrome. ≥44px tap targets. */
.loc-twopane-tabs {
  display: flex;
  gap: 0.25rem;
  margin-block-end: 0.6rem;
  padding: 0.2rem;
  border-radius: 999px;
  background: var(--surface-sunken);
}
.loc-tab {
  flex: 1 1 0;
  min-block-size: 2.75rem;
  padding: 0.4rem 0.6rem;
  border: 1px solid transparent;
  border-radius: 999px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 0.82rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease, border-color 0.15s ease;
}
.loc-tab:hover { color: var(--brand); }
.loc-tab:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
}
.loc-tab.is-active {
  background: var(--surface-raised);
  border-color: var(--accent-border);
  color: var(--brand);
}

/* The two panes: book list (inline-start) + chapter grid (inline-end). Stacks to a
   single column (book list, then chapters) on narrow viewports. */
.loc-twopane-body {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;            /* the ONE content scroll: both panes scroll together */
  display: grid;
  grid-template-columns: minmax(11rem, 1fr) minmax(14rem, 1.3fr);
  gap: 0.85rem;
  align-items: start;
}
@media (max-width: 30rem) {
  /* Single column: let the whole panel scroll as one block (there is only one column
     of content to move, so no pinned header / inner scroll is needed). */
  .reader-loc-panel--twopane {
    inline-size: auto;
    min-inline-size: 14rem;
    max-inline-size: calc(100vw - 1.5rem);
    display: block;
    overflow-y: auto;
  }
  .loc-twopane-body { grid-template-columns: 1fr; overflow-y: visible; }
}

/* LEFT pane — the filtered book list. It scrolls WITH the body scroll area, so it
   carries no scroll of its own. */
.loc-twopane-books {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.loc-book-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
}
/* The section filter / type-ahead hide rows via the [hidden] attribute. .loc-book-row
   sets display:flex, which would otherwise BEAT the UA [hidden]{display:none} (equal
   specificity, author rule wins) and leave "hidden" rows visible — so restore it. */
.loc-book-row[hidden] { display: none; }
.loc-book-row.is-selected {
  border-color: var(--accent-border);
  background: var(--surface-sunken);
  /* "Selected" accent rule on the inline-start edge (RTL-safe). */
  border-inline-start: 3px solid var(--accent-border);
}
.loc-book-select {
  flex: 1 1 auto;
  min-block-size: 2.75rem;
  padding: 0.45rem 0.6rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  /* Book name is a TITLE, not a gold link. */
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.92rem;
  font-weight: 600;
  text-align: start;
  cursor: pointer;
}
.loc-book-row:hover { background: var(--surface-sunken); }
.loc-book-select:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: -2px;
  border-radius: var(--radius);
}
.loc-book-row.is-selected .loc-book-select { color: var(--brand); }
.loc-book-count {
  flex: 0 0 auto;
  padding-inline-end: 0.6rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
}

/* RIGHT pane — the selected book's chapter grid, headed by a link to the book page
   (keeps the book-landing page reachable). Reuses the shared .chapter-grid /
   .chapter-link tokens; the selected-tile chrome accent is added here. */
.loc-twopane-chapters-head { margin: 0 0 0.4rem; }
.loc-twopane-bookname {
  font-family: var(--font-ui);
  font-size: 0.92rem;
  font-weight: 600;
  /* The book-page link reads as a title, not gold reading content. */
  color: var(--text-primary);
  text-decoration: none;
}
.loc-twopane-bookname:hover,
.loc-twopane-bookname:focus-visible { text-decoration: underline; }
.loc-twopane-chapters .chapter-grid {
  padding: 0;
  border-top: 0;
  grid-template-columns: repeat(auto-fill, minmax(2.5rem, 1fr));
}
.loc-twopane-chapters .chapter-link { min-block-size: 2.75rem; }
.loc-twopane-chapters .chapter-link:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
}

/* Custom (theme-aware) scrollbar for the picker's scroll surfaces — the system-skinned
   bar reads as foreign inside the floating panel. A QUIET neutral thumb (--pane-border,
   not gold — a scrollbar is recessive chrome) on a transparent track, slightly more
   present on hover. Standard scrollbar-* (Firefox/Chromium) + the ::-webkit-* fallback
   (Chrome/Safari/Edge); where neither is honored the native bar shows — pure
   enhancement. Both the two-pane body (desktop scroll) and the panel itself (the
   reader/compare dropdown + the narrow-screen two-pane scroll) are covered. The
   study-page version PICKER panel (.reader-versions-panel) is the same kind of
   floating, scroll-if-long dropdown, so it takes the identical recessive bar.
   The verse-popover scroll surfaces — the mobile bottom sheet itself, its
   horizontal tab strip, and the (most-seen) Explain/commentary note body — are
   the same kind of floating-card scroll, so they take the identical bar too. */
.loc-twopane-body,
.reader-versions-panel,
.reader-loc-panel,
.verse-popover,
.verse-popover-tabs,
.verse-popover-explain-body,
.verse-popover-compare-list {
  scrollbar-width: thin;
  scrollbar-color: var(--pane-border) transparent;
}
.loc-twopane-body::-webkit-scrollbar,
.reader-versions-panel::-webkit-scrollbar,
.reader-loc-panel::-webkit-scrollbar,
.verse-popover::-webkit-scrollbar,
.verse-popover-tabs::-webkit-scrollbar,
.verse-popover-explain-body::-webkit-scrollbar,
.verse-popover-compare-list::-webkit-scrollbar { inline-size: 10px; block-size: 10px; }
.loc-twopane-body::-webkit-scrollbar-track,
.reader-versions-panel::-webkit-scrollbar-track,
.reader-loc-panel::-webkit-scrollbar-track,
.verse-popover::-webkit-scrollbar-track,
.verse-popover-tabs::-webkit-scrollbar-track,
.verse-popover-explain-body::-webkit-scrollbar-track,
.verse-popover-compare-list::-webkit-scrollbar-track { background: transparent; }
.loc-twopane-body::-webkit-scrollbar-thumb,
.reader-versions-panel::-webkit-scrollbar-thumb,
.reader-loc-panel::-webkit-scrollbar-thumb,
.verse-popover::-webkit-scrollbar-thumb,
.verse-popover-tabs::-webkit-scrollbar-thumb,
.verse-popover-explain-body::-webkit-scrollbar-thumb,
.verse-popover-compare-list::-webkit-scrollbar-thumb {
  background-color: var(--pane-border);
  border-radius: 999px;
  /* A transparent border + padding-box clip insets the thumb into a slim pill. */
  border: 3px solid transparent;
  background-clip: padding-box;
}
.loc-twopane-body::-webkit-scrollbar-thumb:hover,
.reader-versions-panel::-webkit-scrollbar-thumb:hover,
.reader-loc-panel::-webkit-scrollbar-thumb:hover,
.verse-popover::-webkit-scrollbar-thumb:hover,
.verse-popover-tabs::-webkit-scrollbar-thumb:hover,
.verse-popover-explain-body::-webkit-scrollbar-thumb:hover,
.verse-popover-compare-list::-webkit-scrollbar-thumb:hover { background-color: var(--text-secondary); }

/* Reduced-motion: drop the tab/control transitions. */
@media (prefers-reduced-motion: reduce) {
  .loc-tab { transition: none; }
}

/* Version chips live inline in the toolbar (reuse the .version-chip token). */
.reader-toolbar-versions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  list-style: none;
  margin: 0;
  padding: 0;
}

/* Compact VERSION DROPDOWN — the study-page variant of the version switcher
   (mockup's top-right "WEB ▾"). A native <details> so it opens with no JS; app.js
   adds click-away/single-open. The summary mirrors the .reader-loc-summary pill so
   the two study controls read as a matched pair; the panel links to the OTHER
   versions via the same no-JS /bible/version switcher the chips use. Chrome — the
   accent on hover/focus is allowed (THEME.md §0); the reading column stays calm. */
.reader-versions { position: relative; }
.reader-versions-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-family: var(--font-ui);
  cursor: pointer;
  list-style: none;
  min-block-size: 2.75rem; /* tap target ≥44px (RD20 a11y) */
}
.reader-versions-summary::-webkit-details-marker { display: none; }
.reader-versions-summary:hover,
.reader-versions[open] > .reader-versions-summary { border-color: var(--brand); }
.reader-versions-summary:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 2px;
}
/* Item 5 (this UX pass) — the LEADING translation glyph on the version dropdown
   summary. Recessive wayfinding cue (--text-secondary), like the picker's book
   glyph; it brightens toward the accent when the control is hovered/open (chrome,
   THEME.md §0). */
.reader-versions-glyph {
  inline-size: 1.1em;
  block-size: 1.1em;
  flex: 0 0 auto;
  color: var(--text-secondary);
}
.reader-versions-summary:hover .reader-versions-glyph,
.reader-versions[open] > .reader-versions-summary .reader-versions-glyph {
  color: var(--brand);
}
.reader-versions-code {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  font-weight: 600;
}
.reader-versions-caret {
  color: var(--text-secondary);
  font-size: 0.8em;
  /* Item 5 — the caret ROTATES on open for visual parity with the picker. Motion is
     functional (open/close affordance); reduced-motion users get the end state with
     no transition (global @media handles transition suppression). */
  transition: transform 0.15s ease;
}
.reader-versions[open] > .reader-versions-summary .reader-versions-caret {
  transform: rotate(180deg);
}
.reader-versions-panel {
  position: absolute;
  inset-block-start: calc(100% + 0.35rem);
  inset-inline-end: 0;
  z-index: 5;
  /* Explicit width so the longest translation NAME ("American Standard Version (1901)")
     fits on ONE line — without it the panel shrink-wrapped to ~14rem and the body's
     min-inline-size:0 let names wrap. Anchored inset-inline-end:0, so it grows LEFTward;
     the viewport cap keeps the left edge on-screen (collapses gracefully on mobile). */
  min-inline-size: 14rem;
  inline-size: 28rem;
  max-inline-size: calc(100vw - 2rem);
  max-block-size: min(70vh, 28rem);
  overflow-y: auto;
  padding: 0.6rem;
  /* P1-7 — soften the border to --pane-border-soft (matching the study cards) and add
     a thin gold top accent so the OPEN panel reads as the same on-brand control as its
     gold-hover summary pill. Chrome accent (a control frame), not reading text — per
     the gold policy. The dropdown is study-page-only (rendered behind the versionMenu
     flag), so no extra .study-page scoping is needed. */
  border: 1px solid var(--pane-border-soft);
  border-block-start: 2px solid var(--accent-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
}
.reader-versions-label {
  margin: 0 0 0.35rem;
  font-family: var(--font-ui);
  font-size: 0.75rem;
}

/* v1 picker — the type-ahead filter. Shipped hidden; app.js reveals + wires it.
   Reuses the two-pane book filter's input idiom (token-only; ≥44px; gold focus
   ring is chrome). */
.reader-versions-filter { margin-block-end: 0.5rem; }
.reader-versions-search {
  inline-size: 100%;
  min-block-size: 2.75rem;
  padding: 0.45rem 0.7rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.9rem;
}
.reader-versions-search:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
  border-color: var(--brand);
}

.reader-versions-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
}

/* PINNED active row — sits above the groups with a quiet eyebrow. */
.reader-versions-pinned { margin-block-end: 0.35rem; }
.reader-versions-eyebrow {
  margin: 0 0 0.2rem;
  font-family: var(--font-ui);
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* GROUP heading — a neutral section label between the pinned row and its rows.
   Not a link, not gold: a plain muted divider label. */
.reader-versions-group-head {
  margin-block-start: 0.5rem;
  padding: 0.3rem 0.6rem 0.2rem;
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}
/* No top margin on the FIRST group head when there is no pinned row (defensive:
   the panel always renders a pinned active row, but keep it tidy regardless). */
.reader-versions-list > .reader-versions-group-head:first-child { margin-block-start: 0; }

/* A version ROW. Three columns: the mono CODE badge, the body (name + the muted
   provenance line), and an optional trailing check (active row only). */
.reader-versions-item {
  display: flex;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 0.5rem 0.6rem;
  min-block-size: 2.75rem; /* tap target ≥44px */
  border-radius: var(--radius);
  color: var(--text-primary);
  text-decoration: none;
}
a.reader-versions-item:hover,
a.reader-versions-item:focus-visible {
  background: var(--surface-sunken);
  text-decoration: none;
}
/* ACTIVE row — gold LEFT-BAR accent + soft gold TINT + trailing check. An
   active-state use of gold chrome (THEME.md §0), NOT a full gold flood: the code
   badge, name, and provenance stay neutral text tokens so the row still reads as
   text, not a button. */
.reader-versions-item.is-active {
  position: relative;
  background: var(--accent-soft);
  border-inline-start: 3px solid var(--brand);
  padding-inline-start: calc(0.6rem - 3px); /* keep text aligned across the bar */
  color: var(--text-primary);
  cursor: default;
}
.reader-versions-item-code {
  flex: 0 0 auto;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 600;
  /* nudge the badge baseline to meet the name's cap height in the column layout */
  padding-block-start: 0.05rem;
}
.reader-versions-item-body {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  min-inline-size: 0; /* allow the name/meta to wrap inside the flex row */
}
.reader-versions-item-name {
  font-size: 0.85rem;
  font-family: var(--font-ui);
  color: var(--text-primary);
}
/* PROVENANCE line ([blurb · ]license). The picker's headline feature, so it must
   meet AA. Measured: --text-secondary on the panel's actual --surface-raised bg is
   dark 6.22 / light 7.50 / sepia 5.93 — all well above AA's 4.5. (In dark mode raised
   is LIGHTER than --surface, so the ratio is slightly LOWER there than the documented
   on-surface 7.5, but still clears AA comfortably.) Do NOT drop to a fainter token. */
.reader-versions-item-meta {
  font-size: 0.75rem;
  font-family: var(--font-ui);
  color: var(--text-secondary);
  line-height: 1.35;
}
/* The trailing check on the active row — gold chrome, decorative (aria-hidden). */
.reader-versions-check {
  flex: 0 0 auto;
  margin-inline-start: auto;
  color: var(--brand);
  font-size: 0.85rem;
  padding-block-start: 0.05rem;
}

/* FOOTER — the "More about these translations →" link, pinned at the panel bottom
   (matching the location picker's "/bible" link treatment). */
.reader-versions-links {
  margin: 0.5rem 0 0;
  padding-block-start: 0.4rem;
  border-block-start: 1px solid var(--pane-border-soft);
  font-family: var(--font-ui);
  font-size: 0.8rem;
}
.reader-versions-links a { color: var(--brand); }

/* "⋯ More" affordance — a native <details> menu (Compare + reading-mode +
   settings). Pushed to the inline-end so the book/chapter control leads. */
.reader-more { position: relative; margin-inline-start: auto; }
.reader-more-summary {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-family: var(--font-ui);
  cursor: pointer;
  list-style: none;
  min-block-size: 2.75rem;
}
.reader-more-summary::-webkit-details-marker { display: none; }
.reader-more-summary:hover { border-color: var(--brand); }
.reader-more-label { font-size: 0.9rem; }
.reader-more-panel {
  position: absolute;
  inset-block-start: calc(100% + 0.35rem);
  inset-inline-end: 0;
  z-index: 5;
  min-inline-size: 12rem;
  padding: 0.35rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  display: flex;
  flex-direction: column;
}
.reader-more-item {
  display: block;
  padding: 0.55rem 0.6rem;
  border-radius: var(--radius);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.9rem;
  text-decoration: none;
}
.reader-more-item:hover { background: var(--surface-sunken); text-decoration: none; }

/* READING SURFACE: paints only with --surface / --text-primary / --text-secondary.
   The gold accent NEVER colors verse body text — it is chrome/links/active only
   (a hard product requirement). Reading-body metrics per THEME.md §3 (19px/1.65,
   66ch).

   Dark-surface calibration (gold-on-navy retheme). The reading body is now
   GENTIUM BOOK PLUS; --text-primary (#e6edf3) on the dark navy --surface
   (#0a1530) measures 15.28:1 (AAA) — kept just below pure white to avoid the
   glare of a maximum-luminance body. The hair of letter-spacing (0.01em) still
   quiets halation of a serif body on the dark navy ground at 19px and is visually
   neutral in light/sepia; AAA body contrast is preserved untouched. NOTE: live
   in-browser legibility of Gentium on the navy ground could not be verified
   headlessly — if sustained reading tests poorly, the documented one-line revert
   to Literata (reorder --font-reading) restores the prior screen-tuned body. */
.scripture {
  max-width: var(--measure);
  font-family: var(--font-reading);
  font-size: 19px;
  line-height: 1.65;
  letter-spacing: 0.01em;          /* quiets halation on the dark navy ground; AAA contrast unchanged */
  margin: 1.25rem 0;
  /* Positioning context for the FLOATING verse popover (R1): the popover is
     inserted as an in-flow sibling of the verse blocks but styled
     position:absolute so it overlays the text without reflowing the chapter.
     .scripture is the tightest ancestor that wraps every verse AND the inserted
     popover, so its content-box is the correct coordinate space for the JS
     top/left math (app.js open()). On mobile the popover becomes position:fixed
     (bottom sheet), where the offset parent no longer applies.
     WARNING: keep .scripture's padding AND border at 0 — app.js position() measures
     the anchor from this element's border-box edge (getBoundingClientRect), which
     only coincides with the absolute-positioning padding-box origin while the border
     is 0; adding padding/border here would silently mis-anchor the popover. */
  position: relative;
}

/* CHAPTER-READER CENTERING. `.container` is max-width 76rem (~1216px) and centers
   the BOX (margin:0 auto), but the reader's children (.scripture, .reader-hero,
   .verse-para) each cap at --measure with NO auto-margins, so they pinned to the
   inline-START edge, leaving a wide dead gutter. Capping main.reader itself at the
   reading measure (the SAME move .study-page makes) lets .container's margin:0 auto
   center the WHOLE reading-width page, so the toolbar re-aligns over the column too.
   The +2*--space-5 accounts for .container's own inline padding so the --measure
   content is fully visible, not clipped. Scoped to main.reader so the compare/study
   surfaces (which set their own widths) are untouched. */
main.reader { max-width: calc(var(--measure) + 2 * var(--space-5)); }

/* CHAPTER-READER ANALYSIS RAIL. When (and ONLY when) the chapter has live Scripture
   Analysis areas, the reader is the modifier .reader--has-rail and renders a .reader-grid:
   the reading column (.reader-main, --measure wide) in col 1 and a ~20rem analysis rail
   (.reader-rail) in col 2 — mirroring the established .bible-search-grid / .bible-search-rail
   pattern for cohesion. Most chapters cite nothing, so the modifier is absent and the plain
   centered single-column reader above is used UNCHANGED (no dead gutter).

   The widened box: just enough to hold --measure + the grid gap + the 20rem rail (+ the
   container's own inline padding), and STILL centered by .container's margin:0 auto. The
   reading column stays --measure; the rail is the extra width, not the column. Below the
   grid breakpoint the rail stacks under the column, so the page stays at the single-column
   reading width — only widen the box once the two-column grid actually engages. */
main.reader.reader--has-rail { max-width: calc(var(--measure) + 2 * var(--space-5)); }
@media (min-width: 52rem) {
  main.reader.reader--has-rail {
    max-width: calc(var(--measure) + 20rem + var(--space-6) + 2 * var(--space-5));
  }
}

/* The two-column grid: single-column baseline (the rail reflows BELOW the reading column
   on mobile — a pure reflow, placement via grid-column, never order:); at >=52rem a
   two-column grid with the reading column in col 1 and the analysis rail in col 2. SOURCE
   ORDER already = reading column THEN rail, so the explicit placement is a placement, not a
   reorder. The hero lives INSIDE .reader-main (col 1), so it centers over the reading
   column, not over the full grid width. */
.reader-grid {
  display: grid;
  gap: var(--space-5);
  align-items: start;
}
.reader-grid > * { min-width: 0; }
@media (min-width: 52rem) {
  .reader-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    gap: var(--space-6);
  }
  .reader-grid > .reader-main { grid-column: 1; }
  .reader-grid > .reader-rail { grid-column: 2; }
}
/* The reading column keeps the reading measure; in the has-rail layout the hero/scripture
   children already cap at --measure, so the column is exactly as wide as the column-only
   reader — the rail is purely additive width. */
.reader-grid > .reader-main { max-inline-size: var(--measure); }

/* The analysis RAIL card — the SAME raised-card recipe as .bible-search-rail (soft border,
   radius, --surface-raised, padding) so the rail reads as one family with the search rail.
   In the ~20rem column the shared analysis-area-groups partial gets a denser presentation
   via this wrapper (tightened type + spacing) WITHOUT editing the shared partial. */
.reader-rail {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
/* The rail panel's own gold heading owns the section title; drop the heading's default
   bottom margin overcrowding and let the card padding breathe. Denser entry rhythm than
   the full-width study panel — the rail column is narrow. */
.reader-rail .study-section { margin: 0; }
/* The analysis panel is the FIRST section in the reader rail, so the shared
   .study-section top-divider hairline (border-block-start) has nothing above it to
   separate from and reads as a stray line above "Examined in Scripture Analysis".
   Drop the leading divider on the rail's first section; any subsequent rail sections
   keep their dividers. */
.reader-rail .study-section:first-child {
  border-block-start: none;
}
.reader-rail .study-analysis .analysis-area { font-size: 0.95rem; }

/* #109 — ONE-TIME ONBOARDING TIP HOST. The reserved-height host is SSR-rendered
   EMPTY + `hidden` as the first child of .reader-main; app.js (initReaderTip) fills it
   and removes `hidden` only when the show gate passes (storage available, not dismissed,
   not immersive).
   TRUE ZERO-BOX HOST: the host carries NO height reserve and we do NOT override the UA
   `[hidden] { display:none }`, so the SSR `hidden` attribute makes the host a genuine
   zero box on every path. On the SHOW path JS un-hides + fills it, so the tip appears and
   pushes scripture down ONCE — the accepted one-time first-visit nudge for a brand-new
   reader (the opacity-only entrance below softens it; it does not prevent the reflow). On
   every NO-SHOW path (dismissed / returning / immersive / no storage / no JS) the host
   stays `hidden` = zero box, so there is no empty band and no shift. There is no standalone
   .reader-tip-host rule: the class survives ONLY as the selector target for the immersive
   display:none belt (near the bottom of this stylesheet). */

/* The injected tip card. QUIET, not a gold flood (it sits atop every cold reader's
   first scripture view): a raised surface, a single quiet --pane-border frame, and
   ONE gold note only — a thin inline-start hairline (the lone gold mark, mirroring
   the .notice-warn inline-start hairline idiom). Body text recesses to
   --text-secondary; the "Tip:" label takes --text-primary weight. NO gold fill, and
   never both a gold border AND gold text. Padding + radius match the .notice card. */
.reader-tip {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  background: var(--surface-raised);
  border: 1px solid var(--pane-border);
  border-inline-start: 3px solid var(--accent-border); /* the lone gold accent */
  border-radius: var(--radius);
  padding: 0.7rem 0.9rem;
  margin-block-end: 1rem;
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.45;
}
/* Opacity-only entrance (no height/transform — that would re-introduce CLS). Gated
   by prefers-reduced-motion: no-preference; the global reduced-motion clamp
   (~L321) already neutralizes the duration otherwise, and 0->1 with a clamped
   duration resolves instantly, so a motion-averse reader sees it appear at once. */
@media (prefers-reduced-motion: no-preference) {
  .reader-tip { animation: reader-tip-fade 150ms ease-out; }
}
@keyframes reader-tip-fade {
  from { opacity: 0; }
  to { opacity: 1; }
}
.reader-tip-body { flex: 1 1 auto; }
.reader-tip-label { color: var(--text-primary); font-weight: 600; }
/* The dismiss control: a real <button> (aria-label="Dismiss tip"), generous hit
   target, quiet glyph. Focus ring comes from the global :focus-visible rule (gold). */
.reader-tip-dismiss {
  flex: 0 0 auto;
  /* Centre the glyph in a >=44x44 hit target (WCAG 2.5.8) while keeping the layout
     box the button contributes to the flex row at its prior ~26x27px footprint, so
     the visible x stays top-right, the card height is unchanged, and the body text
     does not reflow. The 44px box is grown internally then pulled back with negative
     margins (44-26=18px inline, 44-27.2=~16.8px block total). The inline/block splits
     are asymmetric so the CENTRED glyph lands exactly where the old left-aligned glyph
     sat (verified at 360px: glyph centre 312.6,171.4 unchanged). Centering the glyph
     (rather than relying on the parent's align-items:flex-start) also keeps the box
     from poking above the card's top padding. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  margin: -11.94px -13.99px -4.86px -4.01px; /* footprint stays ~26x27; visible glyph unmoved */
  border-radius: 6px;
}
.reader-tip-dismiss:hover { color: var(--text-primary); }

/* CHAPTER-READER HERO. The reader had no hero — just a bare recessive chapter
   numeral after the toolbar, with the <h1> visually-hidden — so the page opened
   weaker than the study/range pages (which open with a framed gold .study-card-
   header). This band makes the <h1> the VISIBLE page title using the study page's
   gold .study-section-heading recipe (open-book glyph + reference), an on-brand
   title + an SEO win. GOLD RULE: the title (chrome) may be gold; the reading column
   below stays calm. The former duplicate recessive chapter numeral (.chapter-opener)
   was dropped — the gold <h1> already reads "<Book> <Chapter>", so the numeral was
   pure duplication. The title is CENTERED over the reading column, over a quiet
   token-only hairline arrival cue (no gold fill). */
.reader-hero {
  max-width: var(--measure);
  margin-block: 0.5rem 1rem;
  padding-block-end: 0.75rem;
  border-block-end: 1px solid var(--pane-border);
}
/* The visible page <h1>: the SAME gold panel-heading recipe the study pages use,
   so the reader's title reads as on-brand chrome matched to the rest of the family.
   It scales up a touch over the panel headings (it is the page title, not a panel
   sub-title). The leading open-book .study-section-icon is golded by the existing
   `.study-section-heading .study-section-icon` rule above. CENTERED: the heading is a
   flex row (from .study-section-heading); justify-content:center centers the glyph +
   text together over the reading column, and margin-inline:auto centers the title box
   itself when it is narrower than the column. */
.reader-hero-title {
  font-size: 1.75rem;
  margin-block-end: 0;
  justify-content: center;
  text-align: center;
}
/* Drop the inherited gold heading underline (--accent-border) + its padding so the
   only arrival cue is the .reader-hero's own token-only --pane-border hairline — the
   centered title carries no gold fill or gold rule of its own (THEME.md §0 — gold stays
   chrome; here the chrome is just the gold TITLE TEXT + glyph). .study-section-heading
   paints a per-element gold hairline and, as a same-specificity selector defined LATER
   in source, would win the tie and double the band's line; we MUST raise the override's
   specificity to beat it regardless of source order. Same idiom as the verse study
   page's .study-card-header > .study-eyebrow strip (see ~.study-card-header above). */
.reader-hero .reader-hero-title {
  padding-block-end: 0;
  border-block-end: 0;
}

/* Mobile: tighten the title size at narrow widths (the band is already a centered
   vertical stack, so this only adjusts the type scale). */
@media (max-width: 24.375rem) {
  .reader-hero-title { font-size: 1.4rem; }
}

/* RD10 — paragraphed prose. Consecutive prose verses are grouped into one
   <p class="verse-para"> with verse numbers inline-superscripted; this is what
   turns a "verse list" into a set edition. Poetry keeps its own per-line blocks
   (.verse-poetry below). */
.verse-para {
  /* Inter-paragraph gap trimmed 0.9rem -> 0.6rem: legal/genealogical chapters open
     MANY short prose paragraphs, and the wider gap read as "scattered" verses. 0.6rem
     (~9.6px) still reads clearly as a paragraph break (we stay above ~0.5rem, below
     which breaks stop registering). Within-paragraph rhythm (19px/1.65) is unchanged —
     this is paragraph segmentation, not line-height. The immersive override
     (html[data-reading="immersive"] .verse-para, 1.15rem) is intentional and untouched. */
  margin: 0 0 0.6rem;
}
/* Each inline prose verse: an inline span so verses flow as prose. Keeps its
   #vN anchor target with scroll-margin so deep-links land below the sticky bars. */
.verse-inline { scroll-margin-block-start: 6rem; }

/* Poetry verses remain block-level stichographic lines (unchanged behavior). */
.verse { margin: 0 0 0.4rem; scroll-margin-top: 5rem; }
.verse-poetry.verse { scroll-margin-block-start: 6rem; }

/* RD6 — reference-label type token (THEME.md §3: 14px mono / 1.4).
   The canonical "Book ch:vv" chip/label treatment, shared by reference chips and
   compare/verse-popover headers. Mono so a citation reads as a precise reference,
   recessive color so it never competes with the reading text. Defined centrally
   so every reference label is consistent; individual components may opt in. */
.reference-label {
  font-family: var(--font-mono);
  font-size: 14px;
  line-height: 1.4;
  color: var(--text-secondary);
}
/* #147 — WCAG 2.2 AA SC 2.5.8 (Target Size (Minimum), 24x24 CSS px) for the
   INTERACTIVE half of the token. The .reference-label rule above is a TYPE token
   shared with non-interactive labels (compare / verse-popover headers), so it is
   left byte-untouched; this separate `a.` rule reaches only the reference LINKS,
   which is exactly the set that has to be a 24px target. Every emitter of
   a.reference-label is a standalone citation link that opens its own head row —
   verified by reading all seven: bible/passages.ejs (h2.passage-item-head),
   bible/search.ejs (li.crossref-item), index.ejs (p.study-spotlight-ref),
   partials/search-band-{precise,fuzzy,associative}.ejs and topics/detail.ejs
   (each a div.*-head flex row). None is a link inside a sentence, so none takes
   the SC 2.5.8 "Inline" exception; raising all of them is a fix on every caller
   rather than a regression on any.

   Why inline-block + min-block-size rather than padding: the token renders at TWO
   different natural heights — 19.59px in its own mono face, but 17px where a
   caller re-faces it to --font-ui (.crossref-ref does), because an inline box
   reports its FONT box, not its line-height. Vertical padding sized for one is
   wrong for the other (0.15rem leaves the re-faced case at 21.78px, still short).
   A min-block-size floor lands both on exactly 24px, participates in layout so
   hit areas cannot overlap the line above, and matches the min-block-size idiom
   this sheet already uses for its 44px targets. inline-block (not inline-flex)
   keeps the box's baseline on the text baseline, so a reference stays aligned
   with the preview prose that follows it on the same line in .crossref-item. */
a.reference-label {
  display: inline-block;
  min-block-size: 24px;
}

/* RD6 — section-head type token (THEME.md §3: 24px / 1.3, weight 600).
   Defined now so RD10's pericope/section headings have a ready, consistent
   slot. It is reading-surface chrome (set in the reading face, text tokens
   only, no brand red), sitting above the relevant verse. Empty-tolerant: the
   class only styles a heading when one is actually rendered. */
.section-head {
  font-family: var(--font-reading);
  font-size: 24px;
  line-height: 1.3;
  font-weight: 600;
  color: var(--text-primary);
  max-width: var(--measure);
  margin: 1.5rem 0 0.5rem;
}
.verse-num {
  font-family: var(--font-ui);
  font-size: 12px;
  font-weight: 700;
  color: var(--text-secondary);
  vertical-align: super;
  margin-inline-end: 0.3rem;
  text-decoration: none;
  /* RD9: the verse number is now also a touch opener (app.js). Give it a real
     tap target without disturbing the inline baseline. */
  padding-inline: 0.1rem;
}
/* RD9: the verse number is the ONLY popover opener, so it must READ as clickable
   on desktop. On hover/focus it resolves to the quiet --cross-ref blue (the same
   recessive link ink the cross-ref glyph uses — NOT gold/--brand, which is
   chrome-only; a verse number is reading-column text), underlines, and shows the
   pointer cursor. Keyboard parity is automatic (it is a real <a>). */
.verse-num:hover,
.verse-num:focus-visible {
  color: var(--cross-ref);
  text-decoration: underline;
  cursor: pointer;
}
/* Inline prose verses: a little breathing room before each verse number except
   the first in a paragraph, so numbers read as quiet markers between sentences. */
.verse-inline + .verse-inline .verse-num { margin-inline-start: 0.15rem; }
/* RD9 — deep-linked verse emphasis. A targeted verse gets the subtle
   --search-match tint (not a spectral color, THEME.md §1) PLUS a brief pulse so
   a #vN landing is noticeable without being loud. The pulse is reduced-motion
   safe: under prefers-reduced-motion the animation is neutralized globally and
   the static tint remains as the (color + box) cue. Works for inline prose
   verses (span) and block poetry verses alike. */
.verse:target,
.verse-inline:target {
  background: var(--search-match);
  color: var(--text-primary);
  border-radius: 4px;
  animation: verse-target-pulse 1.4s ease-out 1;
}
@keyframes verse-target-pulse {
  0% { box-shadow: 0 0 0 0.35rem var(--search-match); }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.version-note { font-size: 0.85rem; }

/* --- R8: Poetry stichography (THEME.md §3) ---
   "Psalms must never become paragraph mush." Poetry verses keep their line
   structure: a hanging indent (the verse number sits in the hang, wrapped lines
   indent under the first word) via logical properties so it flips for RTL, and
   parallel members step in +1.5em per indent level. reading-poetry metrics:
   19px / 1.5 (vs prose 1.65). The reading column stays calm — text tokens only,
   no brand. Poetry verses each sit on their own line (display: block already)
   so consecutive stichs stack rather than flowing as one paragraph. */
.verse-poetry {
  font-size: 19px;
  line-height: 1.5;
  /* Hanging indent: indent the whole block, pull the first line back out so the
     verse number hangs to the start edge and continuation lines align under the
     text. Logical properties keep this correct under dir="rtl". */
  padding-inline-start: 1.5em;
  text-indent: -1.5em;
  margin-block-end: 0.15rem;
}
/* Parallel members: each indent level adds one +1.5em step to the block's start
   padding (the hanging -1.5em first-line pull is preserved on top). q1 (level 0)
   is flush; q2 (level 1) and q3 (level 2) step inward. */
.verse-poetry[data-indent="1"] { padding-inline-start: 3em; }
.verse-poetry[data-indent="2"] { padding-inline-start: 4.5em; }
.verse-poetry[data-indent="3"] { padding-inline-start: 6em; }

/* --- R8: Footnotes ---
   In-text marker: recessive superscript in --text-secondary (no color-only
   meaning — it is a small letter, and underlines on focus/hover), never brand.
   Apparatus list at the chapter foot uses the footnote type token (14px). */
.footnote-marker {
  font-family: var(--font-ui);
  color: var(--text-secondary);
  text-decoration: none;
  margin-inline-start: 0.1em;
}
.footnote-marker sup { font-size: 0.7em; line-height: 0; }
.footnote-marker:hover sup,
.footnote-marker:focus-visible sup { text-decoration: underline; }

.chapter-footnotes {
  max-width: var(--measure);
  margin: 1.5rem 0;
  padding-top: 1rem;
  border-top: 1px solid var(--pane-border);
}
.chapter-footnotes-heading {
  font-family: var(--font-ui);
  font-size: 1rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 0.5rem;
}
.footnote-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-family: var(--font-reading);
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-secondary);
}
.footnote-item { margin: 0 0 0.4rem; scroll-margin-top: 5rem; }
/* Highlight a footnote when linked to from its in-text marker (no-JS path). */
.footnote-item:target { background: var(--search-match); color: var(--text-primary); border-radius: 4px; }
.footnote-backref {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text-secondary);
  text-decoration: none;
  margin-inline-end: 0.5em;
}
.footnote-backref:hover,
.footnote-backref:focus-visible { text-decoration: underline; }

/* The Notes tab rendered into the verse popover by app.js (JS-enhanced path).
   Popover is overlay chrome, but the note text itself reads as apparatus. */
.verse-popover-notes-heading {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-notes-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.9rem;
  line-height: 1.5;
}
.verse-popover-notes-list li { margin: 0 0 0.35rem; }
.verse-popover-note-marker {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text-secondary);
  margin-inline-end: 0.4em;
}

.reader-pager {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  margin: 1.5rem 0;
  padding-top: 1rem;
  border-top: 1px solid var(--pane-border);
}

/* --- RD13: persistent low-profile edge pager ---
   A quiet prev/next pair pinned to the viewport mid-edges so long-form reading
   doesn't require scrolling to the foot pager. Real links (no-JS baseline is the
   foot pager; these are an additive convenience). Recessive chrome — no brand red
   in the column; the controls sit OUTSIDE the reading measure. Hidden on narrow
   viewports (foot pager + keyboard arrows serve there) and quieted in immersive
   mode. */
.edge-pager { display: none; }
@media (min-width: 1100px) {
  .edge-pager { display: block; }
  .edge-pager-prev,
  .edge-pager-next {
    position: fixed;
    inset-block-start: 50%;
    transform: translateY(-50%);
    z-index: 30;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    inline-size: 2.75rem;
    block-size: 2.75rem;
    border: 1px solid var(--pane-border);
    border-radius: 999px;
    background: var(--surface-raised);
    color: var(--text-secondary);
    font-size: 1.5rem;
    line-height: 1;
    text-decoration: none;
    opacity: 0.5;
    transition: opacity 0.15s ease, border-color 0.15s ease, color 0.15s ease;
  }
  .edge-pager-prev { inset-inline-start: 1rem; }
  .edge-pager-next { inset-inline-end: 1rem; }
  .edge-pager-prev:hover,
  .edge-pager-next:hover {
    opacity: 1;
    color: var(--text-primary);
    border-color: var(--brand);
    text-decoration: none;
  }
}
/* Immersive reading mode: auto-hide the edge pager until pointer-near (it stays
   in the DOM/no-JS path; reduced-motion users get an instant change via the
   global reduced-motion rule). */
html[data-reading="immersive"] .edge-pager-prev,
html[data-reading="immersive"] .edge-pager-next { opacity: 0.18; }
html[data-reading="immersive"] .edge-pager-prev:hover,
html[data-reading="immersive"] .edge-pager-next:hover { opacity: 1; }

/* --- Search --- */
.search-form { display: flex; gap: 0.5rem; max-width: 32rem; margin: 1rem 0; }
.search-form input { flex: 1; padding: 0.6rem 0.8rem; border: 1px solid var(--pane-border); border-radius: var(--radius); background: var(--surface); color: var(--text-primary); }
.search-results { list-style: none; padding: 0; margin: 1rem 0; display: grid; gap: 1rem; }
/* RD-hotfix — each precise/fallback result reads as its own bordered PANEL; the
   .search-results grid `gap` (above) now spaces the cards, replacing the former
   border-bottom-only divider. Reuses this app's NEUTRAL card idiom — the same
   tokens as the .bible-search-rail "always-visible card" (full --pane-border,
   --radius, --surface-raised). No gold/accent, no left-rule, no hover/lift chrome:
   a calm static reading surface. The subordinate associative/fuzzy bands stay flat
   lists (byte-untouched) so the precise→associative→fuzzy trust hierarchy reads. */
.search-hit {
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
/* RD17 — result card head: reference in mono (reference-label token) + recessive
   book/testament chips + the book-scope link, on one wrapping row. */
.search-hit-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 0.6rem;
}
.search-hit-ref { font-weight: 600; color: var(--cross-ref); }
.search-hit-ref:hover, .search-hit-ref:focus-visible { text-decoration: underline; }
/* Snippet is reading text: reading font + text tokens; match highlight is the
   subtle --search-match tint, never brand red. RD17 nudges it to reading size. */
.search-hit-snippet { margin: 0.35rem 0 0; font-family: var(--font-reading); font-size: 1.05rem; line-height: 1.55; }
.search-hit-snippet mark { background: var(--search-match); color: var(--text-primary); padding: 0 2px; border-radius: 2px; }

/* ============================================================================
   BIBLE SEARCH REDESIGN — hero band + two-column (results MAIN | refine RAIL).
   Modeled on the .analysis-landing two-column idiom: content first in SOURCE
   order, the rail second, placed by GRID (never `order:`) so no-JS / screen
   reader / crawler order is the sensible linear order. Collapses to ONE column
   on narrow widths (the rail drops BELOW results — a pure reflow). The hero
   reuses the .analysis-search-form pill verbatim (the ONE gold CTA = the Search
   button). Gold stays CHROME-ONLY here; verse snippets honor the --measure cap.
   ============================================================================ */

/* Hero — a calm centered opener; the search pill + suggested-search row sit
   beneath the headline. The hero search reuses .analysis-search-form (the pill),
   capped narrower than the homepage so it reads as a focused search opener. */
.bible-search-hero { margin-block: var(--space-5) var(--space-6); text-align: center; }
.bible-search-hero-title {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  margin-block: 0 var(--space-2);
}
/* Leading title magnifier — decorative, muted gold chrome. A SEPARATE class from
   .analysis-search-icon on purpose: that class has a @media(max-width:30rem) rule
   that hides the input-pill magnifier on phones, which would wrongly hide this
   title glyph too. Sized to roughly pair with the h1 text (~cap-height). */
.bible-search-hero-title-icon {
  flex: 0 0 auto;
  inline-size: 0.9em;
  block-size: 0.9em;
  color: var(--brand);
  opacity: 0.75;
}
.bible-search-hero-subtitle {
  margin-block: 0 var(--space-4);
  color: var(--text-secondary);
  max-inline-size: var(--measure);
  margin-inline: auto;
}
/* The hero search pill is centered + capped (the .analysis-search-form base is
   full-width); the suggested row sits below it. */
.bible-search-hero .bible-search-form {
  max-inline-size: 36rem;
  margin-inline: auto;
  margin-block-start: 0;
}
/* Suggested-search row — honest, static WORD chips (no popular/trending claim).
   Quiet recessive chips; gold is NOT used on them (they are content links). */
.bible-search-suggest {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: 0.4rem 0.5rem;
  margin-block-start: var(--space-4);
}
.bible-search-suggest-label { color: var(--text-secondary); font-size: 0.9rem; }
.bible-search-suggest-chip {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-size: 0.9rem;
  text-decoration: none;
}
.bible-search-suggest-chip:hover,
.bible-search-suggest-chip:focus-visible {
  border-color: var(--accent-border);
  text-decoration: none;
}
/* search-results-redesign §3.1 — in-page JUMP NAV. Restyled to the CHIP-LITE PILL
   register that matches the verse-page .study-jumpnav (transparent ground, 1px
   --pane-border pill, 999px radius, recessive --text-secondary text; gold text +
   --brand-fill border ONLY on hover/focus, never a filled ground — gold stays
   chrome-only). It keeps its OWN .bible-search-jumpnav-link class — NOT a
   .bible-search-suggest-chip clone, and still visually distinct from the "Try
   searching" chip row above it: those chips are FILLED (--surface-raised ground +
   --text-primary text) while these stay TRANSPARENT + recessive, so a scanning
   reader never confuses "jump within this page" with "search something else". Each
   link owns its own 44px tap target from day one (WCAG 2.5.8), not inherited from
   the chip recipe. */
.bible-search-jumpnav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.2rem 0.5rem;
  margin-block: var(--space-4) var(--space-3);
}
.bible-search-jumpnav-label { color: var(--text-secondary); font-size: 0.9rem; }
.bible-search-jumpnav-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;         /* own WCAG 2.5.8 tap target (not inherited from the chip) */
  padding-block: 0.3rem;
  padding-inline: 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--text-secondary);
  text-decoration: none;
}
.bible-search-jumpnav-link:hover,
.bible-search-jumpnav-link:focus-visible {
  color: var(--brand);
  border-color: var(--brand-fill);
}

/* search-results-redesign §3.1 (Hannah) — anchor-jump landing offset for the four
   jump-nav target headings under the sticky .site-header (position:sticky; top:0;
   z-index:50). Matches the existing .verse / .footnote-item precedent VERBATIM (same
   5rem, same reasoning). Without it a jump-link click lands the heading flush under /
   behind the sticky header. */
#bible-search-results-heading,
#bible-search-assoc-heading,
#bible-search-fuzzy-heading,
#bible-search-related-heading { scroll-margin-top: 5rem; }
/* CONTEXT-SCOPED SEARCH banner + "Search all" escape hatch (Scripture Analysis
   family). Reuses .bible-search-suggest for the centered flex row + the recessive
   chip recipe (the escape link is a .bible-search-suggest-chip); this modifier
   reseats the block rhythm so the banner sits tight under the search-context blurb
   and above the search pill, and gives the banner NOTICE-WEIGHT so a scanning reader
   can't mistake it for the suggestion-chip row below: a raised surface + a gold
   chrome edge (the same left-accent-rule idiom the picker's "you are here" row uses).
   Gold stays CHROME-ONLY — it lives on the inline-start edge, NEVER as a fill or on
   the label text; the label keeps its recessive reading ink (--text-secondary, via
   .bible-search-suggest-label — no gold added). All tokens resolve per-theme, so it
   degrades cleanly in light/dark/sepia. */
.analysis-search-scope {
  margin-block: var(--space-3) 0;
  padding: var(--space-3);
  border-radius: var(--radius);
  border-inline-start: 3px solid var(--accent-border);
  background: var(--surface-raised);
}
.bible-search-landing { margin-block: var(--space-4); max-inline-size: var(--measure); }

/* Two-column grid (single-column baseline; columns at the breakpoint). Source
   order = results then rail, so the stacked phone view reads results first and
   the rail (filters) below — the "Refine results" anchor keeps it reachable. */
.bible-search-grid {
  display: grid;
  gap: var(--space-5);
  align-items: start;
}
.bible-search-grid > * { min-width: 0; }
@media (min-width: 52rem) {
  .bible-search-grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    gap: var(--space-6);
  }
  /* Explicit placement (NOT order:) — results to col 1, rail to col 2. Source
     order already matches this, so it is a pure placement, not a reorder. */
  .bible-search-main { grid-column: 1; }
  .bible-search-rail { grid-column: 2; }
}

/* Results header: count + provenance (the searched translation, stated ONCE). */
.bible-search-results-head { margin-block: 0 var(--space-2); font-size: 1.2rem; color: var(--brand); }
.bible-search-provenance { margin-block: 0 var(--space-3); font-size: 0.9rem; }
.bible-search-version-code { color: var(--text-primary); font-weight: 600; }
/* The "Refine results ↓" jump — a small quiet in-page anchor for mobile, where
   the rail sits below results. Harmless on desktop (the rail is already beside). */
.bible-search-refine-jump { margin-block: 0 var(--space-4); font-size: 0.9rem; }
@media (min-width: 52rem) { .bible-search-refine-jump { display: none; } }

/* Lean result-card action row: Read verse · Open chapter · Compare. Quiet text
   links (NOT gold — these are content navigation, not the sanctioned CTA). The
   snippet above honors --measure so result text stays readable. */
.bible-search-main .search-hit-snippet { max-inline-size: var(--measure); }
.search-hit-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1rem;
  margin-block-start: 0.5rem;
}
.search-hit-action { font-size: 0.9rem; color: var(--cross-ref); }
.search-hit-action:hover,
.search-hit-action:focus-visible { text-decoration: underline; }

/* Refine RAIL — an always-visible card holding the controls (no <details>). */
.bible-search-rail {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
.bible-search-refine-form { display: flex; flex-direction: column; gap: var(--space-3); }
.bible-search-field { display: flex; flex-direction: column; gap: 0.3rem; border: 0; padding: 0; margin: 0; }
.bible-search-field > label,
.bible-search-field > legend { font-size: 0.85rem; color: var(--text-secondary); padding: 0; }
.bible-search-field select,
.bible-search-refine-input {
  padding: 0.45rem 0.55rem;
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text-primary);
  font: inherit;
}
.bible-search-check { flex-direction: row; align-items: center; gap: 0.45rem; }
.bible-search-check label { font-size: 0.95rem; color: var(--text-primary); }

/* Segmented control — real radio inputs + labels (NO JS widget). The radio is
   visually hidden; its label is the styled segment. The CHECKED segment is a
   sanctioned ACTIVE-STATE gold fill (chrome), matching the pager's active pill. */
.bible-search-seg-options {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
}
.bible-search-seg-radio {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
.bible-search-seg-label {
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-primary);
  font-size: 0.9rem;
  cursor: pointer;
  min-block-size: 36px;
  display: inline-flex;
  align-items: center;
}
.bible-search-seg-radio:checked + .bible-search-seg-label {
  background: var(--brand-fill);
  border-color: var(--brand-fill);
  color: var(--on-accent);
  font-weight: 600;
}
/* Keyboard focus on the hidden radio lands a visible halo on its segment. */
.bible-search-seg-radio:focus-visible + .bible-search-seg-label {
  outline: 2px solid var(--accent-border);
  outline-offset: 2px;
}

/* Apply Filters — the ONE sanctioned gold CTA in the rail (reuses the
   .analysis-search-submit gold-fill tokens). Full width inside the rail. */
.bible-search-apply { inline-size: 100%; border-radius: 8px; }

/* Per-book FACET list (promoted out of a <details> into the visible rail). */
.bible-search-facet { margin-block-start: var(--space-4); padding-block-start: var(--space-3); border-block-start: 1px solid var(--pane-border); }
.bible-search-facet-heading { margin-block: 0 var(--space-2); font-size: 1rem; color: var(--brand); }
.bible-search-facet-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.bible-search-facet-item a {
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.35rem 0.5rem;
  border-radius: 8px;
  text-decoration: none;
  color: var(--text-primary);
}
.bible-search-facet-item a:hover,
.bible-search-facet-item a:focus-visible { background: var(--surface-sunken); }
.bible-search-facet-book { flex: 1; }
.bible-search-facet-count { color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.bible-search-facet-more > summary { cursor: pointer; padding: 0.35rem 0.5rem; font-size: 0.9rem; color: var(--cross-ref); }

/* #17 P0 — cross-version recall union surfaces. All NEW, search-page-scoped
   classes (no shared rule is edited): the confidence band wrapper, the factual
   "matched in X" per-hit note, the "Show results in" helper line, and the
   "Related passages" cross-ref rail (which REUSES the .crossref-* row classes). */
.bible-search-band { display: block; }
/* The OR-fallback sub-state stays quieter (not hidden). Owner decision (follow-up to
   the gold section-heading pass): its section TITLE now renders in the same brand gold
   as every other search section heading (a heading is chrome), so the lower-confidence
   signal is carried by the softened COUNT (rule below) + the honest disclosure sentence
   + the bounded "Show 25 more (same weak signal)" reveal — NOT by the heading color.
   The former left inset rule was removed (owner-confirmed); no compensating emphasis is
   added. */
.bible-search-band--fallback .bible-search-results-head { color: var(--brand); font-weight: 600; }
/* search-results-redesign §3.2.2 — soften the OR-fallback COUNT's visual weight so a
   stopword-collision total ("22,529") never reads as a bold, confident finding the way a
   real result count does. SCOPED under the EXISTING --fallback modifier, so the base
   .bible-search-provenance rule (shared with the precise state) is byte-untouched. */
.bible-search-band--fallback .bible-search-provenance-count { color: var(--text-secondary); font-weight: 400; }
/* search-results-redesign §3.2 (ruling E.1) — the bounded "Show 25 more (same weak
   signal)" reveal that REPLACES the numbered pager on the OR-fallback substate (a
   same-weak-relevance heap has no meaningful deep pages). Styled as a QUIET BORDERED
   PILL BUTTON (not a bare underlined text link) so it reads as a deliberate control
   rather than inline body copy — matching the page's own chip-lite pill geometry
   (.bible-search-jumpnav-link / .study-jumpnav-link: inline-flex, 1px --pane-border,
   999px radius, --font-ui, its OWN >=44px WCAG 2.5.8 tap target) but COLORED with the
   content-navigation token --cross-ref instead of that idiom's gold hover: this is the
   LOW-CONFIDENCE fallback band, so the control stays SUBORDINATE and NON-gold (gold is
   chrome-only; the sanctioned CTA is Search / Apply Filters only). The min-block-size
   owns the >=44px tap target at EVERY pointer type, so this class needs NO (pointer:
   coarse) growth rule (it carries none). */
.bible-search-more { margin-block: var(--space-3) 0; font-size: 0.9rem; }
.bible-search-more-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-block: 0.3rem;
  padding-inline: 0.9rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  font-family: var(--font-ui);
  color: var(--cross-ref);
  white-space: nowrap;
  text-decoration: none;
}
/* Hover/focus: a quiet interactive state — a subtle surface fill + the content-nav
   border warms to --cross-ref. NO gold, NO underline (it is a button now, not a text
   link). :hover / :focus-visible stay at parity (pointer == keyboard). */
.bible-search-more-link:hover,
.bible-search-more-link:focus-visible {
  background: var(--surface-sunken);
  border-color: var(--cross-ref);
  text-decoration: none;
}
/* The factual recall-union note under a hit's snippet — recessive, reading-neutral. */
.search-hit-note { margin: 0.3rem 0 0; font-size: 0.85rem; font-variant-numeric: tabular-nums; }
/* The "Show results in" helper line under the rail translation select. */
.bible-search-field-help { margin: 0.3rem 0 0; font-size: 0.82rem; line-height: 1.4; }
/* The "Related passages" rail section — same rail-section spacing as the facet. */
.bible-search-relatedpassages {
  margin-block-start: var(--space-4);
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--pane-border);
}
.bible-search-related-note { margin-block: 0 var(--space-2); font-size: 0.85rem; }
/* #17 P2.1 — the topical co-membership annotation on a "Related passages" rail row.
   ADDITIVE metadata, NOT a ranking signal (SPEC-p2-1 §1): small, recessive, clearly
   secondary to the reference + preview above it. NEW selector only — .crossref-item /
   .crossref-ref / .crossref-text (shared with the study page) stay byte-untouched. */
.bible-search-related-topictag { margin: 0.25rem 0 0; font-size: 0.8rem; }

/* #17 P1 — the "Related by meaning" (semantic / fuzzy) band. All NEW, search-page-
   scoped selectors (no shared rule is edited — the base .search-hit / .search-results
   / .bible-search-band[--precise|--fallback] rule DECLARATIONS are unedited; note that
   search-3section (docs/SPEC-search-3section-results.md §5) later ADDS a separate,
   additive position-based top-separator rule for --precise:not(:first-child) — it edits
   none of these existing blocks). It is a
   SUBORDINATE band below the precise results: set off by a top rule, a recessive
   secondary-color heading, and quieter reading-ink previews. Gold stays chrome-only —
   the band introduces NO new gold element. */
/* search-results-redesign §3.5 — the fuzzy band's mobile collapse wrapper. The band is
   wrapped in a native <details OPEN> so a mobile reader can collapse this speculative
   band with NO JS; DEFAULT OPEN, so no-JS + first-view parity hold. The <details> stays
   a PLAIN BLOCK at every width and now carries the band's top-separator rule (moved here
   from .bible-search-band--fuzzy so the rule sits ABOVE the heading, which now lives in
   the <summary>). On MOBILE the summary is a real tap toggle (a rotating chevron + a
   pointer cursor). On DESKTOP the toggle chrome is neutralized (no chevron, default
   cursor) so it reads as a plain, non-collapsible heading — open by default, no visible
   affordance to collapse. (display:contents was considered but rejected: keeping
   <details> a block lets the separator live on the wrapper and renders byte-identically
   to the prior bare section on desktop, with less CSS.) HARD RULE §3.5: only the FUZZY
   band is ever wrapped — never the associative (named-scholar) band. */
.bible-search-fuzzy-wrap {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border);
}
.bible-search-fuzzy-summary {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  list-style: none;   /* Firefox: drop the default disclosure marker */
  cursor: default;    /* desktop default; the mobile block below restores pointer */
}
.bible-search-fuzzy-summary::-webkit-details-marker { display: none; } /* Chrome/Safari */
@media (max-width: 51.999rem) {
  .bible-search-fuzzy-summary { cursor: pointer; }
  /* Custom rotating chevron, MOBILE ONLY (collapsed ▸ / open ▾). */
  .bible-search-fuzzy-summary::before {
    content: '▾';
    color: var(--text-secondary);
    font-size: 0.85em;
    line-height: 1;
  }
  .bible-search-fuzzy-wrap:not([open]) > .bible-search-fuzzy-summary::before { content: '▸'; }
}
@media (min-width: 52rem) {
  /* Desktop MUST be non-collapsible (§3.5): hiding the chevron/cursor alone still lets a
     stray mouse click on the heading toggle the <summary> and collapse the north-star band
     with no affordance to reopen it. pointer-events:none kills the desktop mouse-toggle
     cleanly (a rare keyboard Enter/Space residual is acceptable — the band is OPEN by
     default and there is no visible affordance). Touch keeps its toggle via the mobile
     block above. */
  .bible-search-fuzzy-summary { pointer-events: none; }
}
/* The band section itself is now a plain block (its top-separator moved to the wrapper). */
.bible-search-band--fuzzy { display: block; }
.bible-search-fuzzy-head { margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--brand); }
.bible-search-fuzzy-disclosure { margin: var(--space-1) 0 0; font-size: 0.9rem; line-height: 1.45; max-inline-size: var(--measure); }
.bible-search-fuzzy-provenance { margin: var(--space-1) 0 var(--space-3); font-size: 0.82rem; line-height: 1.45; max-inline-size: var(--measure); }
.bible-search-fuzzy-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.bible-search-fuzzy-hit { padding-block-end: var(--space-3); border-block-end: 1px solid var(--pane-border); }
.bible-search-fuzzy-hit:last-child { padding-block-end: 0; border-block-end: 0; }
.bible-search-fuzzy-hit-head { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.bible-search-fuzzy-preview { margin: 0.3rem 0 0; font-family: var(--font-reading); font-size: 1rem; line-height: 1.55; color: var(--text-secondary); max-inline-size: var(--measure); }
.bible-search-fuzzy-note { margin: 0.25rem 0 0; font-size: 0.82rem; }

/* #17 P2 — the "Grouped by topic" (ASSOCIATIVE) search band (Nave's / Torrey's
   curated topical index). NEW SCOPED SELECTORS ONLY — no shared rule is edited (the
   base .search-hit / .search-results / .bible-search-band[--precise|--fallback|
   --fuzzy] rule DECLARATIONS stay unedited (the shared-class scoping proof) — though
   search-3section (docs/SPEC-search-3section-results.md §5) ADDS a separate, additive
   position-based separator rule for --precise:not(:first-child) that edits none of these
   blocks). A SUBORDINATE
   band set off from the precise results by a top rule, with a recessive heading and
   quieter reading-ink previews; the editorial-finding-aid disclosure + per-source PD
   attribution read as calm secondary text. Gold stays chrome-only — NO new gold
   element (the "browse"/"see all" links inherit the app link treatment). */
.bible-search-band--associative {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border);
}
.bible-search-assoc-head-row { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-3); flex-wrap: wrap; }
.bible-search-assoc-head { margin: 0; font-size: 1.05rem; font-weight: 600; color: var(--brand); }
.bible-search-assoc-browse { font-size: 0.85rem; white-space: nowrap; }
.bible-search-assoc-topic { margin: var(--space-2) 0 0; font-size: 0.95rem; color: var(--text-secondary); }
.bible-search-assoc-topic-name { font-weight: 600; color: var(--text-primary); }
.bible-search-assoc-disclosure { margin: var(--space-1) 0 0; font-size: 0.9rem; line-height: 1.45; max-inline-size: var(--measure); }
.bible-search-assoc-attribution { margin: 0.25rem 0 0; font-size: 0.82rem; line-height: 1.4; }
.bible-search-assoc-attribution:last-of-type { margin-block-end: var(--space-3); }
.bible-search-assoc-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.bible-search-assoc-hit { padding-block-end: var(--space-3); border-block-end: 1px solid var(--pane-border); }
.bible-search-assoc-hit:last-child { padding-block-end: 0; border-block-end: 0; }
.bible-search-assoc-hit-head { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.bible-search-assoc-preview { margin: 0.3rem 0 0; font-family: var(--font-reading); font-size: 1rem; line-height: 1.55; color: var(--text-secondary); max-inline-size: var(--measure); }
.bible-search-assoc-note { margin: 0.25rem 0 0; font-size: 0.82rem; }
.bible-search-assoc-seeall { margin: var(--space-3) 0 0; font-size: 0.9rem; }
.bible-search-assoc-also { margin: var(--space-2) 0 0; font-size: 0.85rem; }

/* search-3section (docs/SPEC-search-3section-results.md) — the confidence-adaptive
   order means any of the three main-column bands can render first inside
   .bible-search-main. The precise/fallback band never needed a top separator before
   (it was always first); it needs one now, for when the fallback order pushes it to
   the end. Scoped to :not(:first-child) so the DEFAULT (precise-first) order is
   visually byte-identical to today — this rule is inert whenever precise IS first. */
.bible-search-main > .bible-search-band--precise:not(:first-child) {
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border);
}

/* The associative/fuzzy bands' EXISTING unconditional top-separator (added by
   P1/P2, assuming they always followed the precise band) must be neutralized on the
   rare occasion the fallback order puts one of them first. Zeroes out ONLY when
   :first-child; the .bible-search-band--associative / .bible-search-fuzzy-wrap rules
   above are otherwise untouched — this is a new, additive override, not an edit to
   either existing declaration block. */
.bible-search-main > .bible-search-band--associative:first-child,
.bible-search-main > .bible-search-fuzzy-wrap:first-child {
  margin-block-start: 0;
  padding-block-start: 0;
  border-block-start: none;
}

/* search-results-redesign §3.1a — GOLD-CHROME-LEAK FIX. These three links declared NO
   color of their own and so inherited the base `a { color: var(--brand) }` identity gold
   (rgb(200,161,59)). On the disclosed, never-to-be-emphasized topical co-membership tag
   that put a gold streak down a vote-ranked rail (9/15 rows on "love") — a live violation
   of "gold is chrome-only"; the two associative "browse"/"see all" links are in-page
   content navigation, which the house rule (see .search-hit-action's own comment) keeps
   OFF gold. All three are recolored to the content-navigation token --cross-ref (the same
   blue .search-hit-action / .crossref-ref already use in this view). The base `a` rule is
   NOT touched — these are three narrowly-scoped overrides. Gold stays chrome-only. */
.bible-search-related-topictag a,
.bible-search-assoc-browse,
.bible-search-assoc-seeall a { color: var(--cross-ref); }
/* Match the hover/focus underline their sibling content-nav links carry (.crossref-ref,
   .bible-search-jumpnav-link, .bible-search-more-link) so the three behave consistently. */
.bible-search-related-topictag a:hover,
.bible-search-related-topictag a:focus-visible,
.bible-search-assoc-browse:hover,
.bible-search-assoc-browse:focus-visible,
.bible-search-assoc-seeall a:hover,
.bible-search-assoc-seeall a:focus-visible { text-decoration: underline; }

/* search-results-redesign §3.3 — on wide viewports the associative + fuzzy bands lay out
   as a CARD GRID instead of a single full-width column (their rows carry far less per-row
   content than a precise hit, so full width is wasted and inflates scroll length).
   auto-fill + minmax(22rem, 1fr) settles to 2 columns at the ~816px main-column width but
   degrades to 1 column on any narrower pane automatically (no brittle fixed 1fr 1fr); the
   22rem floor keeps each preview at a readable measure. Mobile stays single-column (the
   base grid rule). SCOPED to these two search-only lists ONLY — NOT .search-results
   (shared with the precise band) and NOT any .crossref-* rule. */
@media (min-width: 52rem) {
  .bible-search-assoc-list,
  .bible-search-fuzzy-list {
    grid-template-columns: repeat(auto-fill, minmax(22rem, 1fr));
  }
}
/* search-results-redesign §3.3 — line-clamp the PREVIEW paragraph (only) so a short card
   beside a tall card in a 2-up row does not go ragged; a fixed 3-line cap holds card
   heights even. FIRST use of line-clamp in this file (no prior precedent — grep-confirmed
   in §4). 3 lines (not 2): real previews run 140–300+ chars, and 3 lines keeps enough of
   the longer OT previews useful while still bounding height. GUARDRAIL (§5.1): NEVER clamp
   the disclosure paragraph — only .bible-search-*-preview — so the disclosure keeps full,
   un-shrunk weight in the narrower column. */
.bible-search-assoc-preview,
.bible-search-fuzzy-preview {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}

/* #17 P2 — the /topics browse surface (an SSR, no-JS, indexable finding aid). NEW
   SELECTORS ONLY. It reuses the shared page shell (head/header/footer) + the shared
   pagination pager; only the index grid, the A–Z letter nav, the finding-aid framing
   note, and the per-topic verse list are scoped here. Gold stays chrome-only. */
.topics-page { padding-block: var(--space-5) var(--space-6); }
.topics-hero { max-inline-size: var(--measure-wide, 60rem); }
.topics-hero-title { margin: 0 0 var(--space-2); }
.topics-note {
  margin: var(--space-2) 0 var(--space-4);
  padding: var(--space-3) var(--space-4);
  border: 1px solid var(--pane-border);
  border-radius: var(--radius-md, 8px);
  background: var(--pane-bg, transparent);
  font-size: 0.9rem;
  line-height: 1.5;
  max-inline-size: var(--measure);
}
.topics-filter-form { display: flex; gap: var(--space-2); flex-wrap: wrap; align-items: center; margin-block-end: var(--space-4); }
.topics-filter-input { flex: 1 1 16rem; min-inline-size: 0; }
.topics-letters { display: flex; flex-wrap: wrap; gap: var(--space-1); margin-block-end: var(--space-4); list-style: none; padding: 0; }
.topics-letter { display: inline-block; padding: 0.2rem 0.55rem; border: 1px solid var(--pane-border); border-radius: 6px; font-size: 0.85rem; line-height: 1.2; text-decoration: none; }
.topics-letter[aria-current="true"] { font-weight: 700; }
.topics-showing { margin: 0 0 var(--space-3); font-size: 0.85rem; }
.topics-index-list { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: var(--space-2) var(--space-4); }
.topics-index-item { padding-block: 0.35rem; border-block-end: 1px solid var(--pane-border); }
.topics-index-link { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-2); text-decoration: none; }
.topics-index-name { font-weight: 600; }
.topics-index-meta { font-size: 0.78rem; color: var(--text-faint, var(--text-secondary)); white-space: nowrap; }
.topics-empty { margin-block: var(--space-4); color: var(--text-secondary); }

.topics-detail-attribution { margin: 0 0 var(--space-2); font-size: 0.85rem; }
.topics-detail-disclosure { margin: var(--space-2) 0 var(--space-4); font-size: 0.9rem; line-height: 1.5; max-inline-size: var(--measure); }
.topics-source-group { margin-block-end: var(--space-5); }
.topics-source-head { margin: 0 0 0.25rem; font-size: 1.05rem; font-weight: 600; color: var(--text-secondary); }
.topics-source-sub { margin: 0 0 var(--space-3); font-size: 0.82rem; }
.topics-verse-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.topics-verse { padding-block-end: var(--space-3); border-block-end: 1px solid var(--pane-border); }
.topics-verse:last-child { padding-block-end: 0; border-block-end: 0; }
.topics-verse-head { display: flex; align-items: baseline; gap: var(--space-2); flex-wrap: wrap; }
.topics-verse-text { margin: 0.3rem 0 0; font-family: var(--font-reading); font-size: 1rem; line-height: 1.55; color: var(--text-secondary); max-inline-size: var(--measure); }
.topics-verse-note { margin: 0.25rem 0 0; font-size: 0.82rem; }

/* NUMBERED-PILL PAGER (shared: science theme/book lists + Bible search results).
   A centered row of pills — chevron Prev/Next + numbered page pills with '…'
   truncation — in the section's gold-chrome-on-navy family. Gold is CHROME ONLY:
   it lands on the Prev/Next chevrons, the ONE filled current-page pill, and the
   ACTIVE-CONTROL hover/focus state of every INTERACTIVE pager button (the <a>
   page pills and the Prev/Next edge buttons), which fills gold with a dark
   numeral/label. All of these reuse the same --brand-fill ground + --on-accent
   dark-navy foreground as the .analysis-search-submit CTA — AA-clear by
   inheritance in light/dark/sepia. The quiet RESTING page numbers stay reading
   ink (never gilded); gold only appears on active interaction, consistent with
   gold-chrome-only. The current-page numeral and the hover-filled numeral are
   active-control states on the gold fill (exactly like the CTA's label), NOT
   resting content text. */
.pagination { margin-block-start: 1.5rem; }
.pagination-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.4rem;
}
.pagination-item { display: flex; }

/* Quiet (non-current) page pill: reading ink, soft border, transparent ground.
   ≥44px touch target. Both the <a> pills and the current-page <span> share the
   pill geometry via .pagination-pill. */
.pagination-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 44px;
  min-block-size: 44px;
  padding-inline: 0.6rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1rem;
  text-decoration: none;
  line-height: 1;
}
/* Base hover/focus: a gold ring. This is the resting state for the non-link
   current-page <span>; the INTERACTIVE <a> pill rule below supersedes it with a
   full fill. */
.pagination-pill:hover,
.pagination-pill:focus-visible {
  border-color: var(--accent-border);
}
/* INTERACTIVE page link hover/focus: a sanctioned active-control state — fills
   gold with a dark numeral, reusing the .analysis-search-submit CTA tokens
   (--brand-fill ground + --on-accent dark-navy text), AA-clear in every theme.
   :hover and :focus-visible stay at parity (pointer == keyboard). */
a.pagination-pill:hover,
a.pagination-pill:focus-visible {
  background: var(--brand-fill);
  border-color: var(--brand-fill);
  color: var(--on-accent);
}

/* THE current-page pill (filled gold). Reuses the .analysis-search-submit CTA
   tokens VERBATIM — --brand-fill ground + --on-accent dark-navy numeral — so the
   numeral on the gold fill is AA-clear in every theme by inheritance. A non-link
   <span aria-current="page">, so it is not interactive. */
.pagination-pill-current {
  border-color: var(--brand-fill);
  background: var(--brand-fill);
  color: var(--on-accent);
  cursor: default;
}

/* Prev/Next: pill buttons with the card-chevron glyph + visible label. The
   chevron is gold chrome (currentColor inherits --brand on the link). */
.pagination-edge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-block-size: 44px;
  padding-inline: 0.85rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--brand);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1rem;
  text-decoration: none;
}
/* Hover/focus: a sanctioned active-control state — fills gold (same --brand-fill
   ground + --on-accent dark-navy foreground as the current-page pill / CTA). The
   chevron flips to the dark foreground below so it stays legible on the fill; the
   label inherits `color` and follows automatically. :hover / :focus-visible at
   parity (pointer == keyboard). */
.pagination-edge:hover,
.pagination-edge:focus-visible {
  background: var(--brand-fill);
  border-color: var(--brand-fill);
  color: var(--on-accent);
}
.pagination-chevron { display: block; flex: 0 0 auto; color: var(--brand); }
.pagination-edge:hover .pagination-chevron,
.pagination-edge:focus-visible .pagination-chevron {
  color: var(--on-accent);
}
.pagination-edge-label { line-height: 1; }

/* Ellipsis gap: muted, no border, not interactive. */
.pagination-gap {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 2rem;
  min-block-size: 44px;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  user-select: none;
}

/* RD17 — recessive metadata chips (book / testament). Chrome, not reading
   surface: quiet surface-sunken pills, never brand red. The testament chip pairs
   the OT/NT text with a quiet left tone so meaning is not color-only (THEME.md
   §1/§7) — the text itself ("OT"/"NT") carries the meaning. */
.chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-sunken);
  border: 1px solid var(--pane-border);
  color: var(--text-secondary);
}
.chip-book { color: var(--text-secondary); }
.chip-testament { letter-spacing: 0.03em; }
/* D4 — deuterocanon testament chip. OT/NT read as quiet neutral pills; the
   deuterocanon is the distinct, less-common section, so its chip takes the
   theme-invariant gold accent family (soft gold fill + 35% gold border + the
   gold accent text) to set it apart without a hardcoded hue. Token-only, so it
   resolves correctly on dark/light/sepia. */
.chip-dc {
  background: var(--accent-soft);
  border-color: var(--accent-border);
  color: var(--brand);
}

/* RD17 — "refine within results" GET field. */
.search-refine { display: flex; gap: 0.5rem; max-width: 28rem; margin: 0.5rem 0 1rem; }
.search-refine input {
  flex: 1;
  padding: 0.5rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
}
.search-refine button {
  padding: 0.5rem 0.85rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--text-primary);
  cursor: pointer;
}
.search-summary { margin: 0.75rem 0 0.5rem; }

/* RD17 — per-book hit-count breakdown (collapsed <details>). */
.search-breakdown {
  margin: 0 0 1rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
.search-breakdown > summary {
  cursor: pointer;
  padding: 0.5rem 0.85rem;
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 0.9rem;
}
.search-breakdown-list {
  list-style: none;
  margin: 0;
  padding: 0.25rem 0.6rem 0.6rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
  gap: 0.25rem;
}
.search-breakdown-item a {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 0.4rem 0.5rem;
  border-radius: 6px;
  color: var(--text-primary);
  text-decoration: none;
}
.search-breakdown-item a:hover { background: var(--surface-sunken); text-decoration: none; }
.search-breakdown-book { flex: 1; }
.search-breakdown-count {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text-secondary);
}

/* RD17 — neutral zero state. */
.search-empty { margin: 1rem 0; }
.search-empty-tips { margin: 0.5rem 0 0; padding-inline-start: 1.25rem; display: grid; gap: 0.25rem; }

/* --- Tools --- */
.tool-grid { list-style: none; padding: 0; margin: 1.5rem 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr)); gap: 1rem; }
.tool-card {
  border: 1px solid var(--pane-border-soft);
  border-radius: 12px;
  background: var(--surface-raised);
  padding: 1.1rem;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}
/* Catalog chrome — the featured card is the Lemma "focal card" (§5.3): a gold
   border + a soft gold glow instead of a drop shadow. */
.tool-card-featured {
  border-color: var(--accent-border);
  box-shadow: 0 0 0 1px var(--accent-border), 0 0 28px -8px var(--brand);
}
.tool-card-head { display: flex; gap: 0.75rem; align-items: center; }
.tool-icon { border-radius: 8px; }
.tool-name { margin: 0; font-size: 1.2rem; }
.tool-tagline { margin: 0; color: var(--text-secondary); }
.tool-desc { margin: 0; }
.tool-actions { margin: 0; margin-top: auto; }

/* --- Support (/support) -----------------------------------------------------
   Structure ported from the sibling app's /support (lemma.gebible.app): a hero
   band, a two-up band of context panels, one wide panel carrying the four-card
   grid and the whole comparison matrix, then a closing two-up band. Every flat
   <h2>-led group is a bordered, filled panel with a gold title, and the cards
   nested inside a panel (.support-ledger-item, .pricing-card,
   .pricing-table-wrap) step up one elevation so they read as cards ON a panel
   rather than merging into it — the layering is page → panel → card.

   FOUR THINGS THAT DID NOT COME WITH THAT STRUCTURE. Each is a content ruling,
   not a style preference, so none of them is a class to add later on a whim:
     - a featured "Recommended" card and a highlighted table column. IDENTICAL
       chrome on all four cards is the point — one .pricing-card rule, no
       featured/most-popular variant, no badge. The ladder's one difference is a
       SCHEDULE (new features open on $5/$8 first and reach every level after),
       not a value gradient, so a highlight would encode in colour a ranking the
       cards' own copy denies. $5 is now the only rung with an incremental
       benefit and so reads as the most attractive card on merit — answering
       that with chrome is the exact move this rule forbids.
     - per-card tick-lists. The ad-free body is owner-ruled verbatim copy that
       must not be split into bullets.
     - enumerated feature notes, which narrow the no-takeaway rule.
     - the "the free tier's ad helps cover these costs… a paid tier does the
       same" sentence — the offset-equivalence framing the caveat panel killed
       5-of-5.

   GOLD ON THIS PAGE. "Gold is chrome-only" is a SCRIPTURE ANALYSIS guardrail:
   it exists so no analysis surface can accent one pole over the other. This is
   a utility page with no poles, and a gold panel title is the app's existing
   .footer-col-title idiom. It still never marks one rung above another — which
   is the part of the rule that has force here.
   ---------------------------------------------------------------------------- */
/* SHARED, NOT PAGE-LOCAL: .lead is used by 404 / error / credits / commentaries /
   auth-not-configured. It lives in this block for historical reasons only — leave
   the declaration byte-identical; the unchanged shared surfaces are the proof. */
.lead { font-size: 1.15rem; }

/* ---- Hero: eyebrow, title, promise, pledge status, jump link ---- */
.support-hero { margin: 0 0 2rem; }
/* Three facts the page already carries, set as a kicker above the title. It
   names no price on purpose — see the T-02 note in the template. */
.support-hero-eyebrow {
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 0.5rem;
}
.support-hero h1 { margin: 0 0 0.6rem; }
/* Decorative heart glyph leading the <h1> — a NEW sibling-row idiom (the h1
   itself stays untouched, so the rule above still matches it through the
   wrapper). Left-aligned, unlike the centered .analysis-hero-glyph this idiom
   is copied from: no text-align/margin-inline:auto here on purpose. Sized to
   sit with the h1's cap-height without overpowering the larger (2rem UA
   default) heading this page carries versus the 1.2rem h2 that idiom pairs
   with elsewhere. Gold chrome via currentColor, matching every other
   decorative glyph in the app. */
.support-hero-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* Lets the heading shrink below its content width at narrow viewports instead
   of forcing the row wider than the container (flex items default to a
   content-based minimum width). */
.support-hero-title-row h1 { min-inline-size: 0; }
.support-hero-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.support-hero-title-glyph { inline-size: 1.75rem; block-size: 1.75rem; }
.support-lede { font-size: 1.15rem; max-width: 44rem; }
.support-status { color: var(--text-secondary); max-width: 44rem; }
.support-hero-actions { margin: 1.25rem 0 0; }

/* ---- Content panels ---- */
/* The panel fill sits BETWEEN the page and the cards nested inside it, so the
   three elevations stay distinguishable. The app has no third surface token and
   the nested cards already own --surface-raised, so the panel's fill is MIXED
   from the two rather than inventing a fourth: color-mix derives the midpoint
   per theme automatically, and the plain declaration above it is the fallback
   for engines without color-mix (panel and card then share a fill, and the
   border still separates them). */
.support-section {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  padding: var(--space-5);
  margin: 2.5rem 0;
  background: var(--surface-raised);
  background: color-mix(in srgb, var(--surface-raised) 55%, var(--surface));
}
.support-section > :first-child { margin-top: 0; }
.support-section > :last-child { margin-bottom: 0; }
/* Prose in this page's sections keeps a reading measure; the grid and the table
   below deliberately opt out of it so four columns can breathe. */
.support-section > p,
.support-section > ul:not(.pricing-grid) { max-width: 44rem; }
/* Colour only — same family, size and weight as before. See the GOLD note at
   the head of this block for why the analysis guardrail does not bind here. */
.support-section h2 {
  font-family: var(--font-ui);
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--brand);
  margin: 0 0 var(--space-3);
}
/* The one internal jump target on the page (the hero's "See the levels" link,
   rendered only once pledging is live) — offset so a fixed header never covers
   the heading it scrolls to. */
#choose-your-level { scroll-margin-top: 5rem; }

/* Running-cost ledger — one boxed row per cost, so four costs read as four
   things at a glance instead of as a bullet run. */
.support-ledger {
  list-style: none;
  padding: 0;
  margin: 0.9rem 0 1rem;
  display: grid;
  gap: 0.6rem;
}
/* `overflow-wrap: anywhere` because these rows and the contact list carry
   unbreakable tokens — the bare domain and the contact address. Inside a
   half-width PANEL with a painted border, a token wider than the column no
   longer merely runs long, it escapes the border and floats in the grid gap.
   `anywhere` rather than `break-word` so the token also shrinks the intrinsic
   min-content width, which is what keeps the grid track honest. */
.support-ledger-item {
  padding: 0.7rem 0.85rem;
  background: var(--surface-raised);
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.6;
  overflow-wrap: anywhere;
}
.support-ledger-item strong { color: var(--text-primary); }
.support-ways { padding-left: 1.1rem; }
.support-ways li { margin-bottom: 0.5rem; overflow-wrap: anywhere; }
.support-ways strong { color: var(--text-primary); }
.support-ladder-note { max-width: 44rem; color: var(--text-secondary); }
/* The gift band is the one prose panel with an action of its own; its button
   takes the same footed slot the pricing cards use, so it lands on the panel's
   floor instead of floating wherever the copy happens to end. */
.support-gift { display: flex; flex-direction: column; }
.support-gift-actions { margin: auto 0 0; padding-top: 1rem; }

/* Two panels side by side above the tablet breakpoint, stacked below it —
   reusing the page's existing 600px line rather than a new number. Each row
   supplies its own margin; the sections inside give theirs up so the grid `gap`
   is the only space between them. Grid's default align-items:stretch makes both
   panels match the taller one, so a short panel leaves no ragged edge. */
.support-row { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-5); margin: 2.5rem 0; }
.support-row > .support-section { margin: 0; }
@media (min-width: 601px) {
  .support-row-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* The gift band is conditional — when it's absent, its sibling ("Other ways to
   help") is the row's only child and spans the full row rather than sitting
   stranded in a half-width column. */
.support-row-2 > .support-section:only-child { grid-column: 1 / -1; }

/* --- Support (/support): two-column "Other ways to help" when full width ----
   Same board #33 panel-fill class of bug, on the sibling page: when the gift
   band is absent (SUPPORT_GIFT_URL unset), "Other ways to help" is the row's
   only child and spans the full 1120px card (the `:only-child` rule directly
   above), but its `<ul class="support-ways">` still sits under the shared
   44rem prose cap and fills only 63% of it. When the gift band IS configured
   the two sit side by side at ~524px each, where that cap never binds — this
   modifier must NOT fire there, or a genuinely two-up list gets crushed into
   two narrow sub-columns of its own.

   `.support-ways-2col` is a MODIFIER on the `<ul>` itself (alongside
   `.support-ways`, same placement as `.privacy-ledger-2col` above), scoped
   under a NEW `.support-page` hook on <main> AND the existing
   `.support-row-2 > .support-section:only-child` structural selector
   (immediately above) so the rule is dormant unless both are true — genuinely
   full width, not merely present. The multicol container is the `<ul>` itself,
   not the `<section>`, so its `<h2>` sibling is never a descendant of the
   multicol box and needs no `column-span` — unlike the /privacy prose fix,
   there is nothing here that could pull the gold title into a column. `li`
   carries `break-inside: avoid` so a single item never splits across the gap;
   the `<ul>` itself is left free to break BETWEEN items, which is what lets
   the three items actually distribute across two columns instead of leaving
   column two empty. ------------------------------------------------------ */
.support-page .support-row-2 > .support-section:only-child > .support-ways.support-ways-2col {
  max-width: none;
}
@media (min-width: 601px) {
  .support-page .support-row-2 > .support-section:only-child > .support-ways.support-ways-2col {
    columns: 2;
    column-gap: var(--space-6);
  }
  .support-page .support-row-2 > .support-section:only-child > .support-ways.support-ways-2col li {
    break-inside: avoid;
  }
}

/* ---- The four-card ladder ---- */
/* Four across at full width, two at tablet, one on a phone. */
.pricing-intro { max-width: 44rem; }
.pricing-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem;
  margin: 1.5rem 0;
  padding: 0;
  list-style: none;
}
@media (max-width: 1000px) {
  .pricing-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 600px) {
  .pricing-grid { grid-template-columns: minmax(0, 1fr); }
}
/* position: relative is load-bearing, not decoration: .pricing-name is
   .visually-hidden on the two unnamed rungs, .visually-hidden is
   position:absolute, and an abspos box with no positioned ancestor is laid out
   against the initial containing block — contributing its offset to the ROOT's
   scrollable overflow rather than staying inside the card. */
.pricing-card {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  padding: 1.25rem 1.1rem 1.1rem;
  background: var(--surface-raised);
}
/* An explicit three-row grid so the NAME's line box exists on every card. The
   two upper rungs are unnamed, so their <h3> is .visually-hidden — which is
   position:absolute and occupies no space at all. Without the reserved row
   their price rode up a line and the four heads stopped aligning across the
   grid. The rows are placed explicitly because an out-of-flow child claims no
   track of its own, and the first is a minmax() rather than a fixed height so a
   longer name can still wrap instead of clipping. */
.pricing-card-head {
  display: grid;
  grid-template-rows: minmax(1.1rem, auto) auto auto;
  margin-bottom: 0.9rem;
  padding-bottom: 0.9rem;
  border-bottom: 1px solid var(--pane-border-soft);
}
/* line-height is set EXPLICITLY, not inherited: the reserved track above is
   sized to this line box, and the page's inherited 1.65 made a named card's
   name 3px taller than the reservation — so the two named rungs' prices sat
   3px below the two unnamed ones, which is exactly the misalignment the
   reservation exists to prevent. Measured, not assumed. */
.pricing-name {
  grid-row: 1;
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  line-height: 1.4;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--text-secondary);
}
.pricing-price {
  grid-row: 2;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.15rem;
  margin: 0.35rem 0 0.4rem;
  white-space: nowrap;
}
.pricing-amount {
  font-family: var(--font-ui);
  font-size: 2rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
}
.pricing-period { color: var(--text-secondary); font-size: 0.9rem; }
/* min-height reserves TWO lines. The four "who it's for" lines are written to
   fit inside two at every width this grid produces, but they are not the same
   length — without the reservation, whichever one happens to fit on a single
   line at a given width lifts that card's body a row out of step with its
   neighbours, and the comparison stops reading across. */
.pricing-who {
  grid-row: 3;
  margin: 0;
  min-height: 3em;
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.5;
}
/* Full-strength, never muted: each upper rung's body IS its ruled caveat
   sentence, and setting those in muted text beside full-strength sales copy
   would visually demote exactly the sentence the ruling says must not be
   demoted. */
.pricing-body { margin: 0; }
.pricing-current { margin: 0.75rem 0 0; font-size: 0.95rem; color: var(--text-secondary); }
/* margin-top:auto pins the CTA to the card's foot so the four feet line up
   across a row whose bodies are very different lengths. */
.pricing-cta { margin: 1rem 0 0; margin-top: auto; padding-top: 1rem; }
.pricing-cta .btn { display: block; width: 100%; text-align: center; }
/* Not a control — a state. It takes the button's FOOTPRINT so the four card
   feet stay level, but a dashed border and body-weight text keep it from
   reading as something you can press. */
.pricing-pending {
  display: block;
  padding: 0.55rem 1rem;
  border: 1px dashed var(--pane-border);
  border-radius: var(--radius);
  text-align: center;
  font-size: 0.95rem;
  color: var(--text-secondary);
}

/* ---- The full comparison matrix ---- */
/* The table scrolls INSIDE this box — the page body never scrolls sideways.
   position: relative keeps any absolutely-positioned cell content added later
   inside this scroller instead of letting it contribute an offset to the root's
   scrollable overflow. */
.pricing-table-wrap {
  position: relative;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  margin: 1.5rem 0;
  background: var(--surface-raised);
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
}
/* tabindex="0" is what makes the overflowing columns reachable by keyboard, and
   it also makes this div focusable — an unstyled focus ring on a focusable box
   is a real a11y regression, not a nitpick. */
.pricing-table-wrap:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }
/* border-collapse: SEPARATE (with zero spacing), not collapse — the row-header
   column below is position:sticky, and a collapsed table's borders belong to
   the TABLE, so they do not paint on a sticky cell and the divider vanishes
   mid-scroll. Every cell therefore draws its own border-top instead. */
.pricing-table {
  width: 100%;
  min-width: 44rem;
  border-collapse: separate;
  border-spacing: 0;
  font-family: var(--font-ui);
}
/* Both the table's accessible name and its visible header band — which makes
   "What each level includes" the same RANK of thing as the .support-section h2
   panel titles a few rules above, and those are already var(--brand). It takes
   the same gold for the same reason (see the GOLD note at the head of this
   block): a gold title is this app's existing .footer-col-title idiom, not a new
   colour language invented for the payment page.

   WHY THE GUARDRAIL DOES NOT BITE HERE, restated on this rule because it is the
   ONE gold declaration inside the matrix. "Gold is chrome-only" is a SCRIPTURE
   ANALYSIS guardrail: it exists so no analysis surface can accent one pole over
   the other. /support has no poles. The part of the rule that does have force
   here is that gold must never mark one RUNG above another — and a caption is
   laid out across the WHOLE table, so it accents no column.

   That is also exactly where gold stops. .pricing-table-tier,
   .pricing-table-price, the th/td ink, .pricing-mark and .pricing-table-state
   all stay on the text tokens deliberately: gold reaching a per-column or
   per-cell element would be the value signal this ladder cannot honestly carry.
   $8 buys nothing $5 does not, and the single row that separates those two from
   $3 is a matter of TIMING — free and ad-free get every feature eventually — so
   there is no rung, column or cell here that outranks another for gold to mark.
   The timing row gets no accent of its own for the same reason.

   Contrast checked against the fill it actually paints on — .pricing-table-wrap's
   opaque --surface-raised, not the page ground: 5.32:1 light / 6.16:1 dark /
   5.52:1 sepia, all clear of AA at this size. The light and sepia themes already
   declare --brand as AA-safe gold INK (#8a6510 at 5.13:1, #7a5e16 at 5.07:1, both
   on --surface) precisely so the accent can be used as text; no new token was
   added and none is needed. */
.pricing-table caption {
  text-align: left;
  padding: 0.85rem 0.9rem 0.7rem;
  color: var(--brand);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.pricing-table th,
.pricing-table td {
  border-top: 1px solid var(--pane-border-soft);
  padding: 0.7rem 0.9rem;
  text-align: left;
  vertical-align: top;
  font-size: 0.82rem;
  line-height: 1.55;
  color: var(--text-secondary);
}
.pricing-table thead th { border-top: 0; color: var(--text-primary); white-space: nowrap; }
.pricing-table tbody tr:first-child > * { border-top-color: var(--pane-border); }
/* The feature column stays put while the tier columns scroll — without it, a
   phone reader scrolled two columns right is looking at four marks with no idea
   which row they belong to. box-shadow rather than border-right, for the
   border-collapse reason above. The background is an opaque solid so tinted
   cells scrolling underneath are fully occluded. */
.pricing-table-rowhead {
  position: sticky;
  left: 0;
  z-index: 1;
  min-width: 9rem;
  background: var(--surface-raised);
  box-shadow: 1px 0 0 var(--pane-border-soft);
  color: var(--text-primary);
  font-weight: 700;
}
.pricing-table-tier {
  display: block;
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.pricing-table-price { display: block; margin-top: 0.15rem; font-size: 0.78rem; color: var(--text-secondary); font-weight: 500; }
/* The note drops onto its own line under the state chip, rather than running
   on beside it, now that the chip carries real words of its own. */
.pricing-table-note { display: block; margin-top: 0.35rem; font-size: 0.78rem; color: var(--text-secondary); }
/* The mark is aria-hidden; its meaning is carried by adjacent real text, so
   colour is never the only channel. Weight rather than hue: the theme has no
   semantic success/failure token, and inventing a green here would add a colour
   language this app does not otherwise speak — while gold, the one accent it
   does, is chrome and cannot mean "included". */
.pricing-mark { margin-right: 0.35rem; font-weight: 600; }
.pricing-yes .pricing-mark { color: var(--text-primary); }
.pricing-no .pricing-mark { color: var(--text-secondary); }
/* "Included."/"Not included." as a real, visible PILL beside the (aria-hidden)
   glyph, so a column reads at a glance instead of as a wall of near-uniform
   prose — see the .pricing-mark comment above for why weight, not colour,
   separates the two states. */
.pricing-table-state {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  padding: 0.12rem 0.5rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  white-space: nowrap;
}
.pricing-yes .pricing-table-state { color: var(--text-primary); border-color: var(--pane-border); }
.pricing-no  .pricing-table-state { color: var(--text-secondary); }
/* Cell tint is reinforcement ONLY — the pill's own words already carry the
   state. A RECESSED fill for "not included" rather than a hue, for the same
   reason as .pricing-mark. --surface-sunken is an opaque solid, so a tinted
   cell scrolling under the equally-opaque sticky row-head is fully hidden. */
.pricing-table td.pricing-no { background: var(--surface-sunken); }
/* .pricing-mark's own margin-right is sized for the inline layout it has
   everywhere else; inside this flex chip the `gap` owns the spacing, and both
   applying put the glyph roughly twice as far from the word as intended. Zeroed
   HERE rather than on .pricing-mark so that rule stays byte-untouched. */
.pricing-table-state .pricing-mark { margin-right: 0; }

/* --- Privacy (/privacy): decorative title glyph -----------------------------
   The page's first CSS since the ZERO-NEW-CSS verdict (privacy.ejs's header
   comment; SPEC-privacy-page.md §2/§6/§9): a shield glyph leads the <h1> as a
   SIBLING flex row, never a child of the tag itself
   (test/privacy-page.test.js A1 pins `<h1>Privacy</h1>` byte-identical).
   Scoped under `.privacy-page`, the hook SPEC §2 reserved for exactly this.
   Left-aligned (unlike the centered .analysis-hero-glyph this idiom is copied
   from): no text-align/margin-inline:auto here. Every rule below is a NEW
   class; no shared .support-section or .credits-table rule is touched. ------ */
.privacy-page .privacy-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* Lets the heading shrink below its content width at narrow viewports instead
   of forcing the row wider than the container. */
.privacy-page .privacy-title-row h1 { min-inline-size: 0; }
.privacy-page .privacy-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.privacy-page .privacy-title-glyph { inline-size: 1.75rem; block-size: 1.75rem; }

/* --- Privacy (/privacy): two-column ledgers in full-width panels ------------
   Six of the thirteen panels sit full width, and the shared 44rem prose cap
   on `.support-section > ul` (styles.css:3676) leaves ~40% of the panel empty
   for the two that hold short discrete items instead of prose ("The short
   version", "What stays on your device"). `.privacy-ledger-2col` is a
   MODIFIER added on the <ul> alongside `.support-ledger`, on those two lists
   ONLY — "What this site does not do" carries the third `.support-ledger` on
   the page, but it lives in a 524px two-up panel where the cap never binds,
   so it stays plain `.support-ledger` with no modifier and single-column.
   Do not write a blanket `.privacy-page .support-ledger { ... }` rule.
   `.support-ledger` is already `display: grid; gap: 0.6rem`
   (styles.css:3693-3698); this only overrides `max-width` and, above the
   601px line `.support-row-2` already uses (styles.css:3734), the column
   count — via `grid-template-columns`, not CSS `columns`, so a ledger item
   can never split across a column break. Three classes here
   (.privacy-page, .support-ledger, .privacy-ledger-2col) outrank the cap's
   two-classes-plus-type selector on specificity alone, so the shared rule
   stays byte-untouched. ------------------------------------------------- */
.privacy-page .support-ledger.privacy-ledger-2col { max-width: none; }
@media (min-width: 601px) {
  .privacy-page .support-ledger.privacy-ledger-2col {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* --- Privacy (/privacy): two-column PROSE panels ----------------------------
   Board #33 panel-fill follow-up, round two: two panels are pure prose rather
   than a ledger — Advertising (six `<p>` and one opt-out `<ul>`) and Patreon
   (five `<p>`) — and the same 44rem cap on `.support-section > p` / `> ul`
   (styles.css:3675-3676) left them at 63% fill (704px of a 1120px card), for
   the same reason the ledgers were. `.privacy-prose-2col` is a MODIFIER added
   on the `<section>` itself, alongside `.support-section`, on exactly these
   two panels — every other full-width panel on the page already either holds
   a ledger (the `.privacy-ledger-2col` block above), the cookie list (its own
   `.privacy-cookie-split` grid, below), or the device-storage panel's own
   paragraphs (`.privacy-prose-full`, below), so it needs no modifier here,
   and every panel that is not full width already sits inside a
   `support-row-2` two-up row where the cap never binds.

   ROUNDS THREE AND FOUR (board #33) widened this modifier onto a third
   panel, "Cookies this site sets" — round three because its own three (or
   four) `<p class="muted small">` notes sat under the identical 44rem `> p`
   cap the other two prose panels hit; round four because it also replaced
   that panel's `<table>` with the single-column
   `<ul class="support-ledger privacy-cookie-list">` (see that block below)
   without changing which modifier carried the panel. For those two rounds
   `> .privacy-cookie-list` sat alongside `> h2` in the `column-span: all`
   rule below, so the list ran full width above the panel's notes and the
   notes flowed into two columns beneath it, same as Advertising's and
   Patreon's paragraphs.

   ROUND FIVE (v218) took it back out. "Cookies this site sets" wants
   something genuine multi-column structurally cannot do — the list in one
   track, the notes in a second, not interleaved by document position — so it
   now carries `.privacy-cookie-split` instead (the new block below the
   cookie-list block), and `> .privacy-cookie-list` came back out of the
   `column-span: all` rule below, which is why that rule now reads only
   `> h2`. This modifier is back to exactly the two panels round two put it
   on, Advertising and Patreon — the only two panels on the page whose
   content genuinely is one continuous run of prose.

   Genuine CSS multi-column (`columns`, not `grid-template-columns` — unlike
   the ledger fix above, these panels hold a VARIABLE run of variable-height
   blocks, not a fixed grid of short items), scoped to the same 601px line.
   `column-span: all` on the `> h2` is load-bearing: without it, multi-column
   flows the gold panel title into column 1 alongside the prose, because the
   title is a normal-flow child of the same multicol container. `break-inside:
   avoid` on `> p` and `> ul` keeps any one paragraph, or Advertising's short
   opt-out list, from splitting across the column gap — the exact failure mode
   CSS multi-column creates by default if you don't ask it not to. Three
   classes here (.privacy-page, .support-section, .privacy-prose-2col) outrank
   the cap's two-classes-plus-type selector on specificity alone, so
   styles.css:3675-3676 stays byte-untouched. --------------------------------- */
.privacy-page .support-section.privacy-prose-2col > p,
.privacy-page .support-section.privacy-prose-2col > ul {
  max-width: none;
}
@media (min-width: 601px) {
  .privacy-page .support-section.privacy-prose-2col {
    columns: 2;
    column-gap: var(--space-6);
  }
  .privacy-page .support-section.privacy-prose-2col > h2 {
    column-span: all;
  }
  .privacy-page .support-section.privacy-prose-2col > p,
  .privacy-page .support-section.privacy-prose-2col > ul {
    break-inside: avoid;
  }
}

/* --- Privacy (/privacy): full-width single-column PROSE panel ---------------
   Board #33 panel-fill follow-up, round three: "What stays on your device"
   already carries `.privacy-ledger-2col` on its `<ul>` (the two-column ledger
   block above), but its own two `<p>` — an intro line above the ledger, a
   closing line below it — still sat under the shared 44rem cap at 63% fill
   (704px of a 1120px card), the same bug every other exception on this page
   fixes.

   The `.privacy-prose-2col` mechanism just above is the WRONG tool here, and
   this was measured, not assumed: each `<p>` is an isolated singleton, with
   no sibling paragraph or list beside it inside the same multicol flow to
   share a column with. `columns: 2` would strand each one alone in column 1
   at 543px — 48% of the panel, WORSE than the 63% it already has. The exact
   mechanism, since a later reader will otherwise try this again: the `<ul>`
   has to take `column-span: all` (without it the ledger's own grid collapses
   into a ~260px half-column), and a spanner SPLITS the multicol flow into
   separate fragments above and below itself. That leaves one fragment holding
   only the intro `<p>` and one holding only the closing `<p>` — and a single
   `break-inside: avoid` paragraph balanced across two columns simply lands in
   column 1. So `.privacy-prose-full` does the opposite of multi-column: it is
   a MODIFIER added alongside
   `.support-section`, on this one panel only, that just lifts the cap
   outright on the `<p>` — never the `<ul>`, which already has its own
   modifier and its own grid. Neither paragraph here is long enough (one
   line, two lines) to strain readability at 1120px. A panel with a longer
   run of paragraphs needs the `.privacy-prose-2col` treatment above instead
   of this one — do not "unify" the two mechanisms, and do not add this
   modifier to a panel without re-measuring first; the 48%-vs-63% numbers
   above are specific to THIS panel's shape (two short, isolated paragraphs
   bracketing a ledger), not a general verdict against multi-column.

   No `@media` query, unlike every other privacy-page modifier: lifting a
   `max-width` is a no-op below 601px, where `.support-section`'s own width is
   already well under 44rem, so there is nothing for the declaration to do
   at narrow viewports either way. -------------------------------------- */
.privacy-page .support-section.privacy-prose-full > p {
  max-width: none;
}

/* --- Privacy (/privacy): single-column cookie list --------------------------
   Board #33 panel-fill follow-up, round four: "Cookies this site sets" used to
   render `<table class="credits-table">`, and at a 360px viewport that table
   ran 331px wide inside a 264px content box — measured, not assumed — because
   `.credits-table`'s `tbody th { white-space: nowrap }` cannot wrap the
   `pt_session` lifetime cell once the two patron numbers are interpolated in,
   clipping "How long it lasts" off the right edge of the page. The fix reuses
   the exact idiom "What stays on your device" already uses for the identical
   reason: `.support-ledger` / `.support-ledger-item`, whose
   `overflow-wrap: anywhere` (styles.css:3706-3715) was built for unbreakable
   content like that. `.privacy-cookie-list` is applied ALONGSIDE
   `.support-ledger` on the `<ul>` (same placement as `.privacy-ledger-2col`)
   and carries no rule of its own here — the depth (raised surface, border,
   radius, padding) comes free from `.support-ledger-item`, byte-untouched; see
   the `.privacy-cookie-split` block below for the grid that runs it beside
   the panel's notes and the `max-width: none` that keeps it filling the left
   track. The `<li>` carries no privacy-side
   class of its own: anything cookie-specific it ever needs can be reached as
   `.privacy-cookie-list > li` without touching the shared rule, so there is no
   bare hook here to go stale. Deliberately NEVER
   `.privacy-ledger-2col`: staying single-column at every viewport width, not
   fanning out to two columns above 601px like the page's other ledgers, is
   the entire point of this fix. `.credits-table` itself stays byte-untouched
   and still serves /credits and /commentaries. ---------------------------- */
.privacy-page .privacy-cookie-name {
  display: block;
  margin-block-end: 0.3rem;
  font-weight: 600;
  color: var(--text-primary);
}
.privacy-page .privacy-cookie-what { margin: 0; }
.privacy-page .privacy-cookie-life { margin: 0.5rem 0 0; }
.privacy-page .privacy-cookie-life-label {
  display: block;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}

/* --- Privacy (/privacy): cookie panel two-track GRID split -------------------
   Board #33 panel-fill follow-up, round five (v218). Genuine CSS multi-column
   (the `.privacy-prose-2col` block above) flows content in SOURCE ORDER — it
   can balance an arbitrary run of blocks into N columns, but it cannot be
   told "this block goes in column 1, that one in column 2". That is exactly
   what this panel wants: the cookie list on the left, the panel's own
   `<p class="muted small">` notes on the right, never interleaved by document
   position. A two-track CSS Grid can do that where multi-column cannot, which
   is why this one panel leaves `.privacy-prose-2col` behind (see that block's
   ROUND FIVE paragraph) while Advertising and Patreon keep it — their content
   genuinely is one continuous run of prose, with no second track to split
   into.

   The notes needed a wrapper `<div class="privacy-cookie-notes">` for the
   same reason the spanning `<h2>` needs `grid-column: 1 / -1` below: with
   grid auto-placement, four loose `<p>` siblings would each claim their own
   auto-placed cell and snake back into the left track underneath the list
   instead of staying together on the right. One wrapper makes the placement
   deterministic regardless of whether the `patronCookieDomain` conditional
   paragraph renders — three notes or four, the grid still sees exactly two
   cells to place: the list, and the wrapper.

   `max-width: none` on the list exists even though the cap does not
   currently bind: the shared `.support-section > ul:not(.pricing-grid)` cap
   (styles.css:3676) is 44rem = 704px, and the left track here is ~653px at a
   1120px panel (the panel width split 3fr/2fr across the column-gap) —
   inert today. It stays because `.privacy-prose-2col` used to lift that cap
   for this panel and dropping the modifier would otherwise silently
   reintroduce it, and because widening the ratio in the future would clamp
   the list for no visible reason if this declaration were missing.

   The two margin rules exist because `.support-section > :first-child` /
   `> :last-child` (styles.css:3671-3672) reach only DIRECT children, and
   wrapping the notes in a `<div>` changed which elements those selectors
   hit: the wrapper, not its own first and last paragraph, is now the
   section's last child. `margin-top: 0` on both tracks aligns their tops
   under the spanning `<h2>`; `margin-bottom: 0` on the wrapper's own last
   child restores the panel's original bottom spacing. The first-child rule
   is scoped inside the `@media` block on purpose — below 601px the notes
   stack underneath the list rather than sitting beside it, and need their
   ordinary top margin there.

   `.support-section`, `.support-ledger`, `.support-ledger-item` and
   `.credits-table` are untouched by any of this. ---------------------------- */
.privacy-page .support-section.privacy-cookie-split > .privacy-cookie-list {
  max-width: none;
}
.privacy-page .privacy-cookie-notes > :last-child {
  margin-bottom: 0;
}
@media (min-width: 601px) {
  .privacy-page .support-section.privacy-cookie-split {
    display: grid;
    grid-template-columns: minmax(0, 3fr) minmax(0, 2fr);
    column-gap: var(--space-6);
    align-items: start;
  }
  .privacy-page .support-section.privacy-cookie-split > h2 {
    grid-column: 1 / -1;
  }
  .privacy-page .support-section.privacy-cookie-split > .privacy-cookie-list,
  .privacy-page .support-section.privacy-cookie-split > .privacy-cookie-notes > :first-child {
    margin-top: 0;
  }
}

/* --- Privacy (/privacy): the sticky in-page JUMP NAV ------------------------
   Board #33 round six, and the SEVENTH `.privacy-page` exception (see the
   ledger at the top of src/views/privacy.ejs). This is the only exception on
   that page which is not a modifier on a `.support-section` panel: a
   freestanding `<nav>` between the "Last updated" line and "The short version"
   that links all thirteen `<h2>` by id.

   OWN CLASS FAMILY, NOT A REUSE. The app already has two jump-navs —
   `.study-jumpnav` (verse study page, ~6978) and `.bible-search-jumpnav`
   (search results, ~2861). Their pill RECIPE is copied here — transparent
   ground, 1px --pane-border, 999px radius, recessive --text-secondary, gold
   text + --brand-fill border only on hover/focus, own 44px WCAG 2.5.8 tap
   target — with two deliberate departures noted on the `-link` rule below
   (`white-space: nowrap`, and 0.85rem rather than 0.9rem). Their CLASS NAMES
   are not touched, and neither rule block was edited. The unchanged rendering of /v/ and /bible/search is
   the proof of that scoping, and a test asserts neither class string ever
   appears on /privacy. Do not "de-duplicate" these three families into one
   shared rule: this one is sticky and must never wrap, and folding it in would
   drag that behaviour onto two pages that were explicitly ruled in-flow.

   STICKY, unlike both precedents. /privacy carries no second sticky bar of its
   own and no verse to protect, and thirteen sections is more than a reader can
   hold while scrolling a legal document. `z-index: 40` seats it directly under
   `.site-header`'s 50 — the same relationship `.reader-toolbar` has to the
   header on the verse page (~1527).

   `top` IS DERIVED FROM `.site-header`'s CONTRIBUTORS, NOT A PIXEL LITERAL,
   and the two values below are measured, not guessed. Rendered `.site-header`
   heights (getBoundingClientRect, so border-box, at 1440/900/761 and
   760/601/360/320) across four browser base font sizes:

       base font    >=761px (nav)     <=760px (hamburger)
       16px         60.5625           56.1875
       18px         65.765625         58.59375
       20px         73                61
       24px         87.359375         65.78125

   A px literal tracks NONE of that: `top: 60px` is 0.56px off at the default
   base size but 27.4px off at 24px, by which point the bar is riding a third of
   the way up behind the header. Both values below are therefore expressed in
   the header's own terms.

     - <=760px, `calc(1.2rem + 36px)`. Below the app's existing 760px
       responsive-nav breakpoint (~5016 — the SAME line `.site-header` already
       uses to collapse into its hamburger; not a new one) the tallest thing in
       the header is `.nav-toggle`, whose `height: 36px` is a px literal, so the
       px stays px. 1.2rem is `.header-inner`'s `padding: 0.6rem 1.25rem`,
       doubled. Measured residual: 0.98-1.00px at every base size above.
     - >=761px, `calc(2.4rem + 1.2rem)`. With the nav expanded the tallest thing
       is a `.nav-list a` box: `padding: 0.4rem` doubled plus a 1.6 line-height
       on a 1rem font = 2.4rem. Same 1.2rem of `.header-inner` padding. Measured
       residual: 0.96-1.00px at 18/20/24px base, and 2.96px at the default 16px
       — at that ONE size the `.nav-settings` gear's line box (its 20px SVG
       plus the strut's descender) is 2px taller than the nav-link box and wins
       the max, and that term is font-metric-driven, so it is not expressible
       as a rem multiple. Left uncompensated on purpose: see the sign rule next.

   THE RESIDUAL IS ALWAYS AN OVERLAP, NEVER A GAP, AND THAT ASYMMETRY IS THE
   WHOLE POINT. Neither formula adds `.site-header`'s 1px bottom border, so the
   bar always lands about one hairline HIGH. The two bars share
   `background: var(--surface-raised)`, so an overlap is invisible — the header
   simply draws its own bottom border over the top edge of this one, which is
   the join you want. A GAP of the same size is not invisible: it exposes a
   sliver of scrolling page content between two bars. So every rounding here
   goes toward overlap, and the worst case (2.96px at 1440/16px) is absorbed
   entirely by this bar's own 0.5rem top padding — the pills still clear the
   header by 7.4px. Re-measure both values if `.site-header`, `.header-inner`,
   `.nav-toggle` or `.nav-list a` ever change, and keep the sign.

   IT MUST NEVER WRAP, AT ANY WIDTH. Both precedents use `flex-wrap: wrap`,
   which is free on an in-flow strip — one extra row pushes the page down once.
   On a STICKY strip it is a standing tax at every scroll position: thirteen
   44px pills wrapping to three or four rows would hold a fifth of a phone
   screen for the whole visit. So the list is `flex-wrap: nowrap` +
   `overflow-x: auto`, one row at every width — but the row's HEIGHT depends on
   the reader's scrollbar profile, and BOTH numbers are measured, identical at
   1440, 900, 601 and 360:
     - 68.17px where scrollbars are OVERLAID — touch, and any headless run
     - 78.17px on a desktop classic-scrollbar profile, where `scrollbar-width:
       thin` reserves a 10px gutter INSIDE this box (a plain scrollbar would
       reserve 15px)
   Headless numbers are not the product. Measure this bar with
   `headless: false`, or you will under-report its height by exactly that
   gutter — an earlier pass of this component did, and published 68.98px as if
   it were the desktop figure.

   `overflow-x: auto` IS WHAT PREVENTS THE SIDEWAYS BLOWOUT — not `min-width: 0`.
   Per CSS Flexbox §4.5 a flex item's automatic minimum size applies only while
   its computed `overflow` is `visible`, so `overflow-x: auto` has already
   switched `min-width: auto` off by itself. Measured on the live page at 1440:
   `documentElement.scrollWidth` is 1440 as shipped, still 1440 with
   `min-width: auto` forced back on, and 2383 only once `overflow-x` is ALSO
   returned to `visible`. The declaration stays as defence-in-depth — it costs
   nothing and states the intent — but do not describe it as the thing doing the
   work, and do not remove the `overflow-x` believing `min-width` has it covered.

   AND THE READER HAS TO BE ABLE TO TELL IT SCROLLS. A horizontally-scrolling
   row nobody knows is scrollable is just a truncated list, and at 360px there is
   very little of it to go on: the list's clip box measures 243px with overlay
   scrollbars (228px on a classic-scrollbar desktop at the same width), which
   holds exactly ONE whole pill plus about half of the second — 57% and 48% of
   it respectively. So if that row ever ended flush at the container edge, a
   reader would take a thirteen-entry index for a list of one or two. Two
   affordances, both CSS-only:
   `scrollbar-width: thin` keeps a real scrollbar on desktop (hiding it would
   make "there is more" LESS discoverable, not more), and the mask gradient
   fades the last 1.25rem of the row, which is the one that also works on touch,
   where the scrollbar is invisible until you already scrolled. Measured at
   360px the cut also lands MID-PILL, which is the clearest signal of the three
   — but it is a consequence of where thirteen arbitrary pill widths happen to
   fall, so the fade is what guarantees the affordance at widths nobody
   measured. `scroll-padding-inline-end` is sized ABOVE the fade so that a
   keyboard user tabbing to the last pill never has it scrolled to rest under
   the fade with a half-visible focus ring.

   NOT FULL-BLEED, and deliberately so. `<main>` is `.container` (76rem cap), so
   above ~1216px the header's raised surface spans the window while this strip's
   matching surface spans only the centred column, leaving the outer gutters in
   the page background for that one band. Accepted: nothing is ever positioned
   in those gutters on this page, and reproducing `.site-header`'s
   wrapper-plus-inner-container structure for a strip this simple is not worth
   the extra markup layer. Do not build a breakout hack for it. ------------- */
.privacy-page .privacy-jumpnav {
  position: sticky;
  top: calc(2.4rem + 1.2rem);   /* .nav-list a box (0.8rem padding + 1.6 line-height)
                                    + .header-inner padding; the header's 1px border is
                                    left off so the residual is an overlap. See above. */
  z-index: 40;                  /* under .site-header's 50, as .reader-toolbar is */
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin-block: 1.25rem 0;
  /* 0.4rem, not the 0.5rem this started at. The focus-ring clearance the pills
     need has to live INSIDE the scrollbox (see the list's padding below, and
     why), so 0.1rem of the bar's own top padding was moved in there rather than
     added on top of it — the pill sits the same 11.2px below the bar's top edge
     either way, and the row stays inside the one-row height budget. */
  padding-block: 0.4rem;
  /* Opaque, and the same token .site-header uses: without a ground of its own a
     sticky bar lets page content scroll visually through its text, and matching
     the header's token makes the two read as one chrome stack rather than as a
     panel that happens to be pinned. */
  background: var(--surface-raised);
  border-block-end: 1px solid var(--pane-border);
}
@media (max-width: 760px) {
  /* The app's OWN existing responsive-nav breakpoint, not a new one: this is the
     line at which .primary-nav collapses behind .nav-toggle and the header drops
     to its second (and only other) rendered height. There is no third height and
     no continuum between them. */
  .privacy-page .privacy-jumpnav { top: calc(1.2rem + 36px); }
}
.privacy-page .privacy-jumpnav-label {
  flex: 0 0 auto;               /* never shrink: the label is the orientation, and
                                    the list beside it is what gives way instead */
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 0.9rem;
}
.privacy-page .privacy-jumpnav-list {
  display: flex;
  flex-wrap: nowrap;            /* NEVER wrap — sticky makes a wrapped row a standing
                                    height cost the two in-flow precedents don't pay */
  align-items: center;
  gap: 0.4rem 0.6rem;
  margin: 0;
  /* EVERY SIDE OF THIS SHORTHAND IS A MEASUREMENT, NOT SPACING. The global
     focus ring is `outline: 2px solid` at `outline-offset: 2px` (~line 306), so
     it is painted from 2px to 4px OUTSIDE a pill's border box and needs 4px of
     clearance on any side that can clip.

     TWO things clip here, independently, and both had to be accounted for:
       - the scrollbox. `overflow-x: auto` forces `overflow-y: auto` (CSS
         Overflow §3: a non-visible value in one axis computes `visible` to
         `auto` in the other), so this element clips to its PADDING box on all
         four sides, not just horizontally.
       - the mask below. `mask-clip` is unset and therefore `border-box`, so
         anything painted outside the border box is masked away as well.
     Removing only one of them still leaves the ring cut; the block padding has
     to be big enough for both. It previously was not: at 0.15rem/0.1rem the
     measured clearances were 2.39px top and 1.59px on the first pill's left,
     so a keyboard user saw roughly 0.39px of a 2px ring. Now 0.3rem = 4.8px on
     both, with the bottom's 0.35rem = 5.6px already clear.

     The 1.75rem INLINE-END is a THIRD, separate mechanism — nothing to do with
     the two clippers above. It is wider than the fade, so at full scroll the
     fade lands on empty padding instead of on the last pill. Without it the row
     can only scroll until that pill is flush against the clip edge (measured:
     5.27px of clearance, all of it inside the 20px fade), leaving "How to reach
     me" and its ring at about a quarter opacity, and leaving the fade
     suggesting more content at the one position where there is none.
     `scroll-padding` cannot fix that: it positions within the scrollable
     extent, and at the end of the row there is no extent left to give. Extra
     END padding is what creates it. Measured clearance 5.27px -> 28.27px. */
  padding: 0.3rem 1.75rem 0.35rem 0.3rem;
  list-style: none;
  overflow-x: auto;             /* THIS is what keeps the row from blowing the page
                                    out sideways — see the header comment above */
  min-width: 0;                 /* defence-in-depth only; overflow-x has already
                                    switched the automatic minimum size off */
  scrollbar-width: thin;        /* visible, not hidden: a hidden scrollbar makes
                                    "there are more pills" LESS discoverable. It
                                    reserves a real 10px gutter inside this box on
                                    a classic-scrollbar desktop — that gutter is
                                    the whole 68.17 / 78.17px height difference. */
  scroll-padding-inline-end: 1.75rem;  /* the mid-list half of the fade problem: a pill
                                          tabbed to from the left is scrolled only just
                                          into view, which would park it under the fade */
  /* The edge fade — the touch-side half of the "there is more" affordance, since
     a touch scrollbar only appears once you have already scrolled. Both spellings
     ship: unprefixed `mask-image` is Chrome 120+/Firefox 53+/Safari 15.4+, the
     -webkit- form covers everything older. Purely decorative: where neither is
     supported the row still scrolls and still cuts mid-pill. */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 1.25rem), transparent 100%);
  mask-image: linear-gradient(to right, #000 calc(100% - 1.25rem), transparent 100%);
}
.privacy-page .privacy-jumpnav-item { margin: 0; flex: 0 0 auto; }
/* The same CHIP-LITE pill the two precedents use, copied rather than shared:
   transparent ground at rest (gold is chrome-only and NEVER a fill), 1px
   --pane-border, the app's 999px pill radius, recessive --text-secondary text,
   and its own >=44px tap target (WCAG 2.5.8) — border-box is global, so
   min-block-size: 44px IS the full 44px box. TWO declarations differ from the
   precedents, not one: `white-space: nowrap` is added, because a pill that
   wrapped internally would break the single-row height budget this bar is built
   on; and `font-size` is 0.85rem where both precedents use 0.9rem, because
   thirteen entries is a longer row than the 2-4 they carry. The smaller size
   still measures 6.21:1 against the bar's ground, comfortably over AA. */
.privacy-page .privacy-jumpnav-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-block: 0.3rem;
  padding-inline: 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-secondary);
  text-decoration: none;
  white-space: nowrap;
}
.privacy-page .privacy-jumpnav-link:hover,
.privacy-page .privacy-jumpnav-link:focus-visible {
  color: var(--brand);
  border-color: var(--brand-fill);
}

/* Landing offset for the thirteen jump targets — clears BOTH sticky bars
   (.site-header + .privacy-jumpnav), so a jump never parks a gold panel title
   underneath them. ONE flat value at every width.

   DERIVED FROM THE HEADFUL STACK, which is the tall one: with the scrollbar
   gutter included the stuck stack bottoms out at 135.78px (900/1440) and
   133.37px (601/360), so 9rem = 144px leaves 8.2px and 10.6px of slack
   respectively. That is real but thin — it is NOT the ~17px an overlay-scrollbar
   (or headless) measurement suggests, because that measurement is 10px short of
   the bar's desktop height. Verified headfully at all four widths after a real
   click: every one of the thirteen targets lands BELOW the stack, never under
   it. If this ever needs more air, the number to move is this one and the
   reason to move it would be cosmetic — at 9rem the panel's own top padding,
   not its heading, is what sits behind the bar.

   Landing short — a heading tucked under the bars — is the failure that
   matters, and a few extra px is harmless, so unlike `top` above this does not
   need a breakpoint-conditional second value. Scoped under `.privacy-page` like
   every other rule in this family, even though the ids are page-unique. */
.privacy-page #privacy-short-version,
.privacy-page #privacy-collects,
.privacy-page #privacy-does-not,
.privacy-page #privacy-cookies,
.privacy-page #privacy-device-storage,
.privacy-page #privacy-advertising,
.privacy-page #privacy-consent,
.privacy-page #privacy-search,
.privacy-page #privacy-patreon,
.privacy-page #privacy-children,
.privacy-page #privacy-links,
.privacy-page #privacy-changes,
.privacy-page #privacy-contact {
  scroll-margin-block-start: 9rem;
}

/* --- Terms (/terms): decorative title glyph ---------------------------------
   THE PAGE'S FIRST AND ONLY CSS, and it retires a property this page shipped
   with: terms.ejs's header comment and test/terms-page.test.js T-28 asserted
   that no `.terms-` selector existed in this file at all. An OWNER OVERRIDE of
   docs/SPEC-terms.md §4.0, ruled 2026-08-12, put the app's standard
   [glyph][title] row on the page — §4.0 had ruled a glyph out precisely to keep
   that verdict, and the owner ruled the other way. Retired by the D19 route
   /privacy set: one named family, scoped under the `.terms-page` hook that has
   sat empty since the page shipped, with T-28 INVERTED rather than deleted (it
   now pins these four rules and goes red on a fifth).

   WHAT THE OVERRIDE DID NOT CHANGE — SPEC §5.3's 40rem argument, still binding.
   `.container narrow` is a 40rem container, so the shared 44rem cap on
   `.support-section > p` and `.support-section > ul` can never bind on this
   page. NO PANEL NEEDS A MODIFIER, there is no `.terms-page .support-section`
   rule, and there must not be one: the exception is this ONE hero family and
   nothing structural.

   The four rules are `.privacy-page .privacy-title-…` above, rescoped and
   parked at the END of the /privacy run so the two sibling utility pages' CSS
   stays adjacent; that family is byte-untouched, as is every shared class
   /terms borrows. Left-flush like /privacy, so the beta gate's block-end margin
   correction (`.beta-gate-title-row`, which exists because CENTRING made the
   ~0.6rem glyph offset visible) is deliberately NOT copied here — this page
   inherits /privacy's accepted rhythm, measured identical to it at 1280px and
   390px, and that rule stays untouched too. T-01/T-02 pins
   `<h1>Terms</h1>` byte-identical: the row goes AROUND the heading, never
   inside it. ------------------------------------------------------------- */
.terms-page .terms-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* Lets the heading shrink below its content width at narrow viewports instead
   of forcing the row wider than the container. */
.terms-page .terms-title-row h1 { min-inline-size: 0; }
.terms-page .terms-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.terms-page .terms-title-glyph { inline-size: 1.75rem; block-size: 1.75rem; }

/* --- About (/about): decorative title glyph ---------------------------------
   THE PAGE'S FIRST AND ONLY CSS, and a copy in SHAPE of the `.terms-` family
   directly above rather than an extension of it. That distinction is the whole
   design: test/terms-page.test.js T-28 pins the `.terms-` selector set by
   EQUALITY and goes red on a fifth member, so a `.terms-page, .about-page`
   grouping or a re-scoped selector would break a neighbouring page's scoping
   proof to save four lines. A separate `.about-` family sits outside that set,
   leaves T-28 byte-green, and gets its own set-equality pin in
   test/about-page.test.js — four rules, and a fifth is a new decision.

   THE 40rem ARGUMENT CARRIES OVER UNCHANGED. `.container narrow` is a 40rem
   container, so the shared 44rem cap on `.support-section > p` and
   `.support-section > ul` can never bind on /about either. There is no
   `.about-page .support-section` rule and there must not be one: `.lead`,
   `.muted`, `.support-section`, `.support-ledger` and `.support-ledger-item`
   are shared with /privacy, /support, /terms and /credits, and the unchanged
   rendering of those four pages is the proof this one is correctly scoped.

   Left-flush like /privacy and /terms, so the beta gate's centring correction
   (`.beta-gate-title-row`) is deliberately not copied here.
   --------------------------------------------------------------------------- */
.about-page .about-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* Lets the heading shrink below its content width at narrow viewports instead
   of forcing the row wider than the container. */
.about-page .about-title-row h1 { min-inline-size: 0; }
.about-page .about-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.about-page .about-title-glyph { inline-size: 1.75rem; block-size: 1.75rem; }

/* --- Contact (/contact): title glyph, page width, lede measure, panel grid ---
   NINE RULES IN TWO GROUPS, and the set is pinned by EQUALITY in
   test/contact-page.test.js — a tenth is a DECISION, not a refactor.

   THE FIRST FOUR ARE DECORATION: the [glyph][title] row, a copy in SHAPE of the
   `.about-` family directly above rather than an extension of it — for exactly
   the reason that family is itself a copy of `.terms-` rather than a grouping
   with it. test/terms-page.test.js T-28 pins the `.terms-` selector set by
   EQUALITY and test/about-page.test.js A-22 does the same for `.about-`, so an
   `.about-page, .contact-page` grouping or a re-scoped selector would break a
   neighbouring page's scoping proof to save four lines. A separate `.contact-`
   family sits outside both sets and leaves both pins byte-green. THIS IS THE
   SIXTH SUCH FAMILY (.support-hero-, .privacy-, .terms-, .about-,
   .beta-gate-), which makes it the established idiom on this run of utility
   pages rather than a deviation worth arguing about.

   THE OTHER FIVE ARE STRUCTURE, all of them consequences of one owner ruling:
   the page width, the lede's measure, and the three that build the panel grid.
   Each is documented at its own declaration below. NONE of the nine names a
   shared primitive — not `.container`, not `.lead`, not `.support-section` —
   which is what keeps /privacy, /support, /terms, /credits and /about
   byte-identical and is this page's whole scoping proof.

   THE 40rem ARGUMENT IS RETIRED — THIS PAGE IS 64rem AND TWO-UP. Owner ruling:
   /contact drops `.container narrow` and caps at 64rem, with its four panels in
   a two-column grid above the house 52rem breakpoint. The widening is a
   COMPOUND selector, `.container.contact-page`, never a descendant one:
   `.contact-page .container` would be a page-scoped override of a shared
   primitive, which the set-equality pin bans by name. At (0,2,0) it beats
   `.container`'s own (0,1,0) 76rem cap on the same property, `max-width`.

   THE SHARED 44rem CAP IS RE-DERIVED HERE, not assumed away. `.support-section
   > p` and `> ul:not(.pricing-grid)` cap prose at 44rem = 704px. TWO-UP the
   container's content box is 1024 - 2x24 = 976px, one column is
   (976 - 24 column-gap) / 2 = 476px, and a panel's own 1px borders plus
   `var(--space-5)` padding leave 476 - 2 - 48 = 426px of text column. 426 < 704,
   so THE CAP CANNOT BIND TWO-UP — 278px of headroom, measured in the browser at
   1280px and 1024px rather than only computed. It DOES bind in one narrow band,
   and stating that is better than repeating a "can never bind" line that stopped
   being true: single-column, a panel's text column is viewport - 98px, which
   passes 704px at 803px of viewport, so between 803px and the 832px breakpoint
   the cap trims at most 29px off a 733px panel (measured: 733 vs 704 at 831px).
   ~4% of ragged right in a 29px-wide window of viewport widths is ACCEPTED, and
   it is deliberately NOT routed around — there is no `.contact-page
   .support-section` rule and there must not be one. `.lead`, `.support-section`,
   `.support-ledger` and `.support-ledger-item` are shared with /privacy,
   /support, /terms, /credits and /about, and the unchanged rendering of those
   five pages is the proof this one is correctly scoped.

   WHAT THE CAP DOES NOT REACH IS THE LEDE, which sits outside the grid by
   design and so inherits no `.support-section` rule at all. That is a separate
   consequence of the same widening and it is answered by `.contact-lede`
   below, not by loosening anything here.

   Left-flush like /privacy, /terms and /about, so the beta gate's centring
   correction (`.beta-gate-title-row`) is deliberately not copied here.
   --------------------------------------------------------------------------- */
.contact-page .contact-title-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
/* Lets the heading shrink below its content width at narrow viewports instead
   of forcing the row wider than the container. */
.contact-page .contact-title-row h1 { min-inline-size: 0; }
.contact-page .contact-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.contact-page .contact-title-glyph { inline-size: 1.75rem; block-size: 1.75rem; }

/* The page width, per the ruling above. COMPOUND, so it is not an override of
   the shared `.container` primitive scoped behind the page hook. */
.container.contact-page { max-width: 64rem; }

/* THE LEDE'S MEASURE, and it is a direct consequence of the rule above rather
   than a separate design idea. `.lead` (this file, in the /support block) is
   SHARED with 404, error, /credits, /commentaries and auth-not-configured, and
   it is only `font-size: 1.15rem`: it never carried a max-width because every
   other page that uses it is `.container narrow`, where 40rem caps the measure
   for it. /contact is the first surface to put `.lead` in a WIDE container, and
   at 64rem the lede ran the full 976px content box — measured at ~96 characters
   a line against the panels' ~62. The panels were never at risk; they inherit
   `.support-section > p`'s 44rem cap. The lede is the one run of prose on this
   page that no cap reaches, because it sits OUTSIDE the grid by design.

   44rem, so the lede shares ONE measure with the panel prose it introduces —
   the number this sheet already uses nine times, not a new one. The element
   keeps BOTH classes: the size still comes from the shared primitive and only
   the cap is page-owned, which is the additive form of what `.support-lede`
   does by replacing `.lead` and redeclaring its font-size. `.lead`'s own
   declaration stays byte-identical, exactly as the comment above it asks.

   NOT `.contact-page .lead` — the by-name guard in test/contact-page.test.js
   forbids forking a shared primitive behind the page hook, correctly. NOT
   `.container.contact-page > .lead` either: that regex would miss it, but it is
   the same page-scoped override in a different spelling. A new class is the
   honest form. */
.contact-lede { max-width: 44rem; }

/* The four panels, two-up above the house 52rem breakpoint and stacked below
   it. MOBILE-FIRST: one column is the UNCONDITIONAL default, so the narrow
   rendering is the one that needs no media query to be correct, and 52rem is
   reused rather than invented — this stylesheet already had seven blocks at
   that line before this page existed, against two at 64rem and four at 72rem.

   THE GRID IS ON A NEW WRAPPER and the four `<section class="support-section">`
   become items by being its children. No rule in this family targets
   `.support-section`: that is what keeps the shared primitive unforked and
   /privacy, /support, /terms, /credits and /about byte-identical.

   THE ASYMMETRIC GAP IS DELIBERATE, not a typo. Grid items' margins do not
   collapse the way in-flow siblings' do, so the items give theirs up and the
   gap becomes the only space between them — and row-gap is then set to the
   2.5rem those margins used to collapse TO, so the single-column rendering
   keeps exactly the vertical rhythm the page shipped with and only the column
   gutter is new. The wrapper carries the same 2.5rem block margins the first
   and last panel used to contribute, so the space under the lede and above the
   terminal ad unit is unchanged as well.

   NO `order:` AND NO `grid-area:`. The panels are placed in SOURCE ORDER, so
   the routing the four headings encode — the address first — is the same order
   a screen reader and a keyboard walk in. Default `align-items: stretch` gives
   the two panels of a row a common top and bottom edge, so a short panel leaves
   no ragged edge; it is the same behaviour `.support-row` relies on. */
.contact-panels {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 2.5rem var(--space-5);
  margin: 2.5rem 0;
}
.contact-panels > * { margin: 0; }
@media (min-width: 52rem) {
  .contact-panels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* --- Settings --- */
.settings-form fieldset {
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  margin: 1rem 0;
  padding: 1rem 1.1rem;
}
.settings-form legend { font-weight: 700; padding: 0 0.4rem; }
.radio-row { display: flex; gap: 1.25rem; flex-wrap: wrap; }
.settings-form select { padding: 0.5rem 0.6rem; border: 1px solid var(--pane-border); border-radius: 8px; background: var(--surface); color: var(--text-primary); }

/* --- Settings: header gear trigger + in-place dialog ---
   The gear is a nav <a> (inherits .nav-list a's hover: neutral → gold). We make
   it a centered square icon button with a comfortable touch target, and tint the
   glyph gold on hover/focus to match the rest of the header chrome. Token-only,
   CSP-safe (the SVG itself uses currentColor). */
.nav-settings {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Comfortable touch target (≥44px tall via padding) while keeping the glyph
     small; line-height:0 prevents the icon from stretching the row. */
  padding: 0.5rem;
  line-height: 0;
  color: var(--text-primary);
}
.nav-settings:hover,
.nav-settings:focus-visible { color: var(--brand); }
.nav-settings-icon { display: block; }

/* In-place settings dialog (Lemma §5.10 / docs/theming-guidelines.md). Centered
   card on the raised surface with the standard pane border, the 16px dialog
   radius, and the modal shadow. margin:auto re-centers it (the browser's default
   dialog centering still applies, but make it explicit so a future global margin
   reset can't break it). A navy/theme scrim dims the page behind. */
.settings-dialog {
  width: min(460px, calc(100vw - 2rem));
  max-width: calc(100vw - 2rem);
  margin: auto;
  padding: 1.25rem 1.5rem 1.5rem;
  border: 1px solid var(--pane-border);
  border-radius: 16px;
  background: var(--surface-raised);
  color: var(--text-primary);
  box-shadow: var(--shadow);
}
.settings-dialog::backdrop {
  /* A neutral dark scrim; fixed dim so it reads on every theme (the dialog's own
     surface tokens carry the theme). */
  background: rgba(5, 10, 24, 0.6);
}

/* Title row: dialog heading on the left, a small square Close button on the
   right. The Close button uses the soft-button hover idiom (neutral → gold). */
.settings-dialog-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.settings-dialog-title {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 700;
}
.settings-dialog-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
  transition: color 120ms, border-color 120ms, background 120ms;
}
.settings-dialog-close:hover,
.settings-dialog-close:focus-visible {
  color: var(--brand);
  border-color: var(--accent-border);
  background: var(--accent-soft);
}
.settings-dialog-close-icon { display: block; }

/* Inside the dialog the .settings-form fieldsets reuse the standalone-page rules
   above; only trim the outer margins so the card stays compact. */
.settings-dialog-form fieldset:first-of-type { margin-top: 0.75rem; }
.settings-dialog-actions { margin: 1rem 0 0; }

/* --- Blog post body (reading surface — no brand red adjacent to prose) --- */
.blog-post { max-width: var(--measure); }
.blog-post-body { font-family: var(--font-reading); font-size: 1.1rem; line-height: 1.8; }
.blog-post-body h1, .blog-post-body h2, .blog-post-body h3 { font-family: var(--font-ui); line-height: 1.3; }
.blog-post-body blockquote {
  /* Neutral rule (NOT brand) so red never sits beside reading text. Logical
     property so it flips under dir="rtl". */
  border-inline-start: 3px solid var(--pane-border);
  margin: 1rem 0;
  padding: 0.25rem 1rem;
  color: var(--text-secondary);
}
.blog-post-body code {
  background: var(--surface-sunken);
  padding: 0.1rem 0.35rem;
  border-radius: 4px;
  font-size: 0.9em;
}

/* --- Notices / errors --- */
.notice { border: 1px solid var(--pane-border); border-radius: var(--radius); padding: 1rem 1.1rem; margin: 1rem 0; }
.notice-info { background: var(--surface-raised); }
/* A calm "couldn't parse this" notice (the /passages unparsed-token list). NOT an
   alarm: a sunken surface with a quiet left rule, never brand/danger red near the
   reading column. The token list inside reads as plain content. */
.notice-warn { background: var(--surface-sunken); border-inline-start: 3px solid var(--text-secondary); }
.notice-warn ul { margin: 0.5rem 0 0; padding-inline-start: 1.25rem; }

/* --- Passage collection (/passages) --- a multi-reference reading surface. Each
   passage is its own section: a citation-link heading (same family as
   .reference-label / .search-hit-ref — never brand color near reading text), the
   reader-block scripture, and a quiet "study" hand-off to the canonical /v page. */
.passage-item { margin: var(--space-6) 0; padding-block-end: var(--space-5); border-block-end: 1px solid var(--pane-border); }
.passage-item:last-of-type { border-block-end: 0; }
.passage-item-head { margin: 0 0 var(--space-3); font-size: 1.1rem; }
.passage-item-head a { color: var(--cross-ref); font-family: var(--font-mono); }
.passage-item-study { margin-block-start: var(--space-3); font-size: 0.9rem; }
.passage-item-study a { color: var(--cross-ref); }
.error-stack { text-align: start; background: var(--surface-sunken); padding: 1rem; border-radius: var(--radius); overflow: auto; }

code { font-family: var(--font-mono); }

/* --- Ads --- */
/* THEME.md §6 / RD20: ads stay OUT of the reading column and reserve fixed slot
   dimensions so a load never shifts layout (CLS). The reader ad include sits
   AFTER the chapter text in reader.ejs, so on mobile it naturally falls below the
   first screenful of scripture. */
.ad-slot {
  display: block;
  margin: 1.25rem 0;
  min-height: 100px; /* reserve space to avoid layout shift */
}
.ad-unit { min-height: 100px; }
/* RD20 — the reader/mobile responsive ad can render taller than 100px; reserve a
   little more on narrow viewports so the post-load reflow stays negligible. */
@media (max-width: 760px) {
  .ad-slot { min-height: 250px; }
  .ad-unit { min-height: 250px; }
  .ad-placeholder { min-height: 250px; }
}
.ad-placeholder {
  min-height: 100px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.25rem;
  border: 1px dashed var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--text-secondary);
  text-align: center;
}
.ad-placeholder-label { font-weight: 600; }
.ad-placeholder-note { font-size: 0.8rem; }

/* --- Ad POSITION modifiers (docs/SPEC-ad-placement.md §2.1) ---
   Three positions: `top` and `mid` are Utility-zone only; `terminal` is the
   floor and the ONLY position the Reading and Analysis zones ever carry. These
   are NEW modifier classes — the shared `.ad-slot` rules above are deliberately
   left byte-untouched, so the unchanged surfaces are their own scoping proof.
   Nothing here changes which unit is served; only rhythm and reserved height. */

/* TOP — structurally the CLS-hostile position: it sits above everything, so any
   post-load reflow moves the whole page down. Hence a short, hard reservation
   and Utility-zone confinement. */
.ad-slot--top { margin: 0 0 1.5rem; }

/* MID — one unit at a section seam inside main content. Generous symmetric
   space so it reads as a break between sections rather than as part of either. */
.ad-slot--mid { margin: 2rem 0; }

/* TERMINAL — after the last content block, before the pager/footer. */
.ad-slot--terminal { margin: 2rem 0 0; }

@media (max-width: 760px) {
  /* The top unit keeps the SHORT banner reservation on mobile, overriding the
     250px the block above gives every other slot. A 250px block sitting above
     the content would push the page's actual purpose below the fold, and on a
     short page it also drives the Better Ads density ratio (§3.1) — whose
     numerator counts only ads INSIDE main content — toward the 30% threshold.
     Same specificity as the rule it overrides, so this block must stay after it. */
  .ad-slot--top,
  .ad-slot--top .ad-unit,
  .ad-slot--top .ad-placeholder { min-height: 100px; }
}

/* --- Footer ---
   A wide three-column "fat footer" inside the raised surface, framed by a thin
   gold-bordered panel feel: a centered gold four-point star over gradient
   hairlines (mirroring the home .hero-rule), then a brand column, an EXPLORE
   nav, and a SOURCES & LICENSES column, closing on a full-width bottom bar. All
   token-driven (no hardcoded hex), theme-aware (dark/light/sepia), CSP-safe
   (icons are inline SVG with presentation attributes; no inline style). */
.site-footer {
  background: var(--surface-raised);
  border-top: 1px solid var(--pane-border);
  margin-top: 2rem;
  flex-shrink: 0;
}

/* Top divider: the centered gold star flanked by gradient hairlines, the exact
   .hero-rule idiom (gradient fading from transparent through --pane-border-soft
   into --accent-border). */
.footer-rule {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  max-width: 22rem;
  margin: 1.5rem auto 0;
}
.footer-rule::before,
.footer-rule::after {
  content: "";
  flex: 1 1 auto;
  block-size: 1px;
}
.footer-rule::before {
  background: linear-gradient(to right, transparent, var(--pane-border-soft) 35%, var(--accent-border));
}
.footer-rule::after {
  background: linear-gradient(to left, transparent, var(--pane-border-soft) 35%, var(--accent-border));
}
.footer-flourish {
  flex: 0 0 auto;
  inline-size: 0.85rem;
  block-size: 0.85rem;
  color: var(--brand);
}

/* FOUR peer columns: brand · Explore · Scripture Analysis · Sources & licenses.
   The two link columns take equal tracks (they carry the same row anatomy), the
   brand sits slightly wider than a link column for the logo lockup, and Sources
   keeps the widest track because it holds attribution PROSE, not one-line rows. */
.footer-inner {
  display: grid;
  grid-template-columns: 1.1fr 1fr 1fr 1.4fr;
  gap: 2rem;
  max-width: 76rem;
  margin: 0 auto;
  padding: 1.75rem 1.25rem 1.5rem;
}

/* Gold uppercase eyebrow heading with a short gold underline tick (the
   .lex-source-head / .about-head idiom). Real <h2> for landmark labelling. */
.footer-head {
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--brand);
  margin: 0 0 0.85rem;
  padding-block-end: 0.5rem;
  position: relative;
}
.footer-head::after {
  content: "";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 0;
  inline-size: 2.25rem;
  block-size: 2px;
  background: var(--brand);
}

/* --- Column 1: brand --- */
.footer-brand-col { display: flex; flex-direction: column; gap: 0.75rem; }
.footer-brand-lockup { display: flex; align-items: center; gap: 0.6rem; }
.footer-logo { display: block; flex: 0 0 auto; border-radius: 8px; inline-size: 4.5rem; block-size: 4.5rem; }
.footer-brand { font-weight: 700; margin: 0; font-size: 2rem; }
.footer-brand-rule {
  display: block;
  inline-size: 2.75rem;
  block-size: 2px;
  border-radius: 999px;
  background: var(--brand);
}
.footer-tagline {
  color: var(--text-secondary);
  margin: 0;
  font-size: 0.92rem;
  max-width: 22ch;
  line-height: 1.5;
}

/* Support CTA + funding-candor note, under the tagline in the brand column.
   Ported from the sibling app Lemma's footer as ANATOMY ONLY — none of its CSS
   and none of its class names came with it, because that footer is a different
   design system.

   NO NEW SHARED PRIMITIVE, and nothing here is a modifier of an existing one.
   Three new classes, all .footer-support*, consumed by one block in one column;
   every .footer-* rule above and below stays byte-untouched.

   NOT .btn AND NOT .btn-ghost. Both are gold FILLS, and this footer closes every
   Scripture Analysis page, where a solid-gold control under a contradictions
   argument reads as that page's verdict rendered in the verdict colour. (This
   used to add "— the same reasoning that keeps .patron-callout-btn off those two
   classes". That cross-reference is RETIRED: the owner ruling of 2026-08-13 put
   a solid gold fill on the patron callout's action, so it is no longer an
   example of the caution above. It still refuses .btn and .btn-ghost, but now
   for the shared-primitive reason alone. Nothing in that ruling reaches this
   control, whose treatment is unchanged.)

   What the control does take is the footer's OWN interaction idiom: a
   reading-ink label on a 35%-gold hairline at rest, lifting on hover/focus to
   the exact accent-soft fill + --brand label pair that .footer-links a:hover
   has always used one column over. So it introduces no gold semantics this
   footer was not already carrying on every Analysis page.

   NO FOCUS RULE HERE, deliberately. The global :focus-visible rule supplies a
   2px solid gold ring site-wide via --focus-ring; a second declaration here
   could only make this one control inconsistent with every other.

   min-block-size 44px is the tap target. inline-flex + centring grows the box
   around a 0.9rem label rather than padding it off its own baseline, and
   align-items: flex-start on the wrapper is what shrink-wraps the control:
   .footer-brand-col is a COLUMN flex container, so a stretched child would run
   the full width of the grid track. The wrapper also owns the gap between the
   control and its caption, so that pair reads as one unit instead of inheriting
   .footer-brand-col's larger 0.75rem column gap between them. */
.footer-support {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
}
.footer-support-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 44px;
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--accent-border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
  transition: color 120ms, background 120ms;
}
.footer-support-cta:hover,
.footer-support-cta:focus-visible {
  background: var(--accent-soft);
  color: var(--brand);
  text-decoration: none;
}
/* The candor line. Type treatment is .footer-honesty's verbatim (0.82rem / 1.5 /
   --text-faint) — this footer's established register for a line that qualifies
   rather than sells.

   25ch IS MEASURED, NOT COPIED FROM .footer-tagline. Reusing that rule's 22ch
   looks like it would line the column's two prose blocks up and does not: `ch`
   scales with font-size, so 22ch resolves to 204px on the 0.92rem tagline but
   only 182px here at 0.82rem. At 182px the ads-ON sentence breaks "ad-supported,"
   across two lines at its own hyphen and runs to three lines. 24ch (199px) is the
   first value that holds the word together; 25ch is that with enough slack left
   that a font swap to the system fallback cannot push it back over, and it lands
   the rendered text (194px) flush with the tagline's (191px) as a side effect
   rather than as the reason. Re-measure if either font-size moves.

   The cap binds at every width: the brand track is 264px at 1440, 211px at the
   narrowest 4-column width, and wider still at both folded steps. */
.footer-support-note {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text-faint);
  max-width: 25ch;
}

/* --- Column 2: EXPLORE nav --- one <a> per row, icon + label + chevron, with
   faint decorative hairline dividers between rows. */
.footer-explore { min-width: 0; }
.footer-links { list-style: none; margin: 0; padding: 0; }
.footer-links li + li { border-top: 1px solid var(--pane-border-soft); }
.footer-links a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.6rem 0.25rem;
  color: var(--text-primary);
  text-decoration: none;
  border-radius: 8px;
  transition: color 120ms, background 120ms;
}
.footer-links a:hover,
.footer-links a:focus-visible {
  color: var(--brand);
  text-decoration: none;
  background: var(--accent-soft);
}
/* The icon/label/chevron row primitives are SHARED by the Explore list and the
   Scripture Analysis column beside it, so the two read identically. Reuse them
   from a new column; never redefine them for one. (The .footer-link-icon here is
   gold chrome; on a soon row it sits on the inert <span> as harmless decoration —
   only the chevron, reserved for live rows, implies navigability.) */
.footer-link-icon {
  flex: 0 0 auto;
  color: var(--brand);
}
.footer-link-label {
  flex: 1 1 auto;
  font-family: var(--font-ui);
  font-size: 0.95rem;
}
.footer-link-chevron {
  flex: 0 0 auto;
  color: var(--text-faint);
  transition: transform 140ms ease, color 120ms;
}
.footer-links a:hover .footer-link-chevron,
.footer-links a:focus-visible .footer-link-chevron,
.footer-analysis-links li a:hover .footer-link-chevron,
.footer-analysis-links li a:focus-visible .footer-link-chevron,
.footer-analysis-all li a:hover .footer-link-chevron,
.footer-analysis-all li a:focus-visible .footer-link-chevron {
  color: var(--brand);
  transform: translateX(2px);
}

/* --- Column 3: SCRIPTURE ANALYSIS nav --- a PEER column beside Explore, not a
   sub-group inside it. It is labelled by the shared .footer-head <h2> eyebrow
   (the same gold uppercase + underline tick Explore and Sources carry), so this
   family needs no heading rule of its own: the former .footer-subhead / ::after
   pair was retired when the <h3> was promoted, and nothing else in the codebase
   referenced it. Gold stays chrome-only — a structural eyebrow LABEL is chrome,
   the section NAMES in the list below stay reading ink, only an actual link goes
   gold on hover/focus, and the .badge keeps its own recessive treatment.
   min-width: 0 mirrors .footer-explore / .footer-sources so a long section name
   can shrink inside its grid track instead of forcing the track wider. */
.footer-analysis { min-width: 0; }
.footer-analysis-links,
.footer-analysis-all { list-style: none; margin: 0; padding: 0; }
/* Hairline dividers between rows, matching .footer-links li + li. The "All
   Scripture Analysis" hub row (.footer-analysis-all) sits flush under the
   per-section list as a continuation, so it gets the same top hairline. */
.footer-analysis-links li + li,
.footer-analysis-all li { border-top: 1px solid var(--pane-border-soft); }
/* Lay each row out like an Explore row: a leading gold icon, the label (which
   grows to fill so the trailing chevron|badge sits flush at the inline-end), and
   that trailing element. The 0.6rem block padding keeps the ~44px row height the
   block layout had (the flex switch does not shrink it). The hub "see them all"
   row (.footer-analysis-all) reuses this row layout verbatim. */
.footer-analysis-links li a,
.footer-analysis-links li .is-coming-soon,
.footer-analysis-all li a {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  padding: 0.6rem 0.25rem;
  border-radius: 8px;
  font-family: var(--font-ui);
  font-size: 0.95rem;
  text-decoration: none;
}
.footer-analysis-links li a,
.footer-analysis-all li a { color: var(--text-primary); }
/* GOLD ONLY on the live link's hover/focus (matches .footer-links a:hover). */
.footer-analysis-links li a:hover,
.footer-analysis-links li a:focus-visible,
.footer-analysis-all li a:hover,
.footer-analysis-all li a:focus-visible {
  color: var(--brand);
  text-decoration: none;
  background: var(--accent-soft);
}
/* Inert "soon" rows: a non-link <span aria-disabled>, recessive and not
   interactive. Name stays reading-adjacent (--text-secondary, NOT gold); the
   .badge keeps its existing recessive treatment. */
.footer-analysis-links li .is-coming-soon {
  color: var(--text-secondary);
  cursor: default;
}

/* --- Column 4: SOURCES & LICENSES --- */
.footer-sources { min-width: 0; }
.footer-source-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.85rem; }
.footer-source-item {
  display: flex;
  gap: 0.65rem;
  align-items: flex-start;
}
.footer-source-icon {
  flex: 0 0 auto;
  color: var(--brand);
  margin-block-start: 0.1rem;
}
/* Attribution / license prose: no dimmer than --text-faint (AA on navy).
   min-width: 0 overrides the flex item's default min-width: auto so the
   paragraph can shrink below its min-content width; overflow-wrap: anywhere
   then breaks long unbreakable tokens (raw URLs in license strings) rather
   than forcing the row — and the whole page — wider than the viewport. */
.footer-source-text {
  margin: 0;
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--text-faint);
  min-width: 0;
  overflow-wrap: anywhere;
}
.footer-source-text a { color: var(--brand); }
/* MULTI-PARAGRAPH source item. The base .footer-source-item is a flex ROW — correct
   for the one-icon/one-paragraph items, but the commentary credit emits the PD summary
   plus one verbatim notice per CC BY-SA voice, and three sibling paragraphs in a flex
   row become three side-by-side sub-columns that break mid-word. A two-track grid keeps
   the icon in its own column and stacks every paragraph in the second. Scoped to a NEW
   modifier: .footer-source-item and .footer-source-text stay byte-untouched, so the
   single-paragraph items render exactly as before. Declared AFTER .footer-source-text
   deliberately — a modifier belongs below its base rule, and test/footer-source-overflow
   .test.js extracts that base rule by first-match on the selector, so a child selector
   naming it above the rule would shadow what the #113 assertions read. */
.footer-source-item--stack {
  display: grid;
  grid-template-columns: auto 1fr;
  row-gap: 0.5rem;
}
.footer-source-item--stack > .footer-source-text { grid-column: 2; }
/* P1-1 — honesty micro-note: recessive but legible (--text-faint). */
.footer-honesty {
  margin: 1rem 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--text-faint);
}

/* --- Bottom bar --- full-width, above a hairline, centered. */
.footer-bottom { border-top: 1px solid var(--pane-border-soft); }
.footer-bottom-inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.4rem 1.25rem;
  max-width: 76rem;
  margin: 0 auto;
  padding: 1rem 1.25rem;
}
.footer-copy {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.footer-shield { flex: 0 0 auto; color: var(--brand); }
.footer-report { margin: 0; font-size: 0.85rem; }
.footer-report a { color: var(--text-faint); }
.footer-report a:hover,
.footer-report a:focus-visible { color: var(--brand); }

/* INTERMEDIATE STEP: 4 -> 2 -> 1, never 4 -> 1. Four tracks still FIT at 1024px —
   measured headfully at 217/197/197/276 with zero horizontal overflow — but the two
   link columns are already down to ~197px there and multi-word names ("Messianic
   Prophecies", "All Scripture Analysis") wrap to two lines. Below that the squeeze
   only worsens, so the grid folds to a 2x2 first: brand | Explore over Scripture
   Analysis | Sources & licenses, in source order.

   The lower bound is NOT decoration. This block and the 760px block below it have
   equal specificity, so a bare `max-width: 1000px` here would depend on staying
   ABOVE that block in source order to avoid re-applying two columns on a phone.
   Pinning the range makes the two steps disjoint and order-independent. */
@media (min-width: 761px) and (max-width: 1000px) {
  .footer-inner {
    grid-template-columns: 1fr 1fr;
    gap: 1.75rem 2rem;
  }
}

/* Stack all four columns on narrow screens (matches the responsive-nav
   breakpoint). The star rule + bottom bar stay full-width and centered. */
@media (max-width: 760px) {
  .footer-inner {
    grid-template-columns: 1fr;
    gap: 1.75rem;
    padding-block: 1.5rem;
  }
  .footer-bottom-inner { flex-direction: column; }
}

/* --- Responsive nav --- */
@media (max-width: 760px) {
  .nav-toggle { display: block; }
  .primary-nav {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0.5rem;
    padding-top: 0.5rem;
  }
  .primary-nav.open { display: flex; }
  .nav-list { flex-direction: column; align-items: stretch; }
  .nav-list-end { margin-inline-start: 0; }
  .nav-dropdown-menu { position: static; box-shadow: none; }
}

/* --- R6: Continue reading card --- */
.continue-reading { margin: 1.25rem 0; }
/* Gold uppercase letter-spaced eyebrow that IS the real <h2> — the heading text
   itself is uppercased/letter-spaced here (NOT a decorative span). Mirrors the
   "section eyebrow" idiom (Lemma §5.12 / theming guidelines §3.3). Theme-aware
   via --brand (the AA-safe gold-ink on light/sepia); no hardcoded hex. */
.continue-reading-heading {
  margin: 0 0 0.55rem;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--brand);
}
/* The richer lockup: a circular book icon (thin gold ring) · the chapter ref in
   the large reading serif · a faint divider · the cue · a chevron at the far
   right. The WHOLE card stays one <a>; the icon/divider/cue/chevron are all
   decorative (aria-hidden in the markup) so the link's accessible name is just
   the ref. */
.continue-reading-card {
  display: flex;
  align-items: center;
  gap: 0.85rem;
  padding: 0.9rem 1.1rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: 14px;
  background: var(--surface-raised);
  text-decoration: none;
  color: var(--text-primary);
  transition: border-color 120ms, background 120ms;
}
/* Hover-lift card (Lemma §5.3): a subtle one-step lift to a gold-tinted edge. */
.continue-reading-card:hover { text-decoration: none; border-color: var(--accent-border); }
.continue-reading-card:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
/* Circular gold-ring book icon (the signature icon badge, Lemma §5.4). */
.continue-reading-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  inline-size: 2.5rem;
  block-size: 2.5rem;
  border-radius: 999px;
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  color: var(--brand);
}
.continue-reading-glyph { display: block; }
/* The chapter ref in the large reading serif (it is "content", not chrome). */
.continue-reading-ref {
  font-family: var(--font-reading);
  font-weight: 700;
  font-size: 1.35rem;
  line-height: 1.1;
  color: var(--text-primary);
}
/* Faint vertical divider between the ref and the cue (hidden when wrapped tight). */
.continue-reading-divider {
  flex: 0 0 auto;
  inline-size: 1px;
  block-size: 1.5rem;
  background: var(--pane-border);
}
.continue-reading-cue {
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 0.9rem;
}
/* Chevron pinned to the far right (decorative affordance, slides slightly on
   hover). margin-inline-start:auto pushes it to the end. */
.continue-reading-chevron {
  display: block;
  flex: 0 0 auto;
  margin-inline-start: auto;
  color: var(--brand);
  transition: transform 120ms ease;
}
.continue-reading-card:hover .continue-reading-chevron,
.continue-reading-card:focus-visible .continue-reading-chevron {
  transform: translateX(2px);
}
/* On narrow widths the divider + cue drop so the lockup stays a clean
   icon · ref · chevron row; nothing is lost (the cue is decorative). */
@media (max-width: 30rem) {
  .continue-reading-divider,
  .continue-reading-cue { display: none; }
}

/* RD12 — device-local recents trail. Rendered by app.js from localStorage; hidden
   for no-JS users (the server continue card is their baseline). Quiet chrome — no
   brand red; the chips read as recessive navigation, not reading surface. */
.recents { margin-block-start: 0.9rem; }
/* Smaller gold eyebrow; the "(on this device)" disclosure rides in the eyebrow
   itself (.recents-note), not only a tooltip. */
.recents-label {
  margin: 0 0 0.5rem;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brand);
}
.recents-note {
  font-size: 0.92em;
  font-weight: 600;
  color: var(--text-secondary);
}
.recents-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
/* Pill chips (Lemma §5.2). */
.recents-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.25rem;
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  text-decoration: none;
  transition: color 120ms, border-color 120ms, background 120ms;
}
.recents-link:hover,
.recents-link:focus-visible {
  color: var(--brand);
  border-color: var(--accent-border);
  background: var(--accent-soft);
  text-decoration: none;
}

/* P2-8 — device-local "Saved passages" homepage section. A sibling to "Recently
   read"; rendered hidden + filled by app.js (initSavedTrail) from the gb_saved
   localStorage list. Reuses the recents chip idiom (quiet pills, no brand red in the
   reading surface). The device-local microcopy is the honesty contract. */
.saved-passages { margin-block-start: var(--space-5); }
.saved-passages-heading {
  margin: 0 0 0.35rem;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--brand);
}
.saved-passages-note {
  font-size: 0.92em;
  font-weight: 600;
  color: var(--text-secondary);
}
.saved-passages-scope {
  margin: 0 0 0.6rem;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-secondary);
}
.saved-passages-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
}
.saved-passages-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 2.25rem;
  padding: 0.4rem 0.85rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  text-decoration: none;
  transition: color 120ms, border-color 120ms, background 120ms;
}
.saved-passages-link:hover,
.saved-passages-link:focus-visible {
  color: var(--brand);
  border-color: var(--accent-border);
  background: var(--accent-soft);
  text-decoration: none;
}

/* --- R6: Book/chapter picker --- */
.book-picker-testament { font-size: 1rem; margin: 1rem 0 0.5rem; }
.book-picker-list { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.4rem; }
.book-picker-details {
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
.book-picker-summary {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 0.75rem;
  padding: 0.6rem 0.85rem;
  cursor: pointer;
}
/* F1: the book name is now a real link (no-JS → chapter 1) but reads as a title,
   not a brand-red link, so it inherits the primary text color in this index. */
.book-picker-name { font-weight: 600; color: var(--text-primary); text-decoration: none; }
.book-picker-name:hover,
.book-picker-name:focus-visible { text-decoration: underline; }
.book-picker-count { font-size: 0.85rem; }
.chapter-grid {
  list-style: none;
  margin: 0;
  padding: 0.6rem 0.85rem 0.85rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(2.5rem, 1fr));
  gap: 0.35rem;
  border-top: 1px solid var(--pane-border);
}
.chapter-link {
  display: block;
  text-align: center;
  padding: 0.4rem 0;
  border: 1px solid var(--pane-border);
  border-radius: 6px;
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 0.9rem;
  text-decoration: none;
}
.chapter-link:hover { background: var(--surface-sunken); text-decoration: none; }

/* --- R7: Search filters --- */
.search-filters {
  margin: 0.75rem 0 1rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
.search-filters > summary {
  cursor: pointer;
  padding: 0.5rem 0.85rem;
  font-weight: 600;
}
.search-filters-body {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  gap: 0.85rem;
  padding: 0.25rem 0.85rem 0.85rem;
}
.search-filter-field { display: flex; flex-direction: column; gap: 0.25rem; }
.search-filter-field label { font-size: 0.85rem; color: var(--text-secondary); }
.search-filters select {
  padding: 0.4rem 0.5rem;
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--text-primary);
}
.search-filter-check { flex-direction: row; align-items: center; gap: 0.4rem; }
.search-hit-more { margin-inline-start: 0.75rem; font-size: 0.85rem; }

/* --- R1: Reusable verse popover (overlay chrome — brand accents allowed) --- */
.verse { position: relative; }
/* DESKTOP: a FLOATING overlay anchored to the activated verse. It is inserted
   in-flow right after the verse's block (so source/tab/reading order is intact
   for AT) but positioned absolute so opening it does NOT reflow the chapter — the
   old in-flow `display:block; margin:0.5rem 0` split the reading column apart
   "in the middle of the chapter". Coordinates are computed by app.js open() from
   the trigger's rect, relative to the .scripture positioned ancestor; the
   box-shadow keeps it reading as a raised floating layer. z-index sits ABOVE the
   reading column (max z-index 1 inside .reader-main) but BELOW the sticky
   .reader-toolbar (40) and .site-header (50) so a scrolled-open popover never
   covers the chrome bars. The mobile @media (max-width:640px) block LATER in
   source re-pins this to position:fixed (bottom sheet), so the mobile sheet owns
   its own placement and this desktop rule must not fight it. */
.verse-popover {
  position: absolute;
  top: 0;
  inset-inline-start: 0;
  z-index: 35;
  padding: 0.5rem;
  width: max-content;
  max-width: 24rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  font-family: var(--font-ui);
  font-size: 0.95rem;
}
.verse-popover:focus { outline: var(--focus-ring); outline-offset: 2px; }
.verse-popover-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 0.5rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--pane-border);
}
.verse-popover-ref { font-family: var(--font-mono); font-weight: 600; }
.verse-popover-close {
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
  padding: 0 0.25rem;
}
.verse-popover-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  padding-top: 0.5rem;
}
.verse-popover-action {
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  background: var(--surface);
  color: var(--brand);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  padding: 0.5rem 0.7rem;
  min-block-size: 2.75rem;         /* 44px touch target (RD20/WCAG 2.2) — matches the tabs/chips */
  cursor: pointer;
}
.verse-popover-action:hover { background: var(--surface-sunken); }
/* Pass-4 extension area: empty in Pass 1, only spaced when populated. */
.verse-popover-content:not(:empty) {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px solid var(--pane-border);
}

/* RD14 — study drawer tab strip. A real tablist with a brand-underline active
   indicator (chrome — allowed in the overlay, THEME.md §0; the reading column
   never gains brand red). The strip scrolls horizontally if it overflows on a
   narrow sheet rather than wrapping into a tall block. */
.verse-popover-tabs {
  display: flex;
  gap: 0.15rem;
  margin: 0 0 0.5rem;
  border-block-end: 1px solid var(--pane-border);
  /* Recessive scrollbar (thin + ::-webkit-* thumb) comes from the shared
     verse-popover scroll-surface recipe up top, alongside the picker panels. */
  overflow-x: auto;
  /* overflow-x:auto forces overflow-y to compute to auto; pin it hidden so the tabs'
     min-height + -1px margin can't spawn a stray do-nothing vertical scrollbar. */
  overflow-y: hidden;
}
.verse-popover-tab {
  flex: 0 0 auto;
  border: 0;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-weight: 600;
  padding: 0.5rem 0.6rem;
  /* Reserve the underline thickness so activating a tab causes no shift (CLS). */
  border-block-end: 2px solid transparent;
  margin-block-end: -1px;
  cursor: pointer;
  white-space: nowrap;
  min-block-size: 2.75rem;       /* tap target ≥44px (RD20) */
}
.verse-popover-tab:hover { color: var(--text-primary); }
.verse-popover-tab.is-active {
  color: var(--text-primary);
  border-block-end-color: var(--brand);  /* active indicator — brand underline (chrome) */
}
.verse-popover-panel { /* one tab's content; only the active one is shown */ }
.verse-popover-status {
  margin: 0.4rem 0 0;
  min-height: 1.2em;
  font-size: 0.85rem;
  color: var(--note);
}

/* --- RD21: drawer-as-bottom-sheet on mobile ---
   On narrow viewports the anchored popover can clip or cover the verse being
   studied. Keyed off a media query (NOT a new markup pattern — SAME template,
   SAME focus-trap/Esc/outside-close logic in app.js), the popover becomes a
   bottom sheet pinned to the viewport's bottom edge, so the studied verse stays
   visible above it. It slides up via a keyframe; under prefers-reduced-motion the
   global reduced-motion rule neutralizes the animation so it simply appears
   (THEME.md §4). Overlay chrome — brand accents already allowed here. */
@media (max-width: 640px) {
  .verse-popover {
    position: fixed;
    /* Reset the desktop anchored-overlay coordinates so the sheet pins to the
       bottom edge and is not stretched full-height by the base `top:0`. The
       desktop JS does not set top/left on mobile (it is gated on the same 640px
       matchMedia), so the sheet is laid out purely by this CSS. */
    top: auto;
    inset-inline: 0;
    inset-block-end: 0;
    inline-size: auto;
    z-index: 60;
    max-width: none;
    margin: 0;
    padding: 0.85rem 1rem calc(1rem + env(safe-area-inset-bottom, 0px));
    border: 0;
    border-block-start: 1px solid var(--pane-border);
    border-start-start-radius: 14px;
    border-start-end-radius: 14px;
    border-end-start-radius: 0;
    border-end-end-radius: 0;
    box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.35);
    /* Keep the sheet from covering the whole screen so the verse stays visible. */
    max-block-size: 70vh;
    overflow-y: auto;
    animation: sheet-rise 0.18s ease-out 1;
  }
  /* A small grab-handle affordance so the sheet reads as a bottom sheet. */
  .verse-popover::before {
    content: "";
    display: block;
    inline-size: 2.25rem;
    block-size: 0.25rem;
    margin: 0 auto 0.6rem;
    border-radius: 999px;
    background: var(--pane-border);
  }
}
@keyframes sheet-rise {
  0% { transform: translateY(100%); }
  100% { transform: translateY(0); }
}

/* --- R2 / RD5: version chips (reader toolbar chrome) ---
   Chrome, not reading surface, so the active chip may carry a brand accent
   (THEME.md §0). The .version-switcher* wrapper from the old stacked header was
   removed in RD5; the chips now live in .reader-toolbar-versions. Logical
   properties throughout for RTL (THEME.md §5). Tap target ≥44px (RD20). */
.version-chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1;
  padding: 0.6rem 0.8rem;
  min-block-size: 2.75rem;            /* tap target ≥44px (RD20 a11y) */
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface);
  color: var(--text-primary);
  text-decoration: none;
}
.version-chip:hover { border-color: var(--brand); text-decoration: none; }
.version-chip.is-active {
  border-color: var(--brand);
  background: var(--brand-fill);
  color: var(--brand-on-fill);
  cursor: default;
}

/* --- RD8: Reading mode (distraction-free verse surface) ---
   Toggled by html[data-reading="immersive"] (stamped pre-paint server-side from
   the `reading` cookie; flipped live by app.js). All styling lives here in the
   stylesheet (CSP-safe). The reading column itself never gains brand red.

   Immersive mode:
     * hides the cross-ref count;
     * RECESSES verse numbers to visually-hidden (kept in the DOM so #vN
       deep-links/anchors still resolve — THEME.md §3 "hideable in reading mode";
       the verse number is also the popover opener, so this recesses it too);
     * widens vertical rhythm slightly;
     * drops the toolbar to a thin, quiet bar (and the footnotes apparatus
       stays available but the in-text markers recede).
   Study mode is the default state (no attribute) and keeps every affordance. */
html[data-reading="immersive"] .crossref-count { display: none; }
html[data-reading="immersive"] .analysis-cue { display: none; }
/* #109 — defensive belt: the onboarding tip host NEVER renders in immersive reading
   mode (the JS show-gate already excludes immersive, but a user can toggle immersive
   client-side without reload, so this CSS hide guarantees it stays gone). Mirrors the
   .crossref-count / .analysis-cue immersive hides above. */
html[data-reading="immersive"] .reader-tip-host { display: none; }

/* Verse numbers: visually hidden but PRESENT in the DOM, so #vN still scrolls
   and the popover/study fallbacks keep working. We reuse the .visually-hidden
   recipe rather than display:none (which would drop the anchor box). */
html[data-reading="immersive"] .verse-num {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0);
  white-space: nowrap; border: 0;
}

/* Slightly wider vertical rhythm for sustained reading. */
html[data-reading="immersive"] .scripture { line-height: 1.78; }
html[data-reading="immersive"] .verse-para { margin-block-end: 1.15rem; }

/* Recede the in-text footnote markers (kept, not removed — they remain links). */
html[data-reading="immersive"] .footnote-marker { opacity: 0.45; }

/* Drop the toolbar to a thin, quiet bar. It stays sticky + reserves height, so
   no CLS. On hover/focus-within it returns to full presence (auto-hide feel
   without removing access); reduced-motion users get an instant change (the
   global reduced-motion rule neutralizes the transition). */
html[data-reading="immersive"] .reader-toolbar {
  min-block-size: 0;
  border-block-end-color: transparent;
  opacity: 0.55;
  transition: opacity 0.15s ease;
}
html[data-reading="immersive"] .reader-toolbar-inner { min-block-size: 0; padding-block: 0.25rem; }
html[data-reading="immersive"] .reader-toolbar:hover,
html[data-reading="immersive"] .reader-toolbar:focus-within {
  opacity: 1;
  border-block-end-color: var(--pane-border);
}

/* --- R3: parallel / compare reading view ---
   Reading cells paint only with reading-surface tokens (THEME.md §0/§2): no
   brand red in verse text. The grid uses --compare-cols (set inline) for the
   column count; the first track is the shared verse-number gutter. */
/* Compare header sits below the shared toolbar (RD11): a quiet title + a back
   link, since the toolbar now carries the picker/More controls. */
.compare-header {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.5rem 0.75rem;
  margin-block: 0.25rem 0.5rem;
}
.compare-title { margin: 0; font-size: 1.4rem; }
.compare-subtitle { color: var(--text-secondary); font-weight: 400; font-size: 0.7em; }

/* RD16 — compare controls (the JS-revealed "highlight differences" toggle). */
.compare-controls { margin-block: 0.5rem 0; display: flex; justify-content: flex-end; }
.compare-diff-toggle {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  padding: 0.4rem 0.7rem;
  min-block-size: 2.25rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-secondary);
  cursor: pointer;
}
.compare-diff-toggle[aria-pressed="true"] {
  /* Pressed = differences shown. A quiet diff-token accent (not brand) signals
     the active state, paired with aria-pressed (not color alone). */
  color: var(--text-primary);
  border-color: var(--diff);
}
.compare-diff-toggle:hover { color: var(--text-primary); }

.compare-grid {
  display: grid;
  grid-template-columns: 2.5rem repeat(var(--compare-cols, 2), minmax(0, 1fr));
  margin: 1.25rem 0;
  border-block-start: 1px solid var(--pane-border);
}
.compare-head,
.compare-row {
  display: grid;
  grid-template-columns: subgrid;
  grid-column: 1 / -1;
}
/* Sticky version-label header row. */
.compare-head {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  background: var(--surface);
  border-block-end: 1px solid var(--pane-border);
}
.compare-col-head {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
  padding: 0.5rem 0.6rem;
  border-inline-start: 1px solid var(--pane-border);
}
.compare-head-gutter {
  font-family: var(--font-ui);
  font-size: 0.75rem;
  color: var(--text-secondary);
  padding: 0.5rem 0.4rem;
}
.compare-row {
  border-block-end: 1px solid var(--pane-border);
}
/* RD16 — subtle alternating row tint for scan-ability. --surface-sunken at a low
   alpha via color-mix so it reads as a faint band on any theme (dark/light/sepia)
   without a new token. Falls back to no tint on engines lacking color-mix (still
   perfectly readable — the borders separate rows). */
@supports (background: color-mix(in srgb, white 50%, black)) {
  .compare-row:nth-of-type(even) {
    background: color-mix(in srgb, var(--surface-sunken) 55%, transparent);
  }
}
/* The verse-number gutter sticks to the inline-start edge so it stays visible
   as columns are read across (logical property keeps it correct under RTL).
   Transparent background so the alternating row tint shows through; the sticky
   HEADER gutter keeps its opaque surface (set on .compare-head). */
.compare-gutter {
  padding: 0.6rem 0.4rem;
  background: transparent;
}
.compare-head-gutter { background: var(--surface); }
.compare-gutter .verse-num { vertical-align: baseline; }
.compare-cell {
  font-family: var(--font-reading);
  font-size: 19px;
  line-height: 1.65;
  color: var(--text-primary);
  padding: 0.6rem 0.6rem;
  border-inline-start: 1px solid var(--pane-border);
}
/* When a non-empty cell hosts the shared verse-copy control it also carries
   .verse-copy-ref-line, which turns the cell into a flex row so the icon-only Copy button
   floats to the cell's trailing edge (.verse-copy-inline margin-inline-start:auto — it wraps
   to its own line beneath the reading text, which is acceptable in a narrow column). This
   compound selector (higher specificity than the shared .verse-copy-ref-line center default)
   top-aligns the row so the wrapped reading text and — on mobile — the leading
   .compare-col-tag version pill stay at the cell start rather than floating to the vertical
   center of the multi-line text. */
.compare-cell.verse-copy-ref-line { align-items: flex-start; }
/* The per-cell version tag is only shown when columns are stacked on mobile;
   hidden in the multi-column grid where the header row labels each column.
   RD16 — refined as a small recessive mono pill so each stacked block self-labels
   clearly without competing with the verse text. */
.compare-col-tag {
  display: none;
  font-family: var(--font-mono);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  margin-inline-end: 0.5rem;
  padding: 0.05rem 0.4rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  vertical-align: 0.1em;
}
.compare-cell-empty { color: var(--text-secondary); }
/* Translation-diff slot (THEME.md §1): ochre + dotted underline, never color
   alone, never brand red. Marks cells that differ from the first column. */
.compare-cell-diff .verse-text {
  text-decoration: underline dotted var(--diff);
  text-underline-offset: 3px;
}
/* RD16 — when the reader toggles diff off (app.js adds .compare-hide-diff to the
   grid), suppress the visual mark; the server-computed diff data stays in the
   DOM, so toggling back is instant and the no-JS baseline is unaffected. */
.compare-grid.compare-hide-diff .compare-cell-diff .verse-text {
  text-decoration: none;
}

/* Mobile: stack the columns into per-version blocks, each labeled, keeping the
   verse number aligned at the block start (THEME.md §3 alignment). */
@media (max-width: 760px) {
  .compare-grid {
    display: block;
    border-block-start: none;
  }
  /* Hide the shared header row; each cell self-labels with its version tag. */
  .compare-head { display: none; }
  .compare-row {
    display: grid;
    grid-template-columns: 2.5rem 1fr;
    align-items: baseline;
    border: 1px solid var(--pane-border);
    border-radius: var(--radius);
    margin-block-end: 0.75rem;
    overflow: hidden;
  }
  .compare-gutter { grid-row: 1 / -1; }
  .compare-cell {
    border-inline-start: none;
    border-block-start: 1px solid var(--pane-border);
    padding-block: 0.5rem;
  }
  .compare-row .compare-cell:first-of-type { border-block-start: none; }
  .compare-col-tag { display: inline; }
}

/* --- R4: Cross-references ---
   THEME.md §1: cross-ref links are QUIET BLUE (--cross-ref) + hover underline,
   never brand red. The reader badge is recessive (--text-secondary) gutter
   chrome. Logical properties throughout for RTL (THEME.md §5). Motion is
   functional only; respect prefers-reduced-motion (handled globally). */

/* A1 (owner-decided) — in-reader cross-ref CUE. A hairline chain/link GLYPH +
   count — the study-Bible convention for "cross-reference here" — replacing the
   old bare number that readers mistook for a footnote marker or the next verse
   number. NOT brackets ([N] reads as a textual-critical variant marker). The
   glyph makes the cue unmistakably a cross-reference; the count rides beside it.
   It is the no-JS link to the study page (full cross-ref list) and JS also folds
   the count into the popover's Cross-references tab. Hidden in immersive reading
   mode (RD8). Recessive --text-secondary at rest; quiet-blue only on hover/focus
   (THEME.md §1 — never brand red). BREATHING ROOM: a larger leading gap (0.5em)
   separates the cue from the verse-number so "earth.🔗61" no
   longer reads as one cramped smudge. */
.crossref-count {
  display: inline-flex;
  align-items: center;
  gap: 0.12em;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  line-height: 1;
  color: var(--text-secondary);
  text-decoration: none;
  margin-inline-start: 0.5em;
  vertical-align: baseline;
  white-space: nowrap;
}
/* The chain glyph: a hairline currentColor stroke icon (inherits the link color,
   so it recesses at rest and brightens with the rest of the cue on hover/focus). */
.crossref-count-icon {
  inline-size: 0.85em;
  block-size: 0.85em;
  flex: 0 0 auto;
}
.crossref-count-num { line-height: 1; }
.crossref-count:hover,
.crossref-count:focus-visible { color: var(--cross-ref); text-decoration: none; }
.crossref-count:hover .crossref-count-num,
.crossref-count:focus-visible .crossref-count-num { text-decoration: underline; }

/* #108 — the in-reader ANALYSIS CUE: an ALWAYS-VISIBLE (opacity 1 at rest, no hover
   needed), recessive, GLYPH-ONLY open-book marker at the end of any verse a LIVE
   Scripture Analysis section cites. It mirrors .crossref-count's construction but
   carries NO count/numeral (the count is a contestedness signal, not neutral study
   volume — kept out of the cue entirely). A plain link to the verse's analysis dossier;
   the popover footer is the coexisting other door. Recessive --text-secondary at rest;
   quiet-blue --cross-ref only on hover/focus (THEME.md §1 — NEVER --brand/gold; this is
   reading-column text). Hidden in immersive reading mode (RD8).
   SEPARATION: a LARGER leading gap than .crossref-count (0.6em vs 0.5em) so the two
   trailing ~11px grey glyphs stay distinct and the numberless one never reads as the
   cross-ref cue's missing count. */
.analysis-cue {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  line-height: 1;
  color: var(--text-secondary);
  text-decoration: none;
  margin-inline-start: 0.6em;
  vertical-align: baseline;
  white-space: nowrap;
}
/* The open-book glyph: a hairline currentColor stroke icon (inherits the link color,
   so it recesses at rest and brightens on hover/focus alongside the cross-ref cue). */
.analysis-cue-icon {
  inline-size: 0.85em;
  block-size: 0.85em;
  flex: 0 0 auto;
}
.analysis-cue:hover,
.analysis-cue:focus-visible { color: var(--cross-ref); text-decoration: none; }

/* #110 — TOUCH-ONLY vertical hit-area growth for the two trailing in-reader cues
   (.crossref-count + .analysis-cue). At rest each cue is a ~11px-tall inline box
   (0.68rem text, line-height 1) — well under the WCAG 2.5.8 44px target — and on a
   phone the glyph-only .analysis-cue sits only ~2.4px horizontally from the next
   verse-number opener (.verse-num, the popover trigger), so a small or sideways-
   widened target invites mis-taps. We grow the CLICKABLE box VERTICALLY ONLY, with
   padding-block + an equal-magnitude negative margin-block, so the painted glyph,
   its baseline, the line layout, and the horizontal gap to .verse-num are all
   byte-for-byte unchanged (no added line height, no reflow/CLS). Mirrors the
   .reader-tip-dismiss grow-then-pull-back idiom.
   POINTER-FINE (desktop mouse) IS UNTOUCHED — this lives behind (pointer: coarse),
   so the existing hover/focus affordance and compact rest glyph stay exactly as is.
   NO inline padding/margin here: widening sideways would eat the ~2.4px gap to the
   next verse-number; the whole point is independent tappability without that.
   WHY 10px AND NOT A FULL 22px (→44px): the cues ride INSIDE the .scripture reading
   line box (19px / 1.65 = ~31.35px). A full-44px box needs a ~16.5px margin-block
   overrun per side, which spills into the wrapped lines ABOVE/BELOW and can reach
   THOSE lines' .verse-num openers — re-introducing the very mis-tap we're closing.
   10px caps the overrun at the cue's own line box (~10.88 + 2*10 ≈ 30.9px tall),
   the LARGEST value that keeps the three trailing targets (cross-ref cue, analysis
   cue, next verse-number) independently tappable. Vertical hit area ~11px → ~31px
   (a ~2.8x grow toward the 44px ideal) without any layout shift or horizontal gap loss.
   This is a deliberate PARTIAL satisfaction of WCAG 2.5.8 (~31px of the 44px minimum) —
   the line-box ceiling above caps it; a full 44px reading-column target would instead mean
   enlarging the primary .verse-num opener itself, tracked as a separate follow-up. */
@media (pointer: coarse) {
  .crossref-count,
  .analysis-cue {
    padding-block: 10px;
    margin-block: -10px; /* equal-magnitude pull-back: visual footprint + line layout unchanged */
  }

  /* #111 — TOUCH-ONLY vertical hit-area growth for the PRIMARY popover opener,
     .verse-num (the verse number <a> that opens the actions popover AND is the
     no-JS #vN anchor). This is the single most important reader tap target and the
     exact gesture the #109 onboarding tip teaches ("tap any verse number…"), yet
     #110 grew only the two SECONDARY trailing cues.
     MECHANISM (DIFFERS from #110): .verse-num is a DEFAULT inline <a> — the base rule
     (~L2511) sets no `display`, so it stays a non-replaced inline box. Per CSS2.1
     §10.8, vertical padding on a non-replaced inline box extends its background and
     hit/border region but does NOT change the line-box height (line-height governs
     that), so padding-block ALONE grows the tappable rectangle with no reflow/CLS —
     the painted glyph, its baseline, the line layout, and the rhythm are unchanged.
     So NO compensating negative margin-block is used here: per §8.3 a vertical margin
     on a non-replaced inline box has no layout effect — it would be INERT. (This is
     the key contrast with #110's cues, whose inline-FLEX box makes the equal-magnitude
     pull-back load-bearing; transplanting that idiom onto this inline box was wrong.)
     NO horizontal change: the existing padding-inline (0.1rem) and the ~2.4px gap to
     the trailing cues are untouched (widening sideways would eat that gap).
     WHY 7.5px (box ~30px) — the cap is the SMALLEST verse-num-to-verse-num vertical
     spacing across all layouts. That minimum is single-stich poetry (Job dialogue
     e.g. /v/job/3, Lamentations e.g. /v/lamentations/3), where every verse is ONE
     line so consecutive verse-numbers stack at a measured ~30.9px pitch. The hit box
     must not exceed that pitch or adjacent verse-number boxes overlap. Measured base
     box ≈ 15px, so 15 + 2*7.5 = ~30px clears the ~30.9px pitch with ~0.9px margin —
     provably no overlap — while staying as large as the constraint allows. (Prose
     ~62px and couplet-poetry ~59px pitches are far larger and never binding; only
     single-stich poetry is.) A deliberate PARTIAL satisfaction of WCAG 2.5.8 (~30px
     of the 44px minimum) — the single-stich pitch caps it, not a shortcut; a full
     44px target would mean restructuring the reading column, a separate follow-up.
     POINTER-FINE (desktop mouse) IS UNTOUCHED: this lives behind (pointer: coarse),
     so the hover/focus cue (quiet --cross-ref blue + underline + pointer cursor), the
     title tooltip, the #vN anchor, data-verse-open, and the immersive-mode rules all
     stay exactly as is. */
  .verse-num {
    padding-block: 7.5px;
  }

  /* #114 — TOUCH-ONLY vertical hit-area growth for the inline Scripture Analysis
     links, family-wide. A rendered audit found these tap targets sub-44px (WCAG
     2.5.8) on touch, identically across /science, /contradictions, AND /analysis/*
     because every analysis surface inherits these SHARED classes — so the fix lands
     here once and all three families get it. Four targets:
       .science-breadcrumb a      — the "Scripture Analysis"/section breadcrumb link
       .analysis-howto-link a      — the quiet hand-off cross-links: "About our approach →"
                                      / "How this is built →" on the /science and
                                      /contradictions LANDING pages, the cross-links on the
                                      /analysis hub, and the methodology-page links. On the
                                      two landing pages TWO of these stack ~12px apart, so
                                      this one is PITCH-CAPPED (see below), NOT full 44px.
       .science-passage-context    — the HERO "Read in context →" link (dossier hero
                                      AND the /science detail hero; same affordance)
       .analysis-entry-statement   — the stacked cited-entry statement links in the
                                      grouped "Also examined in" panels
     MECHANISM (same as #111, NOT #110): these are DEFAULT inline / block <a> elements
     with NO display override added here, so per CSS2.1 §10.8 padding-block ALONE grows
     the hit/background box; per §8.3 a vertical margin on the inline ones would be
     INERT, so NO negative margin-block is used (transplanting #110's inline-flex
     pull-back here would be dead code). VERTICAL ONLY — no padding-inline/margin-inline:
     the breadcrumb's two side-by-side links and the existing inter-link spacing must
     not shift, and growing sideways would eat those gaps. Touch-only: pointer-fine
     (desktop mouse) is byte-for-byte unchanged. Gold stays chrome-only (layout only —
     no link color touched).

     FULL 44px (isolated single lines, generous block space below — no pitch
     constraint): the breadcrumb sits alone above the hero with space-3 beneath, and the
     HERO .science-passage-context "Read in context →" link is an isolated affordance,
     always alone or far-apart (measured ~45px clear wherever it appears — dossier hero,
     science/contradictions detail). Measured base boxes (390px, coarse): breadcrumb
     17px, .science-passage-context 19px. padding-block 14px / 13px takes them to ~45px —
     at or past the 44px target, render-verified with no overlap.

     .analysis-howto-link a is a DELIBERATE PARTIAL (~31px, not full 44px): it is NOT
     always isolated. On the /science and /contradictions LANDING pages TWO of these
     quiet hand-off links STACK adjacently ("About our approach →" immediately above
     "How this is built →"), ~12px apart with a ~17.3px inner line-box gap. A full-44px
     box (padding-block 13px → ~45px) OVERLAPS the pair by ~8.7px — the very mis-tap the
     #110/#111 pitch caps avoid. The no-overlap ceiling is padding-block ≤ 8.6px; we use
     6px (→ ~31px box), clearing the ~17.3px line-box gap with ~5.3px comfortable
     clearance (render-verified, zero overlap, both landing pages). Same line-pitch idiom
     as #110/#111 and .analysis-entry-statement below: padding-block only; NO margin-block
     (inert on inline boxes per §8.3); NO horizontal axis. A full 44px here would need
     restructuring the stacked hand-off pair — a separate follow-up; the line pitch caps
     it, not a shortcut.

     .analysis-entry-statement is a DELIBERATE PARTIAL (~37px, not full 44px): it is a
     display:block link inside a flex-column <li> (statement over its meta line), and
     consecutive entries stack. The binding constraint is the inter-entry pitch — the
     statement's padded box must not collide with the NEXT entry's statement target.
     Measured base box 24.8px; the tightest rendered statement-to-statement clearance
     (statement.bottom → next statement.top) is ~35.6px across a fixed 3.19px flex gap
     to its own meta + a 12px inter-li gap. padding-block 6px grows the box to ~37px
     and reflows the rows apart, keeping a comfortable clearance to the next target
     (render-verified, zero overlap). A full 44px here would need restructuring the
     stacked-list rhythm — a separate follow-up; the row pitch caps it, not a shortcut. */
  .science-breadcrumb a {
    padding-block: 14px;
  }
  .science-passage-context {
    padding-block: 13px;
  }
  .analysis-howto-link a {
    /* PITCH-CAPPED at 6px (~31px box), NOT 13px: two of these stack ~12px apart on the
       /science + /contradictions landing pages (~17.3px line-box gap); 13px → ~45px would
       overlap by ~8.7px. 6px clears the gap with ~5.3px. See the #114 note above. */
    padding-block: 6px;
  }
  .analysis-entry-statement {
    padding-block: 6px;
  }

  /* 2026-06-30 dossier tap-target benchmark — TOUCH-ONLY vertical hit-area growth for
     three DOSSIER-ONLY tap targets a rendered audit found sub-44px (WCAG 2.5.8) on the
     per-verse Analysis dossier (/analysis/verse/<book>/<ch>/<v>). Same line-pitch mechanism as #111/
     #114: padding-block ALONE grows the hit/background box on these default inline/block
     <a>/<summary> elements (CSS2.1 §10.8); NO margin-block (inert on inline boxes per
     §8.3); NO horizontal axis; touch-only so pointer-fine is byte-for-byte unchanged.
     Unlike #114's pitch-capped targets, all three are ISOLATED on the dossier (no
     adjacent stacked twin), so each gets the FULL ~44px lift, not a capped partial.
       .analysis-entry-more > summary — the per-entry "More on this question" both-pole
         disclosure (base ~19px). padding-block 13px + min-block-size 44px → ~45px box.
         GLOBAL-SAFE: .analysis-entry-more renders ONLY under the enrichEntries gate, which
         ONLY the dossier passes (analysis-area-groups.ejs), so no other surface sees this
         rule. NO `display` change — display:flex on a <summary> suppresses the UA
         disclosure triangle in Chrome/Safari; padding-block alone preserves it.
       .analysis-dossier-method a — the inline "How this is built →" methodology link. Its
         <p> carries .analysis-hub-mission.analysis-dossier-method but NOT .analysis-howto-
         link, so the #114 6px pitch-cap does NOT reach it; isolated → full 13px (~44px).
       .analysis-dossier-context .analysis-dossier-context-link — the "Continue reading →"
         tail exit. Its <p> DOES carry .analysis-howto-link, whose #114 rule pitch-caps the
         link at 6px for the stacked landing-page pair — but on the dossier this link is
         isolated, so it earns the full 44px. The two-class selector (0,2,0) outranks
         .analysis-howto-link a (0,1,1) and wins WITHOUT touching that 6px landing rule. */
  .analysis-entry-more > summary {
    padding-block: 13px;
    min-block-size: 44px;
  }
  .analysis-dossier-method a {
    padding-block: 13px;
  }
  .analysis-dossier-context .analysis-dossier-context-link {
    padding-block: 13px;
  }

  /* search-results-redesign §3.7 — TOUCH-ONLY vertical hit-area growth for two undersized
     /bible/search tap targets a rendered audit found sub-44px (WCAG 2.5.8): the precise
     card's per-hit action row (.search-hit-action, ~23px) and the rail per-book facet rows
     (.bible-search-facet-item a, ~37px). Behind (pointer: coarse) so the desktop
     mouse/hover experience is UNTOUCHED. Both classes are search-page-only (grep-confirmed
     in §3.7) — a direct edit, no shared-class risk, no modifier. The two targets need
     DIFFERENT mechanisms because their base padding + neighbor spacing differ:
       .search-hit-action — the #110 .crossref-count/.analysis-cue idiom: padding-block +
         an equal-magnitude negative margin-block pull-back (valid HERE because the base has
         ~0 vertical padding). 10px → ~43px. The action row is the LAST element in a card and
         a single non-wrapping line at real widths, so the vertical overflow spills only into
         inert snippet/note text above and the inter-card gap below — no adjacent TAP target.
       .bible-search-facet-item a — the negative-margin idiom is WRONG here: the base already
         carries 0.35rem (~5.6px) block padding, so a `padding-block` longhand would REPLACE
         (shrink) it, and a negative margin-block would overpull past the list's tight
         0.15rem (2.4px) gap and overlap adjacent hit-boxes. The link is a block-level flex
         item in a flex COLUMN, so `min-block-size: 44px` grows it cleanly to the WCAG target
         with no overlap and no reflow (the list simply seats each row at ≥44px), leaving the
         base padding intact. */
  .search-hit-action {
    padding-block: 10px;
    margin-block: -10px; /* equal-magnitude pull-back: visual footprint + line layout unchanged */
  }
  .bible-search-facet-item a {
    /* border-box is global (* { box-sizing: border-box }), so 44px is the full box. */
    min-block-size: 44px;
  }
}

/* Per-verse + range study page. Reading-surface discipline: the verse text uses
   reading tokens; only the cross-ref links carry the quiet-blue accent. STUDY-PARITY
   PASS — BOTH the single-verse page AND the verse-range page now carry .study-page on
   <main> (range previously used .reader; it now shares the verse page's study chrome).
   The standalone .study-header (its <h1> + the muted framing line) was removed from
   BOTH modes — the page <h1> moved INTO the .study-card as the gold eyebrow heading —
   so the former .study-header / .study-back / `.study-page .study-header h1` rules are
   gone with it. */
.study-page { max-width: var(--measure); }
.study-verse { margin-block-end: 1.5rem; }

/* The single focused verse, set in the reading serif at a generous display scale
   (the mockup's large serif verse). Only .study-verse (verse mode) is targeted;
   range mode's .scripture text inside the same .study-card keeps the reader's NORMAL
   reading size (a multi-verse passage is not ballooned to the hero serif). */
.study-verse .verse-text {
  font-family: var(--font-reading);
  font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.6rem);
  line-height: 1.55;
}
/* Keep the small static verse-number marker proportional to the enlarged text. */
.study-verse .verse-num-static { font-size: 0.6em; }
/* Static (non-link) verse number on the study page — the verse is the page
   subject, so the number is a marker, not a navigation anchor. */
.verse-num-static {
  font-family: var(--font-mono);
  font-size: 0.75em;
  font-weight: 600;
  color: var(--text-secondary);
  vertical-align: super;
  margin-inline-end: 0.3rem;
}

/* Passage view — context dimming. The surrounding paragraph/strophe verses that
   frame a requested range (e.g. John 3:16-18 shown inside its paragraph) recede
   to the most-recessive reading TEXT token so the requested verses are the clear
   focus, WITHOUT lowering the requested verses' .scripture color. De-emphasis is
   a token swap only — no brand color in the reading column (THEME.md §0). The
   token is --text-faint, the same recessive text family as .muted/.version-note
   (which use --text-secondary), one step quieter. THEME.md §2/§7 require the
   reading surface to clear WCAG AA (≥4.5:1) in every theme; --text-faint measures
   on the reading ground --surface: dark 6.67:1, light 5.63:1, sepia 5.63:1 — all
   AA, so dimmed context stays legible while reading as clearly secondary. The
   verse number inside a context verse follows the same token. */
.verse-context .verse-text,
.verse-context.verse-poetry .verse-text { color: var(--text-faint); }
.verse-context .verse-num-static { color: var(--text-faint); }

/* ============================================================================
   P0-2 — TWO-COLUMN STUDY LAYOUT (single-verse study page only)
   ----------------------------------------------------------------------------
   A CSS-grid reorganization of the SAME server-rendered apparatus — no new data
   flow, no client re-fetch (the no-JS/SEO baseline holds). UNIFIED LAYOUT PASS:
   source order is reading order in BOTH verse and range mode — the reading card
   (verse text / passage) -> Parallel -> Cross-refs -> Explain (column 1, .study-main)
   -> Share -> Notes (column 2, .study-rail). Below the breakpoint there is NO grid,
   so the children flow in that single-column source order (= correct stacked +
   screen-reader order). At the breakpoint, CSS assigns the left wrapper (.study-main)
   to column 1 and the single .study-rail wrapper to column 2; the rail cards stack
   INSIDE .study-rail (flex) so the grid is a clean 2-cell layout.

   THEME.md discipline: the reading column wins every layout tie — two columns
   appear ONLY when there is room for a >=60ch reading measure PLUS the rail, and
   the reading measure is never shrunk below 60ch to fit the rail. Logical
   properties throughout (RTL-ready, THEME.md §5). No position:sticky rail (no
   competing motion on a reading surface; never sticky on mobile). All colors are
   tokens; the reading column paints surface/text tokens only.
   ============================================================================ */

/* Single-column baseline: the grid is just a vertical flow (no columns) so the
   page is correct with no media query and on narrow viewports. */
.study-grid {
  display: grid;
  gap: var(--space-5);
  /* The study card holds the reading measure; the rail cards inherit it here. */
}
.study-grid > * { min-width: 0; } /* let long words wrap inside grid items */

/* Item 3 (this UX pass) — the VERSE-MODE column-1 wrapper. It stacks the verse
   .study-card and the split-out Explain panel as ONE grid cell so .study-grid's
   direct children stay exactly .study-main | .study-rail (the former full-width
   .study-lemma tail was removed — LEMMA-ON-CARD PASS — so verse mode matches range; the
   Explain panel can never auto-flow below the tall rail — the layout invariant).
   A flex column with the same inter-panel gap as the rail. In the single-column
   baseline it is capped at the reading measure + the card's own padding so the
   reading text inside the card still hits the ~66ch measure; the two-column rule
   keeps that cap. The reading column wins (THEME.md). */
.study-main {
  --study-card-pad: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: calc(var(--measure) + 2 * var(--study-card-pad));
}
/* The reading card + the column-1 panels fill the .study-main width (the cap lives on
   .study-main now, not on each panel) so they align as a stacked stack. UNIFIED LAYOUT
   PASS: Parallel, Cross-references AND Explain all carry .study-explain-panel as the
   column-1 reading-panel marker, so this single selector covers all three. */
.study-main > .study-card,
.study-main > .study-explain-panel { max-width: none; }

/* Item 6 (this UX pass) — the VERSE-MODE left CARD. One bordered, raised panel that
   reads as a single unit (mockup's left column): the action toolbar, the reference
   EYEBROW (the page <h1>), the verse HERO, and the version line live inside it. The
   Explain/commentary is now its OWN panel BELOW this card (item 3), not inside it.
   The card's PADDING is added on top of the reading measure (the column max-width is
   widened by 2× the pad in the two-column rule), so the verse text inside the card
   still reaches the full ~66ch measure and never drops below 60ch — the reading
   measure wins (THEME.md). Token border + surface only; NO brand color touches the
   verse text. The card stacks its children with a calm internal rhythm. In the
   single-column baseline the card is capped at the reading measure + its own padding
   so the text column inside still hits the measure. */
.study-card {
  --study-card-pad: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  padding: var(--study-card-pad);
  /* Restyle P1 (STUDY-PANEL-STYLE A2) — match the rail's SOFT border for family
     coherence, and lean on elevation for the lift. The reading card stays the MOST
     present surface (the reading column wins): it layers var(--shadow) twice so its
     lift is strictly stronger than the rail's single var(--shadow) — token-only, no
     hardcoded color — so the rail can never out-shout the reading card. */
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow), var(--shadow);
  max-width: calc(var(--measure) + 2 * var(--study-card-pad));
}
/* The card owns the internal spacing via its flex `gap`; neutralize the legacy block
   margins the .version-note brings so it sits flush in the card rhythm. (Explain is
   no longer a child of .study-card — item 3 split it into its own panel below.) */
.study-card > .version-note { margin-block: 0; }

/* STUDY-PARITY PASS — RANGE-mode reading card. Range reuses the verse .study-card shell
   but keeps the reader's NORMAL reading typography: the requested verses render inside a
   <figure class="study-verse-translation"> wrapping a .scripture article (NOT the
   single-verse hero serif — a multi-verse passage is not ballooned), and the escape
   hatch is a .notice directly under it. Both bring legacy block margins that would
   double up with the card's flex `gap`; neutralize them so the card rhythm is the flex
   gap alone (matching how .version-note was neutralized above). The figure itself is
   already margin:0 (.study-verse-translation, defined later); here we zero the .scripture
   article inside it and the escape-hatch .notice that sit in the card's flex flow. The
   figure's caption (.study-verse-attr) and the dimming/poetry of the verses are
   unaffected — this is a spacing-only rule. Logical block margins (RTL-safe). */
.study-card > .study-verse-translation > .scripture { margin-block: 0; }
.study-card > .notice { margin-block: 0; }

/* PASSAGE-STUDY REDESIGN (Option C) — THE SURROUNDING-PARAGRAPH DISCLOSURE.
   A native <details> that sits in the .study-card flex flow (between the verse figure
   and the escape hatch) on a PARTIAL range. It is tier TWO of the three-tier honesty
   ladder: the main figure serves exactly the requested verses; THIS reveals the whole
   surrounding paragraph/strophe (the context that used to ride along DIMMED in the main
   panel); the escape hatch opens the whole chapter. It is reused-chrome, not a novel
   widget: the summary follows the .commentary-more / .crossref-more disclosure recipe
   (recessive at rest, a chevron affordance, gold only on hover/focus — gold is CHROME
   ONLY). The card owns spacing via its flex `gap`, so the <details> default margins are
   zeroed like the siblings above. */
.study-card > .study-context { margin-block: 0; }

/* The summary is the affordance. It is a real ≥44px touch target (min-height + block
   padding) so a finger can hit it; the label is UI type, recessive (--text-secondary)
   at rest and gold (--brand, chrome) on hover/focus. We suppress the native disclosure
   triangle (the inline chevron SVG below is our marker) across engines. */
.study-context > summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 44px;
  padding-block: var(--space-2);
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--text-secondary);
  cursor: pointer;
  list-style: none; /* Firefox: hide the default marker */
}
.study-context > summary::-webkit-details-marker { display: none; } /* Safari/Chrome */
.study-context > summary:hover,
.study-context > summary:focus-visible { color: var(--brand); }
.study-context > summary:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
  border-radius: var(--radius);
}

/* The chevron is recessive at rest, gold (chrome) on summary hover/focus, and rotates
   90° when the <details> is [open]. The rotation is purely decorative chrome; it is
   guarded by prefers-reduced-motion below so a motion-averse reader gets the state with
   no transition. */
.study-context-chevron {
  flex: none;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}
.study-context > summary:hover .study-context-chevron,
.study-context > summary:focus-visible .study-context-chevron { color: var(--brand); }
.study-context[open] > summary .study-context-chevron { transform: rotate(90deg); }
.study-context-summary-label { font-family: var(--font-ui); }

/* The short framing line inside the OPEN disclosure — a calm caption (NOT gold), naming
   what the reader is now seeing. The surrounding-paragraph text below it is reading
   content: it reuses the .scripture reading face and keeps .verse-context dimming for
   the non-requested verses (no brand color touches the reading column). */
.study-context-intro {
  margin-block: 0.6rem 0.75rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-secondary);
}
.study-context-text { margin-block: 0; }

/* Reduced-motion: drop the chevron rotation transition (the [open] end-state still
   applies — only the animation between states is removed). */
@media (prefers-reduced-motion: reduce) {
  .study-context-chevron { transition: none; }
}

/* AREA 1 — the verse FIGURE (verse mode). The verse + its attribution caption are a
   <figure>/<figcaption>: a quoted primary source with a provenance line. No own
   margins — the card's flex `gap` spaces it; the verse inside stays the hero. */
.study-verse-translation { margin: 0; }
/* The attribution caption — REPLACES the .version-note role on the verse card. A
   recessive UI caption (NOT gold — it is read as a citation, per THEME.md gold-is-
   chrome-only): version name · license, e.g. "World English Bible · Public Domain". */
.study-verse-attr {
  margin-block-start: var(--space-2);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-secondary);
}

/* The reference HEADER on the verse card. It IS the page's single semantic <h1>
   (SEO), kept FIRST in the card ABOVE the large hero verse. It now ALSO carries
   .study-section-heading so the BCV reference reads as the verse card's HEADER,
   matching every other study panel: a leading recessive open-book icon, a GOLD
   (--brand) title, and a thin gold hairline. This RE-GOLDS the reference on purpose —
   we now classify the BCV as a panel TITLE (chrome/wayfinding), not a calm reading-
   column citation — so the gold-policy chrome rule applies (the inverse of the prior
   de-gold). AA: --brand on the card ground (--surface-raised) clears AA in every theme
   (dark 6.16:1, light 5.32:1, sepia 5.52:1) — same token + ground as the panel
   headings, so no fallback is needed.
     The shared .study-section-heading rule below (defined later in source) governs the
   font-family/size/weight, the gold color, the flex icon row, AND the gold hairline; we
   keep only the zero margin here so the card's flex `gap` seats the header above the
   verse. The VERSE stays the visual HERO; only this heading goes gold — the verse text
   and all reading-column prose stay calm (never gold). */
.study-eyebrow {
  margin: 0;
}

/* VERSE-NAV PASS — the verse-card HEADER ROW. A flex row holding the recessive back-nav
   link (inline-start) and the BCV <h1> (which takes the remaining space). The gold
   hairline that .study-section-heading paints as a per-element border-block-end would
   only underline the <h1> portion here (the <h1> no longer fills the row), so we MOVE
   the hairline onto THIS wrapper — it spans the full card width — and strip it from the
   <h1> while inside the header. Logical properties throughout (RTL-safe, THEME.md §5). */
.study-card-header {
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  margin-block-end: 0.75rem;
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--accent-border);
}
/* The <h1> takes the remaining inline space so the BCV title + its hairline-less header
   read as the card's heading; its own border + bottom margin are subsumed by the wrapper.
   Scoped via the .study-eyebrow class (unique to this verse-card <h1>) rather than
   `.study-section-heading` so it does not shadow the canonical panel-heading rule that
   defines the gold title + hairline (the shared rule still owns that contract). */
.study-card-header > .study-eyebrow {
  flex: 1 1 auto;
  min-inline-size: 0;
  margin-block-end: 0;
  padding-block-end: 0;
  border-block-end: none;
}
/* The recessive back-nav link. Navigation CHROME, never reading prose: quiet --text-faint
   at rest, gold (--brand) on hover/focus is allowed (chrome only). ≥44px touch target.
   It sits at the inline-START of the header row, before the BCV heading. Token-only,
   logical properties (RTL-safe). */
.study-card-back {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  min-block-size: 44px;
  padding-block: 0.4rem;
  padding-inline: 0.2rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-faint);
  text-decoration: none;
}
.study-card-back .study-section-icon { color: var(--text-faint); }
.study-card-back:hover,
.study-card-back:focus-visible { color: var(--brand); }
.study-card-back:hover .study-section-icon,
.study-card-back:focus-visible .study-section-icon { color: var(--brand); }
.study-card-back:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.study-card-back-label { font-family: var(--font-ui); }

/* #80 /v-scoped: the reference-line Copy icon on the study-card header (BOTH verse and
   range mode — .study-card-header is unique to bible/passage.ejs) reads borderless at
   rest; the box + gold border appear only on hover/focus. border-COLOR only (base rule
   already reserves a 1px border under box-sizing:border-box) so toggling never shifts
   the box by a pixel. Scoped purely by the ancestor class — the shared .verse-copy-btn /
   .verse-copy-icon bodies stay byte-untouched (shared-class trap). */
.study-card-header .verse-copy-btn {
  border-color: transparent;
  background: transparent;
}
.study-card-header .verse-copy-btn:hover,
.study-card-header .verse-copy-btn:focus-visible {
  border-color: var(--accent-border);
  background: var(--surface-sunken);
}

/* Item 2 / P1-5 (this UX pass) — the verse-mode action shelf: ONE consistent group of
   icon+label controls (Compare, Save, Share — Copy removed in P1-6, Back pulled into the
   verse-card header in the VERSE-NAV pass). Quiet UI chrome; never paints the reading
   column. */
.study-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
/* P1-5 — the BOTTOM action shelf. The action group is now the LAST child of the
   .study-card, beneath the verse + version line. A quiet top divider + top padding
   read it as an ATTACHED action shelf (read, then act), not a control bar at the top.
   Token-only (soft pane border); the card flex `gap` supplies the rest of the rhythm.
   Logical properties for RTL (THEME.md §5). */
.study-toolbar-shelf {
  border-block-start: 1px solid var(--pane-border-soft);
  padding-block-start: var(--space-3);
  margin-block-start: var(--space-1);
}
.study-tool {
  /* >=44px tap target (THEME.md / a11y): pad the ghost button accordingly. */
  min-block-size: 44px;
  display: inline-flex;
  align-items: center;
  /* Item 2 — icon + label sit together with a small gap; the visible label is the
     control's accessible name (the icon is aria-hidden). */
  gap: 0.4rem;
  font-size: 0.9rem;
}
/* The action toolbar's leading icon reuses the recessive .study-section-icon token
   (--text-faint, 1.1em); the label carries the meaning. On hover/focus the ghost
   button's own chrome treatment supplies the quiet accent. */
.study-tool .study-section-icon { color: var(--text-faint); }
.study-tool-label { font-family: var(--font-ui); }
.study-tool-status { /* visually-hidden status region; revealed to AT only */ }
/* LEMMA-ON-CARD PASS (owner request) — on the VERSE-CARD action shelf, make the icons the
   SAME brand gold as the labels. The .btn-ghost base already paints the button TEXT in
   --brand (gold) and flips it to --on-accent on hover/focus (against the gold --brand-fill);
   the icons were the lone exception (forced to --text-faint by the generic .study-tool rule
   above), so a grey icon sat beside gold text and would have stayed grey on the gold hover
   fill. Match the icon to the text: gold at rest, --on-accent on hover/focus. Scoped to
   .study-toolbar-shelf (the bottom action shelf on the .study-card). STUDY-PARITY PASS:
   BOTH verse and range now carry this shelf — range's old thin .study-toolbar-range with
   recessive icons was retired — so the gold-icon treatment applies to both modes' shelf
   identically. The shelf is chrome (not reading content), so gold here is on policy
   (THEME §0); --brand clears AA as an icon/text on the card ground. */
.study-toolbar-shelf .study-tool .study-section-icon { color: var(--brand); }
.study-toolbar-shelf .study-tool:hover .study-section-icon,
.study-toolbar-shelf .study-tool:focus-visible .study-section-icon { color: var(--on-accent); }

/* P2-8 — the DEVICE-LOCAL bookmark/save toolbar button. Meta chrome (toolbar), so
   it may carry a quiet accent when SAVED, but it never paints into the reading
   column. Token colors only; AA contrast on the label. STUDY-PARITY PASS: BOTH verse
   and range now use the SAME bookmark SVG (.study-star-icon) on the Compare·Save·Share
   shelf — the old range-only ☆/★ text glyph (.study-star-glyph) was retired with the
   old thin range toolbar, so both modes share one star treatment. app.js's reflect()
   guards on element presence (the glyph lookup no-ops), so no JS change was needed.
   app.js toggles the .is-saved class; the saved state FILLS + tints the bookmark with
   the brand accent. The icon stays --text-faint at rest like the other toolbar icons. */
.study-tool-star { gap: 0.4rem; }
/* Bookmark SVG saved-state: tint the stroke gold AND fill the bookmark so "saved" reads
   at a glance (a second channel beyond aria-pressed). */
.study-tool-star.is-saved .study-star-icon { color: var(--brand); }
.study-tool-star.is-saved .study-star-icon-shape { fill: var(--brand); }

/* Right-rail card. A calm, recessive container: a soft hairline + raised surface +
   elevation so apparatus reads as a clearly-bounded panel "beside" the text, never
   competing with the verse. The rail cards also carry .study-section (shared
   heading/empty-state styles), so we override its top-hairline + block margins here —
   a card has its own border.

   Restyle P1 (STUDY-PANEL-STYLE A1) — the panels read as DISTINCT, raised cards via
   ELEVATION, not ink: a SOFT border (--pane-border-soft) paired with var(--shadow)
   so the card lifts off --surface without a loud 1px line. This stays calmer than
   the left .study-card (which keeps a stronger shadow so it remains the most present
   surface — the reading column wins; the rail must not out-shout it). The inter-card
   gap is the rail's flex `gap` (var(--space-5)), uniform in both layouts. */
.study-rail-card.study-section {
  margin-block: 0;
  padding: var(--space-5);
  padding-block-start: var(--space-5);
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
}
/* The RAIL — a single flex column that holds every apparatus card (the rail-
   stacking fix). It is ONE grid item in .study-grid, so the grid is a clean 2-cell
   layout (left wrapper + this rail) and the cards stack INSIDE it via flex, top-
   aligned beside the tall left card — never auto-flowing into rows below it. In the
   single-column baseline the rail is capped at the reading measure so its stacked
   text never runs wider than the verse above; the two-column rule lifts that cap. */
.study-rail {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: var(--measure);
}

/* A quiet provenance / source line on an apparatus card (P0-3). Recessive text
   token only; reads as a caption, never a banner, never brand color. */
.study-source-note {
  margin-block: var(--space-3) 0;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-faint);
}

/* P2-8 — DEVICE-LOCAL private notes card (rail). Meta chrome: token colors only, no
   brand color in the textarea (it is read/written like the reading surface but lives
   in the apparatus rail). The device-local microcopy is the honesty contract — kept
   recessive but legible (AA). */
.study-notes-scope {
  margin-block: 0 var(--space-3);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-secondary);
}
.study-notes-field {
  display: block;
  inline-size: 100%;
  box-sizing: border-box;
  min-block-size: 6rem;
  resize: vertical;
  padding: var(--space-3);
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-reading);
  font-size: 0.95rem;
  line-height: 1.5;
}
.study-notes-field:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
  border-color: var(--accent-border);
}
.study-notes-status {
  margin-block: var(--space-2) 0;
  min-block-size: 1.2em; /* reserve space so the card does not jump on first save */
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-faint);
}

/* --- Parallel Translations card (P0-1) --- */
.parallel-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
}
.parallel-row { line-height: 1.5; }
.parallel-meta {
  margin: 0 0 var(--space-1);
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
  font-family: var(--font-ui);
}
/* The version-code badge is a GOLD PILL link to /credits (the neutral sources + license
   table). It replaces the per-row "(license)" tag — the license is stated once,
   authoritatively, on /credits. Chrome (a wayfinding badge, not reading prose), so gold is
   on policy; it mirrors the .btn-ghost gold-pill language (accent-soft ground + gold text,
   fills gold on hover/focus). Token-only; visible focus ring. */
.parallel-code {
  font-family: var(--font-mono);
  font-size: 0.72rem;
  font-weight: 600;
  color: var(--brand);
  text-decoration: none;
  background: var(--accent-soft);
  border: 1px solid var(--accent-border);
  border-radius: 999px;
  padding-block: 0.12rem;
  padding-inline: 0.5rem;
  line-height: 1.5;
  white-space: nowrap;
}
.parallel-code:hover,
.parallel-code:focus-visible {
  background: var(--brand-fill);
  color: var(--on-accent);
  border-color: var(--brand-fill);
}
.parallel-code:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
.parallel-name { font-size: 0.8rem; color: var(--text-secondary); }
/* The verse text in each row uses the reading face but stays at apparatus scale;
   reading-surface discipline — text tokens only, no brand color. */
.parallel-text {
  margin: 0;
  font-family: var(--font-reading);
  font-size: 0.95rem;
  color: var(--text-primary);
}
/* P1-6 — RANGE parallel: each version column shows the WHOLE range, verse-aligned.
   Each verse is its own line with a small leading verse number so a reader can
   compare the SAME verse across columns. Text tokens only (reading-surface
   discipline); the number is recessive metadata. */
.parallel-range { display: grid; gap: var(--space-1); }
.parallel-range-verse { margin: 0; }
.parallel-range-num {
  font-family: var(--font-mono);
  font-size: 0.7rem;
  color: var(--text-faint);
  margin-inline-end: 0.15rem;
}
.parallel-more { margin-block: var(--space-3) 0; }
.parallel-more-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px; /* >=44px tap target */
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--cross-ref);
  text-decoration: none;
}
.parallel-more-link:hover,
.parallel-more-link:focus-visible { text-decoration: underline; }
/* Analysis "Explore {Section} →" footers rest in gold, matching the page's standard link color.
   Scoped to .analysis-area so the sibling "View more translations →" link in study-apparatus.ejs
   (which is NOT inside .analysis-area) keeps its blue --cross-ref color — do NOT flatten this
   into the base .parallel-more-link rule. Hover/focus underline inherited from base. */
.analysis-area .parallel-more-link { color: var(--brand); }

/* UNIFIED LAYOUT PASS — the RANGE "show all translations" BOUND. On a wide range the
   whole-range parallel can be long, so the columns beyond a small curated default set are
   tucked behind a native <details> that REUSES the cross-ref "Show all N" disclosure chrome
   (.crossref-more: recessive summary, gold only on hover/focus — gold is CHROME ONLY). It
   is SSR-first (the extra columns are server-rendered inside the collapsed <details>, fully
   usable JS-off). We only add the spacing between the summary and the revealed columns; the
   summary affordance + the parallel rows themselves inherit their existing rules. The bound
   sits above the "View more →" compare hand-off, which is unchanged. */
.parallel-more-bound { margin-block-start: var(--space-3); }
.parallel-list-rest { margin-block-start: var(--space-4); }

/* --- AREA 2 — Share DROPDOWN (<details>) + Cite block + share dialog --- */

/* The dropdown shell. A native <details> so it is no-JS operable; it is GEBible's
   share SURFACE container (the permalink + intents + Cite block live inside). One
   step of elevation — a panel, not a loud popover. */
.study-share {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
/* The summary is a share CONTROL (chrome): a quiet gold warm on hover/focus is
   on-brand. Icon + "Share" label + a chevron that rotates on [open]. */
.study-share-summary {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 44px; /* >=44px tap target */
  padding: var(--space-3) var(--space-4);
  box-sizing: border-box;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  font-weight: 600;
  color: var(--text-secondary);
  cursor: pointer;
  list-style: none; /* hide the default marker; the chevron is our affordance */
}
.study-share-summary::-webkit-details-marker { display: none; }
.study-share-summary:hover,
.study-share[open] > .study-share-summary { color: var(--brand); }
.study-share-summary:hover { border-color: var(--accent-border); }
.study-share-summary:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
.study-share-summary .study-section-icon { color: var(--text-faint); }
.study-share-summary:hover .study-section-icon,
.study-share[open] > .study-share-summary .study-section-icon { color: var(--brand); }
.study-share-summary-label { margin-inline-end: auto; }
.study-share-chevron {
  inline-size: 1rem;
  block-size: 1rem;
  flex: 0 0 auto;
  transition: transform 0.15s ease;
}
.study-share[open] > .study-share-summary .study-share-chevron { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .study-share-chevron { transition: none; }
}
/* The open menu body: a calm panel inset (sunken step under the dropdown surface). */
.study-share-menu {
  padding: var(--space-4);
  border-block-start: 1px solid var(--pane-border-soft);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
/* A menu item row (the "Share…" entry; the cite Copy buttons reuse it at small). A
   ghost-button look; icons recessive, never a row of gold icons. */
.study-share-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  align-self: flex-start;
  min-block-size: 44px; /* >=44px tap target */
  padding: 0.4rem 0.8rem;
  box-sizing: border-box;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  cursor: pointer;
}
.study-share-item:hover { border-color: var(--accent-border); background: var(--surface-sunken); }
.study-share-item:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.study-share-item.small { min-block-size: 2rem; padding-block: 0.25rem; font-size: 0.8rem; }
.study-share-item-icon {
  inline-size: 1.1em;
  block-size: 1.1em;
  flex: 0 0 auto;
  color: var(--text-secondary);
}

/* The "Cite this verse" block — a plain citation line + Copy + a nested <details>
   with BibTeX/RIS code textareas. Reading-adjacent citation, NOT gold. */
.study-share-cite {
  margin-block-start: var(--space-1);
  padding-block-start: var(--space-3);
  border-block-start: 1px solid var(--pane-border-soft);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.study-share-cite-head { margin: 0; }
.study-share-cite-label {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
}
.study-share-cite-text {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
}
.study-share-cite-formats { margin-block-start: var(--space-1); }
.study-share-cite-formats-summary {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--cross-ref);
  cursor: pointer;
  list-style-position: inside;
}
.study-share-cite-formats-summary:hover,
.study-share-cite-formats-summary:focus-visible { text-decoration: underline; }
.study-share-cite-format { margin-block-start: var(--space-2); }
.study-share-cite-format-head {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-end: var(--space-1);
}
.study-share-cite-format-label {
  font-family: var(--font-mono);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-secondary);
}
/* The code blocks: mono, sunken ground, soft border, readonly + selectable (no-JS
   manual copy path). Not gold. */
.study-share-cite-code {
  display: block;
  inline-size: 100%;
  box-sizing: border-box;
  resize: vertical;
  padding: var(--space-2);
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--text-primary);
  font-family: var(--font-mono);
  font-size: 0.75rem;
  line-height: 1.45;
}
.study-share-cite-code:focus-visible {
  outline: 2px solid var(--accent-border);
  outline-offset: 1px;
}

.share-permalink-line {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-2);
}
.share-permalink-label {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-secondary);
}
/* The canonical URL as selectable real text/href (no-JS copy path). Wraps so a
   long URL never overflows the rail; quiet cross-ref accent (NOT brand gold — the
   permalink string is reading-adjacent, per THEME.md gold-is-chrome-only). */
.share-permalink {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--cross-ref);
  word-break: break-all;
  text-decoration: none;
}
.share-permalink:hover,
.share-permalink:focus-visible { text-decoration: underline; }

/* JS-gated copy button(s). The inline "Copy" sits beside the permalink; the dialog's
   copy buttons sit in .share-dialog-actions. Ghost buttons (.btn .btn-ghost carry the
   base chrome); these only size the target + type. */
.share-action {
  min-block-size: 44px; /* >=44px tap target */
  display: inline-flex;
  align-items: center;
  font-size: 0.85rem;
}
/* VERSE-NAV PASS — the matched Copy / Share PAIR at the end of the permalink row. Both
   are JS-gated (rendered `hidden`; revealed by app.js when capable) so no-JS users never
   see a dead control. The wrapper is a small flex pair that wraps sensibly on narrow
   widths; the two buttons share .share-permalink-action so they read as deliberate
   siblings (identical size/shape). Token-only, ≥44px tap targets, logical properties;
   gold is chrome-only (a quiet --accent-border on hover/focus, never on the label text). */
.share-permalink-actions {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.share-permalink-action {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-block-size: 44px; /* >=44px tap target */
  padding-block: 0.4rem;
  padding-inline: 0.7rem;
  box-sizing: border-box;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  cursor: pointer;
}
.share-permalink-action:hover { border-color: var(--accent-border); background: var(--surface-sunken); }
.share-permalink-action:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.share-permalink-action-icon {
  inline-size: 1.1em;
  block-size: 1.1em;
  flex: 0 0 auto;
  color: var(--text-secondary);
}
.share-permalink-action-label { font-family: var(--font-ui); }

/* The VISIBLE inline fallback region (no-JS): "Or share with:" + the real intent
   anchors. app.js MOVES the .share-intents row into the dialog body and hides this
   wrapper, so it shows ONLY when JS is off (or the dialog is unsupported). */
.share-fallback { margin-block: var(--space-3) 0; }
.share-fallback-label {
  margin: 0 0 var(--space-2);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-secondary);
}
/* The intents as a calm wrapping row of labelled PILL links — each a real <a> with a
   real URL (no-JS baseline intact). Recessive at rest (soft border, --surface ground);
   the LABEL stays --text-primary (reading-adjacent, AA) — gold is reserved for chrome,
   so it appears only as the focus ring + a soft accent border on hover. */
.share-intents {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}
.share-intent {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 44px; /* >=44px tap target */
  padding: 0.4rem 0.8rem;
  box-sizing: border-box;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  text-decoration: none;
}
.share-intent-icon {
  inline-size: 1.15em;
  block-size: 1.15em;
  flex: 0 0 auto;
  color: var(--text-secondary);
}
.share-intent-label { color: inherit; }
.share-intent:hover { border-color: var(--accent-border); }
.share-intent:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}

/* --- The share <dialog> (desktop / no-Web-Share fallback) --- */
/* Mirrors the .settings-dialog idiom: theme surface tokens carry the look; a fixed
   neutral scrim dims the page on every theme; margin:auto re-centers it. */
.share-dialog {
  width: min(420px, calc(100vw - 2rem));
  max-width: calc(100vw - 2rem);
  margin: auto;
  padding: var(--space-4) var(--space-5) var(--space-5);
  border: 1px solid var(--pane-border);
  border-radius: 16px;
  background: var(--surface-raised);
  color: var(--text-primary);
  box-shadow: var(--shadow);
}
.share-dialog::backdrop {
  /* A neutral dark scrim; fixed dim so it reads on every theme (the dialog's own
     surface tokens carry the theme). Token-driven motion is globally neutralized
     under prefers-reduced-motion (the @media reset above). */
  background: rgba(5, 10, 24, 0.6);
}
/* Title row: "Share" heading + a small square Close button, with a thin GOLD hairline
   beneath — the ONE place gold appears in this surface (chrome). */
.share-dialog-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin: 0 0 var(--space-3);
  padding-block-end: var(--space-3);
  border-block-end: 1px solid var(--accent-border); /* gold hairline (chrome) */
}
.share-dialog-title {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--brand); /* gold title words — chrome, AA on --surface-raised */
}
.share-dialog-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  padding: 0;
  border: 1px solid var(--pane-border);
  border-radius: 8px;
  background: transparent;
  color: var(--text-secondary);
  cursor: pointer;
}
.share-dialog-close:hover,
.share-dialog-close:focus-visible {
  color: var(--brand);
  border-color: var(--accent-border);
  background: var(--accent-soft);
}
.share-dialog-close:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
/* The relocated content: the permalink copy, then the moved .share-intents row. */
.share-dialog-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.share-dialog-permalink { margin: 0; }
.share-dialog-actions {
  margin: var(--space-4) 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

/* Two columns ONLY when there is room for a >=60ch reading measure PLUS the rail.
   The reading measure is ~66ch (var(--measure)); a ~22rem rail + the gap needs
   roughly 64rem of content width, so the breakpoint is set there. The .study-page
   container is widened to fit both columns at this breakpoint (it is capped at the
   reading measure below it). The left column is the reading measure; the right is
   a fixed, calm rail width. No sticky positioning — the rail scrolls with the page
   (THEME.md §4: no competing motion on the reading surface). */
@media (min-width: 64rem) {
  /* The container grows by the card's own padding (2× --study-card-pad) on top of
     the measure + rail, so the card's INNER text column still reaches the full
     reading measure — the reading measure wins (THEME.md). --study-card-pad is the
     verse-mode card padding; it is harmless on the range page (no .study-card). */
  .study-page.study-page {
    --study-card-pad: var(--space-5);
    max-width: calc(var(--measure) + 24rem + 2 * var(--study-card-pad));
  }
  .study-grid {
    /* Column 1 is the reading measure PLUS the card's padding, so a ≥60ch (ideally
       ~66ch) text column survives inside the padded card. Column 2 is the calm
       fixed rail. */
    grid-template-columns:
      minmax(calc(60ch + 2 * var(--study-card-pad)), calc(var(--measure) + 2 * var(--study-card-pad)))
      22rem;
    align-items: start;
    column-gap: var(--space-6);
  }
  /* Left column. STUDY-PARITY PASS: BOTH verse and range now use a single .study-main
     wrapper as the column-1 grid item, so one rule covers both. VERSE mode (item 3) it
     stacks the verse .study-card + the Explain panel; RANGE mode it holds the single
     reading .study-card (eyebrow <h1>, the verse figure, the escape hatch, the
     Compare·Save·Share shelf). Capped at the measure + the card's padding so the card's
     inner text column still hits the ~66ch measure (the reading column wins, THEME.md).
     The grid stays a clean 2-cell layout (.study-main | .study-rail) in both modes — no
     rail-stacking. (The former range-only `.study-grid > .study-reading` rule was retired
     with the .study-reading wrapper.) */
  .study-grid > .study-main {
    grid-column: 1;
    max-width: calc(var(--measure) + 2 * var(--study-card-pad));
  }
  /* Right column: the single .study-rail wrapper is the column-2 grid item; its
     cards stack down column 2 in source order via the rail's own flex column. The
     measure cap is lifted here (the rail width is governed by the grid track). */
  .study-grid > .study-rail { grid-column: 2; max-width: none; }
  /* LEMMA-ON-CARD PASS — the former full-width .study-lemma tail panel was removed (the
     Lemma link now lives on the verse-card action shelf), so verse mode is a clean 2-cell
     grid like range mode; no full-width grid child remains to place. */
}

.study-section {
  max-width: var(--measure);
  margin-block: 1.5rem;
  padding-block-start: 1rem;
  border-block-start: 1px solid var(--pane-border);
}

/* --- "On this page" JUMP-NAV (verse study page) ---
   An in-flow anchor strip leading the apparatus (rendered ONLY on a long-scroll
   verse page; see study-apparatus.ejs for the length-gate). NOT sticky / NOT fixed
   — it scrolls away with the page so it never competes with the verse or joins the
   sticky chrome stack. Respects the reading measure (it wraps, never blows out the
   reading column). Gold is chrome here but stays QUIET: the links are recessive
   neutral text at rest, gold ONLY on hover/focus — they must not paint the reading
   column. The <nav>'s aria-label is its accessible name; there is NO heading. */
.study-jumpnav {
  max-width: var(--measure);
  margin-block: 1.5rem 0;
  /* CHIP-LITE PASS — the links are now self-contained bordered chips, so they
     delimit the strip on their own. The container hairline was DROPPED to avoid
     double-framing (chip border + strip rule); the strip stays a quiet wrapping row. */
}
.study-jumpnav-list {
  display: flex;
  flex-wrap: wrap;            /* wrap on narrow screens — never overflow the measure */
  gap: 0.4rem 0.6rem;        /* a touch tighter inline gap now the chips carry their own border */
  margin: 0;
  padding: 0;
  list-style: none;
}
.study-jumpnav-item { margin: 0; }
/* CHIP-LITE affordance — a quiet bordered pill, NOT the gold-fill .pagination-pill family.
   Transparent ground at rest (NEVER a brand fill), a soft 1px --pane-border, the app's pill
   radius (999px) to echo the .pill vocabulary, and recessive --text-secondary text. On
   hover/focus the TEXT goes gold (--brand) and the BORDER may warm to --brand-fill — but the
   BACKGROUND stays transparent (gold is chrome-only and never a filled ground here). The
   inline padding gives comfortable internal spacing while min-block-size keeps the >=44px
   tap target. */
.study-jumpnav-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  padding-block: 0.3rem;
  padding-inline: 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--text-secondary);
  text-decoration: none;
}
.study-jumpnav-link:hover,
.study-jumpnav-link:focus-visible {
  color: var(--brand);
  border-color: var(--brand-fill);
}

/* SCROLL-MARGIN — land an anchor jump BELOW the sticky chrome. On the /v/ study page
   TWO bars are position:sticky at the top: the global .site-header (z-index 50) and
   the .reader-toolbar (z-index 40), which stacks just under it. Without this, a jump
   that lands a heading at the very top would tuck it under those bars. 6rem clears the
   combined stack plus a small gap — the SAME proven offset the reader already uses for
   its deep-link targets (.verse-inline / .verse-poetry use scroll-margin-block-start:
   6rem to "land below the sticky bars"). Applied to the jump-nav's target section
   headings so each jump lands cleanly under the chrome. */
#study-parallel-heading,
#study-analysis-heading,
#study-crossrefs-heading,
#study-explain-heading {
  scroll-margin-block-start: 6rem;
}

/* FOOT-OF-PANEL "↑ Top" link — a quiet in-flow back-to-top affordance at the foot of the
   genuinely-long panels (Cross-references + Explain). It targets the TOP of .study-main
   (#study-main-top), which is where the in-flow jump-nav strip sits — so a reader deep in a
   long panel returns to the contents WITHOUT making anything sticky. The target carries the
   SAME proven 6rem offset the jump-nav section headings use, so the landing clears the sticky
   .site-header + .reader-toolbar stack. */
#study-main-top {
  scroll-margin-block-start: 6rem;
}
/* Recessive, right-aligned at the foot of the panel — reuses the .parallel-more-link
   language (neutral --cross-ref text, gold ONLY on hover/focus, small, >=44px tap target).
   Right-aligned per the owner's request via a flex-end row wrapper. Gold is chrome here and
   stays quiet: never a fill, only a hover/focus accent. */
.study-backtop {
  display: flex;
  justify-content: flex-end;
  margin-block: var(--space-3) 0;
}
.study-backtop-link {
  display: inline-flex;
  align-items: center;
  min-block-size: 44px;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--cross-ref);
  text-decoration: none;
}
.study-backtop-link:hover,
.study-backtop-link:focus-visible {
  color: var(--brand);
  text-decoration: underline;
}
/* P0-2 (this UX pass) — GOLD PANEL TITLES + a GOLD HAIRLINE. A panel heading
   ("Explain this verse", "Cross-references", …) is META-CHROME that FRAMES the
   reading surface — an apparatus LABEL, not text a student reads — so per THEME.md
   the gold accent belongs here (the inverse of the de-golded citation). The heading
   is a flex row: a leading recessive line-icon + the gold title + the recessive
   "(N)" count. A thin gold hairline (--accent-border = 35% gold, calmer than solid
   --brand) sits UNDER the row so the title is separated from the panel body. The
   title word(s) go gold; the icon stays --text-faint (a row of gold icons would
   shout) and the count stays --text-secondary (see .study-section-count). The panel
   BODY — commentary prose, cross-ref links, previews — is unchanged and stays calm,
   so the rail still reads recessive beside the verse. AA verified: var(--brand) on
   the --surface-raised card ground clears AA in every theme (dark 6.16:1, light
   5.32:1, sepia 5.52:1), so the raw brand token is AA-safe — no fallback needed. */
.study-section-heading {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-ui);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--brand);
  margin: 0 0 0.75rem;
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--accent-border);
}
.study-section-icon {
  inline-size: 1.1em;
  block-size: 1.1em;
  flex: 0 0 auto;
  color: var(--text-faint);
}
/* PANEL-TITLE icons match their gold title text (owner request — the same move as the
   action-shelf icons). Panel headings are chrome and already gold (.study-section-heading
   color:--brand), so golding their leading icon is on policy; scoped to the heading so the
   recessive .study-section-icon elsewhere (back-nav link, share summary) is unaffected. */
.study-section-heading .study-section-icon { color: var(--brand); }
.study-empty { font-size: 0.95rem; }

/* Cross-reference list (study page). Each item: a quiet-blue reference link and
   a recessive preview of the target verse text. */
.crossref-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.75rem;
}
.crossref-item { line-height: 1.5; }
.crossref-ref {
  font-family: var(--font-ui);
  font-weight: 600;
  color: var(--cross-ref);
  text-decoration: none;
  margin-inline-end: 0.5rem;
}
.crossref-ref:hover,
.crossref-ref:focus-visible { text-decoration: underline; }
.crossref-preview {
  font-family: var(--font-reading);
  font-size: 0.95rem;
  color: var(--text-secondary);
}

/* AREA 3 — the cross-references panel MOVED into the reading column (.study-main,
   column 1), now ABOVE the Explain panel (column-1 order: verse card → Cross-references
   → Explain). It needs no chrome rules of its own: it inherits the .study-rail-card /
   .study-section chrome (soft border + single shadow + radius + padding) and sits
   ONE step below the verse .study-card (which keeps its double shadow) so the verse
   still wins. The full target-verse text inside inherits the column's ≥60ch measure
   — the reason it left the rail. Inter-panel spacing in column 1 comes from the
   .study-main flex `gap`, so the reorder above Explain needs no order-dependent CSS.
   The class is a markup hook + descendant scope below. */

/* The honest provenance intro: which corpus, what order, which version the text is
   shown in. Recessive caption; the <strong> reference is text-primary, not gold. */
.study-source-intro {
  margin-block: 0 var(--space-4);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
}
.study-source-intro strong { color: var(--text-primary); font-weight: 600; }

/* AREA 3 — each cross-ref item stacks the reference link over the FULL target-verse
   text (ref on its own line, full text beneath) for scannability. */
.crossref-pages { display: block; }
.study-crossrefs-panel .crossref-item {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}
.crossref-item[hidden] { display: none; } /* the JS pager hides off-page items */
/* The NEW full target-verse text, joined in the reader's version. Reading content:
   reading face at body scale, --text-secondary (≥7:1 / AA on the card ground), NO
   brand color. The measure is the column's ≥60ch (the panel is in column 1). */
.crossref-text {
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-secondary);
}

/* CROSS-SECTION "Also examined in" panel (analysis DETAIL pages). It reuses the SAME
   .study-rail-card / .study-explain-panel / .study-section grouped-panel chrome the verse-
   study reverse-link panel uses (soft border + shadow + padding + gold .study-section-
   heading), so it reads as one family. But on a detail page it is NOT inside .study-main /
   .study-rail (which supply the top gap via flex), so it needs its OWN top separation from
   the entry content above it; and it is a quiet pointer panel, so it stays capped at the
   reading measure (inherited from .study-section). Scoped to the two detail surfaces only. */
.science-related-analysis,
.contradiction-related {
  margin-block-start: var(--space-6);
}

/* =========================================================================
   PER-VERSE ANALYSIS DOSSIER re-skin (/analysis/verse/:b/:c/:v)
   -------------------------------------------------------------------------
   A CONSISTENCY RE-SKIN (design-pass consensus), NOT a new visual family: the
   dossier was visually orphaned (its .analysis-dossier-* hooks had no rules and
   it borrowed every class). It now RE-DRESSES the existing structure in the
   Science-detail + Analysis-hub vocabulary so a reader arriving from a Science
   detail page feels they never left the app. These rules only SEAT the borrowed
   chrome onto this page's hooks; they LEAN on existing tokens and invent no new
   colors. The page container is `.container .science-page` (the science-detail
   block rhythm); the breadcrumb (.science-breadcrumb), the hero pair (.analysis-
   hub-title / .analysis-hub-mission), the verse card (.analysis-featured /
   .science-passage), the groups shell (.science-related-analysis), and the
   trailing link (.analysis-howto-link) all come from those families verbatim.

   GOLD IS CHROME-ONLY (load-bearing neutrality guardrail): the reference <h1> +
   the framing line + the verse text read in READING INK, never gold. The only
   gold is existing chrome (the verse card's gold frame edge from .analysis-
   featured, the groups-panel magnifier from .study-section-heading). The new
   verse-card glyph is RECESSIVE currentColor (--text-faint), NOT gold. There is
   NO page-level count anywhere — the only numbers are the per-area counts the
   shared partial renders inside the groups. */

/* The CENTERED hero PAIR wrapper — the reference <h1> + the framing line read as
   one centered focal zone (mirroring the hub's centered title/mission and the
   centered .science-breadcrumb above). It caps to a comfortable measure and
   centers within the content column; both child lines inherit their type/ink from
   the borrowed .analysis-hub-title / .analysis-hub-mission rules. */
.analysis-dossier-hero-head {
  text-align: center;
  margin-block-end: var(--space-5);
}
/* The reference reads in READING INK, never gold (gold is chrome-only). .analysis-
   hub-title supplies margin:0; this only pins the reading-ink color + a hero size
   (the hub title inherits the global h1 size; the dossier reference is a tad
   smaller so the verse CARD stays the dominant hero despite leading). */
.analysis-dossier-ref {
  color: var(--text-primary);
  font-size: 1.5rem;
  line-height: 1.25;
}
/* The framing line sits DIRECTLY under the <h1> (the .analysis-hub-mission rule
   already centers it, caps it to ~60ch, and paints it --text-secondary). This
   only tightens the gap to the reference so the pair reads as one unit. It is the
   ONLY place the "examined across more than one section" idea is stated — no count
   strip, no second sentence. */
.analysis-dossier-framing {
  margin-block-start: var(--space-2);
  font-size: 0.95rem;
}

/* CHANGE 2 — CENTERED CONTENT COLUMN. Everything below the centered hero head (the
   version switcher, the verse card, the groups panel, and the "More" module) lives
   inside .analysis-dossier-body, capped at the reading measure and centered
   (margin-inline: auto) — the SAME centered-body idiom .science-detail-body uses. This
   is what makes the whole page a clean CENTERED single column: before this wrapper the
   verse card + groups panel sat LEFT-aligned in the 1216px container, leaving a dead
   right gutter (a "rail with nothing in it"). No rail is added — the centered hero head
   above and this centered body below now share one measured column, left gutter ≈ right
   gutter. The child blocks already self-center (.analysis-dossier-hero / -context), but
   capping here also seats the full-width switcher + groups panel + More module in the
   measure so nothing strands. */
.analysis-dossier-body {
  max-width: var(--measure);
  margin-inline: auto;
}

/* The verse HERO card — the .analysis-featured gold frame-edge card (chrome) with
   the verse text in reading ink. It is capped to the reading measure and centered
   under the hero pair so it sits as the page's dominant focal block. (The frame
   edge + raised ground come from .analysis-featured / .rail-card; this only seats
   the card's width + block rhythm on the single-column dossier.) Inside
   .analysis-dossier-body the cap is redundant but harmless — the body already caps the
   column; the margin-inline keeps the card centered if the body cap is ever lifted. */
.analysis-dossier-hero {
  max-width: var(--measure);
  margin-inline: auto;
  margin-block: 0 var(--space-5);
}
/* The RECESSIVE open-book study glyph row — the science hero's cite glyph TWINNED
   here but in reading ink, NOT gold: it is decorative chrome that dignifies the
   card as a "study" surface, NOT an eyebrow label (it never re-prints the
   reference — that is the <h1> above). The row carries no text. */
.analysis-dossier-hero-glyphline {
  margin: 0 0 var(--space-2);
  line-height: 1;
}
/* RECESSIVE: --text-faint currentColor, NEVER --brand. This is the single point
   that distinguishes the glyph from the gold .science-cite-icon — the dossier
   glyph is a quiet study mark, not a gilded flourish. The .science-cite-glyph
   class (reused on the <svg>) supplies the 1.1rem sizing. */
.analysis-dossier-cite-icon {
  display: inline-flex;
  align-items: center;
  color: var(--text-faint);
}
/* The version-name caption under the verse text — quiet reading-ink meta (the
   .muted class on the markup already paints --text-secondary; this only tightens
   the gap to the verse text). */
.analysis-dossier-hero-version {
  margin-block: 0 var(--space-3);
  font-size: 0.9rem;
}

/* The groups PANEL shell inherits the science-detail "Also examined in" related-
   analysis chrome verbatim (soft border + single shadow + padding + the gold
   .study-section-heading). On the DOSSIER the verse hero card sits directly above
   this panel and we want a clear gap between the two cards. The catch is the
   CASCADE, not margin collapse: .study-rail-card.study-section (a TWO-class
   selector, ~line 4947) sets `margin-block: 0` on this panel, which out-specifies
   the one-class .science-related-analysis (var(--space-6)) AND a one-class
   .analysis-dossier-groups — so a single-class dossier rule still computes to
   margin-top: 0 and the cards touch (the hero's own margin-block-end is likewise
   zeroed by .science-passage { margin: 0 }, so this panel's top margin is the only
   lever). To win we must MATCH that two-class specificity and sit later in source:
   .analysis-dossier-groups.study-section is (0,2,0) and is defined here BELOW 4947,
   so it beats the `margin-block: 0` override. var(--space-7) = 40px is the gap.
   Scoped to the dossier compound, so the shared panel on the Science-detail and
   Contradiction-detail pages is UNAFFECTED. (A source-level test cannot see this
   override — it is verified by a rendered gap measurement.) */
.analysis-dossier-groups.study-section {
  margin-block-start: var(--space-7);
}

/* #124 — the quiet METHODOLOGY POINTER line. A single LOW, muted line below the
   groups panel: reader-agency framing ("you weigh the evidence") + a one-clause gloss
   on the "critical scholarship" label, then a quiet pointer to the How-this-is-built
   page. REUSES the .analysis-hub-mission muted treatment (--text-secondary, 60ch cap,
   margin:auto); this modifier only adds the low-placement gap above and recedes the
   line to the dossier's quiet meta size. The inline <a> is a plain reading-ink link
   whose arrow goes gold only on hover via the shared .analysis-arrow rule — gold stays
   CHROME-ONLY. NOT a heading; NOT at the top. */
.analysis-dossier-method {
  margin-block: var(--space-5) 0;
  font-size: 0.85rem;
}

/* #125 — DOSSIER mechanism taxonomy chip. A compact recessive category tag rendered
   BELOW the epistemic line for each contradiction entry when the group has >=2 entries
   (a lone entry has no peer to differentiate; the tag is navigation, not substance).
   The loaded-label guardrail resolves the raw DB enum in the model (MECHANISM_LABELS);
   unmapped/absent carries null and emits nothing. Reuses the shared .chip visual
   (surface-sunken pill, --text-secondary ink, no --brand); this rule adds ONLY the
   placement gap. Contradictions-only by field presence. NEW MODIFIER CLASS ONLY — every
   non-dossier caller of analysis-area-groups emits zero bytes (enrichEntries gate). */
.analysis-entry-mechanism {
  margin-block: 0.3rem 0;
}

/* The trailing "Read {reference} in context →" hand-off uses the analysis pages'
   .analysis-howto-link treatment (a plain reading-ink link, the arrow gold only on
   hover/focus via the global .analysis-arrow rule). This only centers it under the
   single-column dossier and gives it a touch more top separation from the groups
   panel above. */
.analysis-dossier-context {
  text-align: center;
  margin-block-start: var(--space-5);
}

/* (d2) NEIGHBORING-CITED-VERSES NAV — the compact prev/next pager at the foot of the
   per-verse Analysis dossier. A quiet navigational block: recessive hairline top border,
   comfortable block padding, flex row with prev on the left and next on the right. The
   links are reading ink (--text-primary) at rest; they go gold (--brand) on hover/focus
   — the same chrome-only interaction as .continue-reading-card and the .analysis-arrow
   idiom. No gold on the reference text at rest (gold stays chrome-only). Each link shows
   the verse reference and, below it in muted --text-secondary, the section names. The
   .analysis-arrow glyphs (← / →) are defined inline in the view; this block styles the
   layout and the state transition only. New modifier classes only — no existing rule is
   touched. */
.analysis-dossier-nav {
  border-top: 1px solid var(--pane-border);
  padding-block: var(--space-5);
}
.analysis-dossier-nav-links {
  display: flex;
  justify-content: space-between;
  gap: var(--space-5);
}
.analysis-dossier-nav-link {
  display: flex;
  flex-direction: column;
  gap: 0.2em;
  text-decoration: none;
  color: var(--text-primary);
  max-width: 46%;
}
.analysis-dossier-nav-next {
  align-items: flex-end;
  text-align: right;
}
.analysis-dossier-nav-section {
  font-size: 0.875em;
  color: var(--text-secondary);
}
.analysis-dossier-nav-link:hover,
.analysis-dossier-nav-link:focus-visible {
  color: var(--brand);
}

/* "More questions about {category}" — the category-sibling KEEP-READING pull on the
   contradiction detail page (the critic's benchmark item 3). A small NAVIGATIONAL block in
   the meta-rail, after "Also examined in" and before Share, so it never competes with the
   answers/commentary. It INHERITS the rail's grouped-panel chrome from .study-rail-card /
   .study-section / the gold .study-section-heading (soft border + single shadow + padding +
   radius + the gold panel heading) — NOT restyled here. Like .contradiction-related, it is
   NOT inside .study-main / .study-rail, so it needs its own top separation from the panel
   above it on the narrow single-column stack. This styles ONLY its plain question-link list,
   reusing the .analysis-entry reading-ink link idiom: reading face, --text-primary (NEVER
   gold — gold stays chrome-only on the panel h2), underline on hover/focus, no badge/count. */
.contradiction-siblings {
  margin-block-start: var(--space-6);
}
.contradiction-siblings-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-inline-size: var(--measure);
}
.contradiction-siblings-item { line-height: 1.5; }
.contradiction-siblings-link {
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary);
  text-decoration: none;
}
.contradiction-siblings-link:hover,
.contradiction-siblings-link:focus-visible { text-decoration: underline; }

/* CLOSELY RELATED — the CURATED keep-reading pointer to the closely-related sibling
   question(s) on the same passages (relatedQuestions). It LEADS the meta-rail (the FIRST
   panel, above "Also examined in" and the category-sibling pull) — moved here from the
   reading spine so every recessive cross-link sits in the rail and never competes with the
   peer answer cards. Like .contradiction-related / .contradiction-siblings it INHERITS the
   rail's grouped-panel chrome from .study-rail-card / .study-section / the gold
   .study-section-heading (soft border + single shadow + padding + radius + the gold panel
   heading) — NOT restyled here. Because it is NOT inside .study-main / .study-rail it needs
   its own top separation from a panel above it on the narrow single-column stack (the
   .contradiction-meta > :first-child rule already zeroes the FIRST rail child, so this only
   bites when it stacks under another block). This styles ONLY its plain question-link list,
   reusing the .contradiction-siblings-* reading-ink link idiom: reading face, --text-primary
   (NEVER gold — gold stays chrome-only on the panel h2), underline on hover/focus, no
   badge/count, capped at the reading measure. Page-scoped (every rule is under
   .contradiction-related-siblings*); no shared/global class is touched. */
.contradiction-related-siblings {
  margin-block-start: var(--space-6);
}
.contradiction-related-siblings-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-inline-size: var(--measure); /* link text stays at the reading measure */
}
.contradiction-related-siblings-item { line-height: 1.5; }
.contradiction-related-siblings-link {
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary); /* reading ink — never gold */
  text-decoration: none;
}
.contradiction-related-siblings-link:hover,
.contradiction-related-siblings-link:focus-visible { text-decoration: underline; }

/* SCHOLARLY-STATUS POINTER — the lightweight, separately-attributed signpost between "The
   tension" and the answers that surfaces the attributed scholarly-consensus STATUS early (a
   DUPLICATE of the full line in the commentary card, not a move). NO card/panel shell — a
   recessive eyebrow over a reading-ink grade line, CENTERED on the page so it reads LIGHTER
   than the bordered tension panel above and the peer answer cards below. (The earlier left-pin
   — a leading gold hairline + left padding —
   was dropped in favor of centering; there is no gold chrome on this element now, and gold stays
   OFF the eyebrow text, the grade word, and the glyph regardless.) Page-scoped (every rule is
   under .contradiction-consensus-pointer-*); no shared/global class is touched. Tokens + logical
   properties only. */
.contradiction-consensus-pointer {
  margin-block: var(--space-5);
  text-align: center; /* CENTERED on the page — no left-edge idiom (the leading gold hairline +
     left padding were dropped: a left-pin conflicts with centering). The eyebrow, grade line,
     and "read more" anchor all center within the (already centered, measure-matched) track. */
}
.contradiction-consensus-pointer-label {
  margin: 0 0 0.5rem;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint); /* recessive eyebrow — the attribution, no gold on the text */
}
.contradiction-consensus-pointer-grade {
  margin: 0;
  margin-inline: auto; /* the grade <p> is --measure-capped (narrower than the card track); auto
     side-margins center that capped block within the track so it doesn't strand left. */
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary); /* reading ink — the grade word is legible, never gold */
  max-inline-size: var(--measure);
}
/* The decorative inline glyph keeps the SAME recessive --text-secondary / pure currentColor
   treatment as the commentary-card line (gold stays OFF the glyph); .consensus-glyph-inline
   (defined later in this file) already sets that color + inline baseline alignment. */
/* The in-page ANCHOR — a signpost to the commentary card, NOT a button. It reuses the
   .parallel-more-link affordance language: small UI text, recessive --cross-ref ink, gold ONLY
   on hover/focus (chrome), an arrow tail. It DROPS to its OWN centered line just below the grade
   word (display:block + a tight top gap) so it reads as a distinct "read more" tail, not part of
   the grade. */
.contradiction-consensus-pointer-link {
  display: block; /* breaks to its OWN line below the grade word; centers via the grade <p>'s
     inherited text-align:center (no own centering needed). */
  margin-block-start: 0.35rem; /* a tight "read more" gap below the grade — NOT a button's space. */
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--cross-ref);
  text-decoration: none;
  white-space: nowrap;
}
.contradiction-consensus-pointer-link:hover,
.contradiction-consensus-pointer-link:focus-visible { text-decoration: underline; }

/* PHASE 2 (grouped) — "Examined in Scripture Analysis" reverse-link panel (verse study
   page). The panel SHELL chrome (soft border + shadow + padding + the gold .study-section-
   heading) is INHERITED from .study-rail-card / .study-explain-panel / .study-section-
   heading — NOT restyled here. This styles ONLY the per-area GROUPS and the entry list.

   Today the panel shows ONE group (Science); the rules scale to N areas (the inter-group
   separation + divider matter only at 2+ areas but are set now). GOLD-CHROME-ONLY: the area
   sub-headers, the entry statement links, and the meta are NEVER --brand — gold lives ONLY
   on the panel h2 (inherited). The area h3 is NEUTRAL strong text; its glyph + count recede.
   The entry statement is reading content (wraps as a sentence, honors --measure). */
.analysis-area {
  margin-block-start: var(--space-4);
  /* #119 — in-page anchor target (the dossier stats strip jumps here). Clear the sticky
     .site-header (position:sticky; top:0; ~3.5rem on the dossier page, which has NO
     reader-toolbar) plus a little breathing room so the jumped-to group's top border +
     sub-header land comfortably below the bar, not flush under it. Inherits the global
     html { scroll-behavior: smooth } (neutralized under prefers-reduced-motion), so the
     jump is reduced-motion-safe with no per-rule work. */
  scroll-margin-block-start: 5rem;
}
/* First group hugs the heading; subsequent groups get a subtle divider + breathing room
   (only visible at 2+ areas). */
.analysis-area:first-of-type { margin-block-start: 0; }
.analysis-area + .analysis-area {
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border-soft);
}
/* The area sub-header (h3) — NEUTRAL strong text between the h2 and body, NOT gold; its
   inline glyph recedes (--text-faint). */
.analysis-area-heading {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 0.4rem;
  font-family: var(--font-ui);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text-primary);
}
.analysis-area-heading .study-section-icon { color: var(--text-faint); flex: none; }
/* Recessive count — mirrors .study-section-count's weight but stays neutral. */
.analysis-area-count { font-weight: 400; color: var(--text-faint); }
/* The neutral per-area lens/framing line — recessive caption, never gold. */
.analysis-area-framing {
  margin: 0 0 0.6rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-faint);
}
.analysis-entry-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-inline-size: var(--measure);
}
.analysis-entry {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  line-height: 1.5;
}
/* The claim text — reading content (a full sentence): reading face, --text-primary,
   NOT gold; underline only on hover/focus. Wraps normally. */
.analysis-entry-statement {
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary);
  text-decoration: none;
}
.analysis-entry-statement:hover,
.analysis-entry-statement:focus-visible { text-decoration: underline; }
.analysis-entry-meta {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-faint);
}

/* #121 — DOSSIER-ONLY per-entry enrichment (the epistemic line + the both-pole named-sources
   disclosure). NEW MODIFIER CLASSES ONLY: the global .analysis-entry / -statement / -meta and
   .analysis-area* / .parallel-more-link rules are byte-untouched, so every NON-dossier caller
   of analysis-area-groups (study-apparatus, reader, the two detail "Also examined" panels) is
   unaffected — these classes only ever render under the dossier's enrichEntries flag. CALM +
   RECESSIVE, matching the muted entry metas; GOLD IS CHROME-ONLY and stays OFF all of these
   (no pole goes gold — the two poles read at EQUAL weight, neither as "the winner"). */

/* #117 — the DOSSIER tension unit. Renders ONLY under enrichEntries, in place of
   .analysis-entry-meta, so every non-dossier caller is untouched (NEW MODIFIER CLASS ONLY;
   the shared .analysis-entry / -statement / -meta rules are byte-unchanged). At ~44 words
   this is READING content, not metadata: reading face at --text-secondary, NOT the 0.85rem
   --text-faint UI register the one-line meta uses. Recessive against the .analysis-entry-
   statement link (--text-primary) so the question still leads. GOLD IS CHROME-ONLY — never
   --brand here. The measure is already bounded by .analysis-entry-list's max-inline-size. */
.analysis-entry-tension {
  margin: 0;
  font-family: var(--font-reading);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text-secondary);
}

/* (B) the epistemic line — `{label}: {value}`. The LABEL is the quiet strong attribution lead
   (#118); the VALUE recedes to the meta ink. Not gold. */
.analysis-entry-epistemic {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-faint);
}
.analysis-entry-epistemic-label {
  font-weight: 600;
  color: var(--text-secondary);
}
.analysis-entry-epistemic-value { color: var(--text-faint); }
/* #126 — institutional attribution on the science "scientific record" line. Quiet
   parenthetical in the same recessive reading-ink as the value (--text-faint); NEVER gold
   (gold is chrome-only). New modifier class only — non-dossier callers emit zero bytes. */
.analysis-entry-epistemic-source { color: var(--text-faint); }
/* #51 — the documented/debated TALLY tail on the anatomy (History/Archaeology) epistemic line.
   Recessive reading-ink count in the same faint register as the value, NEVER gold (gold is
   chrome-only). New modifier class only — it renders solely when an entry carries e.epistemic.tally
   (science anatomy entries), so non-anatomy + non-dossier callers emit zero bytes. */
.analysis-entry-epistemic-tally { color: var(--text-faint); }

/* (A) the both-pole disclosure <details>. The summary is a recessive UI affordance — NOT the
   --cross-ref blue of .crossref-more, NOT gold; calm, matching the entry metas, underline only
   on hover/focus. */
.analysis-entry-more { margin-block-start: 0.3rem; }
.analysis-entry-more > summary {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--text-faint);
  cursor: pointer;
  list-style-position: inside;
}
.analysis-entry-more > summary:hover,
.analysis-entry-more > summary:focus-visible { text-decoration: underline; }

/* The two poles — visually SYMMETRIC (equal weight: same layout, same ink, no per-pole accent
   so neither side reads as winning). */
.analysis-entry-poles {
  list-style: none;
  margin: 0.4rem 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
.analysis-pole {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-faint);
}
.analysis-pole-label {
  font-weight: 600;
  color: var(--text-secondary);
}
.analysis-pole-names { color: var(--text-faint); }
/* The attributed-absence notes (thin pole / un-paneled pointer): recessive + italic so an
   absence reads as provenance, never a verdict. Color comes from the .muted utility on the
   element; the italic distinguishes the absence note from a name list. */
.analysis-pole-blank,
.analysis-pole-blank-attr,
.analysis-entry-no-panel { font-style: italic; }
.analysis-entry-no-panel {
  margin: 0.4rem 0 0;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  line-height: 1.5;
}
/* The un-paneled note's CTA links the SAME e.url as that entry's .analysis-entry-statement
   above, so it takes the SAME reading-ink treatment (NOT the global gold `a {}`): gold stays
   chrome-only and the two same-target links read consistently. Font/style are inherited so the
   link stays inline within the muted italic sentence (no size/face jump); only the color and the
   hover affordance are set — mirroring .analysis-entry-statement. */
.analysis-entry-no-panel-link {
  color: var(--text-primary);
  text-decoration: none;
}
.analysis-entry-no-panel-link:hover,
.analysis-entry-no-panel-link:focus-visible { text-decoration: underline; }
/* The one-sentence pole NOTE (#122): a recessive, indented condensation of that pole's own
   verbatim quotes. The two poles' notes are visually IDENTICAL (symmetric, gold stays
   chrome-only — never colour-code reconcile vs discrepancy). */
.analysis-pole-note {
  margin: 0.2rem 0 0;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-secondary);
}
.analysis-pole-note-label { font-weight: 600; color: var(--text-secondary); }

/* #123 — DOSSIER-ONLY in-tension verse-pair fragment (the always-visible line ABOVE each
   contradiction entry's question link, setting the clashing scriptural snippets side by side).
   NEW MODIFIER CLASSES ONLY — the global .analysis-entry* rules stay byte-untouched, so every
   NON-dossier caller of analysis-area-groups is unaffected (these render only under enrichEntries).
   STRICT SYMMETRY: both sides share the same classes; there is NO per-side selector, accent, or
   weight, so neither side reads as "the contradiction" / "the primary". GOLD IS CHROME-ONLY and
   stays OFF all of these (no --brand, no --cross-ref blue); calm + recessive like the entry metas. */
.analysis-entry-versepair {
  margin: 0 0 0.3rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
}
.analysis-entry-versepair-side { display: inline; }
/* The ref recedes BELOW the snippet (a quiet locator), the snippet reads at the entry-meta ink.
   Neither is bold or italic — the fragment must not out-shout the question link beneath it. */
.analysis-entry-versepair-ref { color: var(--text-faint); }
.analysis-entry-versepair-snippet { color: var(--text-secondary); }
/* Decorative connectors (the ` — ` em dash and the ` / ` side separator): faint + unselectable
   so a copy of the line yields the words, not the ornament. Both are aria-hidden in the markup. */
.analysis-entry-versepair-sep,
.analysis-entry-versepair-em {
  color: var(--text-faint);
  user-select: none;
}

/* AREA 3 — the JS-gated pager controls (hidden no-JS). Ghost-button chrome, ≥44px
   targets, recessive icons, a mono "1 / N" indicator. */
.crossref-pager {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  margin-block-start: var(--space-4);
}
.crossref-pgbtn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-inline-size: 44px;
  min-block-size: 44px; /* >=44px tap target */
  padding: 0.3rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-secondary);
  cursor: pointer;
}
.crossref-pgbtn:hover:not(:disabled) { border-color: var(--accent-border); }
.crossref-pgbtn:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.crossref-pgbtn:disabled { opacity: 0.4; cursor: default; }
.crossref-pgind {
  font-family: var(--font-mono);
  font-size: 0.85rem;
  color: var(--text-secondary);
  min-inline-size: 3.5rem;
  text-align: center;
}

/* P1-6 — the source-verse attribution tag on a RANGE cross-ref union item
   ("(v3)"/"(vv3–4)"). A quiet UI caption (recessive text token), set in the UI face
   so it reads as apparatus metadata, not part of the reference link. */
.crossref-source-tag {
  font-family: var(--font-ui);
  font-size: 0.75rem;
  margin-inline-end: 0.4rem;
}

/* RD15 — curated cross-refs: the count beside the heading + the "Show all N"
   expander on the study page. The expander is a native <details> (no-JS works);
   its summary is a quiet UI affordance, never brand red in the reading column. */
.study-section-count { font-weight: 400; color: var(--text-secondary); }
.crossref-more { margin-block-start: 0.75rem; }
.crossref-more > summary {
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--cross-ref);
  cursor: pointer;
  list-style-position: inside;
}
.crossref-more > summary:hover,
.crossref-more > summary:focus-visible { text-decoration: underline; }
.crossref-list-rest { margin-block-start: 0.75rem; }
.crossref-more-note { margin-block-start: 0.5rem; }

/* RD15 — in-drawer "Show N more" expander for the Cross-references tab. */
.verse-popover-crossrefs-more { margin-block: 0.35rem; }
.verse-popover-crossrefs-more > summary {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--cross-ref);
  cursor: pointer;
  list-style-position: inside;
}
.verse-popover-crossrefs-more > summary:hover,
.verse-popover-crossrefs-more > summary:focus-visible { text-decoration: underline; }

/* Cross-references tab rendered into the verse popover (JS-enhanced path).
   Popover is overlay chrome; ref links keep the quiet-blue cross-ref accent. */
.verse-popover-crossrefs-heading {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-crossrefs-loading,
.verse-popover-crossrefs-empty {
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-crossrefs-list {
  list-style: none;
  margin: 0;
  padding: 0;
  font-size: 0.9rem;
  line-height: 1.5;
}
.verse-popover-crossrefs-list li { margin: 0 0 0.4rem; }
.verse-popover-crossref-ref {
  font-family: var(--font-ui);
  font-weight: 600;
  color: var(--cross-ref);
  text-decoration: none;
}
.verse-popover-crossref-ref:hover,
.verse-popover-crossref-ref:focus-visible { text-decoration: underline; }
.verse-popover-crossref-preview { color: var(--text-secondary); }
.verse-popover-crossrefs-all {
  display: inline-block;
  margin-block-start: 0.25rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--cross-ref);
  text-decoration: none;
}
.verse-popover-crossrefs-all:hover,
.verse-popover-crossrefs-all:focus-visible { text-decoration: underline; }

/* Compare tab rendered into the verse popover (JS-enhanced path). The verse TEXT
   is reading content, so it takes reading ink (--text-secondary), NOT gold chrome.
   The version name + honest per-row license tag are recessive UI. The list caps +
   scrolls (theme-aware scrollbar via the shared verse-popover recipe up top) so a
   tall comparison never pushes the reading column. */
.verse-popover-compare-heading {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-compare-loading,
.verse-popover-compare-empty {
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-compare-list {
  list-style: none;
  margin: 0;
  padding: 0;
  max-block-size: 16rem;
  overflow-y: auto;
}
.verse-popover-compare-row { margin: 0 0 0.6rem; }
.verse-popover-compare-name {
  display: block;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
}
.verse-popover-compare-license {
  font-weight: 400;
  font-size: 0.72rem;
  /* Recede BELOW the version name (--text-secondary): a faint meta tag, not the
     meaning-bearing --note green, so the name leads and the verse text dominates. */
  color: var(--text-faint);
}
.verse-popover-compare-text {
  display: block;
  /* Reading ink (NOT gold) — this is scripture content, not chrome. */
  color: var(--text-primary);
  font-size: 0.9rem;
  line-height: 1.5;
  margin-block-start: 0.1rem;
}
.verse-popover-compare-all {
  display: inline-block;
  margin-block-start: 0.25rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--cross-ref);
  text-decoration: none;
}
.verse-popover-compare-all:hover,
.verse-popover-compare-all:focus-visible { text-decoration: underline; }

/* #94 — recessive "Scripture Analysis" footer POINTER (not a tab, not a preview).
   Stays calm: a quiet --note link, NO gold rule / gold fill (gold is chrome-only,
   and this pointer is recessive overlay chrome). A hairline top border separates it
   from the tab content; the link gains a quiet underline on hover/focus only. */
.verse-popover-analysis-pointer {
  margin-block-start: 0.5rem;
  border-block-start: 1px solid var(--pane-border);
}
.verse-popover-analysis-pointer-link {
  /* Whole row is the hit target: a block ≥44px tall (RD20/WCAG 2.2) so a recessive
     link is still comfortably tappable on a phone. The block padding also supplies
     the separation from the hairline above (was the container's padding). */
  display: flex;
  align-items: center;
  min-block-size: 2.75rem;
  font-family: var(--font-ui);
  font-size: 0.82rem;
  color: var(--text-secondary);
  text-decoration: none;
}
.verse-popover-analysis-pointer-link:hover,
.verse-popover-analysis-pointer-link:focus-visible { text-decoration: underline; }

/* --- R5: Commentary ("Explain this verse") ---
   THEME.md: commentary prose uses the reading/commentary type (17px / 1.6) so a
   note reads like prose, not UI. Source labels are recessive (--text-secondary)
   so the verse and its commentary lead; the source is cited, never the app's
   voice. Reading-surface discipline: no brand red in the commentary body. Logical
   properties throughout (THEME.md §5); motion respects prefers-reduced-motion
   (handled globally). */

/* Study page "Explain" section. In verse mode the column-1 order is
   verse card -> Cross-references -> Explain (the cross-refs panel sits above Explain
   so the curated reference web is not buried under the long 5-source commentary);
   the panel stays calm regardless of order. */
.study-explain { margin-block-start: 1.5rem; }

/* Item 3 (this UX pass) — the VERSE-MODE Explain PANEL. Explain is its OWN distinct
   study panel in the LEFT/reading column, below the verse card. It already carries
   .study-rail-card (soft border + var(--shadow) + var(--space-5) padding + radius),
   so the panel chrome is shared with the rail cards. The .study-explain
   margin-block-start above is already overridden to 0 by .study-rail-card.study-section;
   the .study-main flex `gap` supplies the space between the verse card and this panel.
   The commentary prose inside stays --text-primary, AA, NO brand color (a reading
   surface).

   P0-3 (this UX pass) — SINGLE shadow. The Explain panel sits at the RAIL's
   elevation (one var(--shadow)), NOT the verse card's doubled lift, so the verse
   .study-card stays the MOST-present surface in column 1 (the reading column wins,
   THEME.md). Inheriting the single var(--shadow) from .study-rail-card.study-section
   is sufficient, so the prior double-shadow override is removed; this rule is kept as
   the documented anchor for the panel's column-1 identity. */
.study-explain-panel.study-rail-card.study-section {
  box-shadow: var(--shadow);
}

/* RD3 — recessive, neutral source-framing note (the "presented as a primary
   source — not an endorsement" line). Quiet, small, secondary color so it reads
   as a caption, not a banner. No brand color (chrome restraint). */
.source-framing-note {
  margin-block: 0 1rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-style: italic;
  color: var(--text-secondary);
}
/* VOICE INDEX (task #107) — the commentary ROSTER. The flat stack of <article>
   essays + the JS chip-filter row are RETIRED. The Explain panel is now a scannable
   directory: ONE native <details> per voice, in chronological order (the neutrality
   device — no "best" first). Each <summary> is a one-line row (name · year · incipit
   + a chevron); tapping expands that note inline. The roster scales FLATLY — every
   voice costs one row, equal weight. ZERO new JS: every row opens natively with JS
   off, so the no-JS baseline is a full, openable, chronological, attributed list.
   Same markup + classes render in the popover (app.js initExplain). */
.commentary-roster {
  display: grid;
  gap: var(--space-2);
}
/* One voice row. The recessed --surface inset (vs the card's --surface-raised) reads
   as a quiet quote panel; the inline-start accent rule is the source marker. Logical
   properties keep the edge correct in RTL. No <img>/avatar — the summary row IS the
   citation.
   overflow:hidden establishes a clipping context so the inner flex row (commentary-voice-row,
   nowrap) cannot overflow a width-constrained parent — specifically the popover's max-width:24rem.
   Without it the flex row's intrinsic content width escapes the max-width boundary. On the study
   page the parent column already constrains width so this has no visual effect there. */
.commentary-voice {
  border-inline-start: 3px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface);
  overflow: hidden;
}
/* The summary IS the roster row: chevron · name · meta · (range) · incipit. A
   one-line, comfortable tap target (≥44px) that truncates the incipit on overflow
   so the row never wraps to two lines in the directory. Native marker removed (we
   draw our own chevron); the row stays keyboard-operable as a real <summary>. */
.commentary-voice-row {
  display: flex;
  align-items: baseline;
  flex-wrap: nowrap;
  gap: 0.5rem;
  min-block-size: 2.75rem;
  padding: 0.55rem var(--space-3);
  cursor: pointer;
  list-style: none; /* hide the default disclosure triangle (we draw a chevron) */
  font-family: var(--font-ui);
}
.commentary-voice-row::-webkit-details-marker { display: none; }
.commentary-voice-row:hover { color: var(--text-primary); }
.commentary-voice-row:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
/* The chevron rotates a quarter-turn when the row is open (CSS-only affordance;
   neutralized under prefers-reduced-motion below). It sits on the baseline-aligned
   row but nudged to optically center against the first text line. */
.commentary-voice-chevron {
  flex: 0 0 auto;
  align-self: center;
  color: var(--text-faint);
  transition: transform 0.15s ease;
}
.commentary-voice[open] > .commentary-voice-row .commentary-voice-chevron {
  transform: rotate(90deg);
}
@media (prefers-reduced-motion: reduce) {
  .commentary-voice-chevron { transition: none; }
}
/* The source NAME — the de-stuttered author. The row's anchor; it never shrinks. */
.commentary-voice-name {
  flex: 0 0 auto;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--text-primary);
}
/* The recessive "year · license" meta line — present the source plainly. */
.commentary-voice-meta {
  flex: 0 0 auto;
  font-size: 0.8rem;
  color: var(--text-secondary);
}
/* The optional pericope-range label ("vv. a–b" / "On vv16–18"), so a spanned note
   never reads as a per-verse repeat. Recessive metadata token. */
.commentary-voice-range {
  flex: 0 0 auto;
  font-size: 0.78rem;
}
/* The INCIPIT — the source's OWN first ~9 words (server-truncated on a word
   boundary). It is recessive and TAKES THE SLACK of the row, truncating with an
   ellipsis on overflow so the directory row stays one line. Reading-ink hue is fine
   here: it is the source's own words, not chrome. Kept visible in all states (open
   or closed) for scannability — the design wants the teaser shown either way. */
.commentary-voice-incipit {
  flex: 1 1 auto;
  min-inline-size: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
/* The expanded note body inside a row: the existing lead/rest clamp lives here. A
   little inset from the summary so the prose sits under, not flush-left of, the row. */
.commentary-voice-body {
  padding: 0 var(--space-3) var(--space-3);
}

/* Commentary prose: reading type at the THEME.md commentary size (17px / 1.6).
   Shared by the study page and the popover Explain tab so a note reads the same
   in both. Paragraph/list rhythm only; no brand color inside the prose. */
.commentary-body {
  font-family: var(--font-reading);
  font-size: 17px;
  line-height: 1.6;
  color: var(--text-primary);
}
.commentary-body p { margin-block: 0 0.75rem; }
.commentary-body p:last-child { margin-block-end: 0; }
.commentary-body blockquote {
  margin-inline: 0;
  margin-block: 0.75rem;
  padding-inline-start: 1rem;
  border-inline-start: 2px solid var(--pane-border);
  color: var(--text-secondary);
}
.commentary-body ul,
.commentary-body ol { margin-block: 0 0.75rem; padding-inline-start: 1.5rem; }
.commentary-body li { margin-block-end: 0.25rem; }
.commentary-body h3,
.commentary-body h4 {
  font-family: var(--font-ui);
  font-size: 1rem;
  line-height: 1.3;
  margin-block: 0.75rem 0.4rem;
}

/* G2 readability clamp: dense notes show a lead, then reveal the rest in this
   native <details>. The summary is a recessive UI affordance (quiet --cross-ref
   link tone, never brand red in the reading column); no custom motion, so it is
   inherently reduced-motion-safe. Shared by the study page and the popover tab. */
.commentary-more { margin-block-start: 0.5rem; }
.commentary-more > summary {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--cross-ref);
  cursor: pointer;
  list-style-position: inside;
}
.commentary-more > summary:hover,
.commentary-more > summary:focus-visible { text-decoration: underline; }
.commentary-more[open] > summary { margin-block-end: 0.5rem; }

/* AREA 4 — each PLAIN-TEXT commentary paragraph (escaped). It is a <p> inside
   .commentary-body, so it inherits the reading face / 17px / 1.6 / --text-primary
   and the paragraph rhythm above; this explicit rule documents the class and keeps
   the spacing if .commentary-body's generic p rule ever changes. No brand color. */
.commentary-note { margin-block: 0 0.75rem; }
.commentary-note:last-child { margin-block-end: 0; }

/* AREA 4 — the per-source PROVENANCE line (the full attribution string from the
   bundle). A recessive caption (--text-faint), below the note. NOT gold. A GEBible
   trust feature the rivals omit. */
.commentary-attr {
  margin-block: 0.6rem 0;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  line-height: 1.45;
  color: var(--text-faint);
}

/* "Explain" tab rendered into the verse popover (JS-enhanced path). Popover is
   overlay chrome; the commentary body shrinks slightly to fit the drawer but
   keeps the reading typeface so it stays readable, not UI-dense. */
.verse-popover-explain-heading {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-explain-loading,
.verse-popover-explain-empty {
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin: 0 0 0.35rem;
}
.verse-popover-explain-entry { margin-block-end: 0.85rem; }
.verse-popover-explain-source {
  font-family: var(--font-ui);
  font-size: 0.78rem;
  color: var(--text-secondary);
  margin: 0 0 0.25rem;
}
/* RD14 — drawer commentary uses the SAME commentary-body type as the study page
   (17px / 1.6, THEME.md §3) so a note reads identically in both surfaces. The
   .commentary-body class (applied alongside in app.js) already sets the family/
   size/line-height; here we only cap height + scroll so a long note never pushes
   the reading column. */
.verse-popover-explain-body {
  max-block-size: 16rem;
  overflow-y: auto;
}
.verse-popover-explain-all {
  display: inline-block;
  margin-block-start: 0.25rem;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--cross-ref);
  text-decoration: none;
}
.verse-popover-explain-all:hover,
.verse-popover-explain-all:focus-visible { text-decoration: underline; }

/* --- RD3: Settings "About the text" note ---
   A calm, prose explanation of the primary-source posture. Sits below the
   settings form; recessive, no brand color (chrome restraint). */
.about-text {
  margin-block-start: 2rem;
  padding-block-start: 1.25rem;
  border-block-start: 1px solid var(--pane-border);
}
.about-text h2 { font-size: 1.1rem; margin: 0 0 0.5rem; }
.about-text p { max-width: 60ch; }

/* --- Settings: opt-in "Read offline" section ---
   A JS-only enhancement (the section is rendered hidden and revealed by app.js
   only when the Service Worker + Cache API are available). Mirrors the
   .about-text top hairline so it reads as a sibling note, then lays out the
   Download / Remove controls. Token-driven; no hardcoded colors. */
.offline-section {
  margin-block-start: 2rem;
  padding-block-start: 1.25rem;
  border-block-start: 1px solid var(--pane-border);
}
.offline-section h2 { font-size: 1.1rem; margin: 0 0 0.5rem; }
.offline-section p { max-width: 60ch; }
.offline-controls {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  margin-block-start: 1rem;
}
.offline-version-label {
  flex-basis: 100%;
  margin: 0;
  color: var(--text-secondary);
}
.offline-status { margin-block-start: 0.75rem; }

/* --- RD4: Credits / sources page ---
   A neutral, scannable set of tables (source / what it is / license). Plain
   server-rendered page; no brand color in the body, logical properties for RTL
   readiness (THEME.md §5). */
.credits-page h2 {
  font-size: 1.15rem;
  margin-block: 1.75rem 0.5rem;
}
.credits-table {
  width: 100%;
  border-collapse: collapse;
  margin-block-end: 0.75rem;
  font-size: 0.95rem;
}
.credits-table th,
.credits-table td {
  text-align: start;
  padding: 0.5rem 0.6rem;
  border-block-end: 1px solid var(--pane-border);
  vertical-align: top;
}
.credits-table thead th {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}
.credits-table tbody th {
  font-weight: 600;
  color: var(--text-primary);
  white-space: nowrap;
}
.credits-table td { color: var(--text-secondary); }
/* The CC BY attribution paragraph — readable but recessive. */
.credits-attribution {
  font-size: 0.9rem;
  color: var(--text-secondary);
}
/* The CC BY-SA 4.0 license-deed line under each licensed voice on /commentaries —
   small + recessive, sitting just beneath the voice's verbatim attribution. */
.commentaries-license-line {
  font-size: 0.85rem;
  color: var(--text-faint);
  margin-block-start: 0.25rem;
}

/* =========================================================================
   SCIENCE & SCRIPTURE (/science) — landing, list, and detail pages.
   Tokens-only color (no raw hex). Gold (--brand / --accent-border) is reserved
   for chrome (theme tile/card accents, focus, the tag chip) and NEVER touches
   reading content — the cited verse paints with --surface/--text-primary only,
   like every reading surface (THEME.md §0/§2). Logical properties throughout;
   ≥44px touch targets on the interactive rows; :focus-visible inherits the
   global ring. Added with the /science feature (service-worker CACHE_VERSION
   bumped because styles.css is a precached shell asset).
   ========================================================================= */
.science-page { padding-block-end: var(--space-8); }

.science-breadcrumb {
  font-size: 0.9rem;
  color: var(--text-secondary);
  margin-block-end: var(--space-3);
  text-align: center;
}

/* --- Search form (shared by the LIST view: theme/book/search pages) --- */
.science-search-form {
  display: flex;
  gap: var(--space-2);
  flex-wrap: wrap;
  align-items: stretch;
  margin-block-start: var(--space-3);
  max-width: var(--measure);
}
.science-search-input {
  flex: 1 1 16rem;
  min-block-size: 44px;
  padding: 0.55rem 0.75rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-sunken);
  color: var(--text-primary);
  font: inherit;
}
.science-search-form .btn { min-block-size: 44px; }

/* --- List page (theme / book / search) --- */
.science-context-blurb {
  max-width: var(--measure);
  color: var(--text-secondary);
  line-height: 1.55;
}
/* THEME-context header treatment. The theme page's <h1>, two-stat strip, search
   pill, and blurb form one CENTERED header focal zone (mirroring the /science
   landing's centered hero+stats). These two modifiers are emitted ONLY in the
   theme branch of list.ejs, so the book/search contexts keep the default
   start-aligned heading + start-aligned, column-capped blurb untouched. */
.science-heading-centered { text-align: center; }
/* The centered blurb is CAPPED to the reading measure (inherited from
   .science-context-blurb's max-width) and centered within the column via
   margin-inline:auto — a centered line must not run the full content width. */
.science-blurb-centered {
  margin-inline: auto;
  text-align: center;
}
.science-count { margin-block: var(--space-3); }
/* Paginated "Showing X–Y of N" line (theme context). Same quiet muted treatment
   as .science-count; a distinct hook so it never collides with the book/search
   count line. (The .muted class already carries --text-secondary.) */
.science-showing { margin-block: var(--space-3); }
/* "START HERE" SPOTLIGHT — the deterministic theme page-1 entry point. It REUSES
   the landing Featured card whole (.rail-card + .analysis-featured*, including the
   gold frame, the eyebrow/verse/meaning/link recipes); this modifier adds ONLY the
   content-column block rhythm the landing got from the .rail flex `gap` (which does
   not exist in this single column), seating the card between the centered blurb
   above and the statement list below. No color/chrome is duplicated here. */
.science-start-here { margin-block: var(--space-4); }
/* THEME-page search pill — REUSES the landing's .analysis-search* rules verbatim
   (the pill chrome, the gold submit, the focus halo, the ≥44px targets, the
   narrow-screen drop of the magnifier all come from those global selectors). This
   modifier only SEATS that pill on the single-column .science-list-page: it gives
   the pill its block rhythm so it nests cleanly between the two-stat strip above
   and the context blurb below. The pill spans the FULL content column (no
   inline-size cap) to match the landing's full-width search and the full-width
   statement list below it. No color, no chrome duplication. */
.science-theme-search {
  margin-block: var(--space-3) var(--space-4);
}
.science-statement-list { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-4); }
/* The card adopts the landing Featured card's gold FRAME-EDGE chrome: a 3px
   inline-start gold border (--accent-border, the SAME token .analysis-featured
   uses for its gold frame). Frame-only gold (chrome) — no content text is gold.
   The inline-start padding is widened a step so the claim/cite/teaser do not
   crowd the new edge; the block + inline-end padding are unchanged.

   ELEVATION: the card now lifts off --surface as a raised PANEL via the project's
   single, subtle, theme-aware shadow token (box-shadow: var(--shadow)) — the SAME
   restrained elevation the study rail panels (.study-rail-card) and the analysis
   search pill use. One shadow only (never stacked / never heavier); the
   --surface-raised ground, the 1px soft border, and the gold frame edge are all
   intact, and the lift does not touch text contrast. */
.science-statement-card {
  border: 1px solid var(--pane-border-soft);
  border-inline-start: 3px solid var(--accent-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  padding-block: var(--space-4);
  padding-inline: var(--space-5) var(--space-4);
}
.science-statement-claim { margin-block: 0 var(--space-2); font-size: 1.15rem; line-height: 1.35; }
.science-statement-claim a { color: var(--text-primary); text-decoration: none; }
.science-statement-claim a:hover { text-decoration: underline; }
/* The citation borrows the landing's eyebrow TYPE recipe wholesale via the
   .analysis-featured-eyebrow class on the markup (uppercase, letter-spacing,
   --font-ui, the 0.85rem eyebrow size, muted --text-secondary — NO gold; DRY,
   no rule-body copy). That class also supplies the citation's block rhythm
   (margin-block: 0 var(--space-2)). This modifier ONLY lays the borrowed eyebrow
   out as a row so the leading gold glyph seats beside the citation text on the
   baseline; it sets no type/color/margin so the eyebrow recipe governs those
   (the class wins on equal specificity, being later in the file). */
.science-statement-cite {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-2);
  row-gap: 0;
}
/* Decorative leading open-book glyph — gold CHROME (currentColor → --brand).
   aria-hidden + focusable="false" in the markup; never a link. flex:0 0 auto so
   it never shrinks; nudged up a hair to sit on the citation baseline. */
.science-cite-icon {
  display: inline-flex;
  flex: 0 0 auto;
  align-items: center;
  align-self: center;
  color: var(--brand);
}
.science-cite-glyph {
  inline-size: 1.1rem;
  block-size: 1.1rem;
}
/* Citation TEXT + the reader deep-link stay MUTED (--text-secondary) — gold is
   chrome-only (the frame + glyph). The deep-link keeps a real, focusable
   underline affordance so it stays distinguishable from plain label text inside
   the muted eyebrow style. */
.science-cite-link { color: var(--text-secondary); text-decoration: underline; }
.science-cite-link:hover,
.science-cite-link:focus-visible { color: var(--brand); }
.science-cite-plain { color: var(--text-secondary); }

/* --- Tier-A: verse reference hover/focus PEEK card (Science cite-links only) ---
   Overlay chrome (like the verse popover — THEME.md §0 permits brand accents on
   overlay chrome): the reference label + the top hairline may go gold, and the
   "Read in full →" arrow goes gold ONLY on hover/focus. The VERSE TEXT is reading
   ink (--text-secondary), NEVER gold, and there is NO gold-filled background. The
   card is built/filled by initVersePeek; with JS off it never renders. */
.verse-peek {
  display: block;
  position: absolute;
  z-index: 60;
  margin: 0;
  padding: 0.6rem 0.75rem;
  /* Cap to the viewport so a floating card on a narrow screen can't overflow
     the right edge (the JS clamp pins left = edge; this keeps the right in). */
  max-width: min(26rem, calc(100vw - 16px));
  max-height: 70vh;
  overflow-y: auto;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: var(--shadow);
  font-family: var(--font-ui);
  font-size: 0.95rem;
}
.verse-peek:focus { outline: var(--focus-ring); outline-offset: 2px; }
/* Reference label: chrome — gold is sanctioned here (overlay). Mono, like the
   popover's reference, with a soft gold hairline beneath it. */
.verse-peek-ref {
  margin: 0 0 0.4rem;
  padding-bottom: 0.35rem;
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--brand);
  border-bottom: 1px solid var(--accent-border);
}
.verse-peek-verses { margin: 0; }
/* One line per verse: a recessive verse number + the verse text in READING INK
   (never gold). The serif reading face matches the rest of the app's scripture. */
.verse-peek-verse {
  margin: 0 0 0.3rem;
  color: var(--text-secondary);
  font-family: var(--font-reading);
  line-height: 1.5;
}
.verse-peek-verse:last-child { margin-bottom: 0; }
.verse-peek-num {
  margin-inline-end: 0.4rem;
  font-family: var(--font-ui);
  font-size: 0.75rem;
  font-weight: 600;
  color: var(--text-faint);
  vertical-align: super;
}
.verse-peek-text { color: var(--text-secondary); }
.verse-peek-loading,
.verse-peek-citation-only {
  margin: 0;
  color: var(--text-faint);
  font-size: 0.9rem;
}
/* Honest truncation note — recessive, never gold. */
.verse-peek-truncated {
  margin: 0.4rem 0 0;
  color: var(--text-faint);
  font-size: 0.85rem;
}
/* Provenance line — recessive. */
.verse-peek-version {
  margin: 0.4rem 0 0;
  color: var(--text-faint);
  font-size: 0.8rem;
}
.verse-peek-readmore-row { margin: 0.5rem 0 0; }
/* The single recessive "Read in full →" link: neutral at rest, gold only on
   hover/focus (the arrow rides on currentColor via .analysis-arrow). */
.verse-peek-readmore {
  color: var(--text-secondary);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 600;
}
.verse-peek-readmore:hover,
.verse-peek-readmore:focus-visible { color: var(--brand); }
.science-cite-extra { font-size: 0.9rem; }
.science-statement-teaser { margin-block: 0 var(--space-2); color: var(--text-secondary); line-height: 1.5; }
/* The "Read the entry →" footer affordance is separated from the content block
   (claim + citation + teaser) by a hairline, exactly as the landing's panel
   footer (.analysis-books-footer) sits above the rows: the SAME soft gold
   hairline chrome (border-block-start: 1px solid var(--accent-border)) with the
   SAME var(--space-4) block padding/margin so it breathes. The hairline is
   sanctioned structural chrome — it tints no content text. Margin reset to 0 on
   the inline axis is preserved; only the block-start gains the divider. */
.science-statement-more {
  margin: 0;
  margin-block-start: var(--space-4);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--accent-border);
  font-size: 0.9rem;
}

/* --- Detail page ---------------------------------------------------------------
   RECAST onto the section's own card vocabulary (.analysis-featured gold frame-
   edge hero for the cited passage; .rail-card elevated panels for the science +
   framing; the rail mini-card idiom for the related hub) so the detail page reads
   as one family with /science + the theme/book lists. GOLD IS CHROME-ONLY here:
   the card frame edge, the icon-badge rings + glyphs, the uppercase reference
   eyebrow's glyph, the "→" hover, the tag-chip border, and the panel-title
   hairline. NEVER gold: the claim, the verse/scripture text, the science prose,
   the framing prose, the citation text, the theme name, or the verse-number
   markers (those reuse the reader's recessive .verse-num-static). Tokens-only,
   logical properties, ≥44px targets, :focus-visible, reduced-motion safe, AA in
   all three themes. */
.science-detail-claim { max-width: var(--measure); margin-inline: auto; line-height: 1.25; text-align: center; }

/* META STRIP — a labeled theme TAG (the theme NAME, never presented as a numeric
   stat) beside ONE genuine number (theme.count passages in this field). Sits
   under the claim as a compact orientation row; wraps on narrow viewports. */
.science-detail-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-3) var(--space-4);
  margin-block: var(--space-4) var(--space-5);
}
/* The theme TAG reuses the .science-tag chip recipe (gold chrome border, reading-
   ink label); this modifier only keeps it on the baseline of the strip. */
.science-detail-strip-tag { align-self: center; }
.science-detail-strip-stat {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-size: 0.9rem;
  color: var(--text-secondary);
}
/* Smaller badge than the landing's 2.5rem stat ring — a quiet inline marker. */
.science-detail-strip-badge { inline-size: 2rem; block-size: 2rem; }
.science-detail-strip-text { line-height: 1.4; }
/* The real number is reading ink (NOT gold) — an honest density signal. */
.science-detail-strip-num { font-weight: 600; color: var(--text-primary); }

/* CONTRADICTIONS — the detail-page DESKTOP META-RAIL grid. A page-scoped two-column
   layout. The <h1> QUESTION and the orientation strip ride a FULL-WIDTH header band
   (direct grid children spanning both tracks — see the rule in the media query). BELOW
   that band the two columns begin: the neutral reading SPINE (.contradiction-spine —
   tension → answers → variants → commentary → Sources → the SAB attribution line) is the
   first track; the recessive META-RAIL (.contradiction-meta — "Also examined in" → category
   siblings → Share) is the second. With align-items:start the rail's first block top-aligns
   with the spine's first block (the tension panel). The rail wrapper follows the spine in
   SOURCE ORDER (which itself follows the header band), so below the breakpoint everything
   stacks in reading order via a pure reflow (NO `order:` trick). These classes are
   page-scoped (NOT a reuse of .analysis-landing); they only MIRROR its grid idiom in
   values — the minmax(0, 20rem) rail track and the align-items:start. The grid is gated to
   >= 72rem so the SPINE keeps a comfortable usable width (well above ~48ch) once the rail
   claims its 20rem column; below 72rem the page is a single linear column. */
.contradiction-detail { display: block; }
@media (min-width: 72rem) {
  .contradiction-detail {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    column-gap: var(--space-6);
    align-items: start;
  }
  /* The HEADER BAND — the <h1> question and the orientation strip are direct grid children
     hoisted above the spine/rail cells; each spans BOTH tracks so the title + orientation
     form a full-width centered header row. With the spine column now beginning at the
     tension panel and align-items:start, the meta-rail's first block top-aligns with that
     tension panel. (The <h1> stays measure-capped + centered, and the orientation strip
     stays centered, via the centered-spine rule below — spanning both tracks only widens
     the box those rules center WITHIN.) Inert below this breakpoint, where
     .contradiction-detail is display:block and these items stack in source order. */
  .contradiction-detail > .science-detail-claim,
  .contradiction-detail > .contradiction-orientation {
    grid-column: 1 / -1;
  }
}
/* Each grid cell must be allowed to shrink (min-inline-size:0) so a long token never
   forces the track wider than its share. The spine cell is wider than the reading
   measure; the spine's body blocks stay measure-capped + centered WITHIN it (the rule
   below), so the 19px Gentium scripture never stretches or gets squeezed. */
.contradiction-spine { min-inline-size: 0; }

/* The META-RAIL — the recessive second column. It reuses the .rail family's quiet stacking
   (a flex column with a steady gap) so its cards read as part of the rail vocabulary. It is
   NOT pinned (matches the project's .rail idiom: the right column scrolls with the page, it
   does not stick). Gold stays chrome-only; the rail adds no new headline weight. */
.contradiction-meta {
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
/* Below the grid breakpoint the rail is a full-width stacked column under the spine; it
   keeps the same internal gap and gets a little breathing room from the spine above. */
@media (max-width: 71.99rem) {
  .contradiction-meta { margin-block-start: var(--space-5); }
}

/* CONTRADICTIONS — the detail-page CENTERED SINGLE-COLUMN SPINE. The <h1>
   (.science-detail-claim) is measure-capped AND centered (margin-inline:auto), but the
   body blocks beneath it were measure-capped yet LEFT-PINNED (or uncapped), so the page
   read as a narrow column shoved to the left under a centered headline. These rules cap
   EVERY post-<h1> body block at the reading measure and center the COLUMN (margin-inline:
   auto) so the whole spine is one centered stack under the centered headline. Only the
   COLUMN centers — no text-align is touched, so answer headlines, explanations, scripture,
   commentary, and sources all stay text-left (reading order, not a centered band). The
   tension panel rides the shared .science-panel-framing chrome, so it is scoped here via
   the page-only .contradiction-tension marker to avoid retargeting the /science panels.
   The spine now rides ONE shared "card track" (= the reading measure + the answer card's
   inline padding, calc(--measure + 2 * --space-5)) so EVERY major spine block shares the
   answer cards' outer width — no block sits narrower than the cards. Framed-panel prose
   AND each panel-header gold hairline are RE-CAPPED back to --measure via panel padding
   (the tension + commentary rules below bump padding to --space-5), and the answers
   header/lead stay measure-capped + centered (existing rule, further down). */
.contradiction-orientation,
.contradiction-tension,
.contradiction-consensus-pointer,
.contradiction-answers,
.contradiction-variants,
.contradiction-variants-note,
.contradiction-harmonization,
.contradiction-commentary,
.contradiction-attribution {
  max-width: calc(var(--measure) + 2 * var(--space-5));
  margin-inline: auto;
}

/* The TENSION PANEL is re-capped to --measure by the shared `.science-panel` rule (later
   in source than the group rule above), so widening it to the card track needs a
   page-scoped, HIGHER-specificity selector. The tension <section> is a DIRECT child of
   .contradiction-spine, so `.contradiction-spine > .contradiction-tension` is (0,0,2,0) and
   beats `.science-panel` (0,0,1,0) regardless of source order — without retargeting the
   /science panels. padding:--space-5 (24px) overrides .rail-card's --space-4 (16px) so the
   panel's body prose AND its `.science-panel-header` gold hairline land at exactly --measure
   (card track − 2 × 24px = --measure), matching the answer cards. */
.contradiction-spine > .contradiction-tension {
  max-width: calc(var(--measure) + 2 * var(--space-5));
  padding: var(--space-5);
}

/* The COMMENTARY section widens to the card track via the group rule above; its VISIBLE
   panel is an INNER .rail-card carrying the global --space-4 (16px) padding. Bump it to
   --space-5 (matching the answer cards + the tension panel) so the commentary body prose
   and its `.science-panel-header` hairline also land at exactly --measure. Scoped to the
   commentary so the global .rail-card (used on /science + the verse study page) is
   untouched. */
.contradiction-commentary > .rail-card { padding: var(--space-5); }

/* THE BOTH-POLES SURFACE ("In the commentators' own words") is a PEER to the commentary card and
   takes the SAME measure treatment so the two read as one family: the group rule above caps it to
   the card track + centers it, and its inner .rail-card gets --space-5 padding so its body + the
   `.science-panel-header` hairline land at exactly --measure (matching the commentary card + the
   answer cards). The vertical rhythm mirrors `.contradiction-commentary` below. Scoped so the
   global .rail-card stays untouched. */
.contradiction-harmonization > .rail-card { padding: var(--space-5); }
.contradiction-harmonization { margin-block: var(--space-5); }

/* THE SURFACE CAPTION — a plain reading-ink <p> under the header band (symmetric "each side",
   never a reconcile-only disclaimer). A small gap below the band; measure-capped reading prose. */
.contradiction-surface-caption {
  margin-block: 0 var(--space-2);
  max-width: var(--measure);
  line-height: 1.55;
  color: var(--text-primary);
}
/* THE ERA-REGISTER LINE — the standing historical-register frame, MUTED (it inherits .muted for
   the secondary ink; this rule only owns the spacing + measure). Reads as provenance, never a
   verdict; a slightly tighter gap below seats it as the lead-in to the first pole. */
.contradiction-surface-era {
  margin-block: 0 var(--space-4);
  max-width: var(--measure);
  line-height: 1.55;
}

/* THE POLE LABEL — a quiet sub-label <p> (NOT a heading; the surface adds exactly one <h2>). It
   REUSES the recessive uppercase-eyebrow idiom the answer card's "Cited passages" / the sources
   sub-label use, with a single LEADING GOLD HAIRLINE as the only chrome — IDENTICAL on both poles
   (equal dignity; no pole gets heavier chrome, gold never on a quote/attribution/"winning" side).
   The first pole's label sits tight under the era line; later labels get a clear top gap so the
   two poles read as distinct blocks. */
.contradiction-pole-label {
  margin-block: var(--space-5) var(--space-3);
  padding-block-start: var(--space-2);
  /* Gold pole-label HAIRLINE — the SAME sanctioned structural-chrome token (--accent-border) the
     `.science-panel-header` gold hairline uses; tints no text, identical on BOTH poles. */
  border-block-start: 1px solid var(--accent-border);
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
.contradiction-pole-label:first-of-type { margin-block-start: 0; }

/* THE POLE QUOTE LIST — reset (no bullet/indent); each verbatim quote its own <li> with a clear
   gap between them so a multi-voice pole scans. */
.contradiction-pole-quotes {
  list-style: none;
  margin-block: 0;
  padding-inline-start: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.contradiction-pole-quote { margin-block: 0; }

/* THE QUOTE TEXT — a <blockquote> carrying the VERBATIM public-domain text (the curly quote marks
   are baked into the data; this is the quotation affordance for a no-CSS / reader-mode render).
   Reading ink (it is content, like .science-panel-body), measure-capped, with a quiet inline-start
   hairline + hanging indent as the visual quote treatment — NOT a big gold quote mark (gold stays
   chrome-only). The hairline is the SOFT rule (a separator weight), never brand/gold. */
.contradiction-pole-quote-text {
  margin: 0;
  padding-inline-start: var(--space-4);
  border-inline-start: 2px solid var(--pane-border);
  max-width: var(--measure);
  font-family: var(--font-reading);
  line-height: 1.6;
  color: var(--text-primary);
}
/* THE ATTRIBUTION LINE — the <cite> + optional voice/source, recessive REFERENCE ink (it reuses
   the folded-sources cite idiom: an italic <cite> work-mark in secondary ink, never gold). Seated
   tight beneath its quote with a small top gap + the same inline-start indent so it hangs with the
   quote, reading as that quote's source. */
.contradiction-pole-quote-attr {
  margin-block: var(--space-2) 0;
  padding-inline-start: var(--space-4);
  line-height: 1.5;
  color: var(--text-secondary);
}
.contradiction-pole-quote-cite {
  font-style: italic;
  color: var(--text-secondary);
}
/* THE VOICE DESCRIPTOR — an optional muted genre/stance tag (null everywhere today → renders
   nothing). Recessive faint ink, upright so the italic cite stays the anchor; .muted owns the ink,
   this rule only normalizes the face. */
.contradiction-pole-quote-voice { font-style: normal; }

/* THE HALF-LINE + THE EMPTY-NOTE — both are NOTES about a pole (the id 3 mislabel guard + the id
   439 absence case), LIGHTER than a full quote so they read as notes, not quotes: muted secondary
   ink (inherits .muted), measure-capped, no quote hairline. The empty-note's trailing <cite> reuses
   the recessive italic cite idiom. */
.contradiction-pole-halfline,
.contradiction-pole-empty {
  margin-block: 0 var(--space-3);
  max-width: var(--measure);
  line-height: 1.55;
}
.contradiction-pole-empty .contradiction-pole-quote-cite { color: var(--text-secondary); }

/* TOP-ALIGN the two grid columns. The spine's first block (the tension panel) carries a
   ~24px top margin from the shared `.science-panel { margin-block: --space-5 }`; the rail's
   first card is a `.study-section` (margin-block: 1.5rem) or the Share <details> — different
   first-cards carry different top offsets, so the columns don't reliably top-align under the
   grid's `align-items: start`. Zeroing the FIRST child's top margin in BOTH columns makes
   them start cleanly at the grid cell top, regardless of which optional rail card renders
   first. (0,0,2,0) beats the shared single-class rules; below the 72rem breakpoint the grid
   collapses to one column and this is harmless. */
.contradiction-spine > :first-child,
.contradiction-meta > :first-child { margin-block-start: 0; }

/* CONTRADICTIONS — the detail-page ORIENTATION STRIP. A neutral, scannable row of
   recessive metadata chips placed UNDER the <h1> and ABOVE "The tension", mapping
   where in the text the tension lives (category · mechanism · testament scope ·
   books-in-tension). It mirrors the .science-detail-strip spirit (a centered,
   wrapping orientation row under the centered claim) but its items are the GLOBAL
   recessive .chip pills (surface-sunken, reading ink). NEVER gold — gold is
   chrome-only on this page; these chips are CONTENT. The list is reset (no bullets/
   indent). Tokens-only, logical properties, wraps on narrow viewports. */
.contradiction-orientation {
  list-style: none;
  padding: 0;
  margin-block: var(--space-4) var(--space-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center; /* centered beneath the centered claim */
  gap: var(--space-2) var(--space-3);
}
.contradiction-orientation-item { display: inline-flex; }
/* #147 — WCAG 2.2 AA SC 2.5.8 (24x24) for the orientation strip. THIS is the only
   place in the app where .chip is emitted as an <a>: every other .chip caller
   (search/topics testament chips, the homepage version chips, the messianic
   usage-type chip, the dossier mechanism chip) is an inert <span>/<li>, which is
   not a target at all. So the global .chip recipe is left byte-untouched and the
   24px floor is scoped here, on the modifier class the view already emits — no
   view edit needed, and no other surface moves. Measured 19.89px -> 24px.
   The floor is set on the MODIFIER, not on `a.`, deliberately: this strip mixes
   linked and unlinked chips on one row (the route links a book chip only when
   that book page has content), so raising only the anchors would leave two chip
   heights side by side. Both halves grow together and the row stays uniform. The
   0.75rem step is the same reasoning — 12px is the smallest size these stay
   comfortable to tap at; .chip's 0.72rem (11.52px) is sized for inert metadata
   pills, which is what it remains everywhere else. */
.contradiction-orientation-chip {
  min-block-size: 24px;
  font-size: 0.75rem;
}
/* A book chip is a link; keep the recessive .chip look and give it a quiet hover
   affordance (border + text lift to the brand on interaction — chrome, not a verdict).
   The non-link chips (category/mechanism/scope) inherit the inert .chip look. */
a.contradiction-orientation-chip { text-decoration: none; }
a.contradiction-orientation-chip:hover,
a.contradiction-orientation-chip:focus-visible {
  border-color: var(--brand);
  color: var(--text-primary);
}

/* CONTRADICTIONS — the category-page SORT control (category context only). Two pill
   options usable JS-off: the neutral DEFAULT ("In canonical order") and the OPT-IN
   "Most discussed". Reuses the recessive search-suggest chip look (surface-raised,
   reading ink, rounded). The ACTIVE option is a non-link <span class="is-active"> with a
   filled surface-sunken fill so the current sort reads as selected — NEVER gold (gold is
   chrome-only here; the sort is content, not a verdict). Links lift their border to the
   brand on hover/focus, the same quiet affordance the orientation chips use. */
.contradiction-sort {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.4rem 0.5rem;
  margin-block: var(--space-3) var(--space-4);
}
.contradiction-sort-label { color: var(--text-secondary); font-size: 0.9rem; }
.contradiction-sort-option {
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-size: 0.9rem;
  text-decoration: none;
}
a.contradiction-sort-option:hover,
a.contradiction-sort-option:focus-visible {
  border-color: var(--brand);
  text-decoration: none;
}
.contradiction-sort-option.is-active {
  background: var(--surface-sunken);
  border-color: var(--pane-border);
  font-weight: 600;
}

/* CONTRADICTIONS — the opt-in MANUSCRIPT-VARIANTS panel (the 77 textual-variant
   entries). It reuses the commentary disclosure idiom (.study-share <details> +
   a muted standing note), placed AFTER the answers and BEFORE the commentary so
   neutral textual data leads the adjudicating commentary. Block rhythm only; the
   disclosure chrome (gold marker/hairline) is inherited from .study-share. The
   apparatus line is a quiet, smaller, verbatim source line under the body prose. */
.contradiction-variants { margin-block: var(--space-5); }
.contradiction-variants-note { max-width: var(--measure); margin-block: 0 var(--space-3); }
.contradiction-variants-apparatus {
  margin-block: var(--space-3) 0;
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
}

/* CONTRADICTIONS — the "Proposed answers" PAYLOAD section. The competing answers are
   the page's PRIMARY content (not a footer hub), so the heading is a real payload-section
   heading (heavier than the footer-hub .science-related-heading the answers used to share)
   and each answer is a dedicated PEER card with peer weight. NEUTRALITY (load-bearing):
   every card gets IDENTICAL treatment — same padding, same headline size, the same
   uniform NEUTRAL hairline marker — so equality is visible WITHOUT ranking. No numbers,
   ordinals, checkmarks, or X marks anywhere; gold stays chrome-only (the marker hairline,
   the card frame). The answer text, headline, and lead are reading ink. */
.contradiction-answers {
  display: grid;
  gap: var(--space-4);
  margin-block: var(--space-5);
  /* The CARD TRACK is the reading measure PLUS the answer card's own inline padding
     (2 x --space-5). An answer's explanation prose is measure-capped INSIDE the card, so
     widening the track by exactly the padding lands that prose back at the full reading
     measure instead of measure-minus-the-padding — the old "claustrophobic" squeeze; the
     nested cited-passage cards widen with it. This is NOT a change to --measure or the base
     font: body text still reads at --measure; only the card chrome around it widens. */
  max-width: calc(var(--measure) + 2 * var(--space-5));
}
/* Only the CARDS take the wider track. The "Proposed answers" header band (its gold
   hairline) and the neutral lead stay capped at --measure and centered within the widened
   section (margin-inline:auto), so they keep aligning with the tension panel and the
   commentary above/below — the cards extend symmetrically around that same reading column. */
.contradiction-answers-header,
.contradiction-answers-lead {
  max-width: var(--measure);
  margin-inline: auto;
}
/* The section heading carries "the core of the page" weight — larger than the
   footer-hub .science-related-heading, matching the page's other payload <h2>s. */
.contradiction-answers-heading {
  margin-block: 0;
  font-size: 1.35rem;
  line-height: 1.3;
}
/* A one-line neutral lead: the answers are equal peers. Muted reading ink, capped to
   the reading measure; it sits tight under the heading and above the first card. */
.contradiction-answers-lead {
  margin-block: calc(var(--space-2) * -1) 0;
  max-width: var(--measure);
  line-height: 1.55;
}
/* The PEER card — peer weight: generous padding (a step beyond the base .rail-card),
   a clear card boundary, consistent rhythm card-to-card. The gold frame edge is chrome
   (the same --accent-border token the science/featured frame uses); the contained text
   never goes gold. */
.contradiction-answer {
  padding: var(--space-5);
  border-color: var(--accent-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
/* The answer headline — peer weight, LARGER than the old 1.05rem mini-card claim, in
   reading ink (NOT gold, NOT numbered). The uniform neutral hairline marker seats beside
   it on a baseline row. */
.contradiction-answer-headline {
  margin: 0;
  display: flex;
  align-items: baseline;
  gap: var(--space-3);
  font-size: 1.2rem;
  line-height: 1.35;
  color: var(--text-primary);
}
/* The leading marker — a uniform NEUTRAL repeated hairline glyph (a short gold rule),
   IDENTICAL on every card: equality without ranking. It is decorative chrome (gold is
   allowed here), never a number/ordinal/check/X. A fixed-size flex item so the headline
   text aligns across cards regardless of marker presence. */
.contradiction-answer-marker {
  flex: 0 0 auto;
  inline-size: 1.25rem;
  block-size: 2px;
  margin-block-start: 0.55em; /* drop the rule to sit on the headline's optical baseline */
  border-radius: 999px;
  background: var(--brand);
}
/* The headline text grows to fill the row beside the fixed marker; reading ink. */
.contradiction-answer-headline-text {
  flex: 1 1 auto;
  min-inline-size: 0;
}
/* The explanation body — reading ink (inherits .science-panel-body), seated under the
   headline with the card's gap rhythm. Zero its own block margins so the flex gap owns
   the spacing. */
.contradiction-answer-body { margin: 0; }

/* The "Cited passages" GROUP LABEL above the open verse-cards. It is QUIET chrome — a
   plain, NON-interactive <p>, never a clickable summary — so it gets the recessive
   uppercase-eyebrow treatment the answer card's other quiet labels use (faint ink, the
   UI face, a touch of tracking), NEVER a link/brand colour and NEVER a hover lift. It
   renders on every answer-with-citations (uniform), carries no count, and sits tight
   above the first card (the card grid's own gap owns the spacing below it). */
.contradiction-answer-cites-heading {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
/* The OVERFLOW toggle — the ONE collapsed <details> beneath the open cards holding the
   cards past the first 4. It reuses the shared .study-share chrome (icon + chevron +
   label) verbatim; this rule only seats it beneath the open cards (a small top gap) so
   it reads as a continuation of the citation group, not a detached control. */
.contradiction-answer-passages-overflow { margin-block-start: var(--space-1); }

/* CONTRADICTIONS — the SAB ATTRIBUTION footer, the LAST child of the main spine (the
   "Sources" scholarship block now sits in the spine just above it, beneath the commentary;
   see .contradiction-sources below). One quiet hairline opens it so the provenance reads as
   a deliberate, dignified section — never buried. It stays at full reading prominence (NOT
   shrunk into chrome) because it is the page's honesty signal. The line is muted reading
   ink; the link lifts to the brand on hover/focus. */
.contradiction-attribution {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border-soft);
}
.contradiction-attribution-line { margin-block: 0; line-height: 1.55; }
.contradiction-attribution-link { color: inherit; }
.contradiction-attribution-link:hover,
.contradiction-attribution-link:focus-visible { color: var(--brand); }

/* CONTRADICTIONS — the OPEN "Examining the tension" commentary section (owner tasks
   #14/#15). The commentary now renders as an OPEN reading section by default (no longer a
   collapsed <details>), so the balanced scholarly content surfaces. It rides the same
   neutral .rail-card frame the variants panel uses + the shared .science-panel-header band
   (badge + <h2> title + gold hairline) that "The tension" and "Proposed answers" use, so it
   reads as a PEER section to the answers — never the page's conclusion. The standing
   disclaimer is a visible muted LEAD beneath the band; the commentary prose follows it open;
   the peer-reviewed SOURCES are FOLDED IN as the card's tail (see below). Block rhythm only;
   gold stays chrome-only (the badge ring/glyph + the header hairline). */
.contradiction-commentary { margin-block: var(--space-5); }
/* The disclaimer lead — muted reading ink, a small gap under the header band and above the
   commentary prose, capped to the reading measure (inherits .muted for the secondary ink). */
.contradiction-commentary-disclaimer {
  margin-block: 0 var(--space-3);
  max-width: var(--measure);
  line-height: 1.55;
}
/* The leading caveat's OPENING clause — ONE quiet weight step up from the muted remainder:
   reading ink only (no bold, no gold, no size bump, no uppercase). It makes the attribution
   ("one scholarly reading… not GEBible's position") un-skippable above the consensus grade
   without out-shouting it. Gold stays chrome-only. Page-scoped; .muted is untouched. */
.contradiction-commentary-disclaimer-lead { color: var(--text-primary); }
/* The commentary prose — reading ink (inherits .science-panel-body), seated open beneath
   the disclaimer with no extra top margin (the disclaimer owns the gap above it). The body
   now renders as one <p> PER authored paragraph (the route splits the newline-separated DB
   text), so stacked siblings get a normal reading gap BETWEEN them: each non-final paragraph
   carries a bottom margin while the FINAL one stays flush (the disclaimer still owns the gap
   above the first, and the folded Sources sub-block owns the gap below the last). Scoped to
   .contradiction-commentary-body only — the shared .science-panel-body is untouched. */
.contradiction-commentary-body { margin-block: 0; }
.contradiction-commentary-body:not(:last-of-type) { margin-block-end: var(--space-3); }

/* CONTRADICTIONS — the FOLDED "Sources for this reading" sub-block (owner-decided fold). The
   peer-reviewed scholarship is no longer a peer SECTION with its own <h2>; it is the TAIL of
   the "Examining the tension" card, subordinate to the reading it supports. To keep it clearly
   DISCERNIBLE (the owner condition) it is set off from the commentary prose by a quiet hairline
   divider + generous top spacing — it reads as a bounded sub-block, never blended into the
   prose. It renders the STRUCTURED reading list (the normalized scholarship layer): a SCANNABLE
   citation LIST (.contradiction-sources-list), one <li> per source in the DB's citation_order
   (never re-sorted/ranked). Each row leads with the verbatim bib_core display identity in a
   .contradiction-source-cite (a <cite>), with the nullable page / note / verse-ref appendages
   riding after it as quiet recessive spans (.contradiction-source-pages / -note / -refs) so the
   work reads with typographic hierarchy without any of the appendages competing with it. */
.contradiction-commentary-sources {
  margin-block-start: var(--space-4);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border-soft);
}
/* The quiet "Sources for this reading" SUB-LABEL — a plain <p>, NOT a heading (the fold drops
   the page's <h2> count by one). It takes the SAME recessive uppercase-eyebrow treatment the
   answer card's "Cited passages" sub-label uses, so it reads as a quiet sub-label subordinate
   to the reading — never a peer section title, never gold (gold is chrome-only here). */
.contradiction-sources-heading {
  margin-block: 0 var(--space-3);
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-faint);
}
/* The scannable citation list — reset (no bullet/indent); each citation its own line with
   comfortable line-height and a clear gap between items so a long reference list scans. */
.contradiction-sources-list {
  list-style: none;
  margin-block: 0;
  padding-inline-start: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
/* One citation row — reading ink, generous line-height; a quiet hairline rule between items
   (a soft separator, NOT gold) so adjacent citations are visually distinct without weight. */
.contradiction-source {
  margin-block: 0;
  line-height: 1.55;
  color: var(--text-primary);
  padding-block-end: var(--space-3);
  border-block-end: 1px solid var(--pane-border-soft);
}
.contradiction-source:last-child { padding-block-end: 0; border-block-end: 0; }
/* The cited WORK — the verbatim bib_core display identity wrapped in a <cite>. An italic face
   (the conventional citation idiom) sets the work apart from the recessive page/note/verse
   appendages that follow it on the same line. Reading ink (the citation is content), NEVER gold
   (gold is chrome-only here). The <cite> default browser italics are made explicit + ink-set. */
.contradiction-source-cite {
  font-style: italic;
  color: var(--text-primary);
}
/* The nullable per-use appendages — pages ("pp. 71-79"), the editor note, and any cited verse
   refs. Each rides after the work on the same line in RECESSIVE secondary/faint ink so it never
   competes with the cited work, but stays a normal (upright) face so the italic cite remains the
   visual anchor. Rendered only when the field is present (the view gates each). */
.contradiction-source-pages,
.contradiction-source-note,
.contradiction-source-refs {
  font-style: normal;
  color: var(--text-secondary);
}
.contradiction-source-note { color: var(--text-faint); }

/* CONTRADICTIONS — the meta-rail "Cite this page" control. A Wikipedia-style "cite this
   page" disclosure that reuses the .study-share* chrome verbatim (the disclosure summary,
   chevron, and sunken menu body), so it reads as one family with the Share panel directly
   above it. It sits in the recessive rail, so it inherits the rail's per-child spacing; no
   extra cap is needed (the rail is already ~20rem). Gold stays chrome-only (the summary
   warms to --brand on hover/focus via the inherited .study-share-summary rules). */
.contradiction-cite-note {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.8rem;
  line-height: 1.5;
  color: var(--text-secondary);
}
/* The citation itself — SELECTABLE reading text (the no-JS payload). A comfortable measure
   and line-height; reading ink, NOT mono (it is a citation, kept readable, never gold). The
   long canonical URL inside it must wrap rather than overflow the narrow rail. */
.contradiction-cite-text {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.55;
  color: var(--text-primary);
  overflow-wrap: anywhere;
}

/* CONTRADICTIONS — the LIGHT "Browse by type" RAIL card chip nav. It reuses the
   .bible-search-suggest / -chip idiom (the recessive content pills), but that idiom is
   authored for the centered hero "Try searching:" row (centered, with a top margin). This
   modifier reseats the chip row inside a rail card: START-aligned (the rail reads as a
   left column, not a centered band) and flush to the card header (the .rail-card-header
   already owns the spacing above, so the row drops its own top margin). It is the
   DEFERRED axis, so the chips stay count-less + icon-less — no weight is added here. */
.contradiction-type-chips {
  justify-content: flex-start;
  margin-block-start: 0;
}

/* 1) THE CITED PASSAGE(S) — the HERO. The PRIMARY passage and any additional
   citation blocks are each an .analysis-featured (gold frame-edge, raised) card;
   the verse text inside stays reading ink. Stacked with the content rhythm. In
   the STACKED (short-passage) layout the hero is capped at the reading measure so
   it aligns left-flush with the science/framing panels below it (which share that
   same var(--measure) cap); the two-column override below lifts the cap so a long
   passage fills its co-equal column track. */
.science-passages {
  display: grid;
  gap: var(--space-4);
  margin-block: var(--space-5);
  max-width: var(--measure);
}
.science-passage { margin: 0; }
/* The reference eyebrow row: the borrowed uppercase eyebrow recipe lays out as a
   baseline row so the gold cite glyph seats beside the reference text. */
.science-passage-ref {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-2);
  row-gap: 0;
}
/* The reference link stays MUTED (eyebrow ink) — gold is the glyph + frame only. */
.science-passage-ref-link { color: var(--text-secondary); }
/* Reading content: --text-primary + reading font ONLY (the .scripture face). No
   --brand anywhere on the verse text. PROSE verses flow INLINE so the passage reads
   as a PARAGRAPH (the reader's .verse-para idiom), each carrying its recessive
   inline-superscript verse-number marker; POETRY verses keep the reader's indents. */
.science-passage-text {
  margin-block: 0 var(--space-3);
  padding-inline-start: var(--space-3);
  border-inline-start: 3px solid var(--pane-border);
  color: var(--text-primary);
  line-height: 1.6;
}
/* PROSE verses flow INLINE within the passage — consecutive prose runs together as
   a paragraph (mirrors the reader's .verse-para prose flow), separated by the
   template's trailing space and the inline-superscript .verse-num-static marker.
   POETRY verses stay BLOCK stichographic lines so Psalms never become paragraph mush;
   they use the same .verse-poetry[data-indent] hook as the reader but a TIGHTER indent
   step (1.5/3/4.5em vs the reader's 3/4.5/6em), suited to the narrower passage card.
   (Inline elements ignore vertical margins, so the last-child reset lives on poetry.) */
.science-passage-verse { display: inline; }
.science-passage-verse.verse-poetry { display: block; margin-block: 0 var(--space-2); }
.science-passage-verse.verse-poetry:last-child { margin-block-end: 0; }
.science-passage-verse.verse-poetry[data-indent="1"] { padding-inline-start: 1.5em; }
.science-passage-verse.verse-poetry[data-indent="2"] { padding-inline-start: 3em; }
.science-passage-verse.verse-poetry[data-indent="3"] { padding-inline-start: 4.5em; }
/* The "Read in context" deep-link line + the honest truncation note. The note is
   muted reading ink (an honesty cue, not chrome); the link is a real focusable
   affordance whose arrow goes gold only on hover/focus. */
.science-passage-context-line { margin: 0; font-size: 0.95rem; }
.science-passage-truncated {
  margin-block: var(--space-2) 0;
  font-size: 0.9rem;
  color: var(--text-secondary);
  line-height: 1.5;
}
.science-passage-context { white-space: nowrap; }
.science-passage-empty { margin-block: var(--space-4); }

/* Per-card "Copy" pill — the progressive-enhancement affordance that copies the CITED
   SCRIPTURE (verse text + reference + permalink) in the app's established quote/reference
   format. The button sits on the panel's reference (title) line via the shared
   .verse-copy-* family below (partials/verse-copy-button.ejs). Rendered `hidden` server-
   side (clipboard needs JS); app.js's initVerseCopy() reveals + wires it. Neutral treatment
   mirroring .share-permalink-action: reading-ink label/glyph (never brand red on a reading
   surface), a soft border that warms to the gold --accent-border ONLY on hover/focus (gold
   stays chrome-only), and a >=44px mobile tap target. */
.verse-copy-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-block-size: 44px; /* >=44px mobile tap target (WCAG 2.5.8) */
  padding-block: 0.4rem;
  padding-inline: 0.7rem;
  box-sizing: border-box;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  cursor: pointer;
}
.verse-copy-btn:hover { border-color: var(--accent-border); background: var(--surface-sunken); }
.verse-copy-btn:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

/* SHARED verse-copy family — the canonical partial (partials/verse-copy-button.ejs) that
   sits on a panel's reference (title) line across every cited-verse surface (the /science +
   /messianic + /contradictions passage cards, the dossier hero, the homepage spotlight, and
   the reader passage/parallel surfaces as they adopt it). A NEW class family so no shared
   .science-* / .analysis-* rule shifts (the shared-class trap). Gold stays chrome-only: the
   glyph is --text-primary throughout; gold appears only on the .verse-copy-btn hover/focus
   border above. */

/* The reference (title) line as a SELF-SUFFICIENT flex row: it lays the leading cite glyph +
   reference text out inline and lets the icon copy button push to the row's end (via
   .verse-copy-inline margin-inline-start: auto). It RESTATES the .science-passage-ref flex
   recipe so a surface already carrying that class keeps identical layout, but with
   align-items: center — the 44px icon pill seats on the eyebrow's vertical center rather than
   floating above its text baseline. On a bare ref line (the dossier glyph line, the spotlight
   reference) it supplies the whole flex recipe on its own. Placed AFTER .science-passage-ref
   in this file so, on a row carrying both, its center alignment wins on equal specificity. */
.verse-copy-ref-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: var(--space-2);
  row-gap: 0;
}
/* Wrapper for the icon button + its status live-region: margin-inline-start: auto shoves the
   pair to the row's hard end; the status stays a SIBLING of the button so initVerseCopy()
   resolves it via btn.parentNode.querySelector('[data-verse-copy-status]'). */
.verse-copy-inline {
  margin-inline-start: auto;   /* consume the free space -> hard-right within the flex ref line */
  align-self: center;          /* seat the 44px pill against the ref-line center without overriding the shared align-items */
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
/* Icon-only variant of the .verse-copy-btn pill: a square >=44px tap target with the glyph
   centered and no text gap. Inherits the soft border + gold-on-hover-only chrome from
   .verse-copy-btn (gold stays chrome-only; the glyph stays --text-primary throughout). */
.verse-copy-icon {
  min-inline-size: 44px;
  padding-inline: 0.4rem;
  justify-content: center;
  gap: 0;
}
.verse-copy-glyph { inline-size: 1.1rem; block-size: 1.1rem; }

/* --- COPY FEEDBACK: the transient state on EVERY clipboard control (owner request) ---
   Every copy button in the app already wrote its outcome into a live region, but all but
   one of those regions is .visually-hidden — the feedback existed for screen readers and
   for nobody else, so pressing Copy visibly did nothing at all. app.js's flashCopyState()
   now also stamps .is-copied / .is-copy-failed on the BUTTON for two seconds, and this
   block is the whole visual half of that state. The live regions are untouched, so the
   accessible channel keeps its exact strings and nothing is announced twice.

   A MARK, NOT A COLOUR. THEME.md §1 routes --note to user notes and --danger to
   destructive actions, and the pricing-table rule earlier in this file already settled
   that this app has no semantic success token and must not invent one: a green here would
   speak a colour language nothing else on the site speaks, and gold is chrome and cannot
   mean "succeeded". So the state is carried entirely by SHAPE — a check for success, a
   cross for failure. Shape-only is why a success tick can never read as an editorial mark
   on a Scripture Analysis surface, and why the state survives colour-blindness with no
   second channel bolted on (THEME.md §1: never colour alone). Nothing animates, so there
   is no motion for the reduced-motion clamp at the top of this file to neutralise.

   GENERATED CONTENT, NOT MARKUP, because the canonical [data-verse-copy] pill is stamped
   once per cited passage — 108 of them on /v/john/3/compare — and a second inline <svg>
   per button would have shipped ~46 KB of never-shown glyph on that one page. It also
   keeps app.js free of node-building (CSP) and the shared partial byte-unchanged.

   Every rule below is an ADDITIVE .base.is-* modifier declared AFTER the base rule it
   qualifies, so nothing renders differently at rest and no shared button body is edited
   (the shared-class trap — the unchanged shared-surface tests are the scoping proof). */
.verse-copy-btn.is-copied::after,
.share-permalink-action.is-copied::after,
.study-share-item.is-copied::after,
.share-action.is-copied::after,
.verse-popover-action.is-copied::after { content: '✓'; font-weight: 700; }
.verse-copy-btn.is-copy-failed::after,
.share-permalink-action.is-copy-failed::after,
.study-share-item.is-copy-failed::after,
.share-action.is-copy-failed::after,
.verse-popover-action.is-copy-failed::after { content: '✕'; font-weight: 700; }

/* The canonical pill is ICON-ONLY by design (its label lives on aria-label), so it has no
   text for a mark to trail: the mark REPLACES its copy glyph, sized to the glyph it stands
   in for. .verse-copy-icon's min-inline-size already fixes the pill's width, so the swap
   costs no layout shift. */
.verse-copy-btn.is-copied .verse-copy-glyph,
.verse-copy-btn.is-copy-failed .verse-copy-glyph { display: none; }
.verse-copy-btn.is-copied::after,
.verse-copy-btn.is-copy-failed::after { font-size: 1.1rem; line-height: 1; }

/* .share-permalink-action and .study-share-item are inline-flex WITH a gap, which spaces
   the mark for free; these two lay their contents out without one, so it buys its own. */
.share-action.is-copied::after,
.share-action.is-copy-failed::after,
.verse-popover-action.is-copied::after,
.verse-popover-action.is-copy-failed::after { margin-inline-start: 0.35rem; }

/* MESSIANIC PASSAGE-CARD ACTIONS — the "Read in context" link, the "Show the surrounding
   verses" disclosure, and "Copy" restyled to read as ONE coherent button-pill row
   (messianic detail P4b follow-up). .messianic-passage-btn is a NEW class carried
   ALONGSIDE .science-passage-context on the standalone "Read in context" anchor (that
   shared class is left byte-untouched elsewhere — the inline "Read in context" mentions
   inside prose sentences never get this class). It is a byte-for-byte copy of the
   .verse-copy-btn pill so the two read as twins; the anchor stays a REAL navigating <a>
   (no JS, no button). */
.messianic-passage-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-block-size: 44px; /* >=44px mobile tap target (WCAG 2.5.8), matches .verse-copy-btn */
  padding-block: 0.4rem;
  padding-inline: 0.7rem;
  box-sizing: border-box;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  text-decoration: none; /* override the global `a` underline so it reads as a pill, not a link */
}
.messianic-passage-btn:hover {
  border-color: var(--accent-border);
  background: var(--surface-sunken);
  text-decoration: none;
}
.messianic-passage-btn:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

/* 2) + 3) THE SCIENCE + FRAMING PANELS — elevated .rail-card panels with a leading
   icon-badge and a gold panel-title hairline. The framing panel recedes a step
   (muted body ink) so it never competes with the science. */
.science-panel { margin-block: var(--space-5); max-width: var(--measure); }
.science-panel-header {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-block-end: var(--space-3);
  padding-block-end: var(--space-3);
  /* Gold panel-title HAIRLINE — sanctioned structural chrome; tints no text. */
  border-block-end: 1px solid var(--accent-border);
}
/* Slightly smaller than the landing's 2.5rem badge so the panel header stays
   calm; ring chrome inherited from .icon-badge. */
.science-panel-badge { inline-size: 2.25rem; block-size: 2.25rem; }
.science-panel-title { margin: 0; font-size: 1.15rem; line-height: 1.3; }
.science-panel-body { margin: 0; line-height: 1.6; color: var(--text-primary); }
/* Framing body is SECONDARY — muted ink so it reads as the recessive source-first
   framing, never leading. */
.science-panel-body-framing { color: var(--text-secondary); line-height: 1.55; }

/* #51 — "ANATOMY OF THE CLAIM" aspect list (History/Archaeology detail pages). A calm stacked
   list that REPLACES the raw science prose: per aspect, a status chip + the point (reading ink) +
   an optional muted source + an optional verbatim public-domain quote. Each aspect is a two-column
   grid (chip | point) so the source drops beneath the point and a quote spans full width. */
.science-anatomy {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.science-anatomy-aspect {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: var(--space-3);
  row-gap: var(--space-1);
  align-items: baseline;
}
/* RULE 5 — SYMMETRIC TEMPERATURE. documented + debated read at EQUAL visual weight: same UI ink,
   same size; they differ ONLY by fill-vs-outline (a calm neutral distinction), never gold (chrome-
   only), never a red/alarm hue. Both sit in the recessive secondary ink. */
.science-anatomy-status {
  grid-column: 1;
  display: inline-flex;
  align-items: center;
  font-family: var(--font-ui);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  line-height: 1;
  padding: 0.25rem 0.5rem;
  border-radius: 999px;
  white-space: nowrap;
  color: var(--text-secondary);
  border: 1px solid var(--pane-border);
}
/* documented — quiet FILLED pill (sunken surface). */
.science-anatomy-status--documented { background: var(--surface-sunken); }
/* debated — quiet OUTLINE pill (transparent fill, slightly firmer border) at the SAME salience. */
.science-anatomy-status--debated { background: transparent; border-color: var(--text-faint); }
.science-anatomy-point { grid-column: 2; line-height: 1.6; color: var(--text-primary); }
/* The attribution drops beneath its point (aligned to column 2), recessive reading ink. */
.science-anatomy-source {
  grid-column: 2;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-faint);
}
/* An optional verbatim public-domain quote — spans both columns, reading ink, with a quiet
   inline-start hairline as the quote treatment (NOT a big gold quote mark; gold stays chrome-only),
   mirroring the contradictions pole-quote idiom. */
.science-anatomy-quote {
  grid-column: 1 / -1;
  margin: 0;
  padding-inline-start: var(--space-4);
  border-inline-start: 2px solid var(--pane-border);
  line-height: 1.6;
  color: var(--text-primary);
}
.science-anatomy-quote-attr {
  display: block;
  margin-block-start: var(--space-1);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-faint);
}

/* 4) CITATIONS META — a quiet footer hairline strip; citation text reading ink. */
.science-detail-meta {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--pane-border-soft);
  font-size: 0.9rem;
  color: var(--text-secondary);
}
.science-detail-citations { margin-block: 0 var(--space-2); }
/* Theme chip — chrome, so the gold accent border is allowed here. */
.science-tag {
  display: inline-block;
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  border: 1px solid var(--accent-border);
  color: var(--text-primary);
  text-decoration: none;
  min-block-size: 1.75rem;
  line-height: 1.5;
}
.science-tag:hover { background: var(--accent-soft); }

/* FIX 3 — THREE HONEST WAYS TO READ THIS PASSAGE on the DETAIL page. The block
   reuses the landing's full posture class family verbatim (.analysis-postures /
   .posture-card / .posture-title / .posture-body / .analysis-postures-closing);
   this DETAIL-SCOPED modifier only re-rhythms the block for its detail context.
   The landing's `.analysis-postures` carries a plain `margin-block` because it sits
   between sibling sections on the landing; on the detail page the block joins the
   full-width related-module stack (the citations footer / "Also examined in" /
   "More in this field"), each of which leads with a top hairline separator. So the
   modifier drops the landing's symmetric block margin and instead leads with the
   same top separator + the family's section rhythm, so the postures ride the same
   cadence as the modules around it. Full-width within the container, like its
   neighbours — never inside the recessive two-column rail. */
.science-detail-postures {
  margin-block: var(--space-7) 0;
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--pane-border-soft);
}
/* The section heading inside the detail postures block uses the same shared
   .analysis-section-heading as the landing; zero its default leading margin here so
   the separator + padding above (not a doubled gap) sets the block's top rhythm. */
.science-detail-postures .analysis-section-heading { margin-block-start: 0; }

/* 5) MORE IN THIS FIELD — the related hub. A compact grid of rail mini-cards, each
   a statement claim (link) + its citation + a one-line teaser + an arrow. Reuses
   the .rail-card chrome; the claim + teaser + citation are reading ink (gold lives
   only on the card hover frame, the cite glyph, and the arrow hover). */
.science-related {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--pane-border-soft);
}
.science-related-heading { margin-block: 0 var(--space-4); font-size: 1.2rem; }
/* The theme link in the heading is a real link; gold appears on hover/focus only. */
.science-related-theme-link { color: inherit; }
.science-related-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 18rem), 1fr));
}
.science-related-card { display: flex; flex-direction: column; gap: var(--space-2); }
.science-related-claim { margin: 0; font-size: 1.05rem; line-height: 1.35; }
.science-related-claim a { color: var(--text-primary); text-decoration: none; }
.science-related-claim a:hover { text-decoration: underline; }
/* Citation reuses the borrowed eyebrow recipe (uppercase, muted) laid out as a
   baseline row beside the gold cite glyph. */
.science-related-cite {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  column-gap: var(--space-2);
  row-gap: 0;
  margin: 0;
}
.science-related-teaser { margin: 0; color: var(--text-secondary); line-height: 1.5; font-size: 0.95rem; }
/* Push the "Read the entry →" line to the card foot so cards of unequal text
   length keep their CTA aligned. */
.science-related-more { margin-block: auto 0; font-size: 0.95rem; }

/* --- FIX 6: "The same picture elsewhere in Scripture" curated cross-ref cluster -
   A compact panel listing the OTHER passages that make the same cosmological
   picture (the firmament / fixed-earth clusters). It REUSES the .science-related*
   idiom above verbatim (same heading, same card grid, same card chrome); this
   modifier only tightens the heading->lead->grid rhythm by pulling the descriptive
   lead up under the heading and giving the card grid the normal block flow after
   it. The lead is plain reading ink (DESCRIPTIVE, never a verdict) — gold stays
   chrome-only (the card hover frame, the cite glyph, the arrow), inherited from
   .science-related-card. No new colors, no inline styles. */
.science-related-cluster-lead {
  margin-block: calc(-1 * var(--space-3)) var(--space-4);
  color: var(--text-secondary);
  line-height: 1.5;
}

/* --- WS A: in-page VERSION SWITCHER ------------------------------------------
   The control mirrors the study-page reader-toolbar `versionMenu` dropdown EXACTLY
   (it reuses the .reader-versions* classes, so the dropdown chrome — the gold
   summary frame, caret, the pinned active row's gold ring + check, the panel —
   are inherited verbatim). This block only POSITIONS the switcher above the
   passage hero and supplies the eyebrow label. The version NAMES inside the panel
   stay reading ink (inherited from .reader-versions-item-name); gold is chrome
   only (the select/CTA frame the .reader-versions rules already paint). */
.science-version-switch {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  /* Right-align the whole switcher cluster (label + dropdown stay together) to the
     row's right edge — the far right of the full content width in two-column, the
     right edge of the measure column when stacked. */
  justify-content: flex-end;
  gap: var(--space-2) var(--space-3);
  margin-block-end: var(--space-4);
}
/* The eyebrow label is a quiet UI cue (reading ink, not gold). */
.science-version-switch-label {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-secondary);
}
/* The dropdown shell is the .reader-versions <details>, which already supplies its
   own `position: relative` (the anchor for the absolutely-positioned panel), so no
   extra positioning context is needed here. The .science-version-switch-menu hook
   is kept on the markup for any future detail-only adjustment. */
/* HOISTED: the switcher is now a direct flex child of .science-detail-body (a full-
   width row ABOVE both columns), so the right rail aligns to the VERSE-CARD TOP — not
   the switcher — in two-column mode. Zero its own bottom margin here so the body's
   flex `gap` (var(--space-5)) is the ONLY spacing between it and the passages; the
   default `.science-version-switch` margin-block-end stays for any other (stacked)
   use site. */
.science-detail-body > .science-version-switch { margin-block-end: 0; }

/* --- WS A: deuterocanon-absent HONEST note ----------------------------------
   When the active version lacks a cited (usually deuterocanonical) book, the
   passage degrades to citation-only + this honest note, which OFFERS the versions
   that DO carry it as ?version= links. Muted reading ink (an honesty cue, never a
   blank passage); the offered version links use the default link color (a real
   affordance), and the active-version code is set in reading ink, not gold. */
.science-passage-absent {
  margin-block: 0 var(--space-3);
  font-size: 0.95rem;
  color: var(--text-secondary);
  line-height: 1.55;
}
.science-passage-absent-version { color: var(--text-primary); font-weight: 600; }

/* --- WS B: ADAPTIVE BALANCED TWO-COLUMN BODY --------------------------------
   The middle of the detail page (the cited passage hero + the version switcher
   ABOVE it = LEFT column; "What current science says" at FULL weight + "How the
   text frames it" recessive beneath = RIGHT column). This is a BALANCED ~1:1
   "scripture BESIDE science" split — science is the section's core payload and is
   never demoted to a thin rail.

   DEFAULT (and ALWAYS below the breakpoint): a single stacked column in DOM/source
   order (passage -> science -> framing) — correct for screen readers, no-JS, and
   crawlers, and the calm layout a single-verse / short citation keeps.

   TWO-COLUMN (`.science-detail-2col`, set by the route's `passageIsLong` hint, AND
   only at >=64rem — the same breakpoint the study grid uses): the columns are
   produced by CSS GRID PLACEMENT, NEVER the `order:` property, so source order is
   preserved. The grid has EXACTLY TWO direct children — the passage section (LEFT)
   and the .science-detail-aside wrapper (RIGHT) which stacks the science + framing
   panels in source order (science first, framing beneath). Grouping the right-column
   panels in one wrapper is the SAME proven idiom the study grid uses (.study-rail):
   it makes the grid a clean 2-cell layout, so the right column stacks normally and
   the framing panel sits DIRECTLY beneath the science instead of being stranded by a
   row-span hack. With `align-items: start` both columns top-align. Logical-property
   gap; tokens only.

   STACKED-BODY CAP: the body column is capped at the reading measure and centered
   (margin-inline: auto) so a SHORT passage's empty space is SYMMETRIC on both sides
   rather than dumped on the right — it sits beneath the centered title masthead as a
   balanced block. The two-column rule below LIFTS this cap (max-width: none) so the
   grid fills the full content width; the title (outside the body) stays centered. */
.science-detail-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: var(--measure);
  margin-inline: auto;
}
/* Margin rhythm lives on the wrapper now, so the inner panels don't double it.
   The Share <details> (.science-share) is now the last aside child too, so it
   zeroes its block margin the same way — its spacing comes solely from the aside
   gap (uniform with the science + framing panels). */
.science-detail-body > .science-passages,
.science-detail-body > .science-detail-aside > .science-panel,
.science-detail-body > .science-detail-aside > .science-share { margin-block: 0; }

/* RIGHT-COLUMN ASIDE — groups the science + framing panels into ONE grid child so
   the two-column grid is a clean 2-cell layout (the .study-rail idiom). It stacks
   its panels as a flex column with the SAME gap the body uses between its stacked
   children (var(--space-5)), so the single-column stacked layout is visually
   IDENTICAL to before this wrapper existed. Capped at the reading measure in the
   stacked baseline (like .study-rail); the two-column rule lifts that cap. */
.science-detail-aside {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  max-width: var(--measure);
}

@media (min-width: 64rem) {
  .science-detail-2col {
    display: grid;
    /* Co-equal ~1:1 columns — scripture beside science, neither demoted. */
    grid-template-columns: 1fr 1fr;
    align-items: start;
    gap: var(--space-5) var(--space-6);
    /* Lift the stacked body cap so the grid fills the full content width; the
       title stays centered (it is outside the body) — only the body goes full-width. */
    max-width: none;
  }
  .science-detail-2col > * { min-width: 0; } /* let long words wrap inside cells */
  /* FULL-WIDTH FIRST ROW: the hoisted version switcher spans BOTH columns. It auto-
     places to row 1; the passage section (col 1) and the aside (col 2) then both begin
     at row 2 and — with `align-items: start` — top-align, so the right rail aligns to
     the VERSE-CARD TOP rather than floating above it. No `order:` / no grid-template-
     rows: the switcher auto-places to row 1 and the two columns to row 2. */
  .science-detail-2col > .science-version-switch { grid-column: 1 / -1; }
  /* LEFT column: the passage hero. The reading-measure cap is lifted so it fills
     its co-equal column track. grid-column PLACEMENT (no `order:`, no row-span). */
  .science-detail-2col > .science-passages {
    grid-column: 1;
    max-width: none;
  }
  /* RIGHT column: the aside wrapper — its science + framing panels flow down it in
     source order (science first, framing beneath). The reading-measure cap is lifted
     on the aside AND its panels so each fills the co-equal column track. */
  .science-detail-2col > .science-detail-aside {
    grid-column: 2;
    min-width: 0;
    max-width: none;
  }
  .science-detail-2col > .science-detail-aside > .science-panel { max-width: none; }
}

/* =========================================================================
   ANALYSIS LANDING family (.analysis-*) — the two-column Scripture-Analysis
   section template, debuted on /science and built to be inherited by future
   sections (Worldview/Contradictions/…). Content LEFT (the argument: hero →
   stats → postures → search → field chips → browse-by-book); orientation RAIL
   right (How this works + the live Featured example).

   GOLD IS CHROME-ONLY here (THEME.md §0/§2): allowed on the icon-badge rings,
   the stat divider hairline, the search submit button (.btn), card-frame chrome,
   and link hover/focus. BANNED on stat numbers, the featured verse text, section
   names, and persistent "→"/CTA text at rest — those paint --text-primary /
   --text-secondary. Tokens-only color; logical properties; ≥44px interactive
   targets; visible :focus-visible; reduced-motion-safe (no count-ups/animations).
   AA-verified in dark/light/sepia (numbers + verse on --text-primary; gold marks
   resolve to the AA-safe gold-ink --brand on light/sepia).
   ========================================================================= */
.analysis-landing {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
  gap: var(--space-6);
  align-items: start;
  padding-block-end: var(--space-8);
}
/* Single column on narrow viewports: the rail drops below the content. Source
   order already puts content first, so this is a pure reflow. */
@media (max-width: 52rem) {
  .analysis-landing { grid-template-columns: 1fr; }
}
.analysis-content { min-inline-size: 0; }

/* Shared section heading inside the content column (the rail uses .rail-card-title). */
.analysis-section-heading {
  margin-block: var(--space-6) var(--space-3);
  font-size: 1.2rem;
}

/* --- 1) Hero — CENTERED as a single "section opener" unit WITHIN the left
   content column (the rail stays in its own grid track; the hero is NOT
   full-bleed). The glyph + <h1> center horizontally; the intro BLOCK centers via
   margin-inline:auto but its long-paragraph TEXT stays start-aligned within the
   centered measure (centered body copy of ~5 sentences is hard to read). --- */
.analysis-hero {
  margin-block-end: var(--space-5);
  text-align: center; /* centers the inline glyph + the <h1> */
}
/* Decorative glyph — gold chrome via currentColor (--brand resolves to gold-ink
   on light/sepia). Sized as a small quiet mark; never focusable. Centered as a
   block so the inline text-align above lands it dead-center over the title. */
.analysis-hero-glyph {
  display: block;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  color: var(--brand);
  margin-block-end: var(--space-2);
  margin-inline: auto;
}
.analysis-hero-title { margin-block: 0 var(--space-3); }
.analysis-hero-intro {
  margin-block: 0;
  margin-inline: auto;          /* center the capped block within the column */
  max-inline-size: var(--measure);
  color: var(--text-secondary);
  font-size: 1.05rem;
  line-height: 1.6;
  text-align: start;            /* readable: long body copy stays start-aligned */
}

/* --- 2) Stat strip — EXACTLY two live stats, CENTERED beneath the hero. Each
   stat is a row: a gold-RING .icon-badge (decorative glyph, currentColor →
   --brand) at the inline-start, then the value-over-label pair in
   .analysis-stat-text. Numbers display-size in --text-primary (NOT gold); the
   ONLY gold is the badge ring + glyph (chrome) and the divider hairline. --- */
.analysis-stats {
  display: flex;
  flex-wrap: wrap;
  justify-content: center; /* center the pair within the content column */
  gap: 0;
  margin-block: var(--space-5);
}
.analysis-stat {
  position: relative;
  display: flex;
  flex-direction: row;            /* badge | (value-over-label) */
  align-items: center;
  gap: var(--space-3);
  /* Symmetric padding so the single hairline divider sits CENTERED between the
     two stats (the strip is centered now, not left-flushed). */
  padding-inline: var(--space-5);
}
/* Gold hairline divider between stats (chrome). Drawn on every stat but the
   first, so a single rule handles the one divider and scales if more are added.
   DESKTOP (side-by-side): a VERTICAL hairline on the inline-start edge reads as a
   separator BETWEEN the two stats. */
.analysis-stat + .analysis-stat::before {
  content: "";
  position: absolute;
  inset-block: 0.15rem;
  inset-inline-start: 0;
  inline-size: 1px;
  background: var(--accent-border);
}
/* MOBILE: once the centered strip flex-wraps to STACKED rows, the vertical
   inline-start hairline orphans to the wrapped stat's leading edge and reads as a
   stray indent rule instead of a separator. At the wrap point flip the same gold
   chrome hairline to its HORIZONTAL axis (a top hairline spanning the stat) so the
   "between siblings" divider tracks the stacking axis. 27rem (432px) is the live strip's
   measured (font-settled) wrap boundary AFTER the v132 de-scoreboard rebalance: shrinking
   the count to a quiet "N entries" line made each stat slightly narrower, so the two-section
   strip now stays side-by-side down to 433px (vertical divider preserved, desktop untouched)
   and wraps to stacked at <=432px (horizontal divider). [The pre-rebalance boundary was
   27.5rem/440px — the bigger 2.4rem count made each stat wider; the rebalance moved the wrap
   in by ~8px.] If more sections go live the strip will wrap at a wider viewport — revisit. */
@media (max-width: 27rem) {
  .analysis-stat + .analysis-stat::before {
    inset-block: unset;
    inset-block-start: 0;
    inset-inline: 1.5rem;          /* small inset so the rule reads as a divider, not a full-bleed border */
    inline-size: auto;
    block-size: 1px;
  }
}
/* The value-over-label stack beside the badge. column-reverse keeps the <dd>
   value visually above the <dt> label while DOM order stays dt→dd. */
.analysis-stat-text {
  display: flex;
  flex-direction: column-reverse;
  gap: 0.1rem;
}
/* Stat-specific sizing for the shared gold-ring badge (slightly larger glyph
   than the posture badges; ring chrome inherited from .icon-badge). */
.stat-badge { flex: 0 0 auto; }
.stat-glyph { inline-size: 1.5rem; block-size: 1.5rem; }
.analysis-stat-value {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 2.4rem;
  font-weight: 700;
  line-height: 1;
  color: var(--text-primary); /* NOT gold — this is content */
}
.analysis-stat-label {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}

/* DOSSIER-ONLY rebalance (.analysis-dossier-stats — 5-persona de-scoreboard consensus,
   2026-06-25). The global .analysis-stat* rules above are SHARED with the five science/
   contradictions landing strips, where the label is a UNIT NOUN and the value a corpus-scale
   number, so big-number-over-noun is CORRECT there and must NOT change. The per-verse dossier
   is the ONLY consumer where the label is a proper-noun section NAME and the value a small
   per-verse count — there the shared treatment made the count out-shout the name (it read as a
   SCORE). Scoped to the dossier modifier ONLY: drop column-reverse so the dt→dd DOM order is
   also the visual order (NAME above count), promote the NAME to the primary title-case ink, and
   recede the count to a quiet muted "N entries" line. Gold stays chrome-only (badge ring/glyph +
   divider hairline, unchanged). */
.analysis-dossier-stats .analysis-stat-text {
  flex-direction: column;        /* kill column-reverse: name (dt) above count (dd) */
}
.analysis-dossier-stats .analysis-stat-label {
  font-size: 1.05rem;            /* the NAME is now the primary ink */
  font-weight: 600;
  color: var(--text-primary);
  text-transform: none;          /* title-case as authored ("Science"), not all-caps */
  letter-spacing: normal;
}
.analysis-dossier-stats .analysis-stat-value {
  font-size: 0.85rem;            /* the count recedes to a quiet coverage detail */
  font-weight: 400;
  line-height: 1.3;
  color: var(--text-secondary);
}
/* WAYFINDING (#119) — each dossier stat is an in-page anchor link to its matching
   .analysis-area group below. The link carries the row layout the badge+text formerly
   got from .analysis-stat (display/align/gap mirrored from the global .analysis-stat
   rule above) so the resting strip is BYTE-IDENTICAL to before; .analysis-stat keeps its
   position:relative + padding so the gold ::before divider still positions correctly.
   Resting: no underline, inherited ink — visually unchanged. Hover/focus: underline ONLY
   the section NAME (the count's --text-secondary and the badge gold are untouched at every
   state — gold stays chrome-only). Keyboard focus shows the standard gold focus ring. */
.analysis-dossier-stats .analysis-stat-link {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: inherit;
}
.analysis-dossier-stats .analysis-stat-link:hover .analysis-stat-label,
.analysis-dossier-stats .analysis-stat-link:focus-visible .analysis-stat-label {
  text-decoration: underline;
}
.analysis-dossier-stats .analysis-stat-link:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
  border-radius: 2px;
}

/* --- 3) Posture cards — equal weight, never ranked. --- */
.analysis-postures { margin-block: var(--space-6); }
.analysis-posture-list {
  list-style: none;
  padding: 0;
  margin-block: var(--space-4) 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-4);
}
.posture-card {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
/* The gold-RING badge is chrome (OK); the glyph inside is a NEUTRAL mark. */
.posture-badge { margin-block-end: var(--space-3); }
.posture-glyph { inline-size: 1.4rem; block-size: 1.4rem; }

/* --- Scholarly-consensus GLYPH (the coarse 3-way visual echo of the attributed grade;
   src/views/contradictions/_consensus-glyph.ejs). PURE currentColor — NO gold on the glyph
   (it is reading-ink, never a "winning side" chrome mark). Reuses .posture-glyph for the
   shared house geometry; these rules add ONLY the soft-arm dimming + the two placement
   layouts (inline on the detail line, standalone on the listing card). */
/* The "lean" softening: the WHOLE diverging/converging HALF — the fork/merge arms AND their
   two branch end-dots (both carry .consensus-glyph-arm) — dims together toward the disputed
   middle, while the anchor circle stays full. Plain `opacity` (not stroke-opacity) so it dims
   the stroked arms AND the filled end-dots as one ghosted half; 0.45 reads clearly at 20px.
   No effect on the SPLIT shape (it has no .consensus-glyph-arm element). */
.consensus-glyph-soft .consensus-glyph-arm { opacity: 0.45; }
/* DETAIL placement — the glyph sits inline, on the baseline, just before the grade words. */
.consensus-glyph-inline {
  display: inline-flex;
  vertical-align: text-bottom;
  color: var(--text-secondary);
}
.consensus-glyph-inline .consensus-glyph { inline-size: 1.25rem; block-size: 1.25rem; }
/* LISTING placement — the mark LEADS the card title on the SAME row (this section's
   leading-glyph idiom), its meaning carried by the partial's <title>/aria-label + the
   adjacent visually-hidden text. Reading-ink, recessive. The wrapper is a contradictions-
   SPECIFIC flex row (NOT the shared .science-statement-* rules, so the science listing is
   untouched): a long, multi-line question wraps in its OWN column while the glyph hangs at
   the top-left / first-line — align-items:flex-start keeps it pinned to the first line, never
   pushed onto a row of its own. Graceful-null: a glyph-less card is a single-child flex row,
   visually identical to the bare <h2> it used to be (the <h2> already carries its own bottom
   margin via .science-statement-claim, so the wrapper adds none). */
.contradiction-card-head {
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
}
.contradiction-card-consensus-glyph {
  display: inline-flex;
  /* Nudge the 20px glyph down onto the title's first-line cap height so it reads as a
     leading mark on the baseline, not floating above the ascenders. */
  margin-block-start: 0.2rem;
  color: var(--text-secondary);
}
/* LISTING LEGEND — the small, recessive on-page KEY atop the list (the must-fix): the
   ATTRIBUTED intro line + the 3 base-shape decoder items. Reading-ink/neutral — the SAME
   --text-secondary recessive treatment as the card mark, never gold. The items flex-WRAP so
   the strip stays mobile-safe on a narrow viewport. */
.contradiction-consensus-legend { margin-block: 0 var(--space-3); }
.contradiction-consensus-legend-intro { margin-block: 0 var(--space-2); font-size: 0.9rem; }
.contradiction-consensus-legend-items {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1) var(--space-4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.contradiction-consensus-legend-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  color: var(--text-secondary);
  font-size: 0.9rem;
}
/* The decoder glyph reuses the card mark's recessive sizing/ink (never gold). */
.contradiction-consensus-legend-glyph {
  display: inline-flex;
  color: var(--text-secondary);
}
.posture-title { margin-block: 0 var(--space-2); font-size: 1.1rem; }
.posture-body { margin: 0; color: var(--text-secondary); line-height: 1.55; }
.analysis-postures-closing {
  margin-block-start: var(--space-4);
  max-inline-size: var(--measure);
}

/* --- 3) Search — PROMOTED directly below the stat strip and restyled to the
   homepage "paramount search" PILL idiom (mirrored from .hero-search into the
   .analysis-search* selectors — NOT the .hero-search class itself, which carries a
   56rem homepage cap). The whole .analysis-search-form is ONE rounded pill: a
   leading decorative magnifier, a borderless transparent input, and the inset
   solid-gold submit (the ONE legit gold CTA — an action affordance). The pill now
   fills the FULL content-column width (no cap, no centering) so it spans the same
   measure as the postures + browse-by-book sections below it; the visible heading is
   start-aligned to match those sibling section headings (a centered heading would read
   oddly above a left-edge-anchored full-width bar). --- */
.analysis-search { margin-block: var(--space-6); }
/* Start-align the heading to match the other left-aligned section headings (postures,
   browse-by-book) now that the pill below it spans the full column width. */
.analysis-search-heading { text-align: start; }
/* The pill — a subtle raised surface with a thin border, fully rounded, holding the
   magnifier + borderless input + inset gold button. Spans the full content column. The
   whole pill lights up with the standard gold focus halo on :focus-within. */
.analysis-search-form {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  inline-size: 100%;
  margin-block-start: var(--space-3);
  padding: 0.35rem 0.4rem 0.35rem 0.9rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  box-shadow: var(--shadow);
}
/* The pill (not the input) owns the focus halo. */
.analysis-search-form:focus-within {
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* Leading magnifier — decorative, muted gold chrome; sized/colored here, not inline. */
.analysis-search-icon {
  flex: 0 0 auto;
  inline-size: 1.25rem;
  block-size: 1.25rem;
  color: var(--brand);
  opacity: 0.75;
}
/* The input is borderless/transparent WITHIN the pill (the pill draws the chrome).
   Its own focus outline is removed because :focus-within lights the whole pill. */
.analysis-search-input {
  flex: 1;
  min-width: 0;
  min-block-size: 44px;
  padding: 0.55rem 0.5rem;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--text-primary);
  font: inherit;
}
.analysis-search-input::placeholder { color: var(--text-faint); }
/* The pill owns the focus halo (:focus-within above), so suppress the per-input
   global field-focus halo (Lemma §5.11) here — otherwise the input would draw a
   SECOND halo inside the pill. This covers ALL FOUR analysis search inputs:
   #science-search-input (science landing/listings), #contradictions-search-input
   (contradictions landing/listings), #messianic-search-input (messianic landing/
   listings) and #analysis-search-input (the /analysis hub + /analysis/search
   federated pill). An id selector is REQUIRED: the global field-focus rule's chained
   :not([type=…]) selectors out-specify any plain class, so only an id clears it for
   both :focus and :focus-visible. The pill's :focus-within halo remains the single
   visible focus indicator (a11y focus visibility preserved). The /bible/search pill's
   input is also #q (src/views/bible/search.ejs), but that id is NOT suppressed bare —
   id="q" is ALSO used by the plain /passages form (src/views/bible/passages.ejs),
   where the global field-focus halo is that input's ONLY focus indicator. So the
   suppression below is scoped to `.analysis-search-form #q` (the pill ancestor),
   which leaves the /passages #q untouched while still out-specifying the global rule
   via the id column. */
#science-search-input:focus,
#science-search-input:focus-visible,
#contradictions-search-input:focus,
#contradictions-search-input:focus-visible,
#messianic-search-input:focus,
#messianic-search-input:focus-visible,
#analysis-search-input:focus,
#analysis-search-input:focus-visible,
.analysis-search-form #q:focus,
.analysis-search-form #q:focus-visible {
  outline: none;
  border: 0;
  box-shadow: none;
}
/* The inset gold button — solid --brand-fill with dark-navy --on-accent text (AA on
   the fill in every theme, same tokens the homepage hero clears), rounded to sit
   inside the pill, ≥44px target. */
.analysis-search-submit {
  flex: 0 0 auto;
  min-block-size: 44px;
  padding: 0.6rem 1.4rem;
  border: 1px solid var(--brand-fill);
  border-radius: 999px;
  background: var(--brand-fill);
  color: var(--on-accent);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1rem;
  cursor: pointer;
}
.analysis-search-submit:hover { filter: brightness(1.05); }
/* On very narrow screens drop the leading icon and tighten padding so the input
   keeps usable room and the button stays inset (no overflow) — mirrors the hero. */
@media (max-width: 30rem) {
  .analysis-search-form { padding-inline-start: 0.6rem; }
  .analysis-search-icon { display: none; }
  .analysis-search-submit { padding-inline: 1rem; }
}

/* --- 5) Browse by book — a proper content-column PANEL (mockup styling over the
   honest /science data). The same card chrome as the rail panels (--surface-raised
   fill, --pane-border, 12px radius) scaled to the full content column: a header
   (gold open-book glyph + <h2> + honest subtitle), testament-grouped name·count·
   chevron rows, and a summary footer. The 10-field taxonomy that formerly lived in
   this column as chips now lives ONLY in the rail "Browse by field" panel.

   GOLD IS CHROME-ONLY here: the header glyph, the gold uppercase testament
   eyebrows (structural group labels), the row chevrons, and the footer ring badge
   are gold; the book NAMES, the per-book COUNTS, and the footer STAT numbers are
   reading ink (--text-primary / --text-secondary). The gold eyebrow is small gold
   TEXT, so it must clear AA (≥4.5:1), not just the 3:1 graphic threshold: --brand
   on the panel's --surface-raised ground reads light 5.32:1 / dark 6.16:1 / sepia
   5.52:1 — all clear AA — the same gold-on-raised treatment already cleared for
   the rail panels' glyphs/eyebrows. --- */
.analysis-books-panel {
  margin-block: var(--space-6);
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
/* Header row: the gold open-book glyph (chrome) leading the title + honest
   subtitle stack. Mirrors the .rail-card-header idiom (glyph inline-start of the
   heading) but sized for the wider content-column panel. */
.analysis-books-header {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  margin-block-end: var(--space-3);
}
/* Decorative header glyph — gold CHROME (AA-cleared on --surface-raised: light
   5.32:1 / dark 6.16:1 / sepia 5.52:1). aria-hidden in the markup. */
.analysis-books-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  margin-block-start: 0.1rem;
  color: var(--brand);
}
.analysis-books-glyph { inline-size: 1.5rem; block-size: 1.5rem; }
.analysis-books-heading-text { min-inline-size: 0; }
.analysis-books-title { margin-block: 0; font-size: 1.2rem; }
/* Honest subtitle: muted reading ink that frames what the count MEANS (passages,
   not chapters). Not gold. */
.analysis-books-subtitle {
  margin-block: 0.25rem 0;
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.5;
}
/* Gold uppercase testament eyebrow — sanctioned CHROME (a structural group label,
   not reading content). Small gold TEXT, so AA-cleared as text (≥4.5:1): --brand
   on --surface-raised reads light 5.32:1 / dark 6.16:1 / sepia 5.52:1. */
.analysis-books-eyebrow {
  margin-block: var(--space-4) var(--space-2);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--brand);
}
.analysis-books-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1px;
}
/* Each book row is one block <a> (the whole row is the ≥44px hit area): the book
   NAME (--text-primary content), the muted COUNT (--text-secondary density
   signal), and a trailing chevron (gold chrome). Gold appears only on the chevron
   + the row's hover/focus frame; the name + count stay reading ink. */
.analysis-books-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 44px;
  padding-inline: var(--space-2);
  border-radius: var(--radius);
  color: var(--text-primary);
  text-decoration: none;
}
.analysis-books-row:hover {
  background: var(--surface-sunken);
  text-decoration: none;
}
/* Visible keyboard focus ring — the same recipe as .analysis-field-row so the
   book rows focus identically to the rest of the analysis family. */
.analysis-books-row:focus-visible {
  outline: var(--focus-ring);
  outline-offset: -2px;
}
/* Book NAME = reading content (--text-primary), grows to fill the row. NO gold. */
.analysis-books-name {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-weight: 600;
}
/* Count = an honest density signal (number of citing statements), recessive muted
   text (--text-secondary, clears AA ≥4.5:1 on the card ground). Not gold. */
.analysis-books-count {
  flex: 0 0 auto;
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-secondary);
}
/* Trailing chevron — decorative gold chrome (aria-hidden), a quiet "go" cue. */
.analysis-books-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.analysis-books-chevron-glyph { inline-size: 1rem; block-size: 1rem; }
/* Summary footer bar: a gold ring-badge glyph (chrome) + a one-line honest count.
   The stat NUMBERS are reading ink (--text-primary), NOT gold. A soft gold
   hairline separates the footer from the rows above. */
.analysis-books-footer {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-block-start: var(--space-4);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--accent-border);
}
.analysis-books-footer-badge { flex: 0 0 auto; }
.analysis-books-footer-glyph { inline-size: 1.4rem; block-size: 1.4rem; }
.analysis-books-footer-summary {
  margin: 0;
  color: var(--text-secondary);
  font-family: var(--font-ui);
}
/* The stat numbers in the footer — reading ink, NOT gold (gold is chrome-only). */
.analysis-books-footer-stat {
  color: var(--text-primary);
  font-weight: 700;
}
.analysis-books-footer-sep { color: var(--text-secondary); margin-inline: 0.25rem; }

/* --- RIGHT rail ---
   The rail scrolls with the page in normal flow (NO position: sticky/fixed — the
   owner wants the right column to scroll alongside the content, not pin). */
.rail {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
/* Card FRAME may carry gold chrome; the CONTAINED scripture/prose never does. */
.rail-card {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
.rail-card-title { margin-block: 0; font-size: 1.1rem; }

/* Header row of a rail card: the <h2> title plus a decorative gold header glyph.
   A leading glyph sits inline-start of the title (open-book on Featured, globe on
   Browse-by-field); a trailing glyph (.rail-card-icon-trailing) is pushed to the
   inline-END corner (the ⓘ on How-this-works). Replaces the old bare
   margin-block-end on .rail-card-title — the wrapper now owns the spacing. */
.rail-card-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-block-end: var(--space-3);
}
.rail-card-icon-trailing { margin-inline-start: auto; }
/* Decorative header glyph — gold CHROME (AA-cleared: --brand on --surface-raised
   reads light 5.32:1 / dark 6.16:1 / sepia 5.52:1). aria-hidden in the markup. */
.rail-card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.rail-card-glyph {
  inline-size: 1.25rem;
  block-size: 1.25rem;
}

/* A) How this works. */
.analysis-howto-body { margin: 0; color: var(--text-secondary); line-height: 1.55; }
.analysis-howto-link { margin-block: var(--space-3) 0; font-size: 0.95rem; }

/* The persistent CTA arrow is NOT gold at rest (content/affordance text reads in
   the normal link/ink color); gold appears only on the link's own hover/focus. */
.analysis-arrow { color: inherit; }

/* B) Featured example passage — the crown jewel. The verse text is reading type,
   NO gold (it is scripture content); the card frame's gold accent is chrome. */
.analysis-featured { border-color: var(--accent-border); }
.analysis-featured-eyebrow {
  margin-block: 0 var(--space-2);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}
/* Reading content: --text-primary + reading font ONLY. No --brand anywhere. */
.analysis-featured-verse {
  margin-block: 0 var(--space-3);
  padding-inline-start: var(--space-3);
  border-inline-start: 3px solid var(--pane-border);
  color: var(--text-primary);
  line-height: 1.5;
}
.analysis-featured-meaning {
  margin-block: 0 var(--space-3);
  color: var(--text-secondary);
  line-height: 1.5;
}
.analysis-featured-meaning-label {
  font-weight: 600;
  color: var(--text-primary);
}
.analysis-featured-link { margin: 0; font-size: 0.95rem; }

/* C) Browse by field — the rail panel that is now the SINGLE canonical home of
   the 10-field taxonomy. Each row is one block <a> (the whole row is the hit
   area, ≥44px): a leading gold per-field line icon (chrome), the field NAME
   (--text-primary content — NO gold), the muted COUNT (--text-secondary, ≥4.5:1),
   and a trailing chevron. Gold appears only on the icons/chevron + the row's
   hover/focus frame; the field name + count stay reading ink. */
.analysis-field-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.analysis-field-row {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-block-size: 44px;
  padding-inline: var(--space-2);
  border-radius: var(--radius);
  color: var(--text-primary);
  text-decoration: none;
}
.analysis-field-row:hover {
  background: var(--surface-sunken);
  text-decoration: none;
}
/* Visible keyboard focus ring — the same token recipe as .analysis-tile so the
   field rows focus identically to the rest of the analysis family. */
.analysis-field-row:focus-visible {
  outline: var(--focus-ring);
  outline-offset: -2px;
}
/* Leading per-field glyph — gold CHROME, decorative (aria-hidden). AA on the card
   ground (--surface-raised): light 5.32:1 / dark 6.16:1 / sepia 5.52:1. */
.analysis-field-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.analysis-field-glyph {
  inline-size: 1.25rem;
  block-size: 1.25rem;
}
/* Field NAME = reading content (--text-primary), grows to fill the row. NO gold. */
.analysis-field-name {
  flex: 1 1 auto;
  min-inline-size: 0;
  font-weight: 600;
}
/* Count = an honest density signal, recessive muted text (--text-secondary,
   clears AA ≥4.5:1 on the card ground). Not gold, not a pill. */
.analysis-field-count {
  flex: 0 0 auto;
  font-family: var(--font-ui);
  font-size: 0.85rem;
}
/* Trailing chevron — decorative gold chrome (aria-hidden), a quiet "go" cue. */
.analysis-field-chevron {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.analysis-field-chevron-glyph {
  inline-size: 1rem;
  block-size: 1rem;
}

/* ==========================================================================
   MESSIANIC PROPHECIES (#12) — the fulfillment reading + the counter-reading,
   set side by side. NEW scoped .messianic-* modifier classes ONLY; the shared
   .analysis-* / .science-* / .rail-card / study-share rules the views reuse are
   left BYTE-UNTOUCHED (the unchanged shared-surface tests are the scoping proof).
   Gold is CHROME-ONLY throughout: never on the reference, the scripture, the two
   readings, the summary, or the citation text.
   ========================================================================== */

/* LANDING + LISTINGS — the landing (hero, stats, search, postures, browse-by-book, rail) and
   the shared category/book/search list view reuse the global .analysis-* / .science-list-page /
   .science-statement-* / .analysis-search / .rail-card / .pagination families VERBATIM. The
   shared landing / category / book / search rules stay BYTE-UNCHANGED — #40.3 reused the
   .rail-card.analysis-fields (Browse by category) + .analysis-books-panel (Browse by book) panels
   on the /catalog listing without touching a single shared rule body, and #40.6 (AMENDED RAIL)
   moves the category panel into a real right rail via NEW page-scoped grid classes (below) — again
   without editing a shared rule body. The page-scoped modifiers here:
   .messianic-catalog-browse-category (now margin:0 — the rail's flex gap owns its spacing once the
   panel sits in .messianic-catalog-rail) and .messianic-catalog-browse-note (the one-line scope
   sentence above the book list). The book panel needs NO new rule — .analysis-books-panel self-
   spaces via its own margin-block. (The Phase-1 single-column .messianic-landing + .messianic-
   category-* rules were removed when the landing reflowed onto the shared two-column
   .analysis-landing template with live category/book/search routes.) */
.messianic-catalog-browse-category { margin-block: 0; }
.messianic-catalog-browse-note {
  margin-block: var(--space-4) var(--space-3);
  color: var(--text-secondary);
  font-size: 0.95rem;
  line-height: 1.5;
}

/* CATALOG (#40.6) — the bespoke two-column AMENDED-RAIL grid. A page-scoped layout that MIRRORS
   the .messianic-detail / .contradiction-detail sibling grid idiom in values (NOT a reuse of the
   shared .rail / .analysis-content globals, and NOT the landing's 52rem .analysis-landing). The
   /catalog header zone (h1 / stat strip / search / blurb) stays OUTSIDE this grid as plain self-
   centering siblings — no grid-column span rule is needed (unlike the sibling detail grids, which
   hoist their <h1> INTO the grid). RAIL-FIRST SOURCE ORDER: the rail is first in the DOM, so below
   72rem (display:block) the page stacks rail-then-content (facets before the flat list); at >= 72rem
   explicit grid-column values sit the rail on the RIGHT while the content stays left — DOM/tab order
   unchanged (NO `order:` property, NO grid-template-areas, consistent with the rest of this file). */
.messianic-catalog-grid { display: block; }
@media (min-width: 72rem) {
  .messianic-catalog-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
    column-gap: var(--space-6);
    align-items: start;
  }
  /* Both wrappers are pinned to grid-row 1 so they sit SIDE BY SIDE in the single row. The rail
     is FIRST in source order (for the mobile stack) but placed in column 2; without an explicit
     grid-row the sparse auto-placement algorithm would keep the cursor past row 1 / column 1 after
     the rail lands, bumping the DOM-later content (which wants column 1) down to row 2 — a
     staircase (rail top-right, content below-left). Explicit `grid-row: 1` on both forces the true
     two-column layout. (Below 72rem this whole block is inert — display:block, source order.) */
  .messianic-catalog-rail { grid-column: 2; grid-row: 1; }
  .messianic-catalog-content { grid-column: 1; grid-row: 1; }
}
.messianic-catalog-rail {
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.messianic-catalog-content { min-inline-size: 0; }
/* Below the grid breakpoint the content column is a full-width stacked block UNDER the rail, with a
   little breathing room from the rail above (mirrors the sibling detail rails' mobile top-gap rule,
   applied to the SECOND-stacked child — here the content, since the rail leads in source order). */
@media (max-width: 71.99rem) {
  .messianic-catalog-content { margin-block-start: var(--space-5); }
}
/* Left-align + zero-margin the "About our approach" hand-off inside the rail: the GLOBAL
   .messianic-approach-link rule centers it (right for its full-width /catalog/usage/:kind call
   site, wrong for a left-aligned rail card stack). The global rule body stays byte-untouched. */
.messianic-catalog-rail .messianic-approach-link { text-align: start; margin-block: 0; }

/* DETAIL — the category tag row under the lead-with-verse reference heading. The tag is a
   REAL anchor to the category's own indexable listing page (a live link, not a dead chip); it
   reuses the shared .science-tag pill chrome (gold-border, reading-ink label). */
.messianic-detail-tagrow { margin-block: var(--space-2) var(--space-4); text-align: center; }

/* DETAIL — the DESKTOP TWO-RAIL grid. A page-scoped two-column layout that MIRRORS the
   .contradiction-detail grid idiom in values (NOT a reuse of a shared layout family). The
   <h1> reference + the category tag row ride a FULL-WIDTH header band (direct grid children
   spanning both tracks); below them the neutral reading SPINE (.messianic-spine) is the first
   track and the recessive META-RAIL (.messianic-meta) the second. With align-items:start the
   rail's first block top-aligns with the spine's first block. The rail wrapper follows the
   spine in SOURCE ORDER, so below 72rem the page is a single linear column and everything
   stacks in reading order via a pure reflow (NO `order:` trick). Gated to >= 72rem so the
   SPINE keeps a comfortable reading width once the rail claims its 20rem column. */
.messianic-detail { display: block; }
@media (min-width: 72rem) {
  .messianic-detail {
    display: grid;
    /* The reading SPINE track is capped to the framed-card width (66ch measure + card padding)
       instead of a greedy 1fr, so the reading column no longer floats with ~51px of dead space
       inside a wide track. The freed width becomes symmetric OUTER margin via justify-content:center,
       pulling the recessive rail IN to a tight ~30px gutter (owner-requested) while the spine keeps
       its comfortable reading measure. The header-band `grid-column: 1 / -1` children span this
       centered track group, so the <h1> / tag row / version switcher stay centered on the same axis. */
    grid-template-columns: minmax(0, calc(var(--measure) + 2 * var(--space-5))) minmax(0, 20rem);
    column-gap: 30px; /* owner-set gutter; sits between --space-5 (24px) and --space-6 (32px), so a literal px */
    justify-content: center;
    align-items: start;
  }
  /* The HEADER BAND — the <h1> reference, the category tag row, AND the hoisted version switcher
     each span BOTH tracks so they form full-width rows above the spine/rail cells. Inert below
     this breakpoint, where .messianic-detail is display:block and these items stack in source
     order. */
  .messianic-detail > .science-detail-claim,
  .messianic-detail > .messianic-detail-tagrow,
  .messianic-detail > .messianic-tier-note,
  .messianic-detail > .science-version-switch {
    grid-column: 1 / -1;
  }
}
/* The version switcher rides its OWN full-width band (the grid-column rule above) so it sits
   above BOTH the spine and the rail, not just the reading column. Zero its top (the tag row
   above already supplies the gap) and give a steady gap below before the spine/rail row; the
   shared .science-version-switch rule is left byte-untouched. */
.messianic-detail > .science-version-switch { margin-block: 0 var(--space-5); }
/* Each grid cell must be allowed to shrink so a long token never forces its track wider than
   its share; the spine's body blocks stay measure-capped + centered WITHIN it. */
.messianic-spine { min-inline-size: 0; }
/* The META-RAIL — the recessive second column: a quiet flex-column stack with a steady gap
   (the .rail idiom), not pinned. Its cards inherit the .study-rail-card chrome; gold stays
   chrome-only. */
.messianic-meta {
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
/* Below the grid breakpoint the rail is a full-width stacked column under the spine, with a
   little breathing room from the spine above. */
@media (max-width: 71.99rem) {
  .messianic-meta { margin-block-start: var(--space-5); }
}

/* CENTERED SPINE — cap every framed spine block at the shared card track (= the reading
   measure + the rail-card inline padding) and center the COLUMN (margin-inline:auto), so the
   reading prose never stretches to the full grid cell. Mirrors .contradiction-spine. Only the
   COLUMN centers — no text-align is touched, so headings, readings, scripture, and commentary
   all stay text-left. A uniform margin-block gives the stacked cards a steady rhythm (adjacent
   block margins collapse to one gap; the first-child reset below zeroes the top of the first). */
.messianic-passages,
.messianic-poles,
.messianic-named-panels,
.messianic-commentary,
.messianic-variants {
  max-width: calc(var(--measure) + 2 * var(--space-5));
  margin-inline: auto;
  margin-block: var(--space-5);
}
/* The bare-prose blocks (the absence note) stay at the reading measure, centered. */
.messianic-absence {
  max-inline-size: var(--measure);
  margin-inline: auto;
}
/* The commentary/variants rail cards bump their inner padding to --space-5 so their body prose +
   the .science-panel-header gold hairline land at exactly --measure (card track − 2 × 24px).
   Scoped so the global .rail-card / .science-panel (used across the app) stay byte-untouched. */
.messianic-commentary > .rail-card,
.messianic-variants > .rail-card { padding: var(--space-5); }
/* Top-align the two grid columns: zero the FIRST child's top margin in BOTH tracks so they
   start cleanly at the grid cell top regardless of which optional block renders first. */
.messianic-spine > :first-child,
.messianic-meta > :first-child { margin-block-start: 0; }

/* THE "In brief" SUMMARY — RELOCATED to LEAD the recessive META-RAIL (it used to sit in the
   spine). As a rail card it drops the spine's centered measure + auto-margins (no longer in the
   centered-spine group above) and keeps the .rail-card's own --space-4 padding (no spine padding
   bump). Zero the shared .science-panel margin-block so the rail's flex `gap` is the sole rhythm
   between cards; the rail's > :first-child reset already zeroes its top. */
.messianic-summary-panel { margin-block: 0; }
/* The framing-panel body ink (reading ink via .science-panel-body); this only holds it to the
   reading measure — harmless in the 20rem rail track. */
.messianic-summary { max-inline-size: var(--measure); }

/* THE FOUR CO-EQUAL HEADINGS — the two reading headings (F2) + the two provenance-panel headings
   (F3) each wear the SAME shared .science-panel-header chrome the "In brief" and "Where this
   stands" panels use (a gold icon-badge glyph + a gold hairline beneath), applied on a WRAPPER so
   the <h2> tags stay byte-exact (the #34 co-equality goldens grep them). The shared
   .science-panel-header / .icon-badge / .science-panel-badge rules are reused as-is, untouched.
   Inside the flex header row the heading sheds its own block margins so it centers cleanly against
   the badge; the header row's own margin-block-end supplies the gap to the note/list below. Both
   readings share one neutral glyph and both provenance panels share another, so each co-equal pair
   is identical by construction — gold stays on the badge + hairline, never the heading text. */
.messianic-pole-header .messianic-pole-heading,
.messianic-panel-header .messianic-panel-heading { margin-block: 0; }

/* F2 — TWO CO-EQUAL READINGS, each its OWN framed panel matching the "In brief" summary and
   "Where this stands" commentary panels elsewhere on this page. The outer .messianic-poles
   section no longer carries the .rail-card token (removed from the markup) — each
   .messianic-pole reproduces that frame itself via this page-scoped rule (the global .rail-card
   rule is untouched). ONE shared selector styles BOTH peers identically, by construction — no
   primary/secondary modifier, whichever pole leads under the route's per-passage alternation. */
.messianic-poles { display: block; }
.messianic-pole {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-5);
}
/* The stacked gap — the 2nd (and any later) pole gets a leading margin only. Each pole now
   frames itself, so real vertical space between the two cards replaces the shared gold hairline
   this divider used to draw. */
.messianic-pole + .messianic-pole { margin-block-start: var(--space-5); }
.messianic-pole-heading { margin-block: 0 var(--space-1); font-size: 1.05rem; }
.messianic-pole-note { margin-block: 0 var(--space-3); font-size: 0.9rem; }
.messianic-pole-body { margin: 0; color: var(--text-primary); line-height: 1.6; }

/* Shared section-heading rhythm for the absence block (a bare heading). */
.messianic-section-heading { margin-block: var(--space-6) var(--space-3); }
.messianic-context-body, .messianic-absence-body { margin: 0; color: var(--text-primary); line-height: 1.6; }

/* F3 — the two honestly-labeled NAMED PANELS, each its OWN framed panel — the SAME framed-card
   treatment as the readings above (the outer .messianic-named-panels section carries no
   .rail-card token; each .messianic-panel frames itself). ONE shared selector styles BOTH panels
   identically, by construction. */
.messianic-named-panels { display: block; }
/* #69 — the honest-asymmetry FRAME line above the three provenance panels: a single quiet,
   section-level sentence naming WHY the fulfillment reading carries two panels and the counter-
   reading one (evidentiary, not evaluative). Reading-ink muted (color comes from the .muted
   utility on the markup); held to the reading measure and centered so its text lands flush with
   the panel body prose below (each .messianic-panel spans the section's measure + 2×--space-5 and
   insets its content by --space-5, so a centered --measure block aligns with it); a --space-5
   block-end sets it off from the first panel. NO gold token — gold stays chrome-only on the panel
   badges + hairlines. Additive modifier ONLY: the shared .messianic-panel* rules stay byte-
   untouched (the shared-class trap). */
.messianic-named-panels-note {
  max-inline-size: var(--measure);
  margin-inline: auto;
  margin-block: 0 var(--space-5);
  font-size: 0.9rem;
}
.messianic-panel {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-5);
}
/* The stacked gap — real vertical space between the two framed panels, same rhythm as the
   readings' divider above. */
.messianic-panel + .messianic-panel { margin-block-start: var(--space-5); }
.messianic-panel-heading { margin-block: 0 var(--space-1); font-size: 1.05rem; }
.messianic-panel-note { margin-block: 0 var(--space-3); font-size: 0.9rem; }
.messianic-usage-list, .messianic-scholar-list { list-style: none; margin: 0; padding: 0; }
.messianic-usage, .messianic-scholar { margin-block: 0 var(--space-4); }
.messianic-usage:last-child, .messianic-scholar:last-child { margin-block-end: 0; }
.messianic-usage-head, .messianic-scholar-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  margin-block: 0 var(--space-1);
}
.messianic-usage-ref, .messianic-scholar-name { font-weight: 600; color: var(--text-primary); }
/* The SPINE NT-usage reference becomes a link when it resolves to a reader url (it absorbed the
   removed "New Testament passages" rail card's sole affordance). It keeps the .messianic-usage-ref
   weight + --text-primary ink above (NEVER gold — gold stays chrome-only on the panel chrome); this
   -link modifier adds ONLY the hover/focus underline affordance. */
.messianic-usage-ref-link { text-decoration: none; }
.messianic-usage-ref-link:hover,
.messianic-usage-ref-link:focus-visible { text-decoration: underline; }
.messianic-usage-desc, .messianic-scholar-position { margin: 0; color: var(--text-secondary); line-height: 1.55; }
.messianic-scholar-fullname, .messianic-scholar-meta { font-size: 0.85rem; }
.messianic-scholar-source { margin-block: var(--space-1) 0; font-size: 0.85rem; }

/* #63 — VERBATIM EXEGETE EXCERPT — a <blockquote> carrying a real public-domain quotation of the
   exegete's OWN words on the passage (the curly quote marks are baked into the data). It MIRRORS
   the sibling .contradiction-pole-quote-text verbatim-quote treatment: reading ink (it is content,
   like the position prose it augments), the reading face, measure-capped, with a quiet inline-start
   hairline in the SOFT pane rule as the quote affordance — NOT a gold bar and NOT a big gold quote
   mark (gold stays chrome-only). A recessive register so it reads as a quotation, not a headline. */
.messianic-exegete-excerpt {
  margin-block: var(--space-2) var(--space-1);
  padding-inline-start: var(--space-4);
  border-inline-start: 2px solid var(--pane-border);
  max-width: var(--measure);
  font-family: var(--font-reading);
  line-height: 1.6;
  color: var(--text-primary);
}
/* THE ATTRIBUTION — the <cite> (excerptLocus — excerptEdition), recessive italic REFERENCE ink,
   reusing the folded-sources cite idiom; a small top gap so it hangs beneath its quote. Never gold. */
.messianic-exegete-excerpt-cite {
  display: block;
  margin-block-start: var(--space-2);
  font-style: italic;
  font-size: 0.85rem;
  color: var(--text-secondary);
}
/* THE HONEST FALLBACK — sourcing attempted and stalled: a muted note (inherits .muted ink, NO quote
   hairline) carrying the excerptUnavailable reason + the shared .science-passage-context link back to
   the passage. Lighter than a quote so it reads as a note, not a quotation. */
.messianic-exegete-excerpt-absent {
  margin-block: var(--space-2) var(--space-1);
  max-width: var(--measure);
  line-height: 1.55;
}

/* MANUSCRIPT VARIANTS — a neutral MT-vs-alternative reading note, COLLAPSED behind the
   study-share disclosure inside a rail-card frame. The disclosure is the card's sole child, so
   flatten the study-share's own border/background (the rail-card is the frame) to avoid a
   nested box; the shared .study-share is untouched. */
.messianic-variants-details { border: 0; border-radius: 0; background: none; }
.messianic-variant { margin-block: 0 var(--space-4); }
.messianic-variant:last-child { margin-block-end: 0; }
.messianic-variant-ref { margin-block: 0 var(--space-2); font-weight: 600; }
.messianic-variant-readings { margin: 0 0 var(--space-2); }
.messianic-variant-reading { display: flex; gap: var(--space-2); margin-block: 0 var(--space-1); }
.messianic-variant-label { font-weight: 600; min-inline-size: 6rem; color: var(--text-secondary); }
.messianic-variant-text { margin: 0; color: var(--text-primary); }
.messianic-variant-note { margin: 0; color: var(--text-secondary); line-height: 1.55; }

/* P4b — the passage-hero "Show the surrounding verses" disclosure. Unlike the variants
   panel it sits INLINE in the passage card (no rail-card frame of its own), so flatten the
   study-share box (border/radius/background) to an inline expander; the shared .study-share
   is untouched. The revealed context text gets a small top gap under the summary row. */
.messianic-surrounding-details { border: 0; border-radius: 0; background: none; }
.messianic-surrounding-text { margin-block: var(--space-2) 0; }

/* PASSAGE-CARD ACTIONS ROW — "Read in context" (.messianic-passage-btn) and "Show the
   surrounding verses" (.messianic-surrounding-details) as ONE coherent button-pill row.
   "Copy" no longer sits in this row — it moved to the passage-card reference/title line
   (the shared .verse-copy-inline, above). A wrapping flex row: collapsed pills sit inline;
   because a native <details> can't be told apart from a plain pill by width alone, the
   OPEN disclosure is pinned to flex-basis: 100% so it wraps to its own full-width line
   instead of being squeezed into a narrow flex column. */
.messianic-passage-actions {
  margin-block: var(--space-3) 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}
.messianic-surrounding-details[open] { flex-basis: 100%; }

/* The surrounding-verses <summary> restyled to a button-pill matching .verse-copy-btn.
   Scoped to THIS element only (.messianic-surrounding-details > .study-share-summary) —
   the shared .study-share / .study-share-summary / .study-share-summary-label /
   .study-share-chevron / .study-section-icon rule bodies above are byte-untouched (the
   shared-class trap: the version-variants share dropdown elsewhere keeps its own look).
   It stays a native <summary> — no display change, so the chevron rotate-on-[open] rule
   (inherited, untouched) keeps working as the expand/collapse affordance. Neutral only:
   color stays --text-primary at rest, hover, AND open (overriding the shared dropdown's
   gold-on-hover/open), matching Copy's dim-not-gold chrome — no new emphasis. */
.messianic-surrounding-details > .study-share-summary {
  padding: 0.4rem 0.7rem;
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--text-primary);
  font-weight: normal;
  font-size: 0.85rem;
}
.messianic-surrounding-details > .study-share-summary:hover,
.messianic-surrounding-details[open] > .study-share-summary {
  color: var(--text-primary);
  border-color: var(--accent-border);
  background: var(--surface-sunken);
}
.messianic-surrounding-details > .study-share-summary:focus-visible {
  outline: var(--focus-ring);
  outline-offset: 2px;
}
.messianic-surrounding-details > .study-share-summary:hover .study-section-icon,
.messianic-surrounding-details[open] > .study-share-summary .study-section-icon {
  color: var(--text-faint);
}

/* MORE PROPHECIES ABOUT {category} — the meta-rail category-sibling pull. It INHERITS the
   rail's grouped-panel chrome from .study-rail-card / .study-section / the gold
   .study-section-heading (NOT restyled here); this styles ONLY its plain reference-link list,
   reusing the reading-ink link idiom (reading face, --text-primary, NEVER gold — gold stays
   chrome-only on the panel heading), capped at the reading measure. */
.messianic-siblings-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  max-inline-size: var(--measure);
}
.messianic-siblings-item { line-height: 1.5; }
.messianic-siblings-link {
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary);
  text-decoration: none;
}
.messianic-siblings-link:hover,
.messianic-siblings-link:focus-visible { text-decoration: underline; }

/* ALSO LISTED SEPARATELY AS (#33.5) — the meta-rail honest-disclosure pull (the folded wider-
   catalog rows). It INHERITS the rail's grouped-panel chrome from .study-rail-card /
   .study-section / the gold .study-section-heading (NOT restyled here); this styles ONLY its
   count-in-prose intro + its plain-text row list. Each row is the verbatim reference (muted, via
   the .muted class) over its short description in reading ink (reading face, --text-primary,
   NEVER gold — gold stays chrome-only on the panel heading glyph); the rows carry NO link, so
   there is no link idiom to match. Capped at the reading measure. */
.messianic-also-listed-intro {
  margin: 0 0 var(--space-3);
  max-inline-size: var(--measure);
  line-height: 1.55;
}
.messianic-also-listed-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-inline-size: var(--measure);
}
.messianic-also-listed-item { line-height: 1.5; }
.messianic-also-listed-ref {
  margin: 0 0 var(--space-1);
  font-size: 0.85rem;
}
.messianic-also-listed-desc {
  margin: 0;
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary);
}

/* CITED ALONGSIDE (#64 / P4a) — the meta-rail CO-CITATION pull (the OTHER prophecies cited via
   the SAME New Testament passage). It INHERITS the rail's grouped-panel chrome from
   .study-rail-card / .study-section / the gold .study-section-heading (NOT restyled here); this
   styles ONLY its intro, its per-anchor "Also cited in {ref}:" group headings, and its partner-
   reference list. The partner references are reading-ink (reading face, --text-primary, NEVER
   gold — gold stays chrome-only on the panel heading glyph); the group headings + the overflow
   note are muted (via the .muted class); a catalog partner reuses the shared .messianic-tier-chip
   (styled once, above — no new chip rule). The stacked modifier sets off each 2nd+ group with a
   little top space so the anchors read as distinct. Capped at the reading measure. NAVIGATION,
   not evidence: these link GEBible-hosted prophecy detail pages. */
.messianic-cocite-intro {
  margin: 0 0 var(--space-3);
  max-inline-size: var(--measure);
  line-height: 1.55;
}
.messianic-cocite-groups {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  max-inline-size: var(--measure);
}
.messianic-cocite-group-heading {
  margin: 0 0 var(--space-1);
  font-size: 0.85rem;
}
.messianic-cocite-group-heading-stacked {
  margin-block-start: var(--space-3);
}
.messianic-cocite-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.messianic-cocite-item {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--space-1) var(--space-2);
  line-height: 1.5;
}
.messianic-cocite-link,
.messianic-cocite-ref {
  font-family: var(--font-reading);
  font-size: 1rem;
  line-height: 1.55;
  color: var(--text-primary);
  text-decoration: none;
}
.messianic-cocite-link:hover,
.messianic-cocite-link:focus-visible { text-decoration: underline; }
.messianic-cocite-overflow {
  margin: var(--space-1) 0 0;
  font-size: 0.85rem;
}

/* ============================================================================
   THE WIDER CATALOG (#33.2) — the catalog-only chrome. All NEW page-scoped
   classes: the shared .analysis-*/.science-* rule bodies are left byte-untouched
   (the shared-class trap), so the gold landing/listing/detail surfaces render
   unchanged. Neutral + recessive; gold stays chrome-only.
   ============================================================================ */

/* LANDING — #33.7 the honest three-way COUNT block, directly beneath the gold hero stat
   strip. QUIET + NON-GOLD (reading ink only — no gold ring, no badge chrome): pure
   arithmetic on how the "commonly listed" total partitions into the repeat-listings + the
   additional, contested passages. A centered block capped at the reading measure; the
   clarifying caption is start-aligned prose for readability. Gold stays chrome-only (the
   closing link's .analysis-arrow); the count NUMBERS render in reading ink. */
.messianic-honest-count {
  max-width: var(--measure);
  margin-block: var(--space-3) 0;
  margin-inline: auto;
  text-align: center;
}
.messianic-honest-count-subline {
  margin: 0;
  font-family: var(--font-ui);
  font-size: 0.95rem;
  color: var(--text-primary);
}
.messianic-honest-count-figure {
  font-weight: 700;
}
.messianic-honest-count-sep {
  margin-inline: 0.4rem;
  color: var(--text-secondary);
}
.messianic-honest-count-caption {
  margin-block: var(--space-2) 0;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  color: var(--text-secondary);
  text-align: start;
}
.messianic-honest-count-link {
  margin-block: var(--space-2) 0;
  font-family: var(--font-ui);
  font-size: 0.95rem;
}
.messianic-honest-count-link a {
  color: var(--text-primary);
  text-decoration: none;
}
.messianic-honest-count-link a:hover,
.messianic-honest-count-link a:focus-visible {
  text-decoration: underline;
}

/* LANDING RAIL — the FULL-LIST ENTRY is the section's PRIMARY way into its own table of
   contents (the 24 closely-examined core prophecies), so — unlike the deliberately quiet
   catalog hand-off that shares .messianic-honest-count-link below it — it reads as an
   unmistakable navigation affordance: the house rounded "pill" (neutral --surface-raised
   fill + --pane-border hairline, fully rounded), the same chrome the hero search pill uses,
   legible as clickable at rest without relying on hover. It lives directly in the rail's
   normal flow (unconditional — Tier 1 is always available), immediately above "Browse by
   category", so the pill is stretched to FILL THE RAIL WIDTH (flex + width:100%, in place of
   the inline-flex/content-width sizing an in-column placement would use) with the label +
   arrow centered inside it; box-sizing:border-box keeps the border + inline padding from
   overflowing that fixed width. Gold stays CHROME-ONLY — the label reads in --text-primary
   (never gold), and warmth appears only as the gold focus halo + the .analysis-arrow on
   hover/focus. A NEW modifier class layered over the shared .messianic-honest-count-link
   block, which is left byte-untouched. */
.messianic-full-list-entry a {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  width: 100%;
  box-sizing: border-box;
  padding: var(--space-2) var(--space-4);
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--surface-raised);
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: none;
}
.messianic-full-list-entry a:hover,
.messianic-full-list-entry a:focus-visible {
  border-color: var(--accent-border);
  box-shadow: 0 0 0 3px var(--accent-soft);
  text-decoration: none;
}
.messianic-full-list-entry a:hover .analysis-arrow,
.messianic-full-list-entry a:focus-visible .analysis-arrow {
  color: var(--brand);
}

/* LANDING — the wider-catalog DISCOVERY row in the rail, after the category list. A quiet
   reading-ink link (never gold — gold stays chrome-only on the arrow via .analysis-arrow),
   set off from the category card by its own top margin so it never touches the category rows. */
.messianic-catalog-discovery {
  margin-block-start: var(--space-4);
}
.messianic-catalog-discovery-link {
  font-family: var(--font-ui);
  font-size: 0.95rem;
  color: var(--text-primary);
  text-decoration: none;
}
.messianic-catalog-discovery-link:hover,
.messianic-catalog-discovery-link:focus-visible { text-decoration: underline; }

/* LANDING RAIL (Fix 1) — the GENERAL browse-by-category row alone stacks its name above a muted
   sub-label naming the residual it holds. The namegroup takes the grow role the bare name held on
   the other rows (flex 1 1 auto), so the row layout is otherwise unchanged; the shared
   .analysis-field-row (align-items:center, min-block-size:44px floor) already accommodates the
   taller two-line row, so no shared rule is touched. The sub-label is muted reading ink, NEVER
   gold — it describes the residual (echoes / laments / divine-attribute / unclassed), never "types". */
.messianic-field-namegroup {
  flex: 1 1 auto;
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.messianic-field-sublabel {
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--text-secondary);
  line-height: 1.3;
}

/* LIST — the small neutral "Wider catalog" tier chip on wider-catalog list cards (gold
   cards carry no item.tier, so they render UNCHANGED). A quiet recessive pill (the .chip
   idiom, NOT gold): surface-sunken fill, quiet border, muted UI text — a source marker,
   never a verdict. */
.messianic-tier-chip-row {
  margin-block: 0 var(--space-1);
}
.messianic-tier-chip {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-ui);
  font-size: 0.7rem;
  font-weight: 600;
  line-height: 1;
  letter-spacing: 0.02em;
  padding: 0.2rem 0.5rem;
  border-radius: 999px;
  background: var(--surface-sunken);
  border: 1px solid var(--pane-border);
  color: var(--text-secondary);
}

/* LIST (Fix 3) — a run of consecutive same-reference cards collapses into ONE .science-statement-card
   (chrome reused verbatim) whose reference is a shared NON-link header, followed by a muted count line
   and a list of the individual readings. The reference reads in reading ink (never gold), matching the
   single card's claim weight; the readings hang under a modest indent with reading-ink link treatment. */
.messianic-refgroup-ref {
  margin-block: 0 var(--space-1);
  font-size: 1.15rem;
  line-height: 1.35;
  color: var(--text-primary);
}
.messianic-refgroup-count {
  margin-block: 0 var(--space-3);
  font-family: var(--font-ui);
  font-size: 0.85rem;
}
.messianic-refgroup-list {
  list-style: none;
  margin: 0;
  padding-inline-start: var(--space-3);
  display: flex;
  flex-direction: column;
  /* The INTER-reading gap must READ larger than the gap from a reading's own title down to
     its "Read the entry →" affordance, or Gestalt proximity attaches that affordance to the
     NEXT reading (a measured mis-grouping: ~17px between readings vs ~40px title-to-own-link).
     space-5 widens the inter-reading separation; the scoped .science-statement-more below pulls
     the affordance tight under its own title, flipping the two so own-link < inter-reading. */
  gap: var(--space-5);
}
.messianic-refgroup-reading {
  margin: 0;
}
/* The reading's distinguisher (its neutral summary) is the link — reading ink, underline on
   hover/focus, matching the single card's claim link. NOT gold. */
.messianic-refgroup-reading > a {
  color: var(--text-primary);
  font-weight: 600;
  text-decoration: none;
}
.messianic-refgroup-reading > a:hover,
.messianic-refgroup-reading > a:focus-visible {
  text-decoration: underline;
}
/* Proximity fix (scoped, NOT the global .science-statement-more rule body — the shared-class
   trap): inside a refgroup reading the "Read the entry →" affordance sits TIGHT under its own
   title (a small block-start, no hairline divider, no padding), so it clearly belongs to the
   reading above it rather than floating between two. The global .science-statement-more (used
   on the single card + every other analysis surface) is left byte-untouched. */
.messianic-refgroup-reading .science-statement-more {
  margin-block-start: var(--space-2);
  padding-block-start: 0;
  border-block-start: 0;
}

/* LIST (catalog) — a single quiet "About our approach →" hand-off beneath the intro blurb, so a
   cold/organic visitor who lands on this indexable listing without the landing's framing still
   reaches the neutrality postures (#approach on the landing). A centered reading-ink line closing
   the header zone; gold stays chrome-only (the arrow, via .analysis-arrow). NOT the full posture
   cards — one link only. */
.messianic-approach-link {
  margin-block: var(--space-2) 0;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 0.95rem;
}
.messianic-approach-link a {
  color: var(--text-primary);
  text-decoration: none;
}
.messianic-approach-link a:hover,
.messianic-approach-link a:focus-visible { text-decoration: underline; }

/* DETAIL — the muted wider-catalog tier NOTE (rendered only for a catalog entry; the gold
   detail has no prophecy.tier). A quiet centered line beneath the reference, capped at the
   reading measure, muted (color from .muted). Full-width via the grid-span rule above. */
.messianic-tier-note {
  margin-block: 0 var(--space-4);
  max-inline-size: var(--measure);
  margin-inline: auto;
  text-align: center;
  font-family: var(--font-ui);
  font-size: 0.9rem;
  line-height: 1.5;
}

/* =====================================================================
 * COMMANDMENTS (Scripture Analysis) — v190. NEW `.commandments-*` modifier
 * classes ONLY. The landing reuses the shared `.analysis-landing` two-column
 * grid + `.analysis-*` / `.rail-card` chrome BYTE-UNTOUCHED; these rules only
 * ADD the section's fixed repeated layer grammar, the LD-2 both-pole collapse
 * pair, and the nikkud-capable Hebrew clause. Gold (--brand) is CHROME-ONLY.
 * ===================================================================== */

.commandments-breadcrumb {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin-block: 0 var(--space-4);
}
.commandments-breadcrumb a { color: var(--text-secondary); }
.commandments-breadcrumb a:hover { color: var(--brand); }

/* --- List surfaces --- */
.commandments-list-hero { margin-block-end: var(--space-5); }
.commandments-list-title {
  font-family: var(--font-reading);
  font-size: 1.9rem;
  line-height: 1.2;
  margin: 0 0 var(--space-2);
}
.commandments-list-blurb { color: var(--text-secondary); margin: 0; }
.commandments-list-showing {
  font-family: var(--font-ui);
  font-size: 0.85rem;
  margin-block: 0 var(--space-4);
}
.commandments-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.commandments-list-card { padding: var(--space-4); }
.commandments-list-card-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  font-family: var(--font-ui); font-size: 0.8rem; margin: 0 0 var(--space-2);
}
.commandments-number { font-weight: 600; color: var(--text-secondary); }
.commandments-type-badge {
  font-family: var(--font-ui); font-size: 0.72rem; letter-spacing: 0.03em;
  text-transform: uppercase; padding: 0.12em 0.6em; border-radius: var(--radius-sm);
  border: 1px solid var(--border); color: var(--text-secondary);
}
.commandments-list-card-ref { color: var(--text-secondary); }
.commandments-list-card-title { font-family: var(--font-reading); font-size: 1.1rem; line-height: 1.35; margin: 0; }
.commandments-list-card-title a { color: var(--text-primary); text-decoration: none; }
.commandments-list-card-title a:hover { color: var(--brand); }

.commandments-pager {
  display: flex; align-items: center; justify-content: space-between; gap: var(--space-3);
  margin-block: var(--space-5) var(--space-4); font-family: var(--font-ui); font-size: 0.9rem;
}
.commandments-pager-link { color: var(--text-primary); text-decoration: none; padding: var(--space-2) var(--space-3); border-radius: var(--radius-sm); }
.commandments-pager-link:hover { color: var(--brand); }
.commandments-pager-link.is-disabled { color: var(--text-secondary); opacity: 0.5; pointer-events: none; }
.commandments-pager-status { color: var(--text-secondary); }
.commandments-empty { margin-block: var(--space-5); }
.commandments-licence-foot { margin-block-start: var(--space-6); font-family: var(--font-ui); font-size: 0.78rem; }

/* --- Landing browse rails --- */
.commandments-browse { margin-block: var(--space-5); }
.commandments-observance-note { font-family: var(--font-ui); font-size: 0.85rem; margin: 0 0 var(--space-3); }
.commandments-browse-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.commandments-browse-row {
  display: flex; flex-direction: column; gap: 0.15rem; text-decoration: none;
  padding: var(--space-3) var(--space-4); border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--surface-raised); min-block-size: 44px; justify-content: center;
}
.commandments-browse-row:hover { border-color: var(--brand); }
.commandments-browse-name { font-family: var(--font-reading); font-size: 1.05rem; color: var(--text-primary); }
.commandments-browse-sub { font-family: var(--font-ui); font-size: 0.82rem; }

/* --- Detail: statement + meta --- */
.commandments-detail-statement { font-family: var(--font-reading); font-size: 2rem; line-height: 1.18; margin: 0 0 var(--space-3); }
.commandments-detail-meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-2);
  font-family: var(--font-ui); font-size: 0.85rem; margin: 0 0 var(--space-5);
}
.commandments-detail-ref { color: var(--text-secondary); }

/* --- Detail: the cited verse hero --- */
.commandments-verse { margin-block-end: var(--space-5); }
.commandments-verse-card { padding: var(--space-4) var(--space-5); }
.commandments-verse-ref { display: flex; align-items: center; gap: var(--space-2); }
.commandments-cite-icon { color: var(--brand); display: inline-flex; }
.commandments-verse-text { font-family: var(--font-reading); font-size: 1.2rem; line-height: 1.6; margin: var(--space-2) 0 0; }
.commandments-verse-context, .commandments-verse-absent { font-family: var(--font-ui); font-size: 0.85rem; margin-block: var(--space-3) 0; }
.commandments-verse-context a { color: var(--text-primary); text-decoration: none; }
.commandments-verse-context a:hover { color: var(--brand); }

/* --- Detail: the Hebrew clause (nikkud-capable) --- */
.commandments-hebrew-block { margin-block-end: var(--space-5); }
.commandments-hebrew {
  /* A nikkud-capable Hebrew serif stack: SBL Hebrew / Taamey Frank / Ezra SIL are the
     dedicated pointed-Hebrew faces; Times New Roman is the reliable system fallback that
     carries full vowel-point (nikkud) coverage; then the reading serif. Ensures vowel
     points render in the no-JS baseline (Q7). */
  font-family: "SBL Hebrew", "Taamey Frank CLM", "Ezra SIL", "David CLM", "Times New Roman", var(--font-reading), serif;
  font-size: 1.7rem; line-height: 1.9; margin: 0; display: flex; align-items: center; gap: var(--space-2);
}
.commandments-hebrew-text { display: inline; }

/* --- Detail: Maimonides' own definition (Sefer HaMitzvot primary source) ---
   A fact-card KIN to the Hebrew block, differentiated by its OWN gold top hairline (chrome
   only — never on Rambam's text/provenance) so it is never mistaken for the Masoretic verse.
   The He/En here is PROSE, so it takes a comfortable reading measure + line-height — NOT the
   1.7rem display size of the one-line Masoretic clause. The nikkud-capable Hebrew serif stack
   is DUPLICATED here rather than widening the shared .commandments-hebrew* selector (the
   shared-class trap). Gold (--brand) stays chrome-only. */
.commandments-rambam { border-block-start: 2px solid var(--brand); }
.commandments-rambam-he {
  font-family: "SBL Hebrew", "Taamey Frank CLM", "Ezra SIL", "David CLM", "Times New Roman", var(--font-reading), serif;
  font-size: 1.15rem; line-height: 1.9; color: var(--text-primary);
  max-inline-size: 60ch; margin-block: var(--space-2) var(--space-3);
}
.commandments-rambam-he p { margin: 0 0 var(--space-3); }
.commandments-rambam-he p:last-child { margin-block-end: 0; }
.commandments-rambam-en {
  font-family: var(--font-reading);
  font-size: 1rem; line-height: 1.7; color: var(--text-primary);
  max-inline-size: 66ch; margin-block-end: var(--space-3);
}
.commandments-rambam-en p { margin: 0 0 var(--space-3); }
.commandments-rambam-en p:last-child { margin-block-end: 0; }
.commandments-rambam-provenance { font-family: var(--font-ui); font-size: 0.8rem; color: var(--text-secondary); margin: 0; }

/* --- The fixed repeated layer grammar (section 4) --- */
.commandments-layer { margin-block: var(--space-6) 0; padding-block-start: var(--space-4); border-block-start: 1px solid var(--border); }
.commandments-layer-heading { font-family: var(--font-reading); font-size: 1.3rem; line-height: 1.3; margin: 0 0 var(--space-2); }
.commandments-layer-eyebrow { font-family: var(--font-ui); font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--brand); margin: 0 0 var(--space-1); }
.commandments-layer-note { font-family: var(--font-ui); font-size: 0.85rem; margin: 0 0 var(--space-3); }
.commandments-form-line { font-family: var(--font-ui); font-size: 0.95rem; margin-block: var(--space-4); }
.commandments-form-value { color: var(--text-primary); }

/* Chips + honest-absence + long-tail attributed frame */
.commandments-chip-list { list-style: none; margin: 0 0 var(--space-2); padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.commandments-chip { font-family: var(--font-ui); font-size: 0.85rem; padding: 0.2em 0.7em; border: 1px solid var(--border); border-radius: var(--radius-sm); color: var(--text-primary); }
.commandments-chip-longtail { border-style: dashed; }
.commandments-longtail-frame { color: var(--text-secondary); font-style: italic; }
.commandments-absence { font-family: var(--font-ui); font-size: 0.85rem; margin: 0; }

/* Applicability + sanctions */
.commandments-applicability, .commandments-sanctions { margin-block: var(--space-5) 0; }
.commandments-sanction-group { margin-block-end: var(--space-3); }
.commandments-sanction-cat, .commandments-reception-name, .commandments-cite-kind {
  font-family: var(--font-ui); font-size: 0.8rem; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--text-secondary); margin: 0 0 var(--space-2);
}

/* Layer A movement spread (five co-equal rows) */
.commandments-movement-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.commandments-movement-row { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-4); align-items: baseline; padding: var(--space-2) 0; border-block-start: 1px solid var(--border); }
.commandments-movement-row:first-child { border-block-start: 0; }
.commandments-movement-stream { font-family: var(--font-reading); font-size: 1rem; color: var(--text-primary); min-inline-size: 9rem; }
.commandments-movement-pos { font-family: var(--font-ui); font-size: 0.9rem; color: var(--text-primary); }

/* LD-2 the two adjacent collapsed both-pole blocks, EQUAL visual weight. The pair is now a
   Tier-3 badge panel (a .rail-card + .science-panel-header, styled in the v2 block below); the
   two poles are lighter (border-only) collapsibles inside it, hairline-parity by construction. */
.commandments-poles-pair { display: grid; gap: var(--space-3); margin-block-start: var(--space-3); }
.commandments-pole { border: 1px solid var(--border); border-radius: var(--radius-md); }
.commandments-pole-summary {
  display: block; cursor: pointer; list-style: none;
  padding: var(--space-3) var(--space-4); min-block-size: 44px;
}
.commandments-pole-summary::-webkit-details-marker { display: none; }
/* The title bar — title · chevron on one row; the ambient dek stacks beneath it. */
.commandments-pole-summary-row { display: flex; align-items: center; gap: var(--space-2); min-block-size: 32px; }
/* A3 — the ambient dek, INSIDE the summary (a quiet framing line beneath the title bar) so it
   stays VISIBLE while the pole is collapsed. Aligned to the summary's content box (the summary
   already carries the inline padding), so no extra horizontal padding here. */
.commandments-pole-dek { display: block; margin: var(--space-1) 0 0; font-family: var(--font-ui); font-size: 0.85rem; line-height: 1.45; }
.commandments-pole-title { font-family: var(--font-reading); font-size: 1.1rem; color: var(--text-primary); flex: 1; }
.commandments-pole-chevron { color: var(--brand); transition: transform 0.15s ease; }
.commandments-pole[open] .commandments-pole-chevron, .commandments-enum[open] .commandments-pole-chevron { transform: rotate(180deg); }
.commandments-pole-body { padding: 0 var(--space-4) var(--space-4); }
.commandments-pole-reading { font-family: var(--font-reading); font-size: 1.05rem; line-height: 1.55; margin: 0 0 var(--space-3); }
.commandments-voice { margin: 0 0 var(--space-3); padding-inline-start: var(--space-3); border-inline-start: 2px solid var(--border); }
.commandments-voice-body { font-family: var(--font-reading); line-height: 1.6; margin: 0 0 var(--space-1); }
.commandments-voice-attr { font-family: var(--font-ui); font-size: 0.8rem; color: var(--text-secondary); font-style: normal; }
.commandments-hedge { font-family: var(--font-ui); font-size: 0.9rem; margin: 0 0 var(--space-2); }
.commandments-hedge-frame { color: var(--text-secondary); }
.commandments-hedge-value { color: var(--text-primary); }
.commandments-commentary p { font-family: var(--font-reading); line-height: 1.6; margin: 0 0 var(--space-3); }

/* #23 — the RABBINIC SOURCE-TEXT affordance inside a traditional-pole voice. ALL NEW modifier
   classes: .commandments-voice / -voice-body / -voice-attr / .commandments-pole-body and every
   shared .analysis-* rule stay BYTE-UNTOUCHED (the shared-class trap), so the unchanged
   shared-surface tests are the scoping proof.

   TYPOGRAPHIC CONTRACT: the reproduced passage must read as SECONDARY TO the summary above it,
   never as a pull-quote competing with it. It is subordinated by SIZE and INDENT (a thinner
   hairline nested inside the voice's own 2px rule), NOT by draining its contrast — it is a
   primary source and has to stay readable. NO gold anywhere on the quoted text, the citation
   or the provenance: gold is chrome-only, and here it appears only as a link hover state. */
.commandments-voice-rabbinic { margin-block-start: var(--space-2); }
/* The line-height here is a TAP TARGET, not a typographic preference (#23-fu). These anchors are
   the feature's whole promise on a phone, and they wrap — a wrapped inline anchor hit-tests per
   LINE BOX, not as one box, so each wrapped line was landing at ~15-16px at 390px. 0.8rem x 2.2
   makes every line box ~28px, clearing the 24px WCAG 2.5.8 minimum; the anchor's padding-block
   below then fills that box exactly. Do not lower it back for tightness. */
.commandments-rabbinic-links {
  font-family: var(--font-ui); font-size: 0.8rem; line-height: 2.2;
  color: var(--text-secondary); margin: 0;
}
/* Mirrors the rail citation link's register: full-contrast at rest, gold ONLY on hover/focus.
   `padding-block` expands the HIT AREA without adding to the line box (so it cannot reflow the
   paragraph); the container's line-height above supplies the room it grows into. The anchor
   stays INLINE deliberately — inline-block would make a multi-word citation label an unbreakable
   box and overflow narrow viewports.

   0.4rem is DELIBERATELY the value that fills the line box and stops. Padding on an inline
   element is free to spill past its own line, and at 0.5rem it did: two DIFFERENT citations on
   consecutive wrapped lines overlapped by 6.7px (measured at 390px and 360px), which buys target
   size with a band where a tap lands on the neighbouring link. Sized to the line box there is no
   such band — verify with a rects-overlap measurement, not by eye, if this is ever retuned. */
.commandments-rabbinic-link { color: var(--text-primary); padding-block: 0.4rem; }
.commandments-rabbinic-link:hover, .commandments-rabbinic-link:focus-visible { color: var(--brand); text-decoration: underline; }
/* The trailing out-of-box glyph. Geometry duplicated from the rail's external-link icon rather
   than widening that shared selector into the spine. */
.commandments-rabbinic-link-icon { margin-inline-start: 0.3em; inline-size: 0.72em; block-size: 0.72em; opacity: 0.72; vertical-align: -0.08em; }
/* The identity frame naming the ref reproduced — quiet UI register, never a heading. */
.commandments-rabbinic-frame {
  font-family: var(--font-ui); font-size: 0.8rem; line-height: 1.45;
  color: var(--text-secondary); margin: var(--space-3) 0 var(--space-1);
}
.commandments-rabbinic-text {
  margin: 0; padding-inline-start: var(--space-3);
  border-inline-start: 1px solid var(--border);
  max-inline-size: 62ch;
}
.commandments-rabbinic-text p {
  font-family: var(--font-reading); font-size: 0.92rem; line-height: 1.55;
  color: var(--text-primary); margin: 0 0 var(--space-2);
}
.commandments-rabbinic-text p:last-child { margin-block-end: 0; }
.commandments-rabbinic-scope, .commandments-rabbinic-provenance {
  font-family: var(--font-ui); font-size: 0.78rem; line-height: 1.4; margin: var(--space-1) 0 0;
}
/* #23-fu — the LINK-ONLY note. Deliberately shares .commandments-rabbinic-frame's exact metrics
   and spacing so a reproduced and a non-reproduced citation occupy the SAME vertical rhythm and
   register; the only difference between them stays what follows (text vs. one sentence), which
   is the anti-ladder contract. The citation name takes primary contrast and the reason secondary
   — the same frame/value split .commandments-hedge-* already uses — so the eye can join this
   line to the link above it without either part reading as emphasis. */
.commandments-rabbinic-noquote {
  font-family: var(--font-ui); font-size: 0.8rem; line-height: 1.45;
  margin: var(--space-3) 0 var(--space-1);
}
.commandments-rabbinic-noquote-frame { color: var(--text-primary); }
/* §14.7 — the DRIFT DISCLOSURE, between the reproduced passage and its provenance. It takes the
   scope/provenance METRICS (it belongs to that same apparatus stack under the blockquote, not to
   the voices) and the noquote's frame/value CONTRAST SPLIT, so it reads as one more short note
   about this citation rather than as a new kind of thing on the page. Its own modifier class: the
   shared .commandments-rabbinic-scope/-provenance rule above stays byte-untouched. */
.commandments-rabbinic-sourcenote {
  font-family: var(--font-ui); font-size: 0.78rem; line-height: 1.4; margin: var(--space-1) 0 0;
}
.commandments-rabbinic-sourcenote-frame { color: var(--text-primary); }
/* The standing once-per-pole disclosure — calm, ambient, below the voices. The trailing
   margin keeps it from running into the honest-absence line that can follow it (both are
   muted UI paragraphs); the shared .commandments-absence rule stays byte-untouched. */
.commandments-rabbinic-disclosure {
  font-family: var(--font-ui); font-size: 0.82rem; line-height: 1.45;
  margin: var(--space-3) 0 var(--space-3);
}

/* Queue line (non-spine, both poles deferred symmetrically) — now the calm text inside a framed
   .commandments-queue-card (a .commandments-fact-card), so the frame lives on the card, not here. */
.commandments-queue { margin: 0; font-family: var(--font-ui); font-size: 0.95rem; color: var(--text-secondary); }

/* #23-fu — the SPINE coverage line, the counterpart of .commandments-queue on pages that DO
   carry the deep treatment. Quieter than the queue line by design: the queue line is the whole
   content of its card and has to carry it, whereas this one is an ambient qualifier above two
   poles that are themselves the content. Sits between the pair heading and the poles. */
.commandments-spine-coverage {
  font-family: var(--font-ui); font-size: 0.82rem; line-height: 1.45;
  margin: 0 0 var(--space-3);
}

/* Layer C reception */
.commandments-reception-tradition { margin-block-end: var(--space-3); }
.commandments-reception-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
.commandments-reception-entry { font-family: var(--font-ui); font-size: 0.9rem; display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: baseline; }
.commandments-reception-ref { color: var(--text-primary); font-weight: 600; }
.commandments-reception-stance { color: var(--text-primary); }
.commandments-reception-note { font-size: 0.85rem; flex-basis: 100%; }

/* Layer D ANE */
.commandments-ane-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.commandments-ane-row { display: grid; gap: 0.15rem; font-family: var(--font-ui); font-size: 0.9rem; }
.commandments-ane-corpus { font-family: var(--font-reading); font-size: 1rem; color: var(--text-primary); }
.commandments-ane-type { color: var(--text-primary); }
.commandments-ane-rel, .commandments-ane-section, .commandments-ane-edition { font-size: 0.82rem; }

/* Layer E modern conflicts (inline). The instrument-shape caveat is DE-MUTED to calm body
   contrast — the honest ambient qualifier of the charge, never the quietest line on the layer,
   and never alarm/severity chrome (calm italic reading ink, no color-coding). */
.commandments-instrument-note {
  font-family: var(--font-reading); font-size: 0.95rem; line-height: 1.55; font-style: italic;
  color: var(--text-primary); margin: var(--space-2) 0 var(--space-3);
}
.commandments-conflict-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-4); }
.commandments-conflict-row { padding-block-start: var(--space-2); }
.commandments-conflict-framework { font-family: var(--font-ui); font-size: 0.8rem; letter-spacing: 0.02em; text-transform: uppercase; color: var(--text-secondary); }
.commandments-conflict-class { font-family: var(--font-ui); font-size: 0.9rem; margin: var(--space-1) 0; }
.commandments-conflict-type { color: var(--text-primary); }
.commandments-conflict-summary { font-family: var(--font-reading); line-height: 1.55; margin: 0; }

/* Enumeration cross-index (demoted, collapsible) — now a rail block; the rail's flex `gap`
   owns the spacing, so it carries no standalone block margin. */
.commandments-enum { margin: 0; border: 1px solid var(--border); border-radius: var(--radius-md); }
.commandments-enum-summary { display: flex; align-items: center; gap: var(--space-2); cursor: pointer; list-style: none; padding: var(--space-3) var(--space-4); min-block-size: 44px; }
.commandments-enum-summary::-webkit-details-marker { display: none; }
.commandments-enum-title { font-family: var(--font-ui); font-size: 0.95rem; flex: 1; color: var(--text-primary); }
.commandments-enum-body { padding: 0 var(--space-4) var(--space-4); }
.commandments-enum-list { display: grid; grid-template-columns: auto 1fr; gap: var(--space-1) var(--space-3); margin: 0; font-family: var(--font-ui); font-size: 0.88rem; }
.commandments-enum-label { color: var(--text-secondary); }
.commandments-enum-value { color: var(--text-primary); margin: 0; }

/* Cross-references + further reading */
.commandments-cites { margin-block: var(--space-6) 0; padding-block-start: var(--space-4); border-block-start: 1px solid var(--border); }
.commandments-cite-group { margin-block-end: var(--space-3); }
.commandments-cite-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
.commandments-cite-item { font-family: var(--font-ui); font-size: 0.85rem; color: var(--text-primary); }

.commandments-duplicate { font-family: var(--font-ui); font-size: 0.85rem; margin-block: var(--space-5) 0; }

/* Prev / next */
.commandments-adjacent { display: flex; justify-content: space-between; gap: var(--space-3); margin-block: var(--space-6) 0; font-family: var(--font-ui); font-size: 0.95rem; }
.commandments-adjacent-link { color: var(--text-primary); text-decoration: none; padding: var(--space-2) var(--space-3); border: 1px solid var(--border); border-radius: var(--radius-sm); }
.commandments-adjacent-link:hover { border-color: var(--brand); color: var(--brand); }

/* Attribution (detail + methodology) */
.commandments-detail-licence, .commandments-licence-body, .commandments-methodology-licence { margin-block-start: var(--space-6); }
.commandments-detail-licence-label { font-family: var(--font-ui); font-size: 0.8rem; letter-spacing: 0.03em; text-transform: uppercase; color: var(--text-secondary); margin: 0 0 var(--space-1); }
.commandments-detail-licence-body, .commandments-licence-body, .commandments-methodology-licence { font-family: var(--font-ui); font-size: 0.82rem; line-height: 1.5; }
.commandments-detail-licence-body a, .commandments-licence-body a, .commandments-methodology-licence a { color: var(--text-primary); }
.commandments-detail-licence-body a:hover, .commandments-licence-body a:hover, .commandments-methodology-licence a:hover { color: var(--brand); }

/* ===========================================================================
   DETAIL v2 — the panel-hardened two-track layout + the 3-tier panel hierarchy.
   All NEW .commandments-* modifier classes; the shared .rail-card / .science-panel-*
   / .analysis-* rules are reused BYTE-UNTOUCHED (these only add). MIRRORS the
   .messianic-detail / .contradiction-detail grid idiom in values.
   =========================================================================== */

/* The two-track grid. The <h1> statement + meta strip ride a full-width header band
   (grid-column 1/-1); below them a measure-capped reading SPINE (first in source order) + a
   recessive apparatus RAIL (second). Gated to >= 72rem so the spine keeps a comfortable reading
   width once the rail claims its 20rem column; below it the page is a single linear column,
   spine then rail, via pure reflow (NO `order:` trick). */
.commandments-detail { display: block; }
@media (min-width: 72rem) {
  .commandments-detail {
    display: grid;
    grid-template-columns: minmax(0, calc(var(--measure) + 2 * var(--space-5))) minmax(0, 20rem);
    column-gap: var(--space-6);
    justify-content: center;
    align-items: start;
  }
  .commandments-detail > .commandments-detail-statement,
  .commandments-detail > .commandments-detail-meta { grid-column: 1 / -1; }
}
.commandments-spine { min-inline-size: 0; }
.commandments-rail {
  min-inline-size: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
/* Below the grid breakpoint the rail reflows BELOW the spine IN FULL (no display:none), with a
   little breathing room from the spine above. */
@media (max-width: 71.99rem) {
  .commandments-rail { margin-block-start: var(--space-5); }
}
/* Top-align both tracks: zero the first child's top margin in each. */
.commandments-spine > :first-child,
.commandments-rail > :first-child { margin-block-start: 0; }

/* TIER 2 — spine FACT cards (Hebrew clause, applicability, sanctions, and the non-spine queue
   card): light framed, soft border, eyebrow/heading, NO icon-badge. */
.commandments-fact-card {
  margin-block: var(--space-5) 0;
  padding: var(--space-4) var(--space-5);
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
.commandments-fact-eyebrow { margin-block: 0 var(--space-2); }
.commandments-fact-heading { font-family: var(--font-reading); font-size: 1.1rem; line-height: 1.3; margin: 0 0 var(--space-2); }

/* TIER 3 — attributed-voice PANELS (Layer A / C / D / E + the two-pole pair). A .rail-card
   frame + the shared .science-panel-header badge + gold hairline. */
.commandments-voice-panel { margin-block: var(--space-5) 0; }
/* The heading sits beside the badge inside the flex .science-panel-header; zero its bottom
   margin there (the header owns the gap to the body). */
.commandments-panel-heads { min-inline-size: 0; }
.commandments-panel-heads .commandments-layer-heading { margin-block: 0; }

/* THE RAIL apparatus cards. */
.commandments-rail-card {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  background: var(--surface-raised);
  padding: var(--space-4);
}
/* Gold title register — shared with .commandments-rail-cites-heading below; all five rail
   apparatus card titles (Browse, Traditional sources, Cross-references, Further reading,
   Adjacent commandments) read as one uniform gold register. */
.commandments-rail-heading {
  font-family: var(--font-ui); font-size: 0.8rem; letter-spacing: 0.03em; text-transform: uppercase;
  color: var(--brand); margin: 0 0 var(--space-2);
}
.commandments-rail-note { font-family: var(--font-ui); font-size: 0.82rem; margin: 0 0 var(--space-3); }
.commandments-rail-nav { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
.commandments-rail-nav-link {
  display: flex; align-items: center; min-block-size: 44px;
  font-family: var(--font-ui); font-size: 0.9rem; color: var(--text-secondary);
  text-decoration: none; padding-block: var(--space-1);
}
.commandments-rail-nav-link:hover { color: var(--brand); }
.commandments-rail-adjacent-row { display: flex; justify-content: space-between; gap: var(--space-3); }

/* CITATION register — readable serif, larger size, proper citation formatting; title color
   joins the same gold register as .commandments-rail-heading above (body text below stays
   full-contrast). */
.commandments-rail-cites-heading { font-family: var(--font-reading); font-size: 1.05rem; line-height: 1.3; color: var(--brand); margin: 0 0 var(--space-2); }
.commandments-rail-cite-group { margin-block-end: var(--space-3); }
.commandments-rail-cite-group:last-child { margin-block-end: 0; }
.commandments-rail-cite-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-1); }
.commandments-rail-cite-item { font-family: var(--font-reading); font-size: 0.9rem; line-height: 1.45; color: var(--text-primary); }
/* A faint hairline BETWEEN adjacent citation sources (all three rail panels: Traditional
   sources, Cross-references, Further reading) so each source reads as visibly its own item.
   Adjacent-sibling only => the first item of every list/group has no rule (self-resets at each
   group's <ul> boundary). Neutral --border hairline (the same rule .commandments-layer /
   -cites / -movement-row use) — NEVER gold; gold stays chrome-only. */
.commandments-rail-cite-item + .commandments-rail-cite-item {
  padding-block-start: var(--space-1);
  border-block-start: 1px solid var(--border);
}
.commandments-rail-cite-link { color: var(--text-primary); }
.commandments-rail-cite-link:hover, .commandments-rail-cite-link:focus-visible { color: var(--brand); text-decoration: underline; }
/* The EXTERNAL out-link (Hammurabi -> the PD King 1910 edition): icon spacing only, NO color
   declaration, so it inherits the base .commandments-rail-cite-link white->gold-on-hover and
   gold stays chrome-only. The out-of-box glyph carries the size/opacity/vertical-align; the
   provenance note reuses the .muted utility for its ink (set on the markup). */
.commandments-rail-cite-link-ext { margin-inline-end: 0.1em; }
.commandments-rail-cite-ext-icon { margin-inline-start: 0.3em; inline-size: 0.72em; block-size: 0.72em; opacity: 0.72; vertical-align: -0.08em; }
.commandments-rail-cite-ext-note { font-size: 0.8rem; line-height: 1.4; margin: var(--space-2) 0 0; }
/* A2 (owner-relaxed criterion 4, 2026-07-24) — a bare in-page navigation link that trails a
   "Traditional sources" citation ONLY when that citation is genuinely Maimonides' Sefer HaMitzvot
   at the same locus the "In Maimonides' words" fact-card reproduces. NEUTRAL nav chrome: muted UI
   ink, no underline at rest -> gold + underline ONLY on hover/focus (gold stays chrome-only). It
   is a bare trailing link, never elevated above the citation it follows. NEW modifier class — the
   shared .commandments-rail-cite-item stays byte-untouched (the shared-class trap). */
.commandments-rail-cite-jump {
  font-family: var(--font-ui); font-size: 0.8rem; color: var(--text-secondary);
  text-decoration: none; white-space: nowrap;
}
.commandments-rail-cite-jump:hover, .commandments-rail-cite-jump:focus-visible {
  color: var(--brand); text-decoration: underline;
}
/* Clear the sticky .site-header so the reproduced-text fact-card top isn't hidden under it when a
   reader follows the jump link — the 5rem jump-target offset used across the app (.verse,
   .footnote-item, the search jump-nav headings). Smooth scroll comes from the global
   `html { scroll-behavior: smooth }` (neutralized under prefers-reduced-motion), so no local
   scroll-behavior is needed here. */
#commandments-rambam-target { scroll-margin-top: 5rem; }

/* ============================================================================
   Patron SSO — /patron-login, the ?patron= return notice, and the two entry
   points to them (SPEC-patron-sso.md §5.6).

   EVERY RULE BELOW IS ON A NEW CLASS. No shared rule is touched: .btn,
   .btn-ghost, .pill, .pill-subscriber and .lead are byte-untouched, and the
   unchanged-shared-surface tests are the scoping proof (CLAUDE.md).
   ========================================================================= */

/* The page is prose, so it is held to the site's reading measure rather than
   the full container width. .container supplies the gutters; this only caps. */
.patron-page { max-width: 44rem; }
.patron-lede { font-size: 1.15rem; max-width: 40rem; }

/* ---- "What signing in actually does" ---- */
.patron-panel {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  padding: var(--space-5);
  margin: 2rem 0;
  background: var(--surface-raised);
  background: color-mix(in srgb, var(--surface-raised) 55%, var(--surface));
}
.patron-panel-title { margin: 0 0 var(--space-4); font-size: 1.05rem; }
.patron-facts { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-3); }
.patron-fact {
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-raised);
}

/* The load-bearing paragraph: the sub-floor expectation, set BEFORE the click.
   A left rule and a recessed fill, never an alert colour — this is an honest
   fact about the level, not an error the reader has made. */
.patron-warning {
  border-inline-start: 3px solid var(--pane-border);
  border-radius: 0 var(--radius) var(--radius) 0;
  background: var(--surface-sunken);
  padding: var(--space-4);
  margin: 2rem 0;
}

/* ---- The sign-in control ---- */
.patron-cta { margin: 2rem 0 var(--space-3); }
/* NEVER .btn. Gold is chrome-only, and a third-party sign-in must not look like
   first-party chrome. The FILL and the LABEL are Patreon's own tokens, so this
   control does not re-theme with the site; min-height meets the 44px tap target;
   outline-offset puts the focus ring on the page background, clear of the
   near-black fill.

   THE BORDER IS OURS, NOT PATREON'S, and it is DARK-THEME work. The fill is
   #0e0e10; measured in headless Chrome against each theme's page background:

     theme   fill/page   border/page (--pane-border)
     dark      1.07:1        1.51:1
     light    18.61:1        1.23:1
     sepia    16.01:1        1.35:1

   So WCAG 1.4.11 (3:1 to IDENTIFY a UI component) is already satisfied on light
   and sepia BY THE FILL — a near-black button on a near-white page is its own
   boundary. Only the dark theme has the problem, where the near-black fill sits
   on near-black navy and the control reads by its white label alone.

   The border was `transparent`, present only to keep an outline in Windows High
   Contrast once the fill is overridden. Giving it --pane-border, the site's own
   hairline token (defined in all four themes, so light/sepia stay correct),
   takes the dark boundary from 1.07:1 to 1.51:1. THAT IS AN IMPROVEMENT, NOT A
   PASS — --pane-border is a decorative hairline and reaches 3:1 in no theme. If
   the dark boundary must actually meet 1.4.11, the token has to change, not the
   rule: --text-faint measures 6.67 / 5.63 / 5.63 and --text-secondary 7.48 /
   7.24 / 5.44 across dark/light/sepia. Owner call — a stronger edge is a louder
   control. Patreon's brand pair (fill + label, 19.28:1) is untouched either way;
   the boundary is site chrome drawn AROUND a third-party control, which is ours
   to draw, so no brand rule is at stake in that choice. */
.patron-signin-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: 44px;
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--patreon-black);
  color: var(--patreon-on-black);
  font-family: var(--font-ui);
  font-weight: 700;
  text-decoration: none;
}
.patron-signin-btn:hover,
.patron-signin-btn:focus-visible {
  color: var(--patreon-on-black);
  text-decoration: none;
  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.35);
}
.patron-signin-btn:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.patron-signin-btn:active { transform: translateY(1px); }
/* Held ready for the official post-2023 Patreon mark. The control ships
   TEXT-ONLY until that asset is supplied: a hand-drawn approximation of a
   trademark is worse than no mark. Restoring it is dropping the file in and
   adding one <img class="patron-signin-mark" ...> to patron-login.ejs. Do NOT
   add the path to APP_SHELL in public/service-worker.js — cache.addAll() rejects
   the whole install on a single 404. */
.patron-signin-mark { display: block; inline-size: 16px; block-size: 16px; flex: none; }
.patron-signin-label { display: inline-block; }

.patron-scope-note,
.patron-session-note { color: var(--text-secondary); font-size: 0.9rem; margin: var(--space-2) 0 0; }
.patron-page-footer { margin: 2rem 0 0; }

/* ---- Signed-in / unconfigured states ---- */
.patron-status { font-size: 1.05rem; margin: 1.5rem 0; }
.patron-signout-form { margin: 1.5rem 0 var(--space-3); }
.patron-signout-note,
.patron-disabled-note { color: var(--text-secondary); }

/* ---- The ?patron= return notice ---- */
/* The three variants differ ONLY by their left rule: the notice reports what
   happened, and a full-bleed status colour would read as a verdict on the
   reader. Gold is not used for any of them — it is chrome, never a signal. */
.patron-notice {
  border: 1px solid var(--pane-border);
  border-inline-start-width: 3px;
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  margin: 0 0 2rem;
  background: var(--surface-raised);
}
.patron-notice--ok { border-inline-start-color: var(--hl-green); }
.patron-notice--info { border-inline-start-color: var(--hl-blue); }
.patron-notice--error { border-inline-start-color: var(--hl-orange); }
.patron-notice-title { margin: 0 0 var(--space-2); font-size: 1.05rem; }
.patron-notice-body { margin: 0; }
.patron-notice-actions {
  display: flex; flex-wrap: wrap; gap: var(--space-4);
  margin: var(--space-4) 0 0; font-size: 0.9rem;
}
.patron-notice-dismiss { color: var(--text-secondary); }

/* ---- The two entry points ---- */
/* One quiet line in the /support hero — not a panel, not a button, so it cannot
   compete with the page's argument. */
.support-signin-line { color: var(--text-secondary); max-width: 44rem; margin: var(--space-3) 0 0; }
/* Header pill as a LINK.
   .pill and .pill-subscriber stay BYTE-UNTOUCHED; everything below is on the new
   .pill-link modifier.

   WHY THIS IS MORE THAN `text-decoration: none`. The pill used to be a
   <span class="pill pill-subscriber">. As an <a> inside .nav-list it now matches
   `.nav-list a` (line ~545), which is specificity (0,1,1) and therefore beats
   BOTH .pill and .pill-subscriber at (0,1,0) — it resets background to
   transparent, border to none, color to --text-primary, padding to the nav
   metric and `font: inherit` (which drops the pill's size and weight). The pill
   rendered as plain nav text: verified in-browser, and INVISIBLE to every
   HTML-level check, because the markup is correct and only the cascade is wrong.

   The counter is CLASS specificity, not an !important and not an edit to the
   shared rules: a two-class selector is (0,2,0), and 2 classes beats 1 class +
   1 type. Hover needs (0,3,0) to clear `.nav-list a:hover` at (0,2,1). Only the
   properties `.nav-list a` actually steals are restored, and colours are read
   from the SAME tokens .pill/.pill-subscriber use, so a theme change still
   reaches both spellings. */
.pill.pill-link {
  padding: 0.15rem 0.6rem;
  border-radius: 999px;
  border: 1px solid var(--pane-border);
  background: var(--surface-sunken);
  color: var(--text-primary);
  font-size: 0.8rem;
  font-weight: 600;
  text-decoration: none;
  /* Anchor-specific: a 0.8rem pill is a small tap target once it is a real link.
     24px is the WCAG 2.5.8 (AA) minimum; inline-flex + centring grows the box
     without moving the label off the nav baseline. */
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}
/* `color` is restored here for the same reason background and border are: at
   (0,3,0) this rule beats `.nav-list a:hover` (0,2,1) on every property it
   DECLARES, and on the ones it does not, the nav rule still wins — it sets
   `color: var(--brand)`, i.e. GOLD, which is chrome-only and must never land on
   a non-chrome pill. It was never a live defect, and with the subscriber pill
   retired this rule is now the ONLY thing standing between `.nav-list a:hover`
   and a gold `<a class="pill pill-soon pill-link">`. Do not drop it. */
.pill.pill-link:hover,
.pill.pill-link:focus-visible { background: var(--surface-sunken); color: var(--text-primary); text-decoration: none; }

/* ---- The ad-slot patron callout (partials/ads.ejs, terminal position) ----
   Its own recessed panel, set off by a full 1.5rem, NOT a border-top hairline:
   a hairline directly under an ad unit reads as the ad's own frame, which is
   the exact confusion the element is separated out of the <aside> to avoid. The
   whole .ad-* family stays byte-untouched — nothing here is a modifier of it.

   THE ACTION IS GOLD (owner ruling 2026-08-13) — THE CARD AROUND IT IS NOT.
   This paragraph used to open "NO GOLD, ANYWHERE IN THIS BLOCK, and that is a
   content rule rather than a taste one", on the reasoning that 17 of the ads
   partial's 37 include sites are Scripture Analysis surfaces, where gold is the
   chrome colour and a gold control closing a contradictions page would read as
   the page's verdict rendered in the verdict colour. The owner has since ruled
   the opposite FOR THE ACTION SPECIFICALLY — the same ruling shape, and the same
   scope, as the 2026-08-05 ruling on the sibling ad-blocker notice
   (docs/SPEC-adblock-notice.md; the .quiet-notice-link block further down this
   file is the ratified precedent this one copies). So the old caution is
   overridden on ONE element and nowhere else: .patron-callout-btn ships as a
   solid gold button, on the --brand-fill / --brand-on-fill pairing already used
   site-wide for a solid CTA, while the CARD keeps every bit of its restraint.
   The panel, the prose and the sign-in line still carry no accent token at all,
   and that is the half of the original reasoning still doing the work — a quiet
   card with one gold control on it does not read as a verdict panel on those 17
   Analysis surfaces; a gold-tinted card would. Check 31 in
   test/patron-visibility.test.js enforces that boundary rule by rule, rather
   than banning gold from the block outright the way it used to.

   THE KEYBOARD FOCUS RING is still the deliberate exception and is not declared
   here at all — the global `:focus-visible` rule (line ~306) supplies it
   site-wide, and a focus indicator is browser chrome about the reader's caret,
   not a signal about the argument. */
.patron-callout {
  margin-block-start: 1.5rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-sunken);
}
/* CENTRE-ALIGNED, by the same 2026-08-13 owner ruling that gilded the action.
   The centring is declared on the three CHILD rules rather than as one
   `text-align: center` on the panel, and that is a mechanical choice with a
   reason, not an oversight: check 22 in test/adblock-notice.test.js pins the
   .patron-callout declaration block BYTE-FOR-BYTE as #95's shared-class scoping
   proof, and centring inherited from the panel renders identically to centring
   declared on each of its children. The card looks the same either way and a
   sibling feature's proof survives intact, so the children carry it.

   `margin-inline: auto` on top of the existing 44rem cap is the half that is
   easy to miss — the same pairing .quiet-notice-text uses one block down.
   Without it a capped box sits flush to the panel's start edge on a wide
   surface and only its LINES centre inside that box, which reads as a
   text-alignment bug rather than as a centred card. `margin: 0` becomes
   `margin-block: 0` so the inline axis is free to take that auto.

   .patron-callout-actions is a <p> wrapping an inline-flex <a>: an inline-flex
   box is inline-LEVEL, so `text-align: center` on its block container is what
   centres the button. It needs no `justify-self`/`margin-inline: auto` of its
   own — .quiet-notice-link needs `justify-self` only because that card is a
   grid and this one is not. */
.patron-callout-text {
  margin-block: 0;
  margin-inline: auto;
  max-width: 44rem;
  font-size: 0.9rem;
  color: var(--text-secondary);
  text-align: center;
}
.patron-callout-actions { margin: var(--space-4) 0 0; text-align: center; }

/* THE ACTION — a solid gold button AT REST (owner ruling 2026-08-13; the note at
   the top of this block records what it supersedes). It reuses the --brand-fill
   / --brand-on-fill pairing that .quiet-notice-link, .version-chip.is-active and
   .analysis-search-submit already use for a solid CTA: no new colour, no new
   token, no treatment this stylesheet did not already ship. The whole shape is
   copied from .quiet-notice-link deliberately, down to the 700 weight and the
   filter transition, because that control is the ratified precedent for a
   first-party gold action sitting on a quiet card.

   STILL NEVER .btn AND NEVER .btn-ghost — that half of the old reasoning is
   untouched, and it was never really about the colour. Both are SHARED
   PRIMITIVES: .btn-ghost in particular is an --accent-soft fill with a --brand
   label and an --accent-border edge, a visibly different treatment from this
   one, and borrowing either would make every future edit to a site-wide button
   an edit to this callout as well. The ruling changed this control's COLOUR, not
   its namespace; .patron-callout-btn keeps its own rules and its own class, and
   check 31 in test/patron-visibility.test.js pins both halves of that.

   An <a>, never a <button>, likewise unchanged: a link to another page must stay
   a real link for middle-click, right-click and no-JS navigation. Only its
   visual treatment moved.

   `color` and `text-decoration` are still DECLARED rather than inherited, but
   for the opposite reason they used to be. The base `a` rule sets colour to
   --brand, which on a --brand-fill ground is gold-on-gold and close to
   unreadable; --brand-on-fill is the dark-navy label that pairing exists for.
   The underline `a:hover` adds is out-specified below, same as before.

   min-block-size meets the 44px tap target and is load-bearing for check 32;
   inline-flex + centring grows the box around a 0.9rem label rather than
   padding it off its own baseline. */
.patron-callout-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 44px;
  padding: 0.6rem 1.1rem;
  border: 1px solid var(--brand-fill);
  border-radius: var(--radius);
  background: var(--brand-fill);
  color: var(--brand-on-fill);
  font-family: var(--font-ui);
  font-size: 0.9rem;
  font-weight: 700;
  text-decoration: none;
  transition: filter 120ms;
}
/* THE INTERACTION STATE IS A LIFT, NOT A SWAP. The neutral outline this control
   wore at rest before the ruling is NOT recycled as the hover state: a solid
   button that drops its fill on hover reads as broken rather than as
   responding, and the old rest state was a transparent ground, so reusing it
   here would make hovering look like the control had been disabled. It takes
   the house idiom the ratified sibling uses instead — `filter`, not a second
   hard-coded fill, so the tone lightens without introducing a new hex value or
   a fourth per-theme token.

   text-decoration is redeclared because `a:hover` at (0,1,1) would otherwise add
   an underline a solid button must never show; these two selectors sit at
   (0,2,0) and win. :focus-visible stays PAIRED with :hover, as it was before the
   ruling, so a keyboard reader gets the same response a pointer does — on top of
   the global focus ring, which draws outside the box and is undisturbed by the
   filter. */
.patron-callout-btn:hover,
.patron-callout-btn:focus-visible {
  filter: brightness(1.05);
  text-decoration: none;
}

/* The quieter second line. Its anchor carries an UNDERLINE because it cannot
   carry the site's link colour — that colour is --brand, and the 2026-08-13
   ruling reached the ACTION alone, not this line — so the underline is what
   marks it as a link at all. */
.patron-callout-signin {
  margin: var(--space-3) 0 0;
  font-size: 0.85rem;
  color: var(--text-secondary);
  text-align: center;
}
.patron-callout-signin a { color: var(--text-primary); text-decoration: underline; }

/* ---- #95 the ad-blocker notice (partials/footer.ejs host, injected by app.js) ----
   docs/SPEC-adblock-notice.md §5. A NEW NAMESPACE: nothing above this block is
   modified by #95, and that untouched state is the shared-class scoping proof
   (CLAUDE.md). No selector here begins with `ad` or contains
   advert/sponsor/banner/promo — EasyList's generic cosmetic rules hide those BY
   NAME, and a notice that a blocker hides is a notice that reaches nobody it is
   addressed to. (public/js/app.js deliberately INVERTS that rule for its throwaway
   bait element, which exists to be hidden. See the comment there.)

   THE ACTION IS GOLD (owner ruling 2026-08-05) — THE REST OF THE CARD IS NOT.
   This paragraph used to read "NO GOLD IN THIS BLOCK, AND THAT IS A DECISION, NOT
   AN OVERSIGHT": the original reasoning was that the host sits directly above the
   footer's gold four-point flourish and its gold column eyebrows, so a third gold
   element in that stack would compete with both. The owner has since ruled the
   opposite FOR THE ACTION SPECIFICALLY, so that reasoning is overridden there and
   nowhere else: `.quiet-notice-link` ships as a solid button on its own row, using
   the `--brand-fill` / `--brand-on-fill` pairing already used site-wide for a solid
   gold CTA (`.version-chip.is-active`, `.analysis-search-submit`), replacing the
   plain underlined text-link treatment it used to share with
   `.patron-callout-signin a`. Body and lead-in copy are UNCHANGED by that ruling
   and stay quiet: `--text-secondary` on `--surface-sunken`, no colour token of
   their own. Check 21 in test/adblock-notice.test.js enforces the boundary
   directly — only `.quiet-notice-link` may carry a `--brand` token in this block.
   The keyboard focus ring is still the one exception not declared here at all: the
   global :focus-visible rule supplies it site-wide, on the surrounding surface via
   its `outline-offset`, so it reads clearly even against the gold fill.

   NO ENTRANCE ANIMATION. An element that is invisible until scrolled to gains
   nothing from a fade, and a fade is one more prefers-reduced-motion branch to get
   wrong. Nothing here needs a motion gate. */

/* THE HOST DECLARES NO `display` PROPERTY. THAT IS THE MECHANISM, NOT AN OMISSION.
   The element is SSR'd empty + `hidden`, and it is the UA rule
   `[hidden] { display: none }` that makes it a TRUE ZERO BOX on every no-show and
   no-JS path. Any `display` here (even `display: block`) out-specifies the UA rule
   and paints an empty band on every page for every reader — including patrons and
   readers with JS off. For the same reason: no min-height / min-block-size (a
   height reserve on a box that usually never appears is a permanent tax to avoid
   a one-time below-the-fold shift), and no `overflow-anchor`/`contain` (browser
   scroll anchoring is what absorbs that shift for a reader parked at the document
   foot; suppressing it would create the very jump this is measured against).

   Geometry only: it matches .footer-inner's measure and inline padding so the
   notice lines up with the footer columns below it rather than spanning the full
   viewport. `margin: 0 auto` centres it; the block-end padding is zero because
   .footer-rule below supplies its own 1.5rem block-start margin. */
.quiet-notice-host {
  max-width: 76rem;
  margin: 0 auto;
  padding: 1.5rem 1.25rem 0;
}

/* The card. Quiet by construction: the recessed surface + one hairline frame, the
   .patron-callout pairing (--text-secondary on --surface-sunken), already AA in all
   three themes, so #95 introduces no colour token to the CARD itself — the action
   is the one exception, and it is a button, not a card colour (see the note above).

   THREE-COLUMN GRID (owner ruling 2026-08-05: centered text), not the original
   two-column layout and not flex. Text/alt/link all sit in the CENTER column
   (col 2); the dismiss button sits alone in col 3; col 1 is an EMPTY MIRROR of
   col 3's width. That mirror is the whole mechanism: in the old two-column
   layout, centering column-1 content centered it inside a column already
   narrowed by the dismiss button's width, landing ~25px left of the card's true
   center — a bug, not a look. A flanking empty column of the SAME width makes
   the center column, and anything centered inside it, symmetric relative to the
   WHOLE card. It also means the dismiss button can never overlap the text at any
   width — col 3 is a dedicated track, not shared row space, so there is no
   per-viewport clearance math to keep in sync by hand. 2.75rem (44px) is the
   dismiss button's own WCAG 2.5.8 minimum target, so both flank columns are
   sized to exactly that. minmax(0, 1fr) on the center column keeps it from
   blowing out on a long unbroken token, same role it played before.

   TWO paragraphs plus the action is the shipped shape (owner ruling 2026-08-04,
   N5, plus the 2026-08-05 action-button ruling): the card was delivered at
   three paragraphs, compressed to two, and now gains a third ROW that is a
   button, not a paragraph — the paragraph COUNT the N5 ruling fixed is
   unchanged; only the action's presentation and position moved. */
.quiet-notice {
  display: grid;
  grid-template-columns: 2.75rem minmax(0, 1fr) 2.75rem;
  gap: 0 0.6rem;
  align-items: start;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
  background: var(--surface-sunken);
}
.quiet-notice-text,
.quiet-notice-alt,
.quiet-notice-link { grid-column: 2; }
.quiet-notice-text { grid-row: 1; }
.quiet-notice-alt { grid-row: 2; }
.quiet-notice-link { grid-row: 3; }
.quiet-notice-dismiss { grid-column: 3; grid-row: 1; }

.quiet-notice-text {
  margin-block: 0 var(--space-3);
  margin-inline: auto;
  max-width: 44rem;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-secondary);
  text-align: center;
}
/* The alternative line, in the register of .patron-callout-signin: quieter than the
   body above it. No longer the last child — the action button is, since the
   2026-08-05 ruling moved it onto its own row — so it now carries the same
   block-end gap as .quiet-notice-text rather than none. `margin-inline: auto` on
   top of the shared `max-width: 44rem` is what keeps the WIDE-viewport case
   centered on the card rather than merely filling the (already-centered) grid
   column: without it the capped box would sit flush to the column's start edge. */
.quiet-notice-alt {
  margin-block: 0 var(--space-3);
  margin-inline: auto;
  max-width: 44rem;
  font-size: 0.85rem;
  line-height: 1.5;
  color: var(--text-secondary);
  text-align: center;
}
/* THE ACTION — a solid gold button (owner ruling 2026-08-05; see the note at the
   top of this block for what it supersedes). Reuses the --brand-fill /
   --brand-on-fill pairing .version-chip.is-active and .analysis-search-submit
   already use for a solid CTA fill — no new colour, no new treatment. Still a
   real <a href="/support">, never a <button>: a link to another page must stay a
   real link for middle-click, right-click and no-JS navigation; only ITS VISUAL
   treatment changes. `justify-self: center` (not `margin-inline: auto`) because
   this is a shrink-wrapped inline-flex box, not a max-width block like its two
   siblings above. */
.quiet-notice-link {
  justify-self: center;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-block-start: var(--space-2);
  padding: 0.55rem 1.2rem;
  border: 1px solid var(--brand-fill);
  border-radius: var(--radius);
  background: var(--brand-fill);
  color: var(--brand-on-fill);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 0.85rem;
  text-decoration: none;
  transition: filter 120ms;
}
/* filter, not a second hard-coded fill: the tone lightens without a new hex value.
   text-decoration is redeclared because `a:hover` at (0,1,1) would otherwise add
   an underline a solid button must never show; `.quiet-notice-link:hover` at
   (0,2,0) wins. */
.quiet-notice-link:hover { filter: brightness(1.05); text-decoration: none; }

/* A real <button> (aria-label="Dismiss this notice"), 44x44 per WCAG 2.5.8, quiet
   glyph.

   THE NEGATIVE MARGIN IS OPTICAL, NOT DIMENSIONAL. `min-width`/`min-height: 44px`
   set the target; the pullback only MOVES that box, it never shrinks it, so the
   WCAG 2.5.8 target survives intact (measured: 44x44). It pulls the box 0.5rem
   toward the block-start and 0.6rem toward the inline-end so the glyph sits level
   with the first line of copy instead of floating in the middle of whatever grid
   row its body paragraph sets, and so the oversized hit area tucks INTO the card's
   own padding rather than pushing the text column narrower. The card pads
   var(--space-4) var(--space-5) = 16px/24px, so a 8px/9.6px pullback still leaves
   the button's box inside the card border on both axes (measured) — it does not
   overhang. That stays true at the compressed two-paragraph size: the pullback is
   measured against the CARD's padding, never against the card's height. */
.quiet-notice-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  margin: -0.5rem -0.6rem 0 0;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 1.2rem;
  line-height: 1;
  cursor: pointer;
}
.quiet-notice-dismiss:hover { color: var(--text-primary); }

/* NARROW-WIDTH COLLAPSE — the flank-mirror grid above is the right trade on a wide
   card, where two 2.75rem flank tracks are a rounding error against a ~1100px
   content column. It is the WRONG trade on a phone: at 390px the card itself is
   only ~350px wide, and 48px of card padding plus BOTH 2.75rem flank tracks (88px)
   plus two 0.6rem gaps (19.2px) left the content column ~195px — barely 55% of
   the card. Measured before this rule existed: the body copy wrapped to seven
   short lines, the card grew to 321px tall, and the action button itself wrapped
   onto two lines.

   30rem is this stylesheet's OWN existing small-screen breakpoint (four other
   uses), reused rather than invented. Below it, the dismiss button trades its
   column for its OWN row, `justify-self: end` instead of a mirrored track:
     - a single full-width column is trivially centered on the card (there is
       nothing left to mirror — no column-1/column-3 asymmetry is possible when
       there is only one column), so `.quiet-notice-text`/`-alt`'s existing
       `text-align: center` + `margin-inline: auto` keep working unmodified;
     - the "copy never runs under the dismiss button" guarantee still holds, by a
       DIFFERENT mechanism than the flank column above — the button is a
       different ROW now rather than a different COLUMN, but either way it is
       never shared row space with the copy.
   `justify-self: end` has to be declared explicitly here: without it, a grid
   item defaults to `stretch`, and a lone full-width column would stretch the
   button across the whole card rather than hugging the inline-end edge.

   THE MARGIN'S BOTTOM VALUE IS THE ONE THING THAT DOES need adjusting for this
   row, not just this column. The base rule's `margin: -0.5rem -0.6rem 0 0` was
   tuned for the button sharing ROW 1 with `.quiet-notice-text`, where the text's
   own line-height supplied the visual gap to row 2 and the button needed none of
   its own. Here the button is alone in row 1 with nothing below it contributing
   spacing, and `gap: 0 0.6rem` on the grid is a COLUMN gap only (row-gap 0) — so
   without a bottom value the measured gap between the button's box and the first
   line of body copy is exactly 0px. `var(--space-2)` restores real breathing room
   without touching the top/right pull, which still does the same optical job
   (tucking the 44px target into the card's own padding) it does above 30rem. */
@media (max-width: 30rem) {
  .quiet-notice { grid-template-columns: minmax(0, 1fr); }
  .quiet-notice-text,
  .quiet-notice-alt,
  .quiet-notice-link,
  .quiet-notice-dismiss { grid-column: 1; }
  .quiet-notice-dismiss {
    grid-row: 1;
    justify-self: end;
    margin: -0.5rem -0.6rem var(--space-2) 0;
  }
  .quiet-notice-text { grid-row: 2; }
  .quiet-notice-alt { grid-row: 3; }
  .quiet-notice-link { grid-row: 4; }
}

/* ============================================================================
   PERSISTENT PATREON SIGN-IN CONTROL (partials/auth-control.ejs)
   ============================================================================
   Ported from the sibling app Lemma (its docs/patreon-login-button-spec.md §3,
   §6). Last item in .nav-list-end, after the Support pill and before the gear.

   COLOUR COMES FROM THE --patreon-* TOKENS, NEVER FROM --brand. This is a
   third-party affordance and must not look like GEBible chrome; that visual
   separation is also what keeps it from reading as "GEBible, a Patreon product".
   Those two tokens already existed for /patron-login's .patron-signin-btn — this
   block reuses them rather than introducing a parallel set.

   NOTHING HERE IS A MODIFIER OF A SHARED CLASS. The .pill family, .nav-list,
   .nav-dropdown* and .patron-signin-* are all byte-untouched; every selector
   below is new. */
.header-auth { display: inline-flex; align-items: center; position: relative; }

/* ---- S1: the signed-out sign-in link ----
   `.nav-list a` is (0,1,1) and would otherwise strip the background, border and
   font off this anchor exactly as it did the header pill. Every property that
   rule steals is restored here, and the selector is raised to (0,2,0) with
   .header-auth so it wins on the ones it declares. */
.header-auth .auth-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 32px;
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: 999px;
  background: var(--patreon-black);
  color: var(--patreon-on-black);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 700;
  text-decoration: none;
  white-space: nowrap;
  transition: filter 120ms;
}
/* (0,3,0) to clear `.nav-list a:hover` at (0,2,1), which sets `color: var(--brand)`
   — gold on a near-black brand surface. `filter` rather than a second hard-coded
   hex: the fill is Patreon's, so lightening it is a treatment, not a re-colour. */
.header-auth .auth-btn:hover,
.header-auth .auth-btn:focus-visible {
  background: var(--patreon-black);
  color: var(--patreon-on-black);
  filter: brightness(1.35);
  text-decoration: none;
}
.header-auth .auth-btn:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
/* The mark is an <img> of a local SVG. It cannot inherit currentColor — that is
   the point: it makes recolouring Patreon's mark impossible by construction. */
.auth-btn-mark { display: block; inline-size: 16px; block-size: 16px; flex: none; }

/* ---- S2: the signed-in supporter menu ----
   A native <details>, so it opens with JS off (see the partial for why that is
   load-bearing for a menu containing Log out). It deliberately does NOT reuse
   .nav-dropdown, whose menu is display:none until app.js adds .open. */
.auth-menu { position: relative; }
.auth-menu-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-height: 32px;
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--accent-border);
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--brand);
  font-family: var(--font-ui);
  font-size: 0.8rem;
  font-weight: 600;
  cursor: pointer;
  list-style: none;
  white-space: nowrap;
}
/* Removes the native disclosure triangle — the ▾ caret in the markup is ours,
   and it matches the Tools/Analysis toggles. Both spellings are required:
   WebKit needs the pseudo-element, Firefox honours `list-style`. */
.auth-menu-toggle::-webkit-details-marker { display: none; }
.auth-menu-toggle::marker { content: ''; }
.auth-menu-toggle:hover { background: var(--brand-fill); color: var(--brand-on-fill); }
.auth-menu-toggle:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.auth-menu-star { font-size: 0.75rem; line-height: 1; }
.auth-menu[open] > .auth-menu-toggle .caret { transform: rotate(180deg); }
.auth-menu .caret { display: inline-block; font-size: 0.7rem; transition: transform 120ms; }

/* Mirrors .nav-dropdown-menu's panel treatment without reusing the class, so the
   JS-driven dropdowns keep their rules to themselves. Right-anchored so a menu
   this close to the viewport edge cannot push the header wider. */
.auth-menu-panel {
  position: absolute;
  top: calc(100% + 0.4rem);
  right: 0;
  z-index: 60;
  min-inline-size: 13rem;
  padding: 0.35rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
}
.auth-menu-tier {
  margin: 0;
  padding: 0.4rem 0.55rem 0.5rem;
  border-bottom: 1px solid var(--pane-border-soft);
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 0.78rem;
}
.auth-menu-panel .auth-menu-item {
  display: block;
  min-height: 32px;
  padding: 0.45rem 0.55rem;
  border-radius: 6px;
  color: var(--text-primary);
  font-size: 0.85rem;
  text-decoration: none;
}
.auth-menu-panel .auth-menu-item:hover { background: var(--surface-sunken); color: var(--brand); }

.auth-logout { margin: 0.15rem 0 0; padding: 0; }
.auth-logout-btn {
  display: block;
  inline-size: 100%;
  min-height: 32px;
  padding: 0.45rem 0.55rem;
  border: none;
  border-radius: 6px;
  background: none;
  color: var(--text-secondary);
  font-family: var(--font-ui);
  font-size: 0.85rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
}
.auth-logout-btn:hover { background: var(--surface-sunken); color: var(--brand); }
.auth-logout-btn:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }

/* NO ICON-ONLY NARROW-VIEWPORT RULE, DELIBERATELY — do not "restore" one.
   Lemma's spec collapses this control to a 44x44 icon below 760px because its
   control lives in an always-visible .header-end and genuinely runs out of bar.
   GEBible's header does not work that way: at 760px the ENTIRE .primary-nav goes
   `display: none` behind the hamburger (see the Responsive nav block above), and
   the control rides inside .nav-list-end, so it has no inline presence to
   shrink. An icon-only rule is therefore dead while the menu is shut — and
   actively wrong once it is open, because .nav-list becomes a stacked
   full-width column where a label-less 37px pill reads as an unexplained blob
   between "Support" and the settings gear. Verified by rendering at 390px with
   the menu open; the label stays. */

/* Forced colours (Windows High Contrast). The button is a brand-mark container
   whose colour carries meaning, and the mark is a white <img> that would vanish
   onto a forced light ButtonFace. Pin it, but keep a UA-painted boundary so it
   stays identifiable as a control. forced-color-adjust is used here deliberately
   and narrowly — a logo is the canonical case the property exists for. Do NOT
   extend it to .auth-menu-toggle or .auth-menu-panel; those must keep system
   colours. */
@media (forced-colors: active) {
  .header-auth .auth-btn {
    forced-color-adjust: none;
    background: #0e0e10;
    color: #ffffff;
    border: 1px solid ButtonBorder;
  }
  .header-auth .auth-btn:focus-visible { outline: 2px solid Highlight; outline-offset: 2px; }
}

/* ==========================================================================
   GLOBAL PAGE-SHARE CONTROL (partials/header.ejs)
   docs/SPEC-global-share-affordance.md
   ==========================================================================
   A direct child of the header row, OUTSIDE the collapsing nav, so it survives
   the 760px breakpoint where the nav goes display:none behind the hamburger.

   HEIGHT IS THE CONSTRAINT THAT MATTERS. Two sticky bars derive their `top`
   from the rendered height of the header (the reader toolbar, and the privacy
   jump-nav whose derivation is written out at ~4327: `calc(1.2rem + 36px)`
   below 760px, `calc(2.4rem + 1.2rem)` above). Both formulas assume the tallest
   thing in the header row is the nav toggle (36px) or a nav-link box (2.4rem).
   The 32px min-block-size below keeps this control under both, so neither
   formula moves and neither bar develops a gap. box-sizing is border-box
   globally, so 32px is the WHOLE box, padding included. Do not grow it, and do
   not touch the header row's padding or the toggle's height.

   SELECTOR NAMES IN THIS COMMENT ARE WRITTEN WITHOUT THEIR LEADING DOT, which
   is not a typo — several suites isolate a region of this stylesheet with
   lastIndexOf('.some-class'), and a later mention drags that anchor down here. */
.header-share { position: relative; display: inline-flex; align-items: center; }

.header-share-toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: 32px;
  min-inline-size: 32px;
  /* SYMMETRIC 0.35rem, so the box is the 32px SQUARE the sizes above declare.
     0.35rem/0.5rem made it 36px wide, and the four pixels are not cosmetic:
     measured at a 16px base, the header row at 761px — the narrowest width at
     which the nav is still expanded — had exactly 721px of content in 721px of
     space with a 36px control, so .header-inner's flex-wrap sent the nav to a
     second row and the header grew to 114.94px across a 761-763px band. At 32px
     it fits at every width. Do not restore the wider inline padding. */
  padding: 0.35rem;
  border-radius: 8px;
  color: var(--text-secondary);
  cursor: pointer;
  list-style: none;          /* Firefox: kill the native disclosure triangle */
}
.header-share-toggle::-webkit-details-marker { display: none; }
.header-share-toggle::marker { content: ''; }
.header-share-toggle:hover,
.header-share-toggle:focus-visible { color: var(--brand); background: var(--surface-sunken); }
.header-share-toggle:focus-visible { outline: var(--focus-ring); outline-offset: 2px; }
.header-share-icon { display: block; }

.header-share-panel {
  position: absolute;        /* never grows the header row, open or closed */
  top: calc(100% + 0.4rem);
  inset-inline-start: 0;
  z-index: 60;               /* the same seat the account menu panel takes */
  inline-size: max-content;
  min-inline-size: 15rem;
  max-inline-size: min(26rem, calc(100vw - 2rem));
  padding: 0.6rem 0.7rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.28);
}
.header-share-label {
  margin: 0 0 0.3rem;
  font-family: var(--font-ui);
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-secondary);
}
.header-share-url {
  display: block;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--text-primary);
  overflow-wrap: anywhere;   /* a /v/ URL with a version query must not overflow */
}
.header-share-actions { margin: 0.55rem 0 0; }

/* THE NO-JS CONTRACT, ENFORCED. The Copy button ships with the `hidden` attribute
   and is un-hidden by app.js — but `hidden` alone does not hold it: the UA rule is
   `[hidden] { display: none }` with NO !important, and an author `display` beats a
   UA one regardless of specificity, so `.btn`'s `display: inline-block` renders the
   button anyway. MEASURED, not assumed: with /js/app.js blocked and the panel open,
   the button laid out at 94x35 while still carrying the attribute — i.e. a dead
   clipboard control shown to exactly the reader who cannot use it.

   This is the same fix, and the same reasoning, as the loc-book-row[hidden] and
   crossref-item[hidden] rules already in this stylesheet. It is not "revealing by
   CSS" in reverse — it makes the attribute mean what the markup says it means, and
   app.js still owns the reveal by clearing the attribute.

   (The same collision affects several EXISTING controls — the per-verse copy pill,
   the star, the cross-reference pager and both study-share buttons all render for a
   no-JS reader today. That is a pre-existing, app-wide defect and is deliberately
   NOT fixed here; it belongs to those families' own rules.) */
.header-share-copy[hidden] { display: none; }

/* NARROW VIEWPORTS: the panel spans the header row instead of hanging off the
   toggle, and this is a correctness fix rather than a refinement. Hanging the
   panel off the control means its left edge sits wherever the control sits —
   measured at 125.6px in from the viewport edge — while its only width clamp is
   viewport-relative, which knows nothing about that offset. Below about 560px
   the two disagree and the panel runs off the right edge: at 320px it ended at
   413.6px against a 320px viewport and put 94px of HORIZONTAL SCROLL on the
   document, on exactly the device the installed PWA runs on.

   Re-anchoring is what fixes it, not a narrower clamp: no fixed width can work,
   because at 320px the room left of the right edge is under the panel's own
   minimum. With the control static, the nearest positioned ancestor is the
   sticky header, so the two insets below size the panel from the viewport
   directly and the percentage `top` drops it under the whole header row (below
   the expanded nav too, when the hamburger is open). Measured after: left 16,
   right viewport-16, no horizontal scroll at 320 / 390 / 760.

   THE BREAKPOINT IS THE APP'S EXISTING 760px, the same line the nav already
   collapses at, not a new one invented for this control. It is NOT, however, the
   same mechanism the nav dropdown menus use at that width, and the shared keyword
   makes that easy to misread: nav-dropdown-menu goes position:static so the MENU
   itself leaves positioning and lays out in flow inside the opened nav column.
   Here the HOST goes static while the PANEL stays position:absolute and re-anchors
   to the nearest remaining positioned ancestor, which is the sticky header. Same
   keyword, different element, different outcome. */
@media (max-width: 760px) {
  .header-share { position: static; }
  .header-share-panel {
    inset-inline: 1rem;
    inline-size: auto;
    min-inline-size: 0;
    max-inline-size: none;
  }
}

/* The Copy button's visible answer. app.js routes this control through the shared
   flashCopyState(), which stamps is-copied / is-copy-failed on the pressed button —
   but the mark itself is declared per button family, and the five families listed in
   the COPY FEEDBACK block earlier in this file do not include a sixth. Without these
   two rules the class would land on a button that shows nothing, which is precisely
   the invisible-feedback defect that block was written to end. Declared HERE, as an
   additive modifier on a new class, rather than by extending that block's selector
   list: those bodies are shared with the study and analysis share surfaces and stay
   byte-untouched. Same contract as the rest — a MARK, NOT A COLOUR (a check for
   success, a cross for failure, no hue), so a success tick can never read as an
   editorial signal on a Scripture Analysis surface. The base control is
   display:inline-block with no gap of its own, so the mark buys its own spacing the
   way the share-action rules in that block do. */
.header-share-copy.is-copied::after { content: '✓'; font-weight: 700; }
.header-share-copy.is-copy-failed::after { content: '✕'; font-weight: 700; }
.header-share-copy.is-copied::after,
.header-share-copy.is-copy-failed::after { margin-inline-start: 0.35rem; }

/* ==========================================================================
   BETA ACCESS GATE (docs/SPEC-beta-access-gate.md §5.6)
   ==========================================================================
   The one page the pre-release host serves to a reader who is not through the
   gate. It renders twice — as the 403 body for every gated URL, and as the 200
   body of GET /beta — from one template and one locals builder.

   SELECTOR NAMES ARE WRITTEN WITHOUT THEIR LEADING DOT IN THIS COMMENT, AND
   THAT IS NOT A TYPO. Several suites isolate a region of this stylesheet with
   lastIndexOf('.some-class') and then assert over the slice —
   test/adblock-notice.test.js does exactly that for the #95 notice. A later
   MENTION of one of those selectors, even inside a comment at the far end of the
   file, moves that anchor down here and silently stretches the slice across
   everything in between, so the notice's "no hex literal in this block"
   assertion starts reading hundreds of unrelated rules and goes red. Measured,
   not theorised: it happened while this block was being written. Name a selector
   in a comment down here without its dot, or do not name it.

   EVERYTHING BELOW IS A NEW beta-gate-* CLASS, and that is the shared-class trap
   being obeyed rather than described: no pricing-*, support-*, patron-callout*,
   quiet-notice* or ad-* rule is touched by this block, and the unchanged
   rendering of /support and /patron-login is the scoping proof.

   TWO DELIBERATE REUSES, both byte-untouched:
     - btn / btn-ghost, which are global first-party controls.
     - patron-signin-btn and its two children. A SECOND Patreon button style is
       a trademark and contrast risk this repo has already paid to get right
       (Patreon's near-black at 19.3:1, with the mark carried as an image element
       so CSS cannot alter a trademark), so the sign-in control reuses that
       markup and those rules, and not one declaration in that family is added or
       changed here.

   GOLD STAYS CHROME-ONLY. The "Beta" chip is an outlined --accent-soft /
   --accent-border pill, the same resting treatment btn-ghost uses; it is not a
   solid-gold badge, because a gold fill on this page would read as a value
   ladder on a surface whose whole argument is that there is not one. */

/* ---- REDESIGN (docs/SPEC-beta-gate-layout.md): ONE CENTERED COLUMN ----------
   Before this pass the page was a 76rem container shell with every block capped
   at the reading measure and margin 0 — i.e. left-flush inside a shell nearly
   twice its width, leaving ~490px of dead space down the right at 1280px, in all
   five states. Two separate decisions fix it.

   (1) THE SHELL NARROWS TO 46rem, on the beta-gate class itself. container is a
   SHARED rule and is not touched; beta-gate is declared far later in this file
   at equal specificity, so the cascade lands the narrower cap on this one page
   and nowhere else. container already carries margin: 0 auto, so narrowing IS
   centering.

   (2) THE PANEL EDGES — and BE PRECISE about what centers what, because the
   obvious reading of the rules below is wrong. Every block child also carries
   margin: <block> auto, but auto only distributes FREE space: of the twelve
   measure-capped blocks, exactly TWO have any — the OAuth notice and the closing
   line, the only two the measure narrows below the box they sit in. The other ten
   compute margin-left 0 and simply fill their column. The page is centered by the
   46rem cap above plus container's margin, not by these; the autos are kept for
   uniformity, so that no block can go left-flush if its cap ever starts binding.

   Text widths therefore VARY rather than sharing one pair of x-positions, and
   that follows from the token: measure is a ch value, so it scales with each
   element's own font-size. Five pairs at 1280px — 688px for the header stack,
   both lede paragraphs and every panel's outer edge; 666px for the closing line;
   638px for all panelled body text, the levels grid, the parity line and both
   headings; 633px for the notice at .95rem; 600px for the state note at .9rem.
   A panel's inner box is 638px (688 − 2×24 padding − 2×1 border), NARROWER than
   the 666px measure, which is why measure never binds inside a panel. The lede is
   the other end of the same fact: 66ch at 1.1rem is 733px, so it clamps to the
   688px content box and sits flush with the panel edges rather than inside them.

   What survives all that is the STEP, and the step is the whole visual argument:
   the panels and the card grid stand at 688px while the text inside them stops at
   638px, so the reader can see which parts are the page talking and which parts
   are a defined object.

   BODY COPY STAYS START-ALIGNED. A centered BLOCK reads as design; centered
   SENTENCES of four or five lines read as a poster. This is the same call
   analysis-hero-intro records. Nothing in this block sets text-align at all —
   the two header rows centre as FLEX rows.

   DELIBERATELY NOT PANELS: the header stack (eyebrow, title row, both lede
   paragraphs) and the closing line. A hero in a box is a page inside a page, and
   boxing the sign-off would give "the public site is the whole site" the same
   weight as the ask. A page where everything is a panel is as flat as a page
   where nothing is.

   THREE ELEVATIONS, and the state block is the top one: page → the two
   color-mix panels (what the beta is / the levels) → surface-raised cards (the
   state block itself, and the rung cards nested inside the levels panel). The
   state block also takes pane-border rather than pane-border-soft, because it is
   the answer to the only question this reader actually asked.

   NO MEDIA QUERY, and do not add one. Below ~46rem the shell is full width,
   measure stops binding, every margin-inline: auto becomes a no-op, and the
   levels grid's existing auto-fit drops to one column on its own.
   --------------------------------------------------------------------------- */

.beta-gate { max-width: 46rem; padding-block-end: 3rem; }

/* ---- The OAuth return notice (first child of <main>) ---- */
.beta-gate-notice {
  max-width: var(--measure);
  margin: 0 auto 2rem;
  padding: 0.85rem 1.1rem;
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
  color: var(--text-primary);
  font-size: 0.95rem;
}
/* The three outcomes differ only by a leading rule, never by a fill: this notice
   reports what a redirect said, and a green/red wash would grade it. */
.beta-gate-notice--ok { border-inline-start: 3px solid var(--accent-border); }
.beta-gate-notice--none,
.beta-gate-notice--error { border-inline-start: 3px solid var(--pane-border); }

/* ---- Brand eyebrow (plain text — there is nowhere for a link to go) ---- */
.beta-gate-brand {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin: 0 0 var(--space-2);
}
.beta-gate-brand-name {
  font-family: var(--font-ui);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text-primary);
}
.beta-gate-chip {
  padding: 0.1rem 0.55rem;
  border: 1px solid var(--accent-border);
  border-radius: 999px;
  background: var(--accent-soft);
  color: var(--brand);
  font-family: var(--font-ui);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

/* ---- Title row: the app's [glyph][title] idiom, CENTERED ----
   Copied from support-hero-title-row / privacy-title-row with one declaration
   added (justify-content) and one corrected. THE HEADING'S BLOCK-END MARGIN
   MOVES TO THE ROW: align-items centres flex items on their MARGIN boxes, so a
   1.25rem margin left on the h1 pushes the glyph ~0.6rem above the cap-height it
   is supposed to sit beside. Both idioms this is copied from keep the margin on
   the heading and carry that offset; it is far more visible once the row is
   centred, so it is fixed HERE and only here — neither of those rules is
   touched. */
.beta-gate-title-row {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  margin: 0 0 1.25rem;
}
/* Lets the heading shrink below its content width at narrow viewports instead of
   forcing the row wider than the container. */
.beta-gate-title-row h1 { min-inline-size: 0; }
.beta-gate-title-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
  color: var(--brand);
}
.beta-gate-title-glyph { inline-size: 1.75rem; block-size: 1.75rem; }

.beta-gate-title { margin: 0; }

/* ---- The escape hatch: two onward paths and the word between them ----------
   docs/SPEC-beta-gate-escape-hatch.md. A STACKED column at every width, never a
   wrapping row. A row would need a breakpoint this block does not have (there
   is no media query here and none may be added), and a wrapped row orphans the
   conjunction at the end of a line, which is the one element whose position
   carries meaning. Stacked, the reader always sees way-in / or / way-out top to
   bottom, which is also the shape the request described.

   BOTH OPTIONS TAKE THE SAME TREATMENT, and that is the point of the word
   between them: btn btn-ghost on each, global and byte-untouched, the same pair
   the sign-out control on this page already uses. A gold-filled btn on the
   first option beside a ghost on the second would encode a preference in colour
   on a page whose whole argument is that the reader may take either — the same
   reasoning that keeps a featured modifier off the two rung cards below.

   NO text-align, and none is needed: align-items centres each control as a BOX.
   This block declares none anywhere and a test counts that.

   NOT a jump-nav family. study-jumpnav, bible-search-jumpnav and the sticky
   privacy-jumpnav are all tables of contents into one document; the second
   option here leaves the origin. Selector names appear without their leading
   dots in this comment on purpose — see the block header. */
.beta-gate-choice {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  margin: 0 auto 2rem;
}
/* Keeps a long label inside the column on a narrow phone instead of pushing the
   page wider than the viewport. */
.beta-gate-choice-link { max-width: 100%; }
/* A plain word, not a pill and not gold: it is a conjunction, not a third
   option. Uppercased HERE rather than in the markup so a screen reader is given
   "or" and not "oh arr". */
.beta-gate-choice-or {
  font-family: var(--font-ui);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-secondary);
}

/* The lede carries the honesty anchor — the paragraph naming the public site —
   so it is set at reading size rather than as small print. */
.beta-gate-lede {
  max-width: var(--measure);
  margin: 0 auto 1rem;
  font-size: 1.1rem;
  line-height: 1.6;
}

/* ---- The state block: answer the reader before asking them for anything ----
   The TOP elevation on the page — surface-raised with the stronger pane-border,
   against the two color-mix panels below it. NO GOLD ACCENT RULE, and do not add
   one: this same block renders the thank-you to a paying supporter being told no
   AND the "sign-in isn't switched on" fault state, and a gold edge would
   celebrate one and decorate the other. */
.beta-gate-state {
  margin: 2rem auto;
  padding: var(--space-5);
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
/* The measure cap keeps panelled body text off the panel edge. The auto here is
   INERT and kept for uniformity, not effect: measure resolves to 666px and this
   panel's inner box is 638px, so the cap never binds, there is no free space to
   distribute, and margin-left computes to 0. What steps the text in from the
   edge is the panel's own padding. */
.beta-gate-state p { max-width: var(--measure); margin: 0 auto 1rem; line-height: 1.6; }
.beta-gate-state p:last-child { margin-block-end: 0; }
.beta-gate-state-title { max-width: var(--measure); margin: 0 auto 1rem; font-size: 1.2rem; }
.beta-gate-state-note { color: var(--text-secondary); font-size: 0.9rem; }
/* Controls sit at the START of that text column, never centred: a centred button
   under a ragged-right paragraph floats free of the sentence it belongs to. */
.beta-gate-cta { max-width: var(--measure); margin: 1.5rem auto; }
.beta-gate-signout { max-width: var(--measure); margin: 1.5rem auto 1rem; }

/* ---- "What the beta is" and "The levels" — the two mid-elevation PANELS ----
   The panel fill sits BETWEEN the page and the cards nested inside it, so the
   three elevations stay distinguishable. This app has no third surface token and
   the nested cards already own surface-raised, so the panel fill is MIXED from
   the two rather than inventing a fourth; the plain declaration above it is the
   fallback for engines without color-mix (panel and card then share a fill, and
   the border still separates them). The technique is RE-DERIVED here as a
   beta-gate class rather than by borrowing the utility pages' panel selector —
   the unchanged rendering of those pages is the scoping proof.

   MEASURED, AND RECORDED BECAUSE IT LOOKS LIKE A BUG AND IS NOT. The three
   elevations are distinct by FILL only in dark (10,21,48 → 19,30,61 → 26,37,71)
   and sepia (243,233,214 → 247,238,221 → 250,243,227). In LIGHT the mix
   degenerates: surface and surface-raised are 4–6/255 apart per channel there, so
   every possible ratio of them lands inside that band — 251,251,249 → 253,253,252
   → 255,255,255, contrast ratios of 1.02 and 1.016, which is ONE fill to the eye.
   In that theme the elevations are separated ENTIRELY by pane-border-soft against
   pane-border. No mix ratio fixes this and none should be tried; the only real
   remedy is a fourth surface token, which is a theme-wide decision and out of
   scope here. It is also not this page's problem: support-section, which ships
   this identical technique, resolves to the SAME computed values in light and has
   always looked this way. Verified side by side.

   NO HEADING IS ADDED to the "what the beta is" panel, and none may be. The
   page's copy is frozen; its first sentence already says what the panel is; and
   a third h2 here would compete with the state block at exactly the moment the
   state block has to own the reader's eye. */
.beta-gate-about,
.beta-gate-levels-section {
  border: 1px solid var(--pane-border-soft);
  border-radius: var(--radius);
  padding: var(--space-5);
  background: var(--surface-raised);
  background: color-mix(in srgb, var(--surface-raised) 55%, var(--surface));
}

/* ---- "What the beta is" ---- */
.beta-gate-about { margin: 2rem auto; }
.beta-gate-about p { max-width: var(--measure); margin: 0 auto 1rem; line-height: 1.6; }
.beta-gate-about p:last-child { margin-block-end: 0; }

/* ---- The levels ---- */
.beta-gate-levels-section { margin: 2rem auto 0; }
/* NOT GOLD. The utility pages set their panel headings in --brand; this one sits
   directly above the two pledge cards, which is the one place on this page where
   a gold cue would read as the value ladder the sentence below the pair denies
   in so many words. */
.beta-gate-levels-title { max-width: var(--measure); margin: 0 auto 1.5rem; font-size: 1.3rem; }
.beta-gate-levels-warning {
  max-width: var(--measure);
  margin: 0 auto 1.5rem;
  color: var(--text-secondary);
}
/* Auto-fit rather than a fixed column count: the card set is DERIVED from the
   capability the gate reads, so a rung gained or lost must not need a CSS edit
   to lay out. min-width: 0 on the item is required — a grid item's default
   min-width: auto refuses to shrink below its content and blows the track out. */
.beta-gate-levels {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  gap: 1rem;
  max-width: 46rem;
  margin: 0 auto;
  padding: 0;
  list-style: none;
}
.beta-gate-level {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding: var(--space-5);
  border: 1px solid var(--pane-border);
  border-radius: var(--radius);
  background: var(--surface-raised);
}
/* NO "featured"/"recommended" MODIFIER, and do not add one. The two rungs reach
   the beta identically, the page says so in its own sentence below the pair, and
   a highlighted card would encode in colour a gradient the copy denies. */
.beta-gate-level-price { margin: 0; display: flex; align-items: baseline; gap: 0.25rem; }
.beta-gate-level-amount {
  font-family: var(--font-ui);
  font-size: 1.9rem;
  font-weight: 700;
  color: var(--text-primary);
}
.beta-gate-level-per { color: var(--text-secondary); font-size: 0.95rem; }
.beta-gate-level-who { margin: 0; color: var(--text-secondary); }
.beta-gate-level-includes { margin: 0; color: var(--text-primary); }
.beta-gate-level-cta { margin: auto 0 0; padding-block-start: 0.5rem; }
.beta-gate-pending { color: var(--text-secondary); font-size: 0.95rem; }

.beta-gate-parity {
  max-width: var(--measure);
  margin: 1.5rem auto 0;
  color: var(--text-secondary);
}

.beta-gate-closing {
  max-width: var(--measure);
  margin: 3rem auto 0;
  padding-block-start: 1.5rem;
  border-block-start: 1px solid var(--pane-border);
  line-height: 1.6;
}
