*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font-family: ui-serif, Georgia, "Times New Roman", serif;
  font-size: var(--step-0); line-height: 1.6; text-wrap: pretty;
  -webkit-font-smoothing: antialiased;
}
.skip {
  position: absolute; left: -9999px;
}
/* Clip-based visually-hidden: stays in the accessibility tree (unlike
   display:none / visibility:hidden, which remove it entirely) while taking
   up no visual space. Use for content that must be announced/read but has
   no visible design slot yet, e.g. the page's single required <h1>. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.skip:focus {
  left: var(--gutter); top: 1rem; z-index: 10;
  background: var(--ink); color: var(--paper); padding: 0.6rem 1rem;
}
/* Global link colour: the browser default (#0000EE) is unreadable in dark
   mode (~2.07:1 against dark --paper). --sky is already tuned per scheme
   against --paper, so it fixes every unstyled link at once — the citation
   links in Sources.astro and the confirmation-page back-links alike.
   Underline is kept so colour is never the only affordance. Computed
   (verified 2026-07-27, all clear 4.5:1):
     light, normal bg:  #2a628f on #f4f2ed -> 5.79:1
     dark,  normal bg:  #75aadb on #0b0d10 -> 7.90:1
   Inside .entry--denied, --sky is re-pointed to --sky-invert for that
   subtree (see LineageEntry.astro), so links there inherit the swapped
   value instead of bypassing the override:
     light, denied bg:  #75aadb on #0b0d10 -> 7.90:1
     dark,  denied bg:  #2a628f on #f0eee9 -> 5.59:1
   .skip is unaffected: .skip:focus sets its own color (class + pseudo-class
   beats this element selector), and off-screen/unfocused it is never seen. */
a { color: var(--sky); }
/* Standing masthead credit line, not a banner — quiet enough to not compete
   with the first numeral, but visible on every screenshot of the page.
   --muted on --paper: 5.82:1 (light) / 7.38:1 (dark) — clears 4.5:1 in both. */
.disclaimer {
  color: var(--muted); font-size: var(--step--1);
  max-width: var(--measure);
  margin: 0; padding: 1.5rem var(--gutter) 0;
}
:focus-visible { outline: 3px solid var(--sky); outline-offset: 3px; }

/* Motion is opt-in, never opt-out. Entries are visible by default; the
   reveal is an enhancement applied only when motion is welcome. */
@media (prefers-reduced-motion: no-preference) {
  .entry { animation: rise 0.7s ease-out both; animation-timeline: view(); animation-range: entry 10% cover 30%; }
  @keyframes rise {
    from { opacity: 0; transform: translateY(2rem); }
    to { opacity: 1; transform: none; }
  }
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

/* Confirmation landings: one short message, centred, nothing else competing.
   The kicker and CTA reuse tokens already contrast-verified elsewhere
   (--muted per .disclaimer above; --ink/--paper per .sign__submit below)
   rather than introducing new ones, so this stays axe-clean by construction. */
.outcome {
  max-width: var(--measure);
  margin: 0 auto;
  padding: clamp(6rem, 22vh, 12rem) var(--gutter);
}
.outcome__kicker {
  color: var(--muted); font-size: var(--step--1);
  letter-spacing: 0.08em; text-transform: uppercase;
  margin: 0 0 1.5rem;
}
.outcome__check { color: var(--sky); margin: 0 0 1.5rem; }
.outcome h1 { font-size: var(--step-2); line-height: 1.1; margin: 0 0 1rem; text-wrap: balance; }
.outcome p { margin: 0 0 1.5rem; }
.outcome__cta {
  display: inline-block; text-decoration: none;
  font: inherit; font-size: var(--step-0);
  padding: 0.7rem 1.6rem;
  color: var(--paper); background: var(--ink);
  border: 1px solid var(--ink); border-radius: 2px;
}
.outcome__cta:hover, .outcome__cta:focus-visible { text-decoration: underline; }
.outcome__share-prompt { font-weight: 700; margin-bottom: 0.5rem; }
.outcome__share {
  font: inherit; font-size: var(--step-0);
  padding: 0.7rem 1.6rem; cursor: pointer;
  color: var(--ink); background: transparent;
  border: 1px solid var(--ink); border-radius: 2px;
}
.outcome__share-status:empty { display: none; }
.outcome__share-status { color: var(--muted); font-size: var(--step--1); }

/* The ask. Sits inside the 2026 entry, after its citations. */
.sign { margin-top: 2.5rem; border-top: 1px solid var(--rule); padding-top: 2rem; }
.sign__heading { font-size: var(--step-1); line-height: 1.2; margin: 0 0 1.25rem; }
.sign__noscript { color: var(--muted); font-size: var(--step--1); margin: 0; }
.field { margin: 0 0 1.25rem; }
.field label { display: block; font-size: var(--step--1); letter-spacing: 0.04em; margin-bottom: 0.35rem; }
.field input, .field select {
  width: 100%; padding: 0.7rem 0.8rem;
  font: inherit; font-size: var(--step-0);
  color: var(--ink); background: var(--paper);
  border: 1px solid var(--rule); border-radius: 2px;
}
.field input:focus-visible, .field select:focus-visible { border-color: var(--sky); }
.field input[aria-invalid='true'], .field select[aria-invalid='true'] { border-color: #b3261e; }
.field__hint { font-size: var(--step--1); color: var(--muted); margin: 0.4rem 0 0; }
/* Empty by default and given no reserved height: an empty error paragraph must
   not push the layout around before anything has gone wrong. */
.field__error:empty { display: none; }
.field__error { font-size: var(--step--1); color: #b3261e; margin: 0.4rem 0 0; }
.sign__submit {
  font: inherit; font-size: var(--step-0);
  padding: 0.7rem 1.6rem; cursor: pointer;
  color: var(--paper); background: var(--ink);
  border: 1px solid var(--ink); border-radius: 2px;
}
.sign__submit[disabled] { opacity: 0.6; cursor: progress; }
.sign__status:empty { display: none; }
.sign__status { margin: 1rem 0 0; font-size: var(--step-0); }
.sign__status--ok { color: var(--ink); }
.sign__status--bad { color: #b3261e; }
@media (prefers-color-scheme: dark) {
  .field input[aria-invalid='true'], .field select[aria-invalid='true'],
  .field__error, .sign__status--bad, .wall__more-error { color: #f2b8b5; border-color: #f2b8b5; }
}

/* Records page: the lead line and the return link out to the ask. Both need
   the page gutter, exactly like .disclaimer and .tally above — without it they
   render flush against the viewport edge and the first line of the page reads
   as clipped. Caught by looking at the rendered page: every automated check
   asserted counts, locales, scripts and axe, and not one of them looks at
   layout, so three unstyled elements shipped sitting at x=0. */
.records__intro {
  color: var(--ink); max-width: var(--measure);
  margin: 0; padding: 1.5rem var(--gutter) 0;
}
.records__back {
  max-width: var(--measure);
  margin: 0; padding: 0 var(--gutter) clamp(4rem, 12vh, 8rem);
}

/* Press kit. Same measure and gutter as every other page — without this the
   page renders edge-to-edge at full viewport width, which is what shipped in
   Plan 4 Task A3 because the class was applied and never styled. */
.press {
  max-width: var(--measure);
  padding: clamp(2rem, 6vh, 4rem) var(--gutter) clamp(4rem, 12vh, 8rem);
}
.press h1 { font-size: var(--step-2); line-height: 1.1; margin: 0 0 1.5rem; text-wrap: balance; }
.press h2 {
  font-size: var(--step--1); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); margin: 2.5rem 0 0.5rem;
}
.press p { margin: 0 0 1rem; }
.press ul { margin: 0 0 1rem; padding-left: 1.1rem; }
.press li { margin-bottom: 0.4rem; }

.tally { padding: clamp(3rem, 8vh, 5rem) var(--gutter) 0; }
.counters {
  max-width: var(--measure); margin: 0 auto;
  font-size: var(--step-1); line-height: 1.4; text-wrap: balance;
}
.counters__n { font-variant-numeric: tabular-nums; color: var(--sky); font-weight: 700; }
.counters__sep { color: var(--muted); }

.wall { max-width: var(--measure); margin: 0 auto; padding: 2.5rem 0 clamp(4rem, 12vh, 8rem); }
.wall__heading { font-size: var(--step-1); margin: 0 0 1.25rem; }
.wall__list { list-style: none; margin: 0; padding: 0; }
.wall__item {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: 0.5rem 0; border-bottom: 1px solid var(--rule);
}
.wall__name { overflow-wrap: anywhere; }
.wall__country { color: var(--muted); font-size: var(--step--1); white-space: nowrap; }
.wall__end { color: var(--muted); font-size: var(--step--1); margin: 1.25rem 0 0; }
.wall__more {
  font: inherit; font-size: var(--step-0); margin-top: 1.5rem;
  padding: 0.6rem 1.4rem; cursor: pointer;
  color: var(--ink); background: transparent;
  border: 1px solid var(--ink); border-radius: 2px;
}
.wall__more[disabled] { opacity: 0.6; cursor: progress; }
.wall__more-error:empty { display: none; }
.wall__more-error { color: #b3261e; font-size: var(--step--1); margin: 0.75rem 0 0; }

/* The SVG sits exactly over the dashed placeholder the Numeral already draws.
   With no names loaded the group is empty and only the placeholder shows —
   which is precisely Plan 2's rendering, i.e. the degraded state costs nothing. */
.fill { position: relative; display: inline-block; }
.fill__svg { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.fill__names { fill: var(--sky); }
/* Motion is opt-in, never opt-out — matching the entry reveal. The names
   simply appear for anyone who has asked for reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .fill__names { opacity: 0; transition: opacity 900ms ease-out; }
  .fill__names--on { opacity: 1; }
}

.site-footer {
  padding: 1.5rem var(--gutter, 1.25rem) 2rem;
  text-align: center;
  font-size: var(--step--1);
  color: var(--muted);
}
.site-footer a { color: var(--muted); }

.legal { max-width: 42rem; margin: 0 auto; padding: 3rem var(--gutter, 1.25rem) 4rem; }
.legal h2 { margin-top: 2rem; }
