/* ============================================================
   BASE — reset, document rhythm, typography, a11y primitives
   ============================================================ */

/* ---------- Typefaces ----------
   Self-hosted rather than fetched from Google Fonts. The byte count is
   unchanged at 68KB, so this is not a size optimisation. It removes a
   third party from a site that deliberately ships no analytics, and it
   removes two DNS lookups and TLS handshakes plus a serialised round
   trip, because the font files previously could not begin downloading
   until a stylesheet on another host had arrived and parsed. On the weak
   rural connections this site is built for, those handshakes cost more
   than the kilobytes do.

   One block per family rather than one per weight: these are variable
   fonts, and every weight Google served pointed at this same file. The
   ranges below are the ones Google exposed and are known to work.
   Widening either means first confirming the file's axis goes further.

   Note the body face stops at 600, which is where Google stopped too, so
   this is not a change in behaviour. A weight above 600 on Source Sans 3
   silently clamps rather than failing, so if a heavier body weight is
   ever wanted, widen the range here and check the file supports it.
   Nothing on the site asks for it today: every <strong> is Lexend 600.

   unicode-range is copied verbatim from Google's latin subset. */
@font-face {
  font-family: 'Lexend';
  font-style: normal;
  font-weight: 400 700;
  font-display: swap;
  src: url('../assets/fonts/lexend-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Source Sans 3';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('../assets/fonts/source-sans-3-latin.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

*, *::before, *::after { box-sizing: border-box; }

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

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  font-weight: var(--fw-regular);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Scrolling is locked only on the canvas, where the panel track owns it.
   These were on bare `body`, which silently made any standalone page
   unscrollable: the privacy policy rendered its full height and then
   refused to move past the first screenful. Scoping to .app also restores
   pull-to-refresh on such pages, which overscroll-behavior had disabled. */
body.app {
  overflow: hidden;
  overscroll-behavior: none;
}

h1, h2, h3, h4, h5 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--tracking-tight);
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}

/* .hero__title carries the size so the tag can change. The pre-render emits
   <h1> for the route being generated and <h2> for the panels that are only
   present so travel still works, which keeps one h1 per document without
   changing how any of them look. */
h1, .hero__title { font-size: var(--fs-4xl); }
h2 { font-size: var(--fs-3xl); }
h3 { font-size: var(--fs-xl); line-height: var(--lh-snug); }
h4 { font-size: var(--fs-lg); line-height: var(--lh-snug); font-weight: var(--fw-semibold); }

p, li { max-width: var(--measure); text-wrap: pretty; }
p { margin: 0 0 var(--space-4); }

a {
  color: var(--color-brand);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
  transition: color var(--dur-state) var(--ease-out);
}
a:hover { color: var(--color-brand-hover); }

strong { font-weight: var(--fw-semibold); }

img, svg, video { max-width: 100%; height: auto; display: block; }

hr {
  border: 0;
  border-top: var(--border-hair) solid var(--color-border);
  margin: var(--space-6) 0;
}

ul, ol { padding-left: 1.25em; }
li + li { margin-top: var(--space-2); }

/* URLs, IDs and user-generated strings must reflow, not overflow */
.wrap-anywhere { overflow-wrap: anywhere; min-width: 0; }

/* ---------- Focus: visible, generous, never removed ---------- */
:focus { outline: none; }
:focus-visible {
  outline: 3px solid var(--color-focus);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}
.on-dark :focus-visible,
.panel--inverse :focus-visible { outline-color: var(--color-focus-inverse); }

/* ---------- Screen-reader-only ---------- */
.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* ---------- Skip link ---------- */
.skip-link {
  position: fixed; top: 0; left: 50%;
  transform: translate(-50%, -120%);
  z-index: var(--z-skip);
  background: var(--color-accent);
  color: var(--color-text-on-yellow);
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  padding: var(--space-3) var(--space-5);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
  text-decoration: none;
  transition: transform var(--dur-state) var(--ease-out);
}
.skip-link:focus-visible { transform: translate(-50%, 0); }

/* ---------- Layout helpers ---------- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.container--narrow { max-width: var(--container-narrow); }
.stack > * + * { margin-top: var(--space-4); }
.stack-lg > * + * { margin-top: var(--space-6); }

.eyebrow {
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--tracking-caps);
  text-transform: uppercase;
  color: var(--color-text-muted);
  /* flex-start, not center: when the label wraps the marker must stay
     level with the first line rather than drifting to the middle. */
  display: flex; align-items: flex-start; gap: var(--space-2);
  margin-bottom: var(--space-3);
}
/* Yellow is never allowed to sit directly against white or grey — at
   1.18:1 it simply disappears. Every yellow element on a light surface
   is enclosed by an ink border that gives it an edge to read against. */
.eyebrow::before {
  content: ""; width: 26px; height: 10px; flex: none;
  /* Top-align the chip with the cap height of the label, not with the line
     box, which starts above the visible letters. In Lexend the ascent is
     1em and the cap height 0.7031em, so the tops of the capitals sit
     (half-leading + 0.2969em) below the top of the line box. The static
     value is the answer for the current line-height, and the calc below
     replaces it in browsers that support the `lh` unit so the alignment
     survives a change to the type scale. */
  margin-top: .472em;
  margin-top: calc((1lh - 1.25em) / 2 + .2969em);
  background: var(--color-accent);
  border: 2px solid var(--color-text);
  border-radius: 3px;
}

/* Each branch carries its own colour through the whole panel, so the chip
   follows the branch rather than staying yellow. The border can come off
   here, and only here, because the containment rule in MASTER.md 2.2
   exists for yellow specifically: at 1.18:1 on white it has no edge of its
   own. Blue reads at 9.43:1 and rust at 10.89:1, so both draw their own
   edge and need no enclosure. Box-sizing is border-box, so removing the
   border keeps the 26x10 footprint and simply fills it. */
.panel--campaign  .eyebrow::before { background: var(--path-campaign);  border: none; }
.panel--volunteer .eyebrow::before { background: var(--path-volunteer); border: none; }

/* Both branch colours are dark, so on an inverse band they all but vanish:
   blue on ink is 2.08:1 and rust 1.81:1, against the 16.71:1 the yellow
   chip used to carry there. The 200 tints keep the branch identity while
   restoring presence, at 9.24:1 and 9.14:1. */
.panel--campaign  .section--inverse .eyebrow::before { background: var(--blue-200); }
.panel--volunteer .section--inverse .eyebrow::before { background: var(--rust-200); }
.eyebrow--onbrand { color: rgba(255,255,255,.82); }

.lede {
  font-size: var(--fs-lg);
  line-height: var(--lh-loose);
  color: var(--color-text-muted);
  max-width: 58ch;
}
.panel--inverse .lede, .on-dark .lede { color: rgba(255,255,255,.86); }

/* The depth bar is sticky, so anything scrolled to by an anchor needs
   clearance or its eyebrow ends up behind the bar. */
.section { padding-block: var(--section-y); scroll-margin-top: 5rem; }
.section--sunken { background: var(--color-bg-sunken); }
.section--tint-campaign { background: var(--path-campaign-soft); }
.section--tint-volunteer { background: var(--path-volunteer-soft); }

/* Dark bands break up the page and carry the palette further than a
   white page can. Everything inside one flips to light-on-dark. */
.section--inverse {
  background: var(--color-surface-inverse);
  color: #fff;
}
.section--inverse h2,
.section--inverse h3,
.section--inverse h4,
.section--inverse strong { color: #fff; }
.section--inverse p,
.section--inverse li { color: rgba(255,255,255,.82); }
.section--inverse .eyebrow { color: rgba(255,255,255,.72); }
.section--inverse .lede { color: rgba(255,255,255,.86); }
.section--inverse a { color: var(--color-accent); }
.section--inverse .card {
  background: rgba(255,255,255,.06);
  border-color: rgba(255,255,255,.18);
  box-shadow: none;
}
.section--inverse .card h3 { color: #fff; }
.section--inverse .card p { color: rgba(255,255,255,.74); }
.section--inverse .card__icon { background: rgba(255,255,255,.10); color: var(--color-accent); }
.section--inverse .callout {
  background: rgba(255,255,255,.06);
  border-left-color: var(--color-accent);
}
.section--inverse :focus-visible { outline-color: var(--color-focus-inverse); }

/* Solid brand band, used sparingly for a single high-emphasis stripe. */
.section--brand { background: var(--color-brand); color: #fff; }
.section--brand h2, .section--brand h3 { color: #fff; }
.section--brand p, .section--brand li { color: rgba(255,255,255,.88); }
.section--brand .eyebrow { color: rgba(255,255,255,.78); }

/* Ascending order matters: at a wide viewport every min-width query
   matches, so the last one written wins. */
.grid { display: grid; gap: var(--space-5); }
@media (min-width: 640px)  { .grid--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 700px)  { .grid--2 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 700px)  { .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .grid--3 { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1000px) { .grid--4 { grid-template-columns: repeat(4, 1fr); } }

.tabular { font-variant-numeric: tabular-nums; }
