/* ═══════════════════════════════════════════════════════════════════════════
   THE REGISTER — AffPapa homepage redesign prototype
   Governed by Phase-2-Visual-Direction/15-DESIGN-CONSTITUTION.md
   All accent colours are AffPapa's own tokens. All contrast values measured
   (Evidence/AffPapa-Reference/contrast-results.txt).
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* AffPapa locked identity */
  --coral: #fe454b;
  --coral-hover: #e63e44;
  --sky: #5BA8C0;
  --ink: #0f172a;
  --paper: #fcfcfd;
  --white: #ffffff;
  /* supporting neutrals (AffPapa's existing slate ramp) */
  --ink-2: #334155;
  --ink-3: #475569;
  --muted: #64748b;          /* lightest legal body colour — 4.76:1 */
  --hairline: #e2e8f0;
  --well: #f1f5f9;           /* logo wells, quiet grounds */
  --coral-tint: #fff0f0;     /* coral as soft field, ink text 16.13:1 */
  /* rising direction. affpapa.com's own indicator is #2bcf63, which measures
     2.06:1 on white and misses the 3:1 gate for a meaningful graphical object.
     This is that same hue (142° vs their 140°) at a lightness that clears it:
     5.01:1 on white, 4.89:1 on paper. Used for this indicator and nothing else. */
  --up: #17803d;
  /* system */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);  /* AffPapa's own easing token */
  --max: 1344px;              /* AffPapa's own content max */
  --hdr-h: 64px;
  --r: 4px;                   /* Law VI: radius ≤4px */
  --shadow-open: 0 8px 28px rgba(15, 23, 42, 0.10); /* one meaning: entry open */
}

/* ── reset ── */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  font-family: 'Inter', ui-sans-serif, system-ui, sans-serif;
  font-size: 17px; line-height: 1.6; color: var(--ink-2);
  background: var(--paper);
  font-feature-settings: 'tnum' 1;  /* Law V: tabular numerals everywhere */
}
img { max-width: 100%; display: block; }
[hidden] { display: none !important; }
a { color: inherit; }
h1, h2, h3 { color: var(--ink); line-height: 1.1; }
section { scroll-margin-top: calc(var(--hdr-h) + 12px); }  /* P2-8 fix */
.shell { max-width: var(--max); margin: 0 auto; padding: 0 clamp(16px, 3vw, 32px); }

/* Law XII: one focus ring — 2px ink, 2px offset; visible on every surface */
:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; border-radius: 2px; }
.junction :focus-visible, .foot :focus-visible { outline-color: var(--white); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: var(--white); padding: 12px 20px; font-weight: 600;
}
.skip:focus { left: 12px; top: 12px; }

/* ── type utilities ── */
.rec-label, .facets-tag, .term-tag, .media-chan, .news-cat {
  font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-3);
}
.num { font-variant-numeric: tabular-nums; }

/* ── buttons — Law II: primary = ink on coral (5.24:1) ── */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 10px 22px;
  font: 600 15px/1 'Inter', sans-serif; letter-spacing: 0.02em;
  text-decoration: none; border: 0; border-radius: var(--r); cursor: pointer; white-space: nowrap;
  transition: background-color 160ms var(--ease), color 160ms var(--ease), border-color 160ms var(--ease);
}
.btn-coral { background: var(--coral); color: var(--ink); font-weight: 700; }
.btn-coral:hover { background: var(--coral-hover); }
.btn-ghost { background: transparent; color: var(--ink); border: 1px solid var(--ink); }
.btn-ghost:hover { background: var(--ink); color: var(--white); }
.btn-ink { background: var(--ink); color: var(--white); font-weight: 700; }
.btn-ink:hover { background: #1e293b; }
.btn-lg { min-height: 52px; padding: 14px 30px; font-size: 17px; }

/* ═══ S1 · MASTHEAD ═══ */
.announce { background: var(--ink); color: var(--white); font-size: 15px; }
.announce p { max-width: var(--max); margin: 0 auto; padding: 0 clamp(16px, 3vw, 32px); text-align: center; display: flex; align-items: center; justify-content: center; gap: 6px; min-height: 44px; }
.announce a { color: var(--coral); font-weight: 700; text-underline-offset: 3px; display: inline-flex; align-items: center; min-height: 44px; padding: 0 6px; }

.hdr {
  position: sticky; top: 0; z-index: 100;
  background: var(--white); border-bottom: 1px solid var(--hairline);
}
.hdr-in { display: flex; align-items: center; gap: 28px; height: var(--hdr-h); }
.hdr-logo { display: flex; align-items: center; min-height: 44px; padding: 0 2px; }
.hdr-logo img { height: 26px; width: auto; }
.hdr-nav { display: flex; gap: 4px; margin-right: auto; }
.hdr-nav a {
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 12px;
  font-size: 15px; font-weight: 500; color: var(--ink-2); text-decoration: none; border-radius: var(--r);
}
.hdr-nav a:hover { color: var(--ink); background: var(--well); }
.hdr-actions { display: flex; gap: 10px; }
.hdr-router { display: flex; gap: 2px; border: 1px solid var(--hairline); border-radius: var(--r); padding: 2px; }
.hdr-router button {
  min-height: 38px; padding: 0 14px; font: 600 13px 'Inter', sans-serif; color: var(--ink-3);
  background: transparent; border: 0; border-radius: 3px; cursor: pointer;
}
.hdr-router button[aria-pressed="true"] { background: var(--ink); color: var(--white); }
.hdr-burger {
  display: none; width: 44px; height: 44px; align-items: center; justify-content: center;
  background: transparent; border: 0; color: var(--ink); cursor: pointer;
}
.drawer { display: none; }
.drawer[data-open] {
  display: flex; flex-direction: column; gap: 2px;
  position: fixed; inset: calc(var(--hdr-h)) 0 auto 0; z-index: 99;
  background: var(--white); border-bottom: 1px solid var(--hairline);
  padding: 12px clamp(16px, 3vw, 32px) 20px;
}
.drawer a { min-height: 48px; display: flex; align-items: center; font-size: 17px; font-weight: 500; text-decoration: none; color: var(--ink); border-bottom: 1px solid var(--well); }
.drawer-actions { display: flex; gap: 10px; margin-top: 14px; }
.drawer-actions .btn { flex: 1; }

/* ═══ S2 · HERO — Law V: type at maximum, Law I: the index enters the fold ═══ */
.hero { padding: clamp(20px, 2vw, 32px) 0 0; background: var(--paper); }
.hero h1 {
  font-size: clamp(40px, 6.8vw, 96px); font-weight: 800;
  letter-spacing: -0.03em; line-height: 1.02;
  margin-bottom: 14px; max-width: 20ch;
}
.hero-sub { font-size: clamp(17px, 1.6vw, 22px); color: var(--ink-2); max-width: 52ch; margin-bottom: 18px; }

/* E-4 · the hero ledger extract. Three real rows in the register's grammar —
   top rule, column heads, hairline rows, tabular score — so the first viewport
   shows what the page is rather than asserting it. Not a card: no radius, no
   shadow, no fill (Law VI). Hidden below the two-column hero, where the real
   register is already close to the fold and a specimen would only add length. */
.hero-peek { display: none; }
.peek-cap {
  font-size: 12px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--muted); padding-bottom: 8px; border-bottom: 2px solid var(--ink);
}
.peek-head {
  display: flex; justify-content: space-between; gap: 12px;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); padding: 8px 0 6px;
}
.peek-rows { list-style: none; }
/* Row padding is 6px, not 8px, for a measured reason: at 1280×800 the headline
   is shorter than at 1440, so at 8px the extract became the tallest thing in
   row 1 and set the row's height itself — which cost 10px of the fold gate's
   26px of headroom. At 6px the extract stays shorter than the headline at
   every width, so row 1 keeps its own height and the first record does not
   move. The rows are display-only and non-interactive, so no tap-target
   minimum applies to them. */
.peek-row {
  display: grid; grid-template-columns: 22px 1fr auto; align-items: center; gap: 10px;
  padding: 6px 0; border-top: 1px solid var(--hairline);
}
.peek-row img { border-radius: 3px; background: var(--well); object-fit: contain; }
.peek-name {
  font-size: 14px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.peek-score { font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
/* The extract shows only where the headline genuinely clears column 2. The
   headline spans both columns exactly as frozen — it is never re-flowed to
   make room — so the two share row 1 and the constraint is measured, not
   assumed: clearance is +27px at 1200 and +63px at 1440/1920, but −7px at
   1120, where the headline's second line would touch the extract. 1200px is
   therefore the floor, and below it the extract simply does not exist. */
@media (min-width: 1200px) { .hero-peek { display: block; } }

.stats { display: flex; gap: clamp(28px, 5vw, 72px); align-items: baseline; margin-bottom: 16px; }
.stats > div { display: flex; flex-direction: column-reverse; }
.stats dd {
  font-size: clamp(32px, 4.2vw, 56px); font-weight: 800; letter-spacing: -0.02em;
  color: var(--ink); line-height: 1; font-variant-numeric: tabular-nums;
}
.stats dt { font-size: 13px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted); margin-top: 6px; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: clamp(28px, 3vw, 40px); }

/* B1 · at desktop the hero is two columns: claim left, the doors right,
   so the register's first records rise into the first viewport. */
@media (min-width: 1120px) {
  .hero-in {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(340px, 400px);
    column-gap: clamp(40px, 4vw, 64px);
    align-items: start;
  }
  .hero-in > h1       { grid-column: 1 / -1; grid-row: 1; }
  .hero-main          { grid-column: 1; grid-row: 2; }
  .hero-rail          { grid-column: 2; grid-row: 2; }
  /* E-4 · the extract takes the cell the headline was already leaving empty:
     row 1 / column 2. The headline's breaks are hard-coded and its longest
     line measures 817px against an 822px column, so moving it out of the
     span rewraps nothing — verified at every breakpoint. Because the extract
     is shorter than the headline it never sets row 1's height, so the first
     record does not move by a single pixel. */
  /* R2 · the extract sat 8px above the router card and the two read as one
     four-item stack. The gap is the separation: extract and doors are
     different kinds of object and must not merge into a column of boxes. */
  .hero-peek          { grid-column: 2; grid-row: 1; align-self: end; padding-bottom: 20px; }
  .hero-in > .feats   { grid-column: 1 / -1; grid-row: 3; }
  .hero-cta { margin-bottom: 0; }
  /* doors stack in the rail; coral marks the current side as a left rule */
  .hero-rail .router { grid-template-columns: 1fr; }
  /* the rail is 400px wide and the fold gate is binding, so the card keeps
     all three zones at a tighter scale rather than dropping one. */
  .hero-rail .router { gap: 6px; padding-top: 2px; }
  .hero-rail .door { padding: 9px 11px 9px 12px; column-gap: 10px; }
  .hero-rail .door-mark { width: 40px; height: 40px; }
  .hero-rail .door-mark svg { width: 21px; height: 21px; }
  .hero-rail .door-body { padding-left: 10px; }
  .hero-rail .door-go { width: 24px; height: 24px; }
  .hero-rail .door[aria-selected="true"] .door-go { width: 28px; height: 28px; }
  .hero-rail .door-go svg { width: 17px; height: 17px; }
  .hero-rail .door-copy { max-width: none; }
}

/* the two doors — flow-hover audience controls. A coral circle flows in
   from the lower-left corner (::before), the text turns ink with it, the
   block scales up a shade on hover/focus and presses down on :active.
   Selected rests on the quiet coral tint + coral rule — always distinct
   from the saturated hover field. Coral marks the act (Law II): hover is
   the act about to happen. */
.router { display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: 1fr; gap: 12px; border-top: 3px solid var(--ink); padding-top: 14px; }
.door {
  position: relative; overflow: hidden; isolation: isolate; border-radius: var(--r);
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center; column-gap: 12px;
  text-align: left; cursor: pointer; margin: 0;
  background: var(--white); border: 0;
  box-shadow: inset 0 0 0 1px var(--hairline), inset 3px 0 0 var(--hairline);
  padding: 17px 17px 17px 17px;
  transition: box-shadow 200ms var(--ease), background-color 200ms var(--ease), transform 180ms var(--ease);
}
/* the anchor is a circular field carrying the card’s own mark */
.door-mark {
  width: 50px; height: 50px; display: grid; place-items: center; flex: none;
  background: var(--well); border-radius: 50%; color: var(--ink);
  transition: background-color 300ms var(--ease), color 300ms var(--ease);
}
.door-mark svg { width: 26px; height: 26px; }
.door-mark .mk-accent { stroke: var(--coral); transition: stroke 300ms var(--ease); }
/* copy is separated from the anchor by a rule, not by a gap alone (Law VI) */
.door-body { min-width: 0; border-left: 1px solid var(--hairline); padding-left: 12px; transition: border-color 300ms var(--ease); }
.door-go {
  display: grid; place-items: center; width: 28px; height: 28px; flex: none;
  color: var(--coral); border-radius: 50%;
  transition: color 300ms var(--ease), background-color 300ms var(--ease), transform 200ms var(--ease);
}
.door-go svg { width: 20px; height: 20px; }
.door::before {
  content: ""; position: absolute; z-index: 0;
  left: 0; top: 100%; width: 300%; aspect-ratio: 1; border-radius: 50%;
  background: var(--coral);
  transform: translate(-50%, -50%) scale(0);
  transition: transform 700ms var(--ease);
}
.door > * { position: relative; z-index: 1; }
.door-name { display: block; font-size: clamp(18px, 1.6vw, 22px); font-weight: 700; color: var(--ink); margin-bottom: 6px; transition: color 300ms var(--ease); }
.door-copy { display: block; font-size: 15px; line-height: 1.5; color: var(--muted); max-width: 44ch; transition: color 300ms var(--ease); }
.door[aria-selected="true"] {
  background: var(--coral-tint);
  box-shadow: inset 0 0 0 1px rgba(254, 69, 75, 0.30), inset 3px 0 0 var(--coral);
}
/* release fix: on the tinted selected ground the description takes the darker
   slate - --muted on --coral-tint measures 4.30:1 (fails AA at 15px); --ink-3
   measures 6.85:1. Hover/focus flood states still turn it ink (later rules). */
.door[aria-selected="true"] .door-copy { color: var(--ink-3); }
/* the reference tints this disc pink; measured, a coral mark on a pink disc
   is 2.64:1 and misses the 3:1 graphical gate (and still misses it at 4%
   tint, 2.93:1). White is the only ground that keeps the mark coral — 3.41:1
   — and it still reads as a distinct disc on the tinted card. */
.door[aria-selected="true"] .door-mark { background: var(--white); color: var(--coral); }
.door[aria-selected="true"] .door-body { border-left-color: rgba(254, 69, 75, 0.35); }
.door[aria-selected="true"] .door-go {
  background: var(--coral); color: var(--white); width: 32px; height: 32px;
}
.door-name::after {
  content: "●"; color: var(--coral); font-size: 10px; vertical-align: 4px; margin-left: 8px;
  transition: color 300ms var(--ease);
}
@media (hover: hover) {
  .door:hover { transform: scale(1.02); }
  .door:hover::before { transform: translate(-50%, -50%) scale(1); }
  .door:hover .door-name, .door:hover .door-copy,
  .door:hover .door-name::after { color: var(--ink); }
  .door:hover .door-mark { background: var(--white); color: var(--ink); }
  .door:hover .door-mark .mk-accent { stroke: var(--ink); }
  .door:hover .door-body { border-left-color: rgba(15, 23, 42, 0.28); }
  .door:hover .door-go { color: var(--ink); background: transparent; transform: translateX(3px); }
  .door:hover[aria-selected="true"] .door-go { background: var(--white); }
}
.door:focus-visible { transform: scale(1.02); }
.door:focus-visible::before { transform: translate(-50%, -50%) scale(1); }
.door:focus-visible .door-name, .door:focus-visible .door-copy,
.door:focus-visible .door-name::after { color: var(--ink); }
.door:focus-visible .door-mark { background: var(--white); color: var(--ink); }
.door:focus-visible .door-mark .mk-accent { stroke: var(--ink); }
.door:focus-visible .door-body { border-left-color: rgba(15, 23, 42, 0.28); }
.door:focus-visible .door-go { color: var(--ink); background: transparent; transform: translateX(3px); }
.door:focus-visible[aria-selected="true"] .door-go { background: var(--white); }
.door:active { transform: scale(0.98); }
.router-status, .vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

.feats {
  display: flex; flex-wrap: wrap; gap: 8px 20px; list-style: none;
  border-top: 1px solid var(--hairline); margin-top: 2px; padding: 10px 0 0;
}
.feats li { font-size: 15px; font-weight: 500; color: var(--ink-3); display: flex; align-items: center; gap: 20px; }
.feats li::after { content: ""; width: 5px; height: 5px; border-radius: 50%; background: var(--ink-3); }
.feats li:last-child::after { display: none; }

/* ═══ SECTION HEADS — differentiated by rule weight, not repetition ═══ */
.sec-head { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 4px 24px; align-items: end; margin-bottom: 10px; }
.sec-head h2 { grid-column: 1; grid-row: 1; }
.sec-head h2, .media-h { font-size: clamp(28px, 3vw, 40px); font-weight: 800; letter-spacing: -0.02em; }
.sec-lead { grid-column: 1; font-size: 17px; color: var(--muted); max-width: 62ch; }
.sec-link {
  grid-column: 2; grid-row: 1 / span 2; align-self: center; justify-self: end;
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: 15px; font-weight: 700; color: var(--ink); text-decoration: none;
  border-bottom: 2px solid var(--coral); padding-bottom: 2px;
}
.sec-link:hover { color: var(--coral-hover); }
/* L4 · register heads sit tight against their 3px ink rule; editorial heads
   breathe. Differentiation by spacing and rule weight, not by colour or size. */
.vouch .sec-head, .runs .sec-head, .news .sec-head { margin-bottom: 22px; }

/* ═══ S3/S5 · THE REGISTER — Law VI: rules, not boxes ═══ */
.reg { padding: clamp(40px, 4.5vw, 64px) 0 clamp(56px, 6vw, 88px); }
.reg-lead, .reg-op { border-top: 1px solid var(--hairline); padding-top: 20px; }

/* M5 · the register's control stays reachable at any scroll depth */
/* Two elements, one strip: `.facets` is the sticky opaque shell that owns the
   background and the rules; `.facets-row` is the flex line that scrolls inside
   it on mobile. They are separate so the overflow cue can be painted on the
   shell — above the content, but without touching the background. A mask on a
   single combined element fades the background too, which lets the page show
   through a sticky strip. */
.facets {
  position: sticky; top: var(--hdr-h); z-index: 50; background: var(--paper);
  padding: 10px 0; border-top: 3px solid var(--ink); border-bottom: 1px solid var(--hairline);
}
.facets-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 20px; }
.facets-tag { margin-right: 6px; }
.facets label { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; font-weight: 600; color: var(--ink-3); }
.facets select {
  min-height: 44px; padding: 6px 10px; font: 500 15px 'Inter', sans-serif; color: var(--ink);
  background: var(--white); border: 1px solid var(--hairline); border-radius: var(--r);
}
.facets-count { margin-left: auto; font-size: 13px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }
/* N-2 · while pinned, the strip's lower hairline darkens — an instant cue, no shadow (Law VI) */
.facets.is-pinned { border-bottom-color: var(--ink-3); }

/* E-1 · search belongs to the strip, not on top of it. The fold gate at
   1280×800 leaves 26px of headroom, so the field takes the strip's existing
   free width (≈366px at 1280) on the same row and adds no height at all.
   It flexes rather than wraps: wrapping would add a 40px row and push the
   first record out of the first viewport. */
.facets-q { flex: 1 1 200px; min-width: 168px; max-width: 340px; }
.facets-q input {
  flex: 1 1 auto; width: 100%; min-width: 0; min-height: 44px; padding: 6px 10px;
  font: 500 15px 'Inter', sans-serif; color: var(--ink);
  background: var(--white); border: 1px solid var(--hairline); border-radius: var(--r);
}
.facets-q input::placeholder { color: var(--muted); font-weight: 400; }
.facets-q input:focus-visible, .facets select:focus-visible { outline: 2px solid var(--coral); outline-offset: 2px; }
/* the native clear affordance is kept (type=search); it is the fastest way back */

/* E-2 · the selects were the one unauthored surface on the page. Only the OS
   chrome is replaced — the control stays a native <select>, so the mobile
   picker, typeahead and keyboard behaviour are untouched. The chevron is the
   register's own ink at the register's own weight. */
.facets select {
  appearance: none; -webkit-appearance: none;
  padding-right: 30px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='7' viewBox='0 0 10 7'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23475569' stroke-width='1.7' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 11px center;
}
.facets select:hover, .facets-q input:hover { border-color: var(--ink-3); }

/* E-3 · zero results. Part of the register: it sits on the same rule grid
   where the records were, states the cause, and offers the way back. No
   illustration, no icon, no marketing line (Law VI/IX). */
.reg-empty { padding: 34px 0 38px; border-bottom: 1px solid var(--hairline); }
.reg-empty-line { font-size: 17px; font-weight: 600; color: var(--ink); margin-bottom: 14px; }
.reg-reset { min-height: 44px; }

/* Without JavaScript the strip cannot filter, and a search field that swallows
   what you type is worse than no search field at all. So the whole strip is
   withheld rather than shipped inert — `.js` is added by register.js, so the
   default state is "no strip". Everything that matters survives: all 36
   records render, all 144 fields stay reachable, every record still expands
   natively, and the register is simply complete and unfiltered — which is
   exactly what "18 of 18 shown" would have said. */
body:not(.js) .facets { display: none; }

/* The option counts widen every select by 20–28px — enough to break the strip
   onto three rows between 768 and 1279. The counts are worth more than the
   spare width, so the strip gives the width back: a tighter column gap and a
   search field that stops growing. Above 1280 there is room for both at full
   size; below 768 the strip is the single scrolling row M5 established. */
@media (min-width: 768px) and (max-width: 1279px) {
  .facets-row { column-gap: 14px; }
  .facets-q { flex: 0 1 200px; min-width: 148px; }
  .facets label { gap: 6px; }
}

/* the record unit — compact identity summary; the complete record on demand.
   Native <details>: disclosure semantics, Enter/Space, exposed expanded
   state, `name` one-open-per-register exclusivity and no-JS operation all
   come from the platform, not from script. */
/* M-3 · the row acknowledges attention — pointer or keyboard — with an eased
   ground change. No lift, no shadow (Law VI), no hover-only information. */
.rec {
  border-bottom: 1px solid var(--hairline);
  transition: background-color 140ms var(--ease), opacity 180ms var(--ease);
}
.rec:hover, .rec:focus-within, .rec[open] { background: var(--white); }
/* the open record is the acted-on record — coral marks the act (Law II),
   in the same left-rule grammar the hero doors already use */
.rec[open] { box-shadow: inset 3px 0 0 var(--coral); }
/* M-1 · filter result settle: apply() marks the register body for one frame;
   surviving rows start at 0.55 opacity and ease to 1 over 180ms. Rows that
   leave still leave instantly. Layout is never animated. */
.js .reg-body.settling .rec:not([hidden]) { opacity: 0.55; transition: none; }
/* M-2 · audience switch settle: setSide() marks both registers; the reordered
   state eases in over 200ms. The reorder itself is instant — opacity only. */
.reg { transition: opacity 200ms var(--ease); }
.js .reg.side-settling { opacity: 0.6; transition: none; }
.rec-sum {
  list-style: none; cursor: pointer;
  display: grid; align-items: center; gap: 10px 18px; padding: 12px 8px 12px 4px;
  grid-template-columns: 48px minmax(190px, 1.05fr) minmax(200px, 1.5fr) 132px 20px;
  min-height: 44px;
}
.rec-aff .rec-sum { grid-template-columns: 34px 48px minmax(170px, 1.05fr) minmax(180px, 1.5fr) 132px 20px; }
.rec-sum::-webkit-details-marker { display: none; }
.rec-sum .rec-rating { align-items: flex-end; text-align: right; }
/* one disclosure affordance across the product — the FAQ's plus/minus */
.rec-x { position: relative; width: 14px; height: 14px; justify-self: end; }
.rec-x::before, .rec-x::after { content: ""; position: absolute; background: var(--ink); transition: transform 160ms var(--ease); }
.rec-x::before { inset: 6px 0; }
.rec-x::after { inset: 0 6px; }
.rec[open] .rec-x::after { transform: scaleY(0); }
/* the panel — the same object gaining depth. Height eases on the register's
   own token where the engine supports interpolate-size (Chromium); elsewhere
   the state change is instant, which is exactly the reduced-motion behaviour
   (Law IX: nothing depends on the animation for comprehension). */
.reg-body { interpolate-size: allow-keywords; }
.rec::details-content {
  height: 0; overflow: clip;
  transition: height 300ms var(--ease), content-visibility 300ms allow-discrete;
}
.rec[open]::details-content { height: auto; }
.rec-panel { padding: 2px 8px 20px 66px; }
.rec-aff .rec-panel { padding-left: 118px; }
.rec-grid {
  display: grid; grid-template-columns: minmax(190px, 1.1fr) minmax(190px, 1.1fr) minmax(0, 1fr);
  gap: 14px 24px; align-items: start;
  border-top: 1px solid var(--well); padding-top: 14px;
}
.rec-logo { width: 48px; height: 48px; background: var(--well); border-radius: var(--r); display: flex; align-items: center; justify-content: center; overflow: hidden; }
.rec-logo img { width: 40px; height: 40px; object-fit: contain; border-radius: 3px; }
.rec-rank { font-size: 22px; font-weight: 800; color: var(--ink); font-variant-numeric: tabular-nums; position: relative; }
.rec-no1 {
  font-style: normal; white-space: nowrap; vertical-align: 2px; margin-left: 6px;
  font-size: 12px; font-weight: 700; letter-spacing: 0.04em; color: var(--ink);
  background: var(--coral-tint); border: 1px solid var(--coral); border-radius: var(--r);
  padding: 2px 7px;
}
.rec-id { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.rec-name { font-size: 17px; font-weight: 700; color: var(--ink); transition: color 160ms var(--ease); }
.rec-domain { font-size: 13px; color: var(--muted); }
.rec-field { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.rec-value { font-size: 15px; font-weight: 500; color: var(--ink-2); line-height: 1.4; }
/* a value never breaks inside itself — only between its tokens */
.v-t { white-space: nowrap; }
/* revealed-state marker: each expanded value carries a coral rule at the
   register's own scale - structure, not decoration (Law VI: rules, not boxes).
   It is a graphical object, 3.41:1 against white - clears the 3:1 gate - while
   the value text itself stays ink-2 at 10.35:1. Collapsed values are untouched. */
.rec-grid .rec-field .rec-value { border-left: 2px solid var(--coral); padding-left: 10px; }
.rec-end { display: flex; align-items: center; justify-content: flex-end; gap: 14px; }
.rec-offer {
  font-size: 12px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--ink); background: var(--coral-tint); border: 1px solid var(--coral);
  padding: 4px 8px; border-radius: var(--r); white-space: nowrap;
}
/* M1 · the score is labelled like every other field — no title-attribute reliance.
   H3 · its mark is ink: it indicates nothing, so it may not wear the accent. */
.rec-rating-v {
  display: inline-flex; align-items: center; gap: 4px;
  font-size: 15px; font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums;
}
/* R2 · the score's direction mark. Colour reinforces a direction the glyph
   already carries in its shape, so nothing depends on colour alone, and
   nothing depends on the animation. A record with no direction keeps the ink
   mark and does not pulse — no direction is invented to fill the space. */
.rec-rating-v svg { color: var(--ink); }
.rec-rating-v[data-dir="up"] svg { color: var(--up); }
.rec-rating-v[data-dir="down"] svg { color: var(--coral); }
/* Only the rising mark moves. One soft dip per cycle, then a rest — a status
   light, not an alert. The trough is the deepest green can go and still hold
   3:1 against white (3.18:1 at 0.75). Coral is deliberately NOT animated: it
   rests compliant at 3.41:1 but would fall to 2.75:1 at the same trough, so
   the falling mark stays static rather than becoming non-compliant mid-cycle.
   Opacity only: no transform, no size change, no layout in the animation. */
.rec-rating-v[data-dir="up"] svg { animation: score-dir 1800ms ease-in-out infinite; }
@keyframes score-dir { 0%, 44%, 100% { opacity: 1; } 22% { opacity: 0.75; } }
/* H3 - the record's action is a compact coral surface carrying ink text
   (5.24:1 - AA at 15px). Hover/focus flips to ink + white (17.85:1); the house
   --coral-hover is deliberately NOT used as a ground here because ink on
   #e63e44 measures 4.37:1 and would fail AA. Height stays 44px (Law VIII), so
   the record geometry is unchanged. */
.rec-view {
  display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px;
  font-size: 15px; font-weight: 700; color: var(--ink); text-decoration: none;
  background: var(--coral); border-radius: var(--r); white-space: nowrap;
  transition: background-color 160ms var(--ease), color 160ms var(--ease);
}
.rec-view:hover, .rec-view:focus-visible { background: var(--ink); color: var(--white); }
/* N-1 · AffPapa's own transform+color hover idiom, at register scale: 2px nudge */
.rec-view span[aria-hidden] { display: inline-block; transition: transform 160ms var(--ease); }
.rec-view:hover span[aria-hidden], .rec-view:focus-visible span[aria-hidden] { transform: translateX(2px); }

/* offers rail inside S3 */
.offers-block { margin-top: 44px; padding-top: 28px; border-top: 1px solid var(--hairline); }
.offers-block h3 { font-size: 22px; font-weight: 800; letter-spacing: -0.01em; margin-bottom: 4px; }
.offers-block .sec-lead { margin-bottom: 18px; }
.offers-scroll { overflow-x: auto; padding-bottom: 8px; scroll-snap-type: x mandatory; }
/* snap is suspended only while the quiet ticker is driving; any user input restores it */
.offers-scroll.is-auto { scroll-snap-type: none; }
.offers-rail { display: flex; gap: 14px; list-style: none; }
.offer {
  scroll-snap-align: start; flex: 0 0 auto; min-width: 230px;
  display: grid; grid-template-columns: 44px 1fr; gap: 4px 12px; align-items: center;
  border: 1px solid var(--hairline); border-radius: var(--r); padding: 14px 16px; background: var(--white);
}
.offer img { grid-row: span 2; width: 44px; height: 44px; object-fit: contain; background: var(--well); border-radius: var(--r); }
.offer-brand { font-size: 15px; font-weight: 700; color: var(--ink); }
.offer-deal { font-size: 13px; color: var(--ink-3); }
.offer-deal strong { color: var(--ink); }

/* ═══ S4 · THE JUNCTION — ink rest ═══ */
.junction { background: var(--ink); color: var(--white); padding: clamp(48px, 6vw, 80px) 0; }
.junction-in { display: flex; align-items: center; justify-content: center; gap: 40px; flex-wrap: wrap; }
.junction-pair { display: flex; align-items: center; gap: clamp(24px, 4vw, 56px); }
.junction-fig { display: flex; flex-direction: column; }
.junction-fig strong { font-size: clamp(40px, 5vw, 72px); font-weight: 800; letter-spacing: -0.02em; line-height: 1; font-variant-numeric: tabular-nums; }
.junction-fig span { font-size: 15px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: #94a3b8; margin-top: 10px; }
.junction-glyph { font-size: clamp(28px, 3.2vw, 40px); color: var(--coral); font-weight: 700; }

/* ═══ S6 · TERMS — the one coral field ═══ */
.terms { background: var(--coral); padding: clamp(56px, 6vw, 88px) 0; }
.terms-in { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 5vw, 80px); }
.term h2 { font-size: clamp(28px, 3vw, 40px); font-weight: 800; letter-spacing: -0.02em; margin-bottom: 8px; }
.term-tag { color: var(--ink); opacity: 0.85; margin-bottom: 14px; }
.term-note { font-size: 15px; line-height: 1.55; color: var(--ink); margin-bottom: 22px; max-width: 52ch; }
.term + .term { border-left: 1px solid rgba(15, 23, 42, 0.25); padding-left: clamp(32px, 5vw, 80px); }

/* router emphasis — Law: reorder/re-emphasise only, never remove */
body[data-side="operator"] main { display: flex; flex-direction: column; }
body[data-side="operator"] main > section { order: calc(var(--ord, 0) * 1); }
/* the lead position keeps its geometry while the sections swap through it */
body[data-side="operator"] .reg-aff { order: 1; border-top: 1px solid var(--hairline); padding-top: 20px; }
body[data-side="operator"] .reg-op { order: 3; border-top: 0; padding-top: clamp(40px, 4.5vw, 64px); }
body[data-side="operator"] .terms-in .term-op { order: -1; }
body[data-side="operator"] .terms-in .term-op ~ .term { border-left: 0; padding-left: 0; }
body[data-side="operator"] .terms-in .term-aff { border-left: 1px solid rgba(15, 23, 42, 0.25); padding-left: clamp(32px, 5vw, 80px); }
/* M4 · the CTA swap is done by toggling the `hidden` attribute in JS, so the
   semantic state and the visual state can never disagree. No CSS override here. */

/* ═══ S7 · WHO VOUCHES ═══ */
.vouch { background: var(--white); border-bottom: 1px solid var(--hairline); padding: clamp(56px, 6vw, 88px) 0; }
.quotes { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(24px, 3vw, 48px); }
/* M3 · attributions share one baseline regardless of quote length */
.quote { border-top: 3px solid var(--ink); padding-top: 20px; display: grid; grid-template-rows: 1fr auto; }
.quote blockquote p { font-size: 17px; line-height: 1.6; color: var(--ink-2); }
.quote blockquote p::before { content: "“"; color: var(--ink); font-weight: 800; font-size: 22px; margin-right: 2px; }
.quote figcaption { margin-top: 16px; display: flex; flex-direction: column; gap: 2px; }
.quote figcaption strong { font-size: 15px; color: var(--ink); }
.quote figcaption span { font-size: 13px; color: var(--muted); }
.quotes-nav { display: none; align-items: center; gap: 16px; margin-top: 28px; }
.js .quotes-nav { display: flex; }
.js .quote[data-hidden] { display: none; }
.qbtn {
  width: 44px; height: 44px; border: 1px solid var(--ink); border-radius: var(--r);
  background: var(--white); color: var(--ink); font-size: 17px; cursor: pointer;
}
.qbtn:hover { background: var(--ink); color: var(--white); }
.qbtn:disabled { opacity: 0.3; cursor: default; }
#q-count { font-size: 13px; font-weight: 600; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ═══ S8 · WHAT AFFPAPA RUNS — photographic crescendo ═══ */
.runs { padding: clamp(56px, 6vw, 88px) 0; background: var(--paper); }
.events { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(20px, 2.5vw, 32px); }
.event { border-radius: var(--r); overflow: hidden; background: var(--ink); display: flex; flex-direction: column; }
/* H4 · the card carries the artwork's own ratio (634×300), so AffPapa's baked-in
   lettering is never cropped at any width. */
.event img { width: 100%; object-fit: cover; aspect-ratio: 634 / 300; }
.event-meta {
  padding: 18px 22px 20px;
  display: grid; grid-template-columns: 1fr auto; gap: 2px 16px; align-items: center;
}
.event-meta h3 { grid-column: 1; grid-row: 1; color: var(--white); font-size: clamp(18px, 1.6vw, 22px); font-weight: 800; }
.event-meta p { grid-column: 1; grid-row: 2; color: #cbd5e1; font-size: 15px; font-weight: 500; }
.event-meta .btn { grid-column: 2; grid-row: 1 / span 2; }
/* H5 · the one legal deployment of AffPapa's second accent: sky as a filled
   field carrying ink text (6.64:1). Never as text, border or icon. */
.media-band { background: var(--sky); margin-top: clamp(40px, 5vw, 64px); padding: clamp(36px, 4.5vw, 60px) 0; }
.media-h { margin-bottom: 4px; color: var(--ink); }
.media .sec-lead { margin-bottom: 20px; color: var(--ink); }
.media-list { list-style: none; border-top: 3px solid var(--ink); }
.media-list li {
  display: grid; grid-template-columns: 120px 170px 1fr auto; gap: 20px; align-items: center;
  padding: 14px 4px; border-bottom: 1px solid rgba(15, 23, 42, 0.22);
}
.media-list img { width: 120px; height: 75px; object-fit: cover; border-radius: var(--r); background: rgba(255, 255, 255, 0.55); }
.media-title { font-size: 17px; font-weight: 600; color: var(--ink); }
.media-band .media-chan { color: var(--ink); }
.media-list a { display: inline-flex; align-items: center; min-height: 44px; font-size: 15px; font-weight: 700; color: var(--ink); text-decoration: none; border-bottom: 2px solid var(--ink); padding-bottom: 2px; white-space: nowrap; }
.media-list a:hover, .media-list a:focus-visible { border-bottom-color: var(--coral); }

/* ═══ S9 · NEWS — dated editorial list ═══ */
.news { padding: clamp(56px, 6vw, 88px) 0; border-top: 1px solid var(--hairline); }
.news-in { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); gap: clamp(28px, 4vw, 64px); }
/* the featured artwork is AffPapa's 800×500 original — the well carries its
   native 1.6:1 ratio so the baked-in lettering is never cropped or upscaled */
.news-feat img { border-radius: var(--r); margin-bottom: 16px; width: 100%; height: auto; aspect-ratio: 800 / 500; object-fit: cover; background: var(--well); }
.news-meta { font-size: 13px; color: var(--muted); margin-bottom: 8px; }
.news-cat { color: var(--ink-3); }
.news-feat h3 { font-size: clamp(20px, 2vw, 22px); font-weight: 800; letter-spacing: -0.01em; margin-bottom: 10px; }
.news-feat h3 a { text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; }
.news-feat h3 a:hover { color: var(--coral-hover); }
.news-ex { font-size: 15px; color: var(--muted); max-width: 58ch; }
.news-list ul { list-style: none; border-top: 3px solid var(--ink); margin-top: 8px; }
.news-list li { border-bottom: 1px solid var(--hairline); }
.news-list a {
  display: block; padding: 13px 2px; font-size: 17px; font-weight: 600; color: var(--ink);
  text-decoration: none;
}
.news-list a:hover { color: var(--coral-hover); }

/* ═══ S10 · FAQ ═══ */
.faq { padding: clamp(56px, 6vw, 96px) 0 clamp(72px, 8vw, 112px); }
.faq-in { display: block; }
.faq h2 { margin-bottom: 24px; }
.faq h2 { font-size: clamp(30px, 3.2vw, 40px); font-weight: 800; letter-spacing: -0.02em; }
.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-item:first-of-type { border-top: 3px solid var(--ink); }
.faq-item summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  gap: 20px; padding: 18px 2px; min-height: 44px;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item h3 { font-size: 17px; font-weight: 700; }
.faq-item summary:hover h3 { color: var(--coral-hover); }
.faq-x { position: relative; width: 14px; height: 14px; flex-shrink: 0; }
.faq-x::before, .faq-x::after { content: ""; position: absolute; background: var(--ink); transition: transform 160ms var(--ease); }
.faq-x::before { inset: 6px 0; }
.faq-x::after { inset: 0 6px; }
.faq-item[open] .faq-x::after { transform: scaleY(0); }
.faq-item > p { padding: 0 40px 20px 2px; font-size: 17px; color: var(--ink-2); max-width: 68ch; }

/* ═══ FOOTER — the register's final chapter, inverted onto ink ═══
   Content is the live AffPapa footer's own (transcribed; see build.mjs).
   The layout is the house grammar: one 3px rule, labelled columns, hairline
   base — and coral only on the one act (Subscribe). All slate values are the
   existing ramp; every text tone measures ≥4.5:1 on ink, the input border
   3.75:1 (non-text 3:1 gate). */
.foot { background: var(--ink); color: #cbd5e1; padding: clamp(48px, 5vw, 72px) 0 0; }
.foot-grid {
  display: grid; grid-template-columns: minmax(280px, 1.15fr) repeat(3, minmax(170px, 1fr));
  gap: 28px 48px; align-items: start;
  border-top: 3px solid rgba(203, 213, 225, 0.35); padding-top: 32px;
}
/* mono-white mark on ink - the standard dark-surface logo treatment.
   A plain invert() is never used: it flips the coral dot to a false teal. */
.foot-logo { height: 24px; width: auto; filter: brightness(0) invert(1); }
.foot-desc { font-size: 15px; line-height: 1.6; color: #94a3b8; max-width: 36ch; margin: 18px 0 22px; }
.foot-label { display: block; font-size: 13px; font-weight: 600; color: #94a3b8; margin-bottom: 8px; }
.foot-form { max-width: 380px; }
.foot-form-row { display: flex; gap: 8px; }
/* width:0 is load-bearing, not decoration: an <input> carries an intrinsic
   preferred width (~227px here) that still counts toward the flex row's
   min-content size, which pushed the whole page 13px wide at 360px and 52px
   at 320px. flex-grow restores the used width, so nothing moves above 380px. */
.foot-input {
  flex: 1; min-width: 0; width: 0; min-height: 44px; padding: 0 12px;
  font: 500 15px 'Inter', sans-serif; color: var(--white);
  background: transparent; border: 1px solid var(--muted); border-radius: var(--r);
}
.foot-input:focus-visible { border-color: var(--white); }
.foot-status { font-size: 13px; color: #94a3b8; margin-top: 10px; max-width: 42ch; }
.foot-status a { color: #cbd5e1; text-underline-offset: 3px; }
.foot-status a:hover { color: var(--white); }
.foot-h { font-size: 12px; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; color: #94a3b8; margin-bottom: 6px; }
.foot-col ul { list-style: none; }
.foot-col a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: 15px; font-weight: 500; color: #cbd5e1; text-decoration: none;
}
.foot-col a:hover { color: var(--white); }
.foot-social { display: flex; flex-wrap: wrap; gap: 2px; margin-top: 14px; list-style: none; }
.foot-social a { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; color: #cbd5e1; border-radius: var(--r); }
.foot-social a:hover { color: var(--coral); }
.foot-base { border-top: 1px solid rgba(203, 213, 225, 0.18); margin-top: clamp(32px, 4vw, 48px); padding: 18px 0 26px; }
.foot-base-in { display: flex; justify-content: space-between; align-items: baseline; gap: 10px 24px; flex-wrap: wrap; font-size: 13px; color: #94a3b8; }
.foot-note { font-size: 12px; color: #94a3b8; }

/* ═══════════════════════════════ RESPONSIVE ═══════════════════════════════
   Law VII: the field count is constant at every width. Arrangement changes;
   facts do not. Nothing below uses display:none on a record or a field. */

@media (max-width: 1119px) {
  .hdr-nav { display: none; }
  .hdr-router { display: none; }
  .hdr-actions { margin-left: auto; }
  .hdr-burger { display: inline-flex; }

  /* H2 · the compact summary reflows to identity + score on one line, the
     scanning field (Products / Category) as a labelled second line; the
     panel becomes one labelled line per field, action on its own row. */
  .rec-sum { grid-template-columns: 48px minmax(0, 1fr) auto 20px; gap: 8px 12px; padding: 12px 2px 12px 10px; }
  .rec-aff .rec-sum { grid-template-columns: 30px 48px minmax(0, 1fr) auto 20px; }
  .rec-name { overflow-wrap: anywhere; }
  .rec-preview { grid-column: 1 / -1; grid-row: 2; flex-direction: row; align-items: baseline; gap: 12px; }
  /* the label may wrap to two short lines so long names keep a full column */
  /* the score column is capped at the width its label actually needs once it
     has wrapped to two lines ("AFFPAPA" measures 78px), not at a round number.
     The 10px that buys goes to the name column, so single-token brand names
     keep a full line instead of breaking mid-word. */
  .rec-sum .rec-rating { flex-direction: column; align-items: flex-end; text-align: right; gap: 2px; max-width: 84px; }
  .rec-rating .rec-label { flex: none; }
  .rec-field .rec-value { font-size: 15px; }
  .rec-panel { padding: 0 2px 16px 10px; }
  .rec-aff .rec-panel { padding-left: 10px; }
  /* R-fix · one ruled line per field. Where a label sits inline with its
     value the register's own grammar applies at record scale (Law VI):
     each field is a ruled row carrying its own rhythm, so the grid drops
     the gap it needed when the fields were columns. */
  .rec-grid { grid-template-columns: 1fr; gap: 0; padding-top: 0; }
  .rec-grid .rec-field {
    flex-direction: row; align-items: baseline; gap: 12px;
    padding: 11px 0; border-bottom: 1px solid var(--hairline);
  }
  /* R-fix · an inline label is a leading term, not a heading. Sentence case
     at 13px is ~30px narrower than 12px micro-caps, and that width goes to
     the value column — which is what keeps a two-word value on one line.
     Micro-caps stay wherever a label still sits above its value: the desktop
     grid, the score column, and every other label in the interface. */
  .rec-grid .rec-field .rec-label, .rec-preview .rec-label {
    flex: 0 0 118px; font-size: 13px; font-weight: 600;
    letter-spacing: 0; text-transform: none; color: var(--ink);
  }
  .rec-end { justify-content: flex-start; padding-top: 14px; }

  .events { grid-template-columns: 1fr; }
  .news-in { grid-template-columns: 1fr; }
  .foot-grid { grid-template-columns: repeat(3, 1fr); }
  .foot-id { grid-column: 1 / -1; }
  .faq-in { grid-template-columns: 1fr; gap: 24px; }
  .media-list li { grid-template-columns: 100px 1fr; grid-template-rows: auto auto auto; gap: 4px 16px; padding: 16px 2px; }
  .media-list img { grid-row: 1 / span 3; width: 100px; height: 64px; }
  .media-list a { justify-self: start; }
}

@media (max-width: 479px) {
  .hdr-actions { display: none; }
}

@media (max-width: 767px) {
  body { font-size: 17px; }
  .rec-grid .rec-field, .rec-preview { flex-direction: row; align-items: baseline; gap: 12px; }
  .rec-field .rec-value { font-size: 15px; line-height: 1.45; }
  .rec-name { font-size: 17px; }
  .rec-end { align-self: start; }
  .hero h1 { max-width: none; }
  .stats { gap: 20px; justify-content: space-between; width: 100%; }
  .stats dd { font-size: clamp(28px, 8.6vw, 36px); }
  .stats dt { font-size: 12px; }
  .hero-cta .btn { flex: 1 1 100%; }
  /* M6 · the doors must read as a control, not as two paragraphs */
  .router { grid-template-columns: 1fr; }
  .sec-head { grid-template-columns: 1fr; }
  .sec-link { grid-column: 1; grid-row: auto; justify-self: start; margin-top: 6px; }
  /* M5 · one compact sticky strip; it scrolls inside itself, the page never does */
  .facets-row {
    flex-wrap: nowrap; overflow-x: auto; gap: 12px;
    scrollbar-width: none; -ms-overflow-style: none;
    scroll-padding-inline: 20px;   /* a focused select lands clear of the fades */
  }
  .facets-row::-webkit-scrollbar { display: none; }

  /* The scroll had no cue: at 390 the row is ~1006px inside 358px, so two of
     the three filters sat off-screen with a hard clip and nothing to say so.
     A fade on each overflowing edge restores the one thing the clip removed —
     the sense that the line continues. Painted on the shell, so it rides above
     the scrolling content while the strip's own background stays opaque.
     It is a cue, not a control: `pointer-events: none`, never the only route
     to the filters (touch scroll, keyboard and the native picker all work
     unchanged), and it carries no meaning a screen reader needs. Inset from
     the rules top and bottom so neither hairline is dimmed. */
  .facets::before,
  .facets::after {
    content: ''; position: absolute; top: 3px; bottom: 1px; width: 34px;
    pointer-events: none; opacity: 0; transition: opacity 140ms var(--ease);
  }
  .facets::before { left: 0;  background: linear-gradient(to left,  rgba(252, 252, 253, 0), var(--paper) 72%); }
  .facets::after  { right: 0; background: linear-gradient(to right, rgba(252, 252, 253, 0), var(--paper) 72%); }
  /* JS sets data-edge to whichever sides still have content beyond them, so a
     fully-scrolled edge shows nothing to scroll towards and stays clean. */
  .facets[data-edge~="start"]::before,
  .facets[data-edge~="end"]::after { opacity: 1; }
  .facets-tag { display: none; }
  .facets label, .facets-count { flex: 0 0 auto; }
  .facets-count { order: -1; margin-left: 0; }
  .facets select { flex: 0 0 auto; min-width: 118px; }
  /* E-1 · search leads the strip so the primary control needs no scrolling to
     reach; the count follows it, the facets scroll on after. The strip stays
     the single compact scrolling row M5 established — no second sticky line. */
  .facets-q { order: -2; flex: 0 0 auto; width: 210px; max-width: 60vw; }

  .terms-in { grid-template-columns: 1fr; }
  .term + .term { border-left: 0; padding-left: 0; border-top: 1px solid rgba(15, 23, 42, 0.25); padding-top: 32px; }
  body[data-side="operator"] .terms-in .term-aff { border-left: 0; padding-left: 0; }
  .quotes { grid-template-columns: 1fr; }
  .junction-in { justify-content: center; text-align: center; }
  .junction-pair { flex-direction: column; gap: 18px; }
  .junction-glyph { transform: rotate(90deg); }
  .event-meta { grid-template-columns: 1fr; }
  .event-meta .btn { grid-row: auto; justify-self: start; margin-top: 10px; }
  /* footer stacks deliberately: identity + subscribe first, then each group
     as its own ruled band, legal last. No disclosures — terminal content. */
  .foot-grid { grid-template-columns: 1fr; gap: 0; }
  .foot-id { padding-bottom: 26px; }
  .foot-form { max-width: none; }
  .foot-col { border-top: 1px solid rgba(203, 213, 225, 0.18); padding: 18px 0 10px; }
  .foot-base-in { flex-direction: column; align-items: flex-start; gap: 6px; }
}



@media (max-width: 359px) {
  .door-mark { width: 42px; height: 42px; }
  .door-mark svg { width: 22px; height: 22px; }
  .door-go { width: 24px; height: 24px; }
  .door[aria-selected="true"] .door-go { width: 30px; height: 30px; }
  .door-go svg { width: 18px; height: 18px; }
  .stats { flex-wrap: wrap; gap: 14px 24px; }
  .stats dd { font-size: 26px; }
  .rec-grid .rec-field, .rec-preview { flex-direction: column; gap: 3px; }
  .rec-grid .rec-field .rec-label, .rec-preview .rec-label {
    flex: none; font-size: 12px; letter-spacing: 0.1em;
    text-transform: uppercase; color: var(--ink-3);
  }
  /* at the narrowest widths the score joins the labelled lines so the name
     always keeps a full column — no mid-word breaks at any record */
  .rec-sum { grid-template-columns: 48px minmax(0, 1fr) 20px; }
  .rec-aff .rec-sum { grid-template-columns: 26px 48px minmax(0, 1fr) 20px; }
  .rec-sum .rec-rating {
    grid-column: 1 / -1; grid-row: 2; max-width: none;
    flex-direction: row; align-items: baseline; gap: 10px; text-align: left;
  }
  .rec-sum .rec-rating .rec-label { flex: 0 0 112px; }
  .rec-preview { grid-row: 3; }
}

/* ═══ MOTION — Law IX ═══ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { transition: none !important; animation: none !important; }
  /* ::details-content is not reached by the universal selector — kill it explicitly */
  .rec::details-content { transition: none !important; }
  /* flow doors: immediate state change, no scale, no flow transform */
  .door:hover, .door:focus-visible, .door:active { transform: none !important; }
  .door:hover .door-go, .door:focus-visible .door-go { transform: none !important; }
}
