/* ==========================================================================
   Evergrove — site stylesheet
   Implements the "Plate and Page" direction (brand/proposals/EVERGROVE-BRAND-DIRECTION.md).

   Structure:
     1. Tokens          2. Reset & base      3. The ground
     4. Typography      5. Layout            6. Components
     7. Forms           8. Article           9. Responsive & a11y
   ========================================================================== */

/* 1. TOKENS — lifted from plate-and-page/tokens.css. Contrast comes from hue
      difference at low saturation, never from brightness. ------------------ */
:root {
  /* grounds */
  --beige:      #F0E4CD;
  --oat:        #D9C7A4;

  /* text — every one legible on beige */
  --ink:        #4B0500;  /* burgundy      — headlines, body      12.6:1 */
  --forest:     #4B0500;  /* deep brown    — section headings     14.9:1 */
  --oxblood:    #4B0500;  /* structure     — labels, eyebrows     12.6:1 */
  --midnight:   #4B0500;  /* deep brown    — emphasis, links      14.9:1 */
  --ink-soft:   #4B0500;  /* long-form body                       12.6:1 */
  --brick:      #4B0500;  /* the hand                             12.6:1 */

  /* muted accents — FILLS ONLY, these never carry type */
  --moss:       #839958;
  --citron:     #858248;
  --mauve:      #937C91;
  --dusty:      #8494A1;
  --rosy:       #D3968C;

  /* pairings that may carry small text */
  --btn-bg:     #C5B48B;  --btn-fg:  #4B0500;  --btn-edge: #A89470;  /* primary           7.8:1 */
  --win-bg:     #105666;  --win-fg:  #F6EAD2;  /* claims / legal    7.4:1 */
  --win2-bg:    #D3968C;  --win2-fg: #2D2011;  /* tender            6.4:1 */

  --rule:       rgba(75,5,0,.22);
  --rule-soft:  rgba(75,5,0,.12);

  --disp:  'Instrument Serif', Georgia, serif;
  --caps:  'Italiana', Georgia, serif;
  --text:  'Newsreader', Georgia, serif;
  --mono:  'Cutive Mono', ui-monospace, monospace;
  --hand:  'Nothing You Could Do', cursive;

  /* spacing — whitespace is the brand */
  --gut:   clamp(22px, 7vw, 58px);
  /* The header is sticky, so it takes space in flow. A beat asking for a
     full 100svh therefore runs past the bottom of the screen by exactly this
     much, and the foot of the first plate is cut off. Derived from the mark
     plus .site-head__in's padding, so the two cannot drift apart. */
  --head-h: calc(max(clamp(40px, 3.6vw, 52px), 36px) + 36px);
  /* the messages bar, fixed to the foot of the window */
  /* the notice row at the top of the header */
  --strip-h: 38px;
  --env-size: clamp(176px, 18vw, 268px);
  /* the foot is clear now; these are kept at zero so any stray reference in
     the page stylesheets still resolves instead of killing its declaration */
  --stack-h: 0px;  --card-rise: 0px;  --card-h: 0px;  --card-bottom: 0px;
  --chrome:  calc(var(--head-h) + var(--strip-h));
  --stack: clamp(56px, 9vw, 130px);
  --measure: 34em;
}

/* 2. RESET & BASE --------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .site-head { transition: none; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body {
  /* The envelope is fixed to the bottom right and reaches about 0.9 of its own
     width up the screen. Roughly 120px of the foot already sits below the
     membership marks, so this reserves the rest and leaves about 25px of air;
     without it the marks were covered by up to 89px at full scroll. */
  padding-bottom: max(20px, calc(var(--env-size) * .9 - 130px));
  background: var(--beige);
  overflow-wrap: break-word;
  color: var(--ink);
  font-family: var(--text);
  font-weight: 400;              /* 400, never 300 — the readability fix */
  font-size: 17px;
  line-height: 1.75;
  font-optical-sizing: auto;
  position: relative;
  min-height: 100vh;
  overflow-x: hidden;
}

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

/* 3. THE GROUND ----------------------------------------------------------
   One continuous limewash across every page, fixed so it does not scroll.
   Every tone sits in hue 35-48 at saturation under 16% — warm neutral only.
   No coloured washes: the ground's whole job is to let text and the
   botanical plates pop off it. Three layers, all ~0 bytes:
     .ground  broad trowel clouding (CSS radial gradients)
     .mottle  mid-scale plaster tooth (low-frequency turbulence)
     .grain   fine paper grain (high-frequency turbulence)
   ------------------------------------------------------------------------ */
.ground {
  position: fixed;
  inset: 0;
  z-index: -3;
  pointer-events: none;
  background:
    radial-gradient(56% 48% at 12%  8%, rgba(255,252,244,.88), transparent 72%),
    radial-gradient(48% 44% at 88% 16%, rgba(244,232,206,.34), transparent 70%),
    radial-gradient(56% 50% at 74% 74%, rgba(252,245,228,.50), transparent 72%),
    radial-gradient(52% 48% at  6% 82%, rgba(240,227,198,.28), transparent 72%),
    radial-gradient(44% 40% at 46% 42%, rgba(255,254,250,.62), transparent 74%),
    radial-gradient(36% 32% at 68% 30%, rgba(246,236,214,.20), transparent 76%),
    var(--beige);
}

/* The wash is STATIC and fixed. A scroll-linked parallax was tried and pulled:
   translating four full-viewport turbulence-filtered layers forces the browser
   to re-composite those filters every frame, which stutters badly. If the
   floating feel is wanted again, animate something cheap instead — a plain
   gradient layer with no filter on it — and leave the filtered layers alone. */

/* The clouding. Two things matter and both were wrong at first:
   1. The turbulence drives ALPHA only and the fill is a warm tan — grey
      turbulence multiplied over cream lands on khaki, which reads as a green cast.
   2. One baseFrequency makes one blob size, so the wash looked uniform and
      stippled. Real clouding varies in scale, so each layer runs a LOW base
      frequency with many octaves (large forms, finer detail stacked on top)
      and an unequal x/y frequency so nothing comes out circular. The two
      layers use different scales, stretches and seeds. */
.mottle {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  pointer-events: none;
  opacity: .44;
  mix-blend-mode: multiply;
}

/* The lifting half of the wash. A multiply layer can only darken, so texture
   strong enough to see also made the page dingy. This screens a near-white
   turbulence back over it: variation doubles, net lightness holds. */
.mottle-lite {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  pointer-events: none;
  opacity: .58;
  mix-blend-mode: screen;
}

/* The middle of the scale ladder. With only broad clouds and fine grain there
   was a gap, so the wash varied in size but not in texture. Overlay is the
   right blend here: it deepens what is already dark and lifts what is already
   light, so texture increases without shifting the page's overall lightness. */
.mottle-mid {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -2;
  pointer-events: none;
  opacity: .34;
  mix-blend-mode: overlay;
}

/* Grain is not decoration — it is most of what separates this from a flat
   template. Rendered as turbulence so it costs nothing and never pixelates.
   The explicit 100% sizing matters: an <svg> with no dimensions falls back
   to 300×150 and the filtered rect shows as a block in the corner. */
.grain {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: -1;
  pointer-events: none;
  opacity: .34;
  mix-blend-mode: multiply;
}

/* 4. TYPOGRAPHY ----------------------------------------------------------- */

/* Instrument Serif appears above ~60px only, where its high contrast is a
   feature. Anything mid-sized uses Newsreader 600 instead — Instrument has
   no bold cut, which is why mid-size headings previously read thin. */
.display {
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(40px, 7.4vw, 88px);
  line-height: 1.04;
  letter-spacing: -.01em;
  text-wrap: balance;
}
.display em { font-style: italic; color: var(--midnight); }

h1 { font-family: var(--disp); font-weight: 400; font-size: clamp(28px, 3.4vw, 46px); line-height: 1.1; text-wrap: balance; overflow-wrap: break-word; }
h1 em { font-style: italic; color: var(--midnight); }
/* keep headings clear of the sticky header when focused or linked to */
h1, h2, h3, [id] { scroll-margin-top: calc(var(--chrome) + 18px); }
/* A section's divider is its own top border. Landing it 18px below the chrome
   puts that 1px rule inside the header band, where it reads as a line drawn
   across the menu. Landing the section flush instead tucks the rule against
   the header's bottom edge, where it is the edge of the chrome. */
.section[id] { scroll-margin-top: var(--chrome); }

/* THE HEADING CONVENTION, and it is only three steps.
     h1, h2   the display serif. The headline voice.
     h3       the typewriter, tracked caps. The subheading voice, and the same
              language as .eyebrow so a label always reads as a label.
     body     Newsreader, regular. Everything a person actually reads.
   Nothing else is allowed to look like a heading. */
h2 {
  font-family: var(--disp);
  font-weight: 400;
  font-size: clamp(26px, 3.2vw, 38px);
  line-height: 1.18;
  letter-spacing: -.008em;
  color: var(--forest);
  text-wrap: balance;
}
h3 {
  font-family: var(--mono);
  font-weight: 400;
  font-size: clamp(12px, 1.3vw, 13.5px);
  letter-spacing: .18em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--oxblood);
}

/* tracked caps — always small, always tracked, never a headline */
.eyebrow, .label {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--oxblood);
  font-weight: 400;
}
.label-soft { color: var(--midnight); }

/* The wordmark is an asset, not a font. It is set in a licensed didone that
   is not installed anywhere, so it is never re-typeset: assets/img/brand/
   holds it in each brand colour. The text-based rules that used to live here
   approximated it in Italiana, which was always a stand-in. */
.wm {
  display: block;
  flex: none;
  line-height: 0;
  text-decoration: none;
}
.wm img {
  display: block;
  width: auto;
  height: clamp(40px, 3.6vw, 52px);
}

/* standfirst — Newsreader 600, the mid-size workhorse */
.standfirst {
  font-size: clamp(19px, 2.2vw, 21px);
  font-weight: 600;
  line-height: 1.55;
  color: var(--forest);
  max-width: 30em;
}

p { max-width: var(--measure); }
p + p { margin-top: 1.1em; }
.lede { font-size: 19px; line-height: 1.7; }
.soft { color: var(--ink-soft); }

/* the hand — margin notes and asides only, never load-bearing information */
.hand {
  font-family: var(--hand);
  color: var(--brick);
  font-size: clamp(19px, 2.3vw, 25px);
  line-height: 1.5;
  max-width: 36ch;
  text-wrap: balance;
}

/* figures are Newsreader 600 in teal — they are the evidence, they get mass */
.fig { font-weight: 600; color: var(--midnight); font-variant-numeric: tabular-nums; }

a { color: var(--midnight); text-underline-offset: .22em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

em { font-style: italic; }
strong { font-weight: 600; }

/* 5. LAYOUT --------------------------------------------------------------- */
.wrap { width: 100%; max-width: 1320px; margin-inline: auto; padding-inline: var(--gut); }
.narrow { max-width: 760px; }
.section { padding-block: var(--stack); }
/* the page already has the header above it, so the first section does not
   need a full measure of air on top as well */
main > .section:first-child { padding-top: clamp(28px, 3.6vw, 56px); }
.section + .section { border-top: 1px solid var(--rule-soft); }
/* for a section that is a continuation of the one above rather than a new
   subject: no rule, and neither side pays for the gap twice */
.section--runon { padding-top: 0; }
.section + .section--runon { border-top: 0; }
.section:has(+ .section--runon) { padding-bottom: 0; }
/* the reading list draws its own first rule, so a section rule above it
   doubles up. It also runs straight on from the search field: a full section
   beat between a field and the list it filters reads as a hole. */
.section:has(> .posts) { border-top: 0; }
.posts { margin-top: clamp(20px, 2.4vw, 30px); }
/* a shorter beat between sections, where the full rhythm reads as a hole */
.section--snug { padding-block: clamp(40px, 5.2vw, 76px); }
.section:has(+ .section--snug) { padding-bottom: clamp(40px, 5.2vw, 76px); }
/* A section that ends the page does not need its own bottom padding: the
   footer already carries that space above itself, and stacking the two
   leaves a hole under the closing button. */
.section--ends-page { padding-bottom: 0; }

.split {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: start;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1.15fr .85fr; }
  .split--even { grid-template-columns: 1fr 1fr; }
  .split--plate { grid-template-columns: 1fr 380px; }
}

.stack-sm > * + * { margin-top: 14px; }
.stack-md > * + * { margin-top: 26px; }
.stack-lg > * + * { margin-top: 44px; }

/* 6. COMPONENTS ----------------------------------------------------------- */

/* --- skip link --- */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--btn-bg); color: var(--btn-fg);
  padding: 14px 22px; font-family: var(--mono); font-size: 12px;
  letter-spacing: .18em; text-transform: uppercase;
}
.skip:focus { left: 0; }

/* --- site header --- */
/* Invisible at rest — no rule, no fill, sitting straight on the wash. It earns
   a backdrop blur only once content starts passing under it, which is the only
   point at which the nav needs separating from anything. */
.site-head {
  position: sticky; top: 0; z-index: 41;
  background: transparent;
}
/* On scroll the menu frosts to match the strip above it, so the two read as
   one piece of chrome rather than a bar with a lid. */
/* The menu row frosts on scroll. It hangs off the header rather than off the
   inner wrap, because the wrap stops at the page gutter and the frost would
   have ended either side of the wordmark and the button. Top offset by the
   strip, so it covers the menu row only. */
.site-head__in { position: relative; z-index: 1; }
.site-head::after {
  content: "";
  position: absolute;
  top: var(--strip-h); right: 0; bottom: 0; left: 0;
  opacity: 0;
  background: rgba(246,234,210,.58);
  backdrop-filter: blur(14px) saturate(1.05);
  -webkit-backdrop-filter: blur(14px) saturate(1.05);
  transition: opacity .35s ease;
  pointer-events: none;
  z-index: -1;
}
.site-head.is-scrolled::after { opacity: 1; }
.site-head__in {
  display: flex; align-items: center; justify-content: space-between;
  gap: 18px; padding-block: 18px;
}
/* Below ~560px the wordmark, menu and CTA share a narrow row.
   Order: wordmark, then the CTA, then the menu button hard against the right
   edge, so the full "Join the movement" is never what gets clipped. */
@media (max-width: 559px) {
  .site-head__in { gap: 8px; }
  .site-head__in > .wm   { order: 1; margin-right: auto; }
  .site-head__in > .btn  { order: 2; margin-right: 10px; }
  .site-head__in > .mnav { order: 3; }
  .site-head__in > .btn {
    padding: 9px 11px;
    font-size: 11px;
    letter-spacing: .05em;
    white-space: nowrap;
  }
  .wm img { height: 32px; }
}

/* "Join the movement" is four characters wider than what was here before,
   which is the difference between fitting and not on a 320px screen. The
   mark and the letter-spacing give the room back. */
/* 360 to 389 is where most phones sit, and the row is about 3px too wide
   there at the settings above, so the tightening starts higher than it used
   to rather than letting the menu button hang off the edge. */
@media (max-width: 389px) {
  .wm img { height: 29px; }
  .site-head__in { gap: 6px; }
  .site-head__in > .btn { padding: 8px 9px; font-size: 10.5px; letter-spacing: .03em; }
}
.nav { display: none; }
@media (min-width: 1000px) {
  .nav { display: flex; gap: 30px; list-style: none; }
  .nav a {
    font-family: var(--mono); font-size: 13px; letter-spacing: .12em;
    text-transform: uppercase; color: var(--ink-soft); text-decoration: none;
    padding-block: 6px; border-bottom: 1px solid transparent;
    white-space: nowrap;   /* two-word labels must not wrap the header taller */
}
  .nav a:hover, .nav a[aria-current="page"] { color: var(--oxblood); border-bottom-color: var(--oxblood); }
}

/* --- buttons --- */
.btn {
  display: inline-block;
  font-family: var(--mono); font-size: 12.5px; letter-spacing: .16em;
  text-transform: uppercase; text-decoration: none;
  padding: 15px 28px; border: 1px solid var(--btn-edge); border-radius: 999px;
  cursor: pointer;
  background: var(--btn-bg); color: var(--btn-fg);
}
/* Hovered and pressed: the fill drops away and the outline carries the shape.
   Dimming the whole button with opacity read as "disabled" rather than as
   "live", so the fill goes instead. Keyboard focus gets the same state,
   because a keyboard user never hovers. */
.btn:hover, .btn:focus-visible, .btn:active {
  background: transparent;
  color: var(--ink);
  border-color: currentColor;
  opacity: 1;
}
.btn:active { transform: translateY(1px); }
.btn { transition: opacity .18s ease, background-color .14s ease,
                   color .14s ease, border-color .14s ease, transform .1s ease; }
/* on the dark blocks the pressed state has to go the other way */
.window--forest .btn:hover,
.window--forest .btn:focus-visible,
.window--forest .btn:active { background: transparent; color: #4B0500; border-color: #4B0500; }
@media (prefers-reduced-motion: reduce) { .btn:active { transform: none; } }
.btn--ghost { background: transparent; color: var(--midnight); border-color: var(--midnight); }
/* Solid burgundy, hollowing out on hover. Written out rather than left to
   `.btn:hover`, so the inversion cannot be undone by a later variant. */
.btn--deep { background: var(--ink); color: var(--beige); border-color: var(--ink); }
.btn--deep:hover,
.btn--deep:focus-visible,
.btn--deep:active { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn--ghost:hover { background: var(--midnight); color: var(--beige); opacity: 1; }
.btn--sm { padding: 11px 18px; font-size: 12px; }

/* --- hairline rules, never boxes --- */
.rule { border: 0; border-top: 1px solid var(--rule); }

/* ruled rows carry label/value pairs — a record, not a pitch */
.rows { list-style: none; }
.rows li {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 18px; padding-block: 13px; border-bottom: 1px solid var(--rule);
}
.rows li:first-child { border-top: 1px solid var(--rule); }
.rows b { font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
  text-transform: uppercase; font-weight: 400; color: var(--oxblood);
  flex: none; white-space: nowrap; padding-top: 3px; }
.rows span { text-align: right; }
/* Long values read better left-aligned against a fixed label column than
   right-ragged, so widen the label and flip the value once there is room. */
@media (min-width: 720px) {
  .rows b { min-width: 13em; }
  .rows span { text-align: left; flex: 1; }
}

/* --- attention windows — full-colour blocks that pull you out of the flow --- */
.window { padding: clamp(26px, 4vw, 40px); }
/* the sign-off box: two short lines and two buttons, so it does not need the
   full window's air around it */
.window--tight { padding: clamp(22px, 2.6vw, 30px); max-width: 620px; }
.window--tight p { max-width: 46ch; }
.window__do { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 20px; }
.window p { max-width: 42em; }
.window--legal { background: var(--win-bg); color: var(--win-fg); }
.window--legal a { color: var(--beige); }
.window--legal .eyebrow { color: rgba(246,234,210,.74); }
.window--legal .rows li { border-color: rgba(246,234,210,.22); }
.window--legal .rows b { color: rgba(246,234,210,.74); }
.window--legal .fig { color: var(--win-fg); }
.window--tender { background: var(--win2-bg); color: var(--win2-fg); }
.window--tender .eyebrow { color: var(--oxblood); }

/* --- plates --------------------------------------------------------------
   An illustration fades in, then breathes. Markup comes from
   tools/make-plate.py; assets/js/plate.js runs it.

     1. the plate fades up slowly
     2. where a clip is supplied it takes over and loops
     3. otherwise the plate sways gently as one piece

   A stroke-by-stroke sketch is still available (`--draw` on the generator),
   and everything for it is below — it is simply not the default any more.
   -------------------------------------------------------------------------- */
.plate {
  position: relative; display: block; margin: 0;
  --plate-fade: 2.2s;     /* how slowly it arrives */
  --plate-dur: 2.5s;      /* sketch length, only when a plate has one */
  --plate-sway: 0.7deg;   /* how far it moves once arrived */
  --plate-pivot: 50% 97%; /* where it pivots — the foot of the subject */
}
.plate img { display: block; width: 100%; height: auto; }   /* static plates too */
.plate__art {
  transform-origin: var(--plate-pivot);
  opacity: 0;
  transition: opacity var(--plate-fade) ease-out; }
.plate.is-in .plate__art { opacity: 1; }

@keyframes plate-sway {
  0%, 100% { transform: rotate(0deg) }
  25%      { transform: rotate(var(--plate-sway)) }
  75%      { transform: rotate(calc(var(--plate-sway) * -1)) }
}
.plate.is-in .plate__art {
  animation: plate-sway 8.5s ease-in-out infinite backwards;
  animation-delay: calc(var(--plate-fade) + 0.6s); }

/* --- the living layer ----------------------------------------------------
   An optional looping clip takes over once the plate is up. It carries real
   leaf and branch movement, which a CSS rotation cannot — a rotation can only
   tilt the whole picture rigidly.

   The clips have no alpha channel (MP4 cannot), so `multiply` drops their
   white ground out against the page. That works because the artwork is darker
   than the ground everywhere; it would not work on a dark background.

   The still then steps aside completely: `multiply` blends against whatever
   sits behind it, and with the still left in place the clip composited
   against THAT rather than the page, leaving its white ground visible as a
   pale rectangle. */
.plate__life {
  position: absolute;
  width:  var(--life-w, 100%);  height: var(--life-h, 100%);
  left:   var(--life-x, 0);     top:    var(--life-y, 0);
  object-fit: fill;
  filter: contrast(var(--life-contrast, 1));
  mix-blend-mode: multiply;
  opacity: 0; transition: opacity 1.6s ease-out;
  pointer-events: none; }
.plate.is-living .plate__life { opacity: 1; }
.plate.is-living .plate__art  { opacity: 0; animation: none; }

/* --- optional: the stroke-by-stroke sketch -------------------------------
   Only present on plates built with `--draw`. Kept because it took a long
   time to get right, and these are the things that decide whether it reads
   as sketching or as a dissolve:
   - marks are ROUND and overlapping, never a grid of squares
   - mark size comes from ink density, not a fixed count
   - each mark's fade is ~5% of the draw; at 20-40% it becomes a dissolve
   - growth travels ALONG the ink, so nothing appears before what it grows from
   -------------------------------------------------------------------------- */
.plate[data-tiles] .plate__art { transition-delay: calc(var(--plate-dur) * .8); }
.plate[data-tiles].is-in .plate__art { animation-delay: calc(var(--plate-dur) + 1.2s); }

.plate__tiles { position: absolute; inset: 0; pointer-events: none; opacity: 1;
  --k: 1.7;
  transition: opacity .9s ease-out;
  transition-delay: calc(var(--plate-dur) * 1.02); }
.plate__tiles i {
  position: absolute;
  width:  calc(var(--k) * 100% / var(--c));
  height: calc(var(--k) * 100% / var(--r));
  left: calc((var(--gx) - (var(--k) - 1) / 2) * 100% / var(--c));
  top:  calc((var(--gy) - (var(--k) - 1) / 2) * 100% / var(--r));
  background-image: var(--url);
  background-repeat: no-repeat;
  background-size: calc(var(--c) / var(--k) * 100%) calc(var(--r) / var(--k) * 100%);
  background-position:
    calc((var(--gx) - (var(--k) - 1) / 2) * 100% / (var(--c) - var(--k)))
    calc((var(--gy) - (var(--k) - 1) / 2) * 100% / (var(--r) - var(--k)));
  border-radius: 50%;
  opacity: 0;
  transition: opacity var(--fd) ease-out;
  transition-delay: calc(var(--d) * var(--plate-dur)); }
.plate.is-in .plate__tiles i { opacity: 1; }
.plate.is-in .plate__tiles   { opacity: 0; }
@supports (mask-image: radial-gradient(#000, transparent)) or
          (-webkit-mask-image: radial-gradient(#000, transparent)) {
  .plate__tiles i {
    -webkit-mask-image: radial-gradient(closest-side, #000 62%, rgba(0,0,0,0) 100%);
            mask-image: radial-gradient(closest-side, #000 62%, rgba(0,0,0,0) 100%); }
}

/* no JS, or reduced motion: the finished illustration, still */
.plate.is-done .plate__art { opacity: 1; transition: none; animation: none; }

@media (prefers-reduced-motion: reduce) {
  .plate__life { display: none !important; }
  .plate__tiles { display: none !important; }
  .plate__art { opacity: 1 !important; transition: none !important;
                animation: none !important; }
}

/* the typed specimen label that sits under a plate */
.plate figcaption { font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .2em; text-transform: uppercase; color: var(--oxblood);
  text-align: center; margin-top: 12px; }

/* --- cards: hairline-separated, not boxed --- */
.cards { display: grid; gap: clamp(26px, 3.4vw, 40px); grid-template-columns: 1fr; }
@media (min-width: 720px)  { .cards--2 { grid-template-columns: 1fr 1fr; } }
@media (min-width: 900px)  { .cards--3 { grid-template-columns: repeat(3, 1fr); } }
.card { border-top: 1px solid var(--rule); padding-top: 20px; }
.card__face {
  width: 132px; height: 132px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 18px;
  filter: saturate(.92);
}
/* the theme cards carry a typewriter label and a paragraph, nothing else:
   three type styles in a card this small read as a ransom note */
.card h3 { margin-bottom: 12px; line-height: 1.6; text-transform: none; letter-spacing: .13em; }
.card h3 + p { margin-top: 0; }
.card p { font-size: 16.5px; color: var(--ink-soft); }

/* --- article teaser list --- */
.teasers { list-style: none; }
.teasers li { border-top: 1px solid var(--rule); padding-block: 26px; }
.teasers li:last-child { border-bottom: 1px solid var(--rule); }
.teasers a { text-decoration: none; color: inherit; display: block; }
.teasers a:hover h3 { text-decoration: underline; text-underline-offset: .2em; }
.teasers .meta { font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--oxblood); margin-bottom: 8px; }
.teasers p { font-size: 16.5px; color: var(--ink-soft); margin-top: 6px; }

/* --- footer --- */
.site-foot { border-top: 1px solid var(--rule); padding-block: 54px 40px; margin-top: var(--stack); }
.site-foot .cols { display: grid; gap: 34px; grid-template-columns: 1fr; }
/* Between the phone and a wide screen there is not enough width for three
   columns AND a two-column list, so the acknowledgement takes a row of its
   own and the list keeps its two columns. */
@media (min-width: 760px) {
  .site-foot .cols { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 1024px) {
  /* four across: disclaimer, acknowledgement, the map, the memberships */
  .site-foot .cols { grid-template-columns: 1fr 1fr .85fr .7fr; gap: 30px; }
  .site-foot .cols > :first-child { grid-column: auto; }
  /* Between 1024 and 1280 the map's own column is too narrow to split: two
     sub-columns there put "Why Terramation Matters" across three lines.
     Scoped past `.foot-map`, which is declared later in the file. */
  .site-foot .foot-map { columns: 1; }
}

/* Wide enough to give the map a column that genuinely holds two lists, so it
   splits again and the footer stops being so deep. The share is taken from the
   two prose columns, which have the words to spare. */
@media (min-width: 1280px) {
  .site-foot .cols { grid-template-columns: .8fr .8fr 1.15fr .45fr; }
  .site-foot .foot-map { columns: 2; column-gap: clamp(16px, 1.6vw, 26px); }
}

/* Ten links in a single column made the footer taller than anything above
   it. Two columns, flowing down then across so the reading order is still
   top to bottom, on every width. */
.foot-map {
  columns: 2;
  column-gap: clamp(14px, 2vw, 30px);
}
.foot-map li { break-inside: avoid; }

/* the backer's mark sits where the second link list used to */
.foot-badge { align-self: start; }
/* Both marks belong to other organisations, so neither is recoloured; they
   keep their own grounds and simply sit at the same width. */
.foot-badge__mark {
  display: block; width: 150px; height: auto; margin-top: 16px;
  border-radius: 4px;
}
.foot-badge__mark:first-child {
  margin-top: 0;
}
.foot-badge__say {
  font-family: var(--mono); font-size: 11px; letter-spacing: .1em;
  line-height: 1.5; color: var(--ink-soft);
  margin-top: 10px; max-width: 150px;
}
@media (min-width: 760px) { .foot-badge { justify-self: end; text-align: right; }
  .foot-badge__mark { margin-left: auto; }
  .foot-badge__say { margin-left: auto; } }
.site-foot ul { list-style: none; }
.site-foot li { margin-bottom: 9px; }
.site-foot a { font-size: 16px; color: var(--ink-soft); text-decoration: none; }
.site-foot a:hover { text-decoration: underline; }
/* squared off, both edges flush, like the closing passage on the homepage.
   Hyphenation is what stops a justified column this narrow opening rivers. */
.acknowledgement {
  font-size: 15px; line-height: 1.7; color: var(--ink-soft); max-width: 62ch;
  text-align: justify; hyphens: auto; -webkit-hyphens: auto;
}
.colophon {
  font-family: var(--mono); font-size: 12px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--oxblood);
  /* one line on anything wide enough; the separator carries the break on a
     phone, where two lines is the honest answer rather than a squeeze */
  display: flex; flex-wrap: wrap; gap: 0 10px;
  /* p carries a reading measure, which is what was breaking this line */
  max-width: none;
}
.colophon__sep { opacity: .5; }
@media (max-width: 559px) {
  .colophon { gap: 6px 10px; }
  .colophon__sep { display: none; }
}

/* --- status line: the claims rule made structural --- */
.status {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--midnight);
}

/* 7. FORMS ---------------------------------------------------------------- */
.field { margin-bottom: 22px; }
.field label { display: block; font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--oxblood); margin-bottom: 8px; }
.field input[type="text"], .field input[type="email"], .field textarea, .field select {
  width: 100%; font-family: var(--text); font-size: 17px; color: var(--ink);
  background: rgba(255,255,255,.5);
  border: 0; border-bottom: 1px solid var(--rule);
  padding: 11px 2px; line-height: 1.5;
}
.field textarea { min-height: 96px; resize: vertical; }
.field input:focus, .field textarea:focus, .field select:focus {
  outline: 2px solid var(--midnight); outline-offset: 3px; background: rgba(255,255,255,.75);
}
.hint { font-size: 14.5px; color: var(--ink-soft); margin-top: 7px; }

/* Prose lists. The reset zeroes list padding, which with markers drawn outside
   the box left the bullets hanging into the margin, to the left of the
   paragraph they belong to. This sets them just inside it instead. Direct
   children only, so the lists that carry their own layout are untouched. */
.narrow > ul, .article > ul { padding-left: 1.5em; }
.narrow > ul > li, .article > ul > li { margin-bottom: .35em; }

/* radio/checkbox rows — generous hit areas */
.choice { display: block; border-bottom: 1px solid var(--rule); }
.choice:first-of-type { border-top: 1px solid var(--rule); }
.choice label {
  display: flex; gap: 13px; align-items: baseline; cursor: pointer;
  padding: 15px 2px; font-family: var(--text); font-size: 17px;
  letter-spacing: 0; text-transform: none; color: var(--ink); margin: 0;
}
.choice input { margin-top: 5px; accent-color: var(--midnight); width: 17px; height: 17px; flex: none; }
.choice:has(input:focus-visible) { outline: 2px solid var(--midnight); outline-offset: 2px; }

.form-step[hidden] { display: none; }

/* 8. ARTICLE -------------------------------------------------------------- */
.article { max-width: 720px; }
.article > * + * { margin-top: 1.15em; }
.article h2 { margin-top: 1.9em; }
.article h3 { margin-top: 1.5em; }
.article p, .article li { font-size: 17.5px; line-height: 1.8; color: var(--ink-soft); max-width: none; }
.article ul, .article ol { padding-left: 1.2em; }
/* Numerals are right-aligned in their gutter so the full stops line up and the
   text starts on one edge, which is what a set numeral column should do. */
.article ol { padding-left: 2.4em; }
.article ol > li { padding-left: .15em; }
.article ol > li::marker { font-variant-numeric: tabular-nums; }
.article li + li { margin-top: .5em; }
.article blockquote {
  border-left: 2px solid var(--rosy); padding-left: 22px; font-size: 19px;
  font-style: italic; color: var(--ink);
}
.article figure { margin-block: 2em; }

.article figcaption { font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--oxblood); margin-top: 10px; }
/* A documentary photograph, not a specimen plate. The portrait is held well
   short of the column so it does not swallow the page, and its caption is a
   sentence rather than a label, so it drops the caps and the tracking. */
.figure--photo img { max-width: 260px; border-radius: 2px; }
/* The lede runs the full page width: the news box spans it, and the opening
   text and the photograph sit side by side beneath. The body below keeps the
   720px reading measure, so only the top of the article widens. */
@media (min-width: 820px) {
  .lede__row { display: grid; grid-template-columns: minmax(0, 1fr) 260px;
    gap: 40px; align-items: start; }
  .figure--photo--lede { margin: 26px 0 0; }
  /* the figure is the last thing in its cell, so its usual bottom margin is
     only dead space, and the heading that follows the lede does not need the
     full section gap on top of it */
  .article__lede .figure--photo--lede { margin-bottom: 0; }
  .article__lede + h2 { margin-top: 1.05em; }
  .lede__text > * + * { margin-top: 1.15em; }
}
@media (min-width: 1000px) {
  .article:has(.article__lede) { max-width: none; }
  .article:has(.article__lede) > :not(.article__lede) { max-width: 720px; }
  .lede__row { grid-template-columns: minmax(0, 820px) 300px;
    justify-content: space-between; }
  .figure--photo--lede img { max-width: 250px; }
  /* the caption runs a little wider than the photo so the extra words do not
     cost it two more lines and unbalance the columns */
  .figure--photo--lede figcaption { max-width: 300px; }
}
.figure--photo figcaption { text-transform: none; letter-spacing: .01em; font-size: 12.5px;
  line-height: 1.55; max-width: 340px; }
.byline { font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--oxblood); }

.breadcrumb { font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--oxblood); margin-bottom: 26px; }
.breadcrumb a { color: var(--oxblood); text-decoration: none; }
.breadcrumb a:hover { text-decoration: underline; }

/* 9. A11Y ----------------------------------------------------------------- */
:focus-visible { outline: 2px solid var(--midnight); outline-offset: 3px; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap;
}

/* mobile nav (progressive — the <details> works with JS disabled) */
.mnav { display: block; }

/* 10. SPECIMEN ------------------------------------------------------------
   The convention for every illustration on the main page. The artwork is a
   watercolour plate with a real alpha channel, so it sits straight on the
   ground with no keying and no blend mode.

   It fades up over a couple of seconds when it is scrolled to, and then it
   is still. The movement that used to live here (a sway, and the displaced
   canvas in assets/js/living.js) is switched off: living.js is no longer
   loaded by the page. Both are kept because the work is sound and the
   decision was "not yet", not "never". */
.specimen {
  position: relative;
  display: block;
  margin: 0;
  --fade: 2.2s;
}
.specimen img {
  display: block;
  width: 100%;
  height: auto;
  opacity: 0;
  transition: opacity var(--fade) ease-out;
}
.specimen.is-in img { opacity: 1; }

.specimen figcaption {
  margin-top: 16px;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--oxblood);
}

@media (prefers-reduced-motion: reduce) {
  .specimen img { opacity: 1; transition: none; }
}

/* No JS: nothing is ever told to arrive, so arrive by default. */
.no-js .specimen img { opacity: 1; }

/* 11. MESSAGES FROM THE FUTURE -------------------------------------------
   A notice strip across the very top, above the menu, carrying one imagined
   message at a time. It used to sit at the foot of the window, where it
   collided with anything else that wanted the bottom of the screen.

   The torn lower edge is a mask, so the page shows through the rip rather
   than the rip being painted on. Two masks are composited: a soft ragged
   gradient for the tear, and nothing else, because a second hard edge made
   it read as a sawtooth rather than as paper.

   Its height is in --chrome with the header, because every full-screen
   section on the front page is sized off that. */
.strip {
  /* A row of the header, not a bar of its own. Every version where these
     were two elements showed a join between them, whatever was done about
     tone or overlap, because two stacked translucent layers never match one.
     As one element there is nothing to line up. */
  color: var(--ink);
  background: rgba(246,234,210,.58);
  backdrop-filter: blur(14px) saturate(1.05);
  -webkit-backdrop-filter: blur(14px) saturate(1.05);
  /* backdrop-filter opens a stacking context, which traps anything this row
     opens inside it. Without these the disclaimer is painted over by the menu
     row, because that row comes later in the document. */
  position: relative; z-index: 2;
}

.strip__in {
  /* centred as a pair. The "i" is a utility, so it stays out at the edge
     rather than shifting the message off centre. */
  position: relative;
  z-index: 1;
  display: flex; align-items: center; gap: 10px;
  min-height: var(--strip-h);
  /* The "i" is positioned out of flow, so the row reserves its width here or
     the message simply runs underneath it. This has to hold at every width:
     it was previously only reserved below 560px, and at 560 exactly the
     message overlapped the "i" by 15px. */
  padding-right: calc(var(--gut) + 30px);
  /* --nav-x is set by site.js to the left edge of the first menu item, so
     "Messages from" starts exactly where "Home" does. Until it is known, and
     on any width where the menu is a hamburger, it falls back to 0 and the
     message aligns with the wordmark instead, which is what we want there. */
  padding-left: var(--nav-x, var(--gut));
}
.strip__label {
  flex: none;
  font-family: var(--mono); font-size: clamp(10px, 1.45vw, 12px); letter-spacing: .16em;
  text-transform: uppercase; color: var(--oxblood);
  max-width: none;
}
.strip__line {
  flex: 1 1 auto; min-width: 0;
  flex: 0 1 auto;
  font-family: var(--mono); font-size: clamp(9.5px, 1.5vw, 12.5px); letter-spacing: .02em;
  color: var(--ink); margin: 0; max-width: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.ticker__caret {
  display: inline-block; width: .52em; height: 1em;
  margin-left: 1px; vertical-align: -.14em;
  background: var(--ink-soft);
  animation: ticker-blink 1.06s steps(1) infinite;
}
.strip.is-typing .ticker__caret { animation: none; opacity: 1; }
@keyframes ticker-blink { 0%, 49% { opacity: 1 } 50%, 100% { opacity: 0 } }

/* the disclaimer. It is the legal cover, so it is always within reach of
   the messages rather than somewhere else on the page. */
.strip__note {
  /* absolute children sit against the padding box, so this needs the gutter
     back to line up with the right edge of the button below it */
  position: absolute; right: var(--gut); top: 50%; transform: translateY(-50%);
}
.strip__note > summary {
  list-style: none; cursor: pointer;
  width: 15px; height: 15px; border-radius: 50%;
  border: 1px solid var(--oxblood); color: var(--oxblood);
  font-family: var(--mono); font-size: 9px; line-height: 13px;
  text-align: center;
  transition: background .16s ease, color .16s ease;
}
.strip__note > summary::-webkit-details-marker { display: none; }
.strip__note > summary:hover,
.strip__note[open] > summary { background: var(--oxblood); color: var(--beige); }
.strip__note-body {
  position: absolute; top: calc(100% + 10px); right: 0;
  width: min(344px, 86vw); z-index: 50;
  background: var(--win2-bg); color: #4B0500;
  padding: 15px 17px; border-radius: 3px;
  font-family: var(--text); font-size: 13.5px; line-height: 1.55;
  box-shadow: 0 12px 38px rgba(75,5,0,.34);
}
.strip__note-body p { max-width: none; }
.strip__note-body p + p { margin-top: .7em; }
.strip__note-body a { color: #4B0500; text-underline-offset: 3px; }

@media (max-width: 559px) {
  /* on one line there is not room for both, and the message is the point */
  /* with the label gone there is room to read, so the message holds its size
     longer than the shared clamp would give it */
  .strip__line { font-size: clamp(10px, 2.85vw, 12px); }
}

/* Below 600px the label and the message will not sit side by side without the
   message clipping, so the row becomes two: the label, then the message under
   it. Both start at the page gutter, which is where the wordmark starts, so
   the strip reads as the same column as everything below it. The strip's own
   height grows to match, and --chrome follows it, because the header height
   is what the hero, the anchors and the frost band are all measured from. */
@media (max-width: 599px) {
  :root { --strip-h: 54px; }
  .strip__in {
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;
    gap: 1px;
    padding-block: 6px;
  }
  .strip__label { font-size: clamp(9.5px, 2.5vw, 11px); }
  .strip__line { font-size: clamp(10px, 2.85vw, 12px); }
}
@media (prefers-reduced-motion: reduce) {
  .ticker__caret { animation: none; }
}

/* 12. THE CHOOSER ---------------------------------------------------------
   The living legacy question, step one of the supporter journey. Radio
   buttons wearing the plates: the native input stays in the DOM so the
   keyboard, the screen reader and the form all behave, and it is hidden
   visually only. */
.choose {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(132px, 1fr));
  gap: clamp(10px, 2vw, 18px);
  margin: 0;
  padding: 0;
}

.choose__opt {
  display: block;
  position: relative;
  cursor: pointer;
  padding: 10px 10px 12px;
  border: 1px solid var(--rule-soft);
  background: rgba(255, 252, 244, .5);
  transition: border-color .25s, background-color .25s, box-shadow .25s;
}
.choose__opt img {
  display: block;
  width: 100%;
  height: 94px;
  object-fit: contain;
  object-position: bottom center;
}
.choose__opt span {
  display: block;
  margin-top: 10px;
  /* two lines reserved, so a wrapped label never shortens its neighbours */
  min-height: 2.8em;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.4;
  color: var(--ink-soft);
}

/* The input is still there; it is just not what you look at. */
.choose__opt input {
  position: absolute;
  width: 1px; height: 1px;
  opacity: 0;
  margin: 0;
}

.choose__opt:hover { border-color: var(--rule); background: rgba(255, 252, 244, .9); }
.choose__opt:has(input:checked) {
  border-color: var(--forest);
  background: rgba(255, 252, 244, 1);
  box-shadow: 0 0 0 1px var(--forest);
}
.choose__opt:has(input:checked) span { color: var(--forest); }
/* keyboard focus has to be visible even though the input is not */
.choose__opt:has(input:focus-visible) { outline: 2px solid var(--midnight); outline-offset: 3px; }

/* ----- the two plain options, and the write-in ------------------------- */
.choose__other {
  margin-top: clamp(16px, 2.4vw, 24px);
  display: flex;
  align-items: center;
  gap: 12px 16px;
  flex-wrap: wrap;
}
.choose__opt--plain {
  padding: 11px 16px;
  display: inline-block;
}
.choose__opt--plain span { margin-top: 0; min-height: 0; }

.choose__write {
  flex: 1 1 260px;
  min-width: 0;
  font-family: var(--mono);
  font-size: 13px;
  padding: 11px 14px;
  border: 1px solid var(--rule);
  background: rgba(255, 252, 244, .7);
  color: var(--ink);
}
.choose__write:disabled { opacity: .4; cursor: not-allowed; }
.choose__write::placeholder { color: var(--ink-soft); opacity: .6; }

/* "optional" next to a field label */
.opt {
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin-left: .6em;
}

/* the journey never needs the full 1320: a form reads badly wide */
.form-wrap { max-width: 1040px; }

/* a heading focused by the step change should not draw a box */
.form-step h1:focus { outline: none; }

/* selects, same furniture as the text inputs */
.field select {
  width: 100%;
  max-width: 320px;
  font-family: var(--text);
  font-size: 16px;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  background: rgba(255, 252, 244, .7);
  color: var(--ink);
  border-radius: 0;
}
.field select:focus-visible { outline: 2px solid var(--midnight); outline-offset: 2px; }
.field legend {
  display: block;
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .18em; text-transform: uppercase;
  color: var(--oxblood); margin-bottom: 12px;
}


/* a select with its opt-out beside it rather than buried in the options */
/* The control takes the full column and the opt-out sits under it, so the two
   fields in a pair line up whether the control is a select or a text box. */
.with-optout { display: flex; flex-direction: column; align-items: flex-start; gap: 12px; }
.with-optout > select,
.with-optout > input[type="text"] { width: 100%; max-width: none; }
.optout {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--mono); font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink-soft); cursor: pointer;
  margin: 0;
}
.optout input { margin: 0; }

.field textarea {
  width: 100%; max-width: 560px;
  font-family: var(--text); font-size: 16px; line-height: 1.6;
  padding: 12px 14px;
  border: 1px solid var(--rule);
  background: rgba(255, 252, 244, .7);
  color: var(--ink);
  resize: vertical;
}
.field textarea:focus-visible { outline: 2px solid var(--midnight); outline-offset: 2px; }

/* 13. THE JOURNEY --------------------------------------------------------
   One question per screen. The question is the only thing on the page, it
   arrives from below, and the keyboard can do all of it. */
.tf { position: relative; padding-block: clamp(26px, 5vh, 56px) clamp(40px, 8vh, 90px); }

.tf__stage { position: relative; }

.q {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: calc(100svh - var(--chrome) - 150px);
}
.q[hidden] { display: none; }

/* The full-screen minimum gives each question its centred stage. The closing
   screen is short and has no next step, so holding it to a full screen just
   leaves a hole under the box. */
.q#q-done { min-height: 0; justify-content: flex-start; }
/* and the stage's own bottom padding goes with it, so the closing screen sits
   the same distance off the footer as every other page does */
.tf:has(#q-done.is-live) { padding-bottom: 0; }

.q.is-live { animation: q-in .44s cubic-bezier(.22, .68, .3, 1) both; }
/* the one leaving holds its place for a beat so the page does not collapse */
.q.is-leaving {
  position: absolute;
  inset: 0;
  animation: q-out .22s ease-in both;
  pointer-events: none;
}
@keyframes q-in  { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
@keyframes q-out { from { opacity: 1; } to { opacity: 0; transform: translateY(-16px); } }

.q__eyebrow {
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .2em; text-transform: uppercase;
  color: var(--oxblood); margin: 0 0 16px; max-width: none;
}
.q__ask {
  font-family: var(--disp); font-weight: 400;
  font-size: clamp(27px, 3.6vw, 44px);
  line-height: 1.1; letter-spacing: -.01em;
  color: var(--ink); margin: 0; max-width: 18ch;
}
.q__ask:focus { outline: none; }
.q__note { margin-top: 16px; max-width: 42em; color: var(--ink-soft); font-size: 17px; }
.q__body { margin-top: clamp(24px, 4vh, 40px); }

.q__err {
  margin-top: 18px; color: var(--oxblood);
  font-family: var(--mono); font-size: 12px; letter-spacing: .04em;
}

.q__go { margin-top: clamp(26px, 4vh, 40px); display: flex; align-items: center; gap: 18px; flex-wrap: wrap; }
.q__kbd { font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
          text-transform: uppercase; color: var(--ink-soft); }

/* the big single answer: a question with one box deserves a big box */
.q__input {
  font-size: clamp(18px, 2.2vw, 24px) !important;
  padding: 14px 16px !important;
}

.tf__back {
  position: absolute; top: 0; left: var(--gut);
  appearance: none; border: 0; background: none; padding: 6px 0;
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-soft); cursor: pointer;
}
.tf__back:hover { color: var(--oxblood); }

/* the letter beside an option, the way a keyboard-first form marks them */
kbd {
  display: inline-grid; place-items: center;
  min-width: 20px; height: 20px; padding: 0 5px;
  border: 1px solid var(--rule);
  font-family: var(--mono); font-size: 10px; line-height: 1;
  color: var(--ink-soft); background: rgba(255, 252, 244, .7);
  vertical-align: 1px;
}
.choice kbd { margin-right: 10px; }
/* over the picture on a plate, inline on the plain ones that have none */
.choose__opt kbd { position: absolute; top: 8px; left: 8px; z-index: 1; }
.choose__opt--plain { display: inline-flex; align-items: center; gap: 9px; }
.choose__opt--plain kbd { position: static; }
.choose__opt:has(input:checked) kbd { border-color: var(--forest); color: var(--forest); }
.q__kbd kbd { min-width: 18px; height: 18px; }

@media (prefers-reduced-motion: reduce) {
  .q.is-live, .q.is-leaving { animation: none; }
}

/* 14. THE PROCESS --------------------------------------------------------
   Five steps, each a plate beside its sentence, alternating sides so the eye
   is pulled down the page rather than down one column. */
.steps { list-style: none; margin: clamp(10px, 1.6vh, 20px) 0 0; padding: 0; }
.step {
  display: grid;
  gap: clamp(16px, 3vw, 44px);
  align-items: center;
  padding-block: clamp(22px, 3.5vh, 40px);
}
.step + .step { border-top: 1px solid var(--rule-soft); }
.step:first-child { padding-top: 0; }
/* On a phone the label and the sentence come first, then the plate: a reader
   scrolling past an unlabelled illustration has no idea which step it is. */
.step__say { order: -1; }
@media (min-width: 760px) {
  .step { grid-template-columns: 1fr 1fr; }
  .step__say { order: 0; }
  .step:nth-child(even) .step__art { order: 2; }
}
.step__art { margin: 0; }
.step__art img { width: 100%; height: auto; }
.step__n {
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--oxblood); margin-bottom: 12px;
}
.step__say p:not(.step__n) { font-size: 17px; line-height: 1.7; color: var(--ink-soft); }

/* the two questions that started it */
.asks { margin: 22px 0 0; padding-left: 0; list-style: none; counter-reset: ask; }
.asks li {
  counter-increment: ask;
  position: relative;
  padding-left: 42px;
  margin-top: 16px;
  font-family: var(--mono);
  font-size: clamp(13px, 1.4vw, 15px);
  line-height: 1.75;
  letter-spacing: .01em;
  color: var(--forest);
  max-width: 44em;
}
.asks li::before {
  content: counter(ask);
  position: absolute; left: 0; top: .15em;
  font-family: var(--mono); font-size: 11px;
  letter-spacing: .1em; color: var(--oxblood);
  border: 1px solid var(--rule); border-radius: 50%;
  width: 24px; height: 24px; display: grid; place-items: center;
}

/* a card's standfirst: the theme before the answer */
.card__was {
  font-family: var(--text); font-style: italic;
  font-size: 16px; line-height: 1.5;
  color: var(--midnight); margin: 10px 0 12px;
}

.pull {
  font-family: var(--disp); font-style: italic;
  font-size: clamp(22px, 2.6vw, 32px);
  line-height: 1.3; color: var(--midnight);
  max-width: 22ch;
}

/* A question used as a heading. It keeps h2's place in the outline, because
   the hierarchy has to stay h1 then h2, but wears the typewriter so it reads
   as a label rather than a headline. Question-shaped headings are also what
   a search engine and an assistant lift answers from. */
.ask {
  font-family: var(--mono);
  font-weight: 400;
  font-size: clamp(12px, 1.35vw, 14px);
  letter-spacing: .18em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--oxblood);
  margin-top: clamp(32px, 4.5vh, 52px);
  margin-bottom: 14px;
}
.ask:first-of-type { margin-top: clamp(26px, 3.5vh, 40px); }
.ask--on-dark { color: var(--win2-bg); margin-top: 0; }

/* the dark green window, for the legal and status blocks */
/* The blocks are the light green with burgundy type; the button inside them
   is the clay, which is the one place that colour appears as a surface. */
.window--forest { background: #C5B48B; color: #4B0500; }
.window--forest .ask--on-dark { color: #4B0500; }
.window--forest .btn {
  background: #4B0500; color: #F0E4CD; border-color: #4B0500;
}
.window--forest a:not(.btn) { color: #4B0500; text-underline-offset: 3px; }

/* ==========================================================================
   The legal map
   --------------------------------------------------------------------------
   Equirectangular, so a pin's lat/long becomes its x/y with one
   multiplication and the pins cannot drift off the coastline. The map zooms
   by moving the viewBox; pins carry a counter-scale so they stay the same
   size on screen at every zoom, which is the only way the crowded US
   north-east separates without the pins becoming enormous at world view.

   Amber is not in the palette. It is here because a pending jurisdiction has
   to read as neither yes nor no, and nothing in the warm range does that.
   It is used for this map only.
   ========================================================================== */
:root {
  --pin-legal: #4B0500;
  --pin-pending: #7C3230;
  --map-land: #BBA47B;
  --map-edge: #98824C;
  --map-sea: #EDE1CA;
}

/* the hero: the map sits beside the answer rather than below it, so the
   first thing on the page is the thing the page is about */
.legalhero { display: grid; gap: 34px; align-items: center; }
.legalhero__say .standfirst { max-width: 34em; }

@media (min-width: 900px) {
  .legalhero {
    grid-template-columns: minmax(0, 0.8fr) minmax(0, 1fr);
    gap: clamp(34px, 4vw, 64px);
  }
  /* in a column the map is narrower, so it must not also get short */
  .legalhero__map .map__frame { min-height: 290px; }
}

.map {
  position: relative;
  margin-top: 22px;
  background: var(--map-sea);
  border: 1px solid var(--map-edge);
  border-radius: 2px;
  overflow: hidden;
}
.map__frame { display: block; width: 100%; height: auto; touch-action: pan-y; }
.map__land { fill: var(--map-land); stroke: var(--map-edge); stroke-width: .6; }
.map__sea { fill: var(--map-sea); }

/* the viewBox is animated by script, so the transition lives on the group */
.map__g { transition: transform .62s cubic-bezier(.33,.72,.26,1); }

.map__pin { cursor: pointer; }
.map__pin circle { transition: r .16s ease; }
.map__pin .pin__dot { fill: var(--pin-legal); stroke: var(--beige); stroke-width: 1.4; }
.map__pin .pin__halo { fill: var(--pin-legal); opacity: 0; transition: opacity .18s ease; }
.map__pin[data-status="pending"] .pin__dot { fill: var(--pin-pending); stroke: var(--oxblood); }
.map__pin[data-status="pending"] .pin__halo { fill: var(--pin-pending); }
.map__pin:hover .pin__halo,
.map__pin.is-lit .pin__halo { opacity: .22; }
.map__pin:hover .pin__dot,
.map__pin.is-lit .pin__dot { r: 7.5; }
.map__pin:focus { outline: none; }
.map__pin:focus-visible .pin__halo { opacity: .3; }
.map__pin:focus-visible .pin__ring { stroke: var(--ink); stroke-width: 1.6; fill: none; }

/* pending pins pulse once a view settles, so "not yet" is legible at a glance */
@media (prefers-reduced-motion: no-preference) {
  .map__pin[data-status="pending"] .pin__pulse {
    fill: none; stroke: var(--pin-pending); stroke-width: 1.5;
    animation: pin-pulse 2.6s ease-out infinite;
  }
}
@keyframes pin-pulse {
  0%   { r: 5; opacity: .75; }
  70%  { r: 16; opacity: 0; }
  100% { r: 16; opacity: 0; }
}

/* ---- the zoom controls ---- */
.map__views {
  display: flex; flex-wrap: wrap; gap: 7px;
  margin-top: 26px;
}
.map__view {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--oxblood);
  background: transparent; border: 1px solid var(--map-edge);
  padding: 9px 16px; border-radius: 999px; cursor: pointer;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.map__view:hover { border-color: var(--forest); color: var(--forest); }
.map__view[aria-pressed="true"] {
  background: var(--forest); border-color: var(--forest); color: var(--beige);
}

/* ---- the tooltip ---- */
/* HTML rather than SVG text, so the label does not scale with the map */
.map__tip {
  /* left/top are set in pixels by script, already clamped inside the frame,
     so there is no centring transform to push the card back over an edge */
  position: absolute; z-index: 3; left: 0; top: 0;
  --arrow-x: 50%;
  min-width: 130px;
  max-width: min(248px, calc(100% - 16px));
  padding: 11px 13px 12px;
  background: var(--beige);
  border: 1px solid var(--oxblood);
  border-radius: 2px;
  box-shadow: 0 6px 20px rgba(45,32,17,.17);
  opacity: 0; visibility: hidden;
  transition: opacity .15s ease, visibility .15s ease;
  pointer-events: none;
}
.map__tip.is-on { opacity: 1; visibility: visible; }
.map__tip::after {
  content: ""; position: absolute; left: var(--arrow-x); bottom: -5px;
  width: 8px; height: 8px; margin-left: -4px;
  background: var(--beige);
  border-right: 1px solid var(--oxblood); border-bottom: 1px solid var(--oxblood);
  transform: rotate(45deg);
}
/* the pin is off-frame, so there is nothing for an arrow to point at */
.map__tip.is-off::after { display: none; }

/* flipped under the pin, so the arrow moves to the top edge */
.map__tip.is-below::after {
  bottom: auto; top: -5px;
  border: 0;
  border-left: 1px solid var(--oxblood); border-top: 1px solid var(--oxblood);
}
.map__tip-name {
  font-family: var(--disp); font-size: 20px; line-height: 1.12; color: var(--ink);
}
.map__tip-meta {
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; margin-top: 7px; color: var(--forest);
}
.map__tip[data-status="pending"] .map__tip-meta { color: var(--brick); }
.map__tip-note {
  font-family: var(--text); font-size: 13.5px; line-height: 1.46;
  margin-top: 8px; color: var(--ink-soft);
}

/* ---- the roll of jurisdictions ---- */
.roll { margin-top: 44px; }
.roll__group + .roll__group { margin-top: 34px; }
.roll__head {
  display: flex; align-items: baseline; gap: 10px;
  padding-bottom: 9px; border-bottom: 1px solid var(--oat);
}
.roll__head h2, .roll__head h3 { color: var(--oxblood); }
.roll__count {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em;
  color: var(--ink-soft); margin-left: auto;
}
.roll__list {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: 1px;
  grid-template-columns: repeat(auto-fill, minmax(238px, 1fr));
}
.roll__row {
  display: flex; align-items: baseline; gap: 9px;
  width: 100%; text-align: left;
  font-family: var(--text); font-size: 15px; color: var(--ink);
  background: transparent; border: 0; border-bottom: 1px solid transparent;
  padding: 9px 6px; cursor: pointer;
  transition: background .14s ease;
}
.roll__row:hover, .roll__row.is-lit { background: var(--oat); }
.roll__row::before {
  content: ""; flex: 0 0 auto;
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--pin-legal); transform: translateY(-1px);
}
.roll__row[data-status="pending"]::before { background: var(--pin-pending); }
.roll__yr {
  margin-left: auto; font-family: var(--mono); font-size: 11px;
  color: var(--ink-soft); letter-spacing: .04em;
}
.roll__note {
  display: block; width: 100%;
  font-family: var(--text); font-style: italic; font-size: 13px;
  color: var(--ink-soft); padding: 0 6px 0 23px; margin-top: -2px;
}

@media (max-width: 559px) {
  /* The frame is only about 150px tall on a phone, so a full-width card hid
     the map it was describing. Smaller type and a narrower card leave the
     pins visible behind it. */
  /* At a phone's width the frame is only about 150px tall, which is less
     than the tallest card. The sea rect runs well past the viewBox, so an
     explicit height just extends the water and leaves the card somewhere
     to sit without shrinking the map. */
  .map__frame { height: 218px; }
  .map__tip {
    max-width: min(196px, calc(100% - 16px));
    padding: 9px 11px 10px;
  }
  .map__tip-name { font-size: 17px; }
  .map__tip-meta { font-size: 9px; margin-top: 5px; }
  .map__tip-note { font-size: 12px; line-height: 1.4; margin-top: 6px; }
  .roll__list { grid-template-columns: 1fr; }
}

/* ==========================================================================
   The FAQ page
   --------------------------------------------------------------------------
   An accordion, because 25 answers is not a page anybody scrolls. Google
   retired FAQ rich results in May 2026 and gives collapsed content full
   ranking weight under mobile-only crawling, so there is no longer a reason
   to keep it all open. <details> keeps every answer in the initial HTML and
   works with scripting off; the search and the open-all are enhancements.
   ========================================================================== */
.faqtools {
  display: flex; flex-wrap: wrap; gap: 14px; align-items: center;
  margin-top: 4px;
}
.faqfind { flex: 1 1 260px; min-width: 0; position: relative; }
.faqfind__in {
  width: 100%; box-sizing: border-box;
  font-family: var(--mono); font-size: 13px; letter-spacing: .04em; color: var(--ink);
  background: transparent;
  border: 1px solid var(--oat); border-radius: 999px;
  padding: 12px 18px;
  transition: border-color .16s ease;
}
.faqfind__in:focus { outline: none; border-color: var(--forest); }
.faqfind__in::placeholder { color: var(--ink-soft); opacity: .62; }
.faqfind__n {
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft);
  margin-top: 8px; min-height: 13px;
}
.faqall {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--oxblood);
  background: transparent; border: 1px solid var(--oat); border-radius: 999px;
  padding: 12px 20px; cursor: pointer; align-self: flex-start;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.faqall:hover { background: var(--forest); border-color: var(--forest); color: var(--beige); }

.faqjump { margin-top: 26px; }
.faqjump__row { display: flex; flex-wrap: wrap; gap: 7px; }
.faqjump__a {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--midnight); text-decoration: none;
  border: 1px solid var(--oat); border-radius: 999px; padding: 8px 14px;
  transition: background .16s ease, color .16s ease, border-color .16s ease;
}
.faqjump__a:hover { background: var(--forest); border-color: var(--forest); color: var(--beige); }

.faqgrid { margin-top: 34px; }
.faqside { display: none; }
.faqsec + .faqsec { margin-top: 44px; }
.faqsec, .qa { scroll-margin-top: calc(var(--chrome) + 18px); }
/* The section name is the only real heading between the h1 and the
   questions, so it is set in the display face. The questions keep the
   typewriter, which is the convention across the site for a subhead. */
.faqsec__h {
  font-family: var(--disp);
  font-size: clamp(23px, 2.5vw, 29px);
  letter-spacing: normal;
  text-transform: none;
  line-height: 1.14;
  color: #4B0500;
  margin-bottom: 18px;
}

/* ---- one question ---- */
.qalist { border-top: 1px solid var(--oat); }
.qa { border-bottom: 1px solid var(--oat); }
.qa__sum {
  display: flex; align-items: flex-start; gap: 16px;
  padding: 19px 2px; cursor: pointer;
  list-style: none;
  transition: color .16s ease;
}
.qa__sum::-webkit-details-marker { display: none; }
.qa__sum:hover .ask { color: var(--forest); }
.qa__sum:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.qa__sum .ask { flex: 1 1 auto; margin: 0; }

/* the marker is drawn rather than typed, so it can rotate */
.qa__sum::after {
  content: ""; flex: 0 0 auto;
  width: 11px; height: 11px; margin-top: 3px;
  border-right: 1.5px solid var(--oxblood);
  border-bottom: 1.5px solid var(--oxblood);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .22s ease;
}
.qa[open] > .qa__sum::after { transform: rotate(-135deg) translate(-2px, -2px); }
.qa[open] > .qa__sum .ask { color: var(--forest); }

.qa__a { padding: 0 2px 26px; max-width: 42em; }
.qa__a p + p { margin-top: 14px; }

@media (prefers-reduced-motion: no-preference) {
  .qa[open] > .qa__a { animation: qa-in .26s ease both; }
}
@keyframes qa-in {
  from { opacity: 0; transform: translateY(-5px); }
  to   { opacity: 1; transform: none; }
}

.faqnone { margin-top: 30px; font-family: var(--text); color: var(--ink-soft); }
.faqnone__more { margin-top: 18px; max-width: 60ch; }
.faqnone__clear {
  font: inherit; color: var(--midnight); background: none; border: 0;
  padding: 0; cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}
.qa[hidden], .faqsec[hidden] { display: none; }

@media (min-width: 1040px) {
  .faqjump { display: none; }
  .faqgrid {
    display: grid; grid-template-columns: minmax(0, 1fr) 216px;
    gap: clamp(40px, 5vw, 86px); align-items: start;
  }
  .faqbody { grid-column: 1; grid-row: 1; min-width: 0; }
  .faqside {
    display: block; grid-column: 2; grid-row: 1;
    position: sticky; top: calc(var(--head-h) + 26px);
  }
  .faqside__lab {
    font-family: var(--mono); font-size: 10px; letter-spacing: .18em;
    text-transform: uppercase; color: var(--oxblood);
    padding-bottom: 10px; border-bottom: 1px solid var(--oat);
  }
  .faqside__list { list-style: none; margin: 14px 0 0; padding: 0; counter-reset: s; }
  .faqside__list li { counter-increment: s; }
  .faqside__list a {
    display: flex; gap: 10px;
    font-family: var(--text); font-size: 14px; line-height: 1.3;
    color: var(--ink-soft); text-decoration: none;
    padding: 8px 0 8px 12px;
    border-left: 2px solid transparent;
    transition: color .16s ease, border-color .16s ease;
  }
  .faqside__list a::before {
    content: counter(s, upper-roman);
    font-family: var(--mono); font-size: 9.5px; color: var(--ink-soft);
    opacity: .55; min-width: 27px; padding-top: 3px; white-space: nowrap;
  }
  .faqside__list a:hover { color: var(--forest); }
  .faqside__list a.is-here { color: var(--forest); border-left-color: var(--forest); }
  .faqside__list a.is-here::before { color: var(--forest); opacity: 1; }
}

@media (max-width: 559px) {
  .faqall { width: 100%; text-align: center; }
}




/* ==========================================================================
   A video, without handing the visitor to YouTube on arrival
   --------------------------------------------------------------------------
   The poster is served from here and the player is only fetched when someone
   presses play. An ordinary embed would contact Google and set cookies on
   every page view, which is not what the privacy page says we do.
   ========================================================================== */
.ytlite { position: relative; }
.ytlite__btn {
  display: block; width: 100%; padding: 0; margin: 0;
  border: 1px solid var(--rule); border-radius: 3px;
  background: var(--oat); cursor: pointer; overflow: hidden;
  position: relative; line-height: 0;
  transition: border-color .18s ease;
}
.ytlite__btn:hover { border-color: var(--forest); }
.ytlite__btn:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.ytlite__btn img { width: 100%; height: auto; display: block; }

.ytlite__play {
  position: absolute; left: 50%; top: 50%;
  width: 66px; height: 46px; margin: -23px 0 0 -33px;
  border-radius: 23px;
  background: rgba(45, 32, 17, .72);
  transition: background .18s ease, transform .18s ease;
}
.ytlite__play::after {
  content: ""; position: absolute; left: 26px; top: 14px;
  border-style: solid; border-width: 9px 0 9px 15px;
  border-color: transparent transparent transparent var(--beige);
}
.ytlite__btn:hover .ytlite__play { background: var(--forest); transform: scale(1.06); }

.ytlite iframe {
  display: block; width: 100%; aspect-ratio: 16 / 9; height: auto;
  border: 1px solid var(--rule); border-radius: 3px;
}
.ytlite figcaption {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .1em;
  text-transform: uppercase; color: var(--oxblood);
  margin-top: 12px; line-height: 1.6;
}
@media (prefers-reduced-motion: reduce) {
  .ytlite__btn:hover .ytlite__play { transform: none; }
}
/* ==========================================================================
   The consent banner
   --------------------------------------------------------------------------
   Accept and decline are the same control, the same size, the same colour.
   A banner that makes declining harder than accepting is not valid consent
   under the EU rules, and this site will be running ads into those markets.

   The messages bar is also fixed to the foot of the window, so it stands
   down while a choice is outstanding. One piece of furniture at a time, and
   a first-time visitor should not meet both at once.
   ========================================================================== */
/* The strip used to sit at the foot of the window, where it collided with
   the consent banner and had to stand down. It is at the top now, so both
   can be on screen at once. */

.cc {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 60;
  background: var(--beige);
  border-top: 1px solid var(--oxblood);
  box-shadow: 0 -10px 40px rgba(45, 32, 17, .16);
  padding: 18px 0 20px;
  animation: cc-up .34s cubic-bezier(.3,.8,.3,1) both;
}
@keyframes cc-up { from { transform: translateY(100%); } to { transform: none; } }
@media (prefers-reduced-motion: reduce) { .cc { animation: none; } }
.cc.is-gone { animation: cc-down .3s ease both; }
@keyframes cc-down { to { transform: translateY(100%); } }

.cc__in { display: grid; gap: 16px; }
@media (min-width: 860px) {
  .cc__in { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 34px; }
}
.cc__h {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .18em;
  text-transform: uppercase; color: var(--oxblood);
}
.cc__b {
  font-family: var(--text); font-size: 15px; line-height: 1.55;
  color: var(--ink); margin-top: 8px; max-width: 64ch;
}
.cc__b a { color: var(--midnight); text-underline-offset: 3px; }

.cc__acts { display: flex; flex-wrap: wrap; gap: 9px; align-items: center; }
.cc__btn {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; white-space: nowrap;
  color: var(--btn-fg); background: var(--btn-bg);
  border: 1px solid var(--btn-bg); border-radius: 999px;
  padding: 12px 22px; cursor: pointer;
  transition: opacity .16s ease;
}
.cc__btn:hover { opacity: .86; }
/* Accept and decline are the same control in every respect. A solid
   "accept" beside an outlined "reject" is the pattern the French and
   Italian regulators have repeatedly ruled invalid, so both are solid and
   a shared min-width keeps the differing label lengths from reading as a
   hierarchy. */
.cc__btn[data-cc="all"],
.cc__btn[data-cc="none"] { min-width: 168px; text-align: center; }
.cc__link {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft);
  background: none; border: 0; padding: 12px 6px; cursor: pointer;
  text-decoration: underline; text-underline-offset: 4px;
}
.cc__link:hover { color: var(--oxblood); }

.cc__panel { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--oat); }
.cc__opts { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 12px; }
@media (min-width: 860px) { .cc__opts { grid-template-columns: repeat(3, 1fr); gap: 20px; } }
.cc__opts label { display: flex; gap: 10px; align-items: flex-start; cursor: pointer; }
.cc__opts input { margin-top: 3px; flex: none; accent-color: var(--forest); }
.cc__opts span { font-family: var(--text); font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
.cc__opts b {
  display: block; font-family: var(--mono); font-size: 10px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--oxblood); font-weight: 400; margin-bottom: 4px;
}
.cc__opts input:disabled + span b { opacity: .6; }

@media (max-width: 559px) {
  .cc { padding: 15px 0 17px; max-height: 76svh; overflow-y: auto; }
  .cc__acts { gap: 8px; }
  .cc__btn { flex: 1 1 auto; text-align: center; padding: 12px 14px; }
}

/* ==========================================================================
   The catalogue picker
   --------------------------------------------------------------------------
   Replaces the single "next" arrow. Seven options you can see beats one you
   have to click seven times to find. Dimmed-until-chosen is the plainest
   affordance there is: the strip reads as a set of choices before anyone has
   to be told it is one.
   ========================================================================== */
.cat__hint {
  font-family: var(--mono); font-size: 10px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--oxblood);
  margin-top: clamp(10px, 2.2vh, 20px);
}
.cat__thumbs {
  display: flex; flex-wrap: wrap; gap: 9px;
  margin-top: clamp(7px, 1.4vh, 12px);
}
.cat__thumb {
  flex: 0 0 auto;
  width: 54px; height: 54px;
  padding: 0; border: 0; border-radius: 6px;
  background: var(--oat);
  cursor: pointer; overflow: hidden;
  position: relative;
  /* unchosen sits back: lighter, cooler, slightly smaller */
  opacity: .58;
  filter: saturate(.72);
  transform: scale(.95);
  transition: opacity .18s ease, filter .18s ease, transform .18s ease,
              box-shadow .18s ease;
}
.cat__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }

.cat__thumb:hover {
  opacity: .92; filter: saturate(.95); transform: scale(1);
}
.cat__thumb.is-on {
  opacity: 1; filter: none; transform: scale(1);
  /* the ring is drawn outside the image, so the picture is never cropped */
  box-shadow: 0 0 0 2px var(--beige), 0 0 0 4px var(--forest);
}
.cat__thumb:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--beige), 0 0 0 4px var(--ink);
}

@media (prefers-reduced-motion: reduce) {
  .cat__thumb, .cat__thumb:hover, .cat__thumb.is-on { transform: none; }
}

/* On a phone the strip scrolls rather than wrapping to three rows and
   pushing the plate off the screen. */
@media (max-width: 759px) {
  /* .cat__pick is a grid item, and a grid item defaults to min-width:auto,
     which means it refuses to shrink below its content. The thumbnail row is
     wider than the track, so the item grew, the grid grew, and the whole
     homepage scrolled sideways on a phone. */
  .cat__pick { min-width: 0; }
  .cat__thumbs {
    flex-wrap: nowrap;
    /* a flex item will not shrink below its content without this, so the row
       grew to the width of all seven thumbs and took the page with it rather
       than scrolling inside its own box */
    min-width: 0;
    max-width: 100%;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
    padding-block: 6px 8px;
    /* The bleed used to be a negative gutter margin, but this strip's parent is
       not the page wrap, so that pushed it past the viewport edge and gave the
       whole homepage a horizontal scroll on a phone. */
    scrollbar-width: none;
  }
  .cat__thumbs::-webkit-scrollbar { display: none; }
  .cat__thumb { scroll-snap-align: start; width: 56px; height: 56px; }
}

/* ==========================================================================
   A note from our founder
   --------------------------------------------------------------------------
   An envelope in the corner. The illustration already contains the card, the
   opening lines and "Read on", so there is no text to lay over it and the
   whole thing is one button. The note it opens is plain white paper: the
   ruled pad this replaced belonged to the bar at the foot of the window.
   ========================================================================== */
.env {
  position: fixed;
  /* Tucked into the corner so only part of it is on screen, as in the mock.
     Both offsets are a share of its own width, so the proportion that shows
     is the same on a phone as on a desktop. The card and "Read on" sit left
     of centre in the illustration, so a quarter can go off the right edge
     without losing any of the words. */
  /* on :root as --env-size too, so the page can reserve room for it */
  --env-w: var(--env-size);
  right: calc(var(--env-w) * -.26);
  bottom: calc(var(--env-w) * -.17);
  z-index: 35;
  width: var(--env-w);
  padding: 0; border: 0; background: none;
  cursor: pointer; line-height: 0;
  filter: drop-shadow(0 10px 22px rgba(45, 32, 17, .26));
  transition: transform .26s cubic-bezier(.3,.8,.3,1), filter .26s ease;
}
.env img { width: 100%; height: auto; display: block; }
/* on hover it comes further out of the corner rather than just lifting */
.env:hover, .env:focus-visible {
  transform: translate(-14px, -14px) rotate(-2deg);
  filter: drop-shadow(0 16px 30px rgba(45, 32, 17, .32));
}
.env:focus-visible { outline: 2px solid var(--ink); outline-offset: 6px; }

/* it does nothing without the dialog, so it is not offered */
html:not(.has-dialog) .env { display: none; }
/* one thing in the corner at a time */
html.has-cc .env { display: none; }

@media (prefers-reduced-motion: reduce) {
  .env, .env:hover, .env:focus-visible { transition: none; transform: none; }
}

/* ---- the note itself ---- */
.note {
  /* the global reset zeroes every margin, which also removes the auto
     margins a modal <dialog> centres itself with */
  margin: auto;
  border: 0; padding: 0; background: none;
  max-width: min(92vw, 568px);
  max-height: 86svh;
  overflow: visible;
  color: var(--ink);
}
.note::backdrop { background: rgba(45, 32, 17, .62); backdrop-filter: blur(3px); }

/* ---- the leave guard ----
   Same paper as the founder's note, but it asks a question, so the copy is
   set in the body face rather than the typewriter and the two answers sit
   side by side with the safe one leading. */
.leave { max-width: min(92vw, 430px); }
.leave .note__paper { padding: clamp(26px, 4vw, 34px); }
.leave__ask { font-family: var(--text); font-size: 16.5px; line-height: 1.65;
  letter-spacing: normal; color: var(--ink); }
.leave__do { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }
.leave__do .btn--ghost { color: #4B0500; border-color: #4B0500; }
.leave__do .btn--ghost:hover { background: #4B0500; color: var(--beige); }

.note__paper {
  position: relative;
  background: #FCFBF7;              /* paper, not cream: it is a letter */
  padding: clamp(30px, 5vw, 46px) clamp(26px, 5vw, 46px) clamp(32px, 5vw, 48px);
  max-height: 86svh;
  overflow-y: auto;
  border-radius: 2px;
  box-shadow: 0 24px 60px rgba(45, 32, 17, .34);
}
/* Typed, like a letter. Cutive Mono runs small and wide for its size, so it
   needs a touch more size and a lot more leading than the body face to stay
   comfortable over four paragraphs. */
.note__paper p {
  font-family: var(--mono);
  font-size: clamp(13px, 1.5vw, 14.5px);
  line-height: 1.95;
  letter-spacing: .005em;
  color: var(--ink);
  max-width: none;
}
.note__paper p + p { margin-top: 1.15em; }
.note__paper .note__eyebrow {
  font-family: var(--mono); font-size: 10.5px; letter-spacing: .2em;
  text-transform: uppercase; color: var(--oxblood);
  margin-bottom: 22px;
}
/* .note__paper p sets a size, and that selector out-specifies a bare class,
   so the signature has to match its weight to win */
.note__paper .note__sign {
  font-family: var(--hand);
  font-size: clamp(24px, 3vw, 30px);
  color: var(--brick);
  margin-top: 26px;
}
.note__close {
  position: absolute; top: 10px; right: 12px;
  appearance: none; border: 0; background: none;
  font-family: var(--mono); font-size: 20px; line-height: 1;
  color: var(--ink-soft); cursor: pointer; padding: 6px 8px;
}
.note__close:hover { color: var(--oxblood); }

/* ==========================================================================
   The mobile menu
   --------------------------------------------------------------------------
   A <details> rather than a scripted panel, so it opens and closes with no
   JavaScript at all. nav.js only adds what the element cannot do for itself:
   close on Escape, close on a tap outside, and stop the page behind it from
   scrolling.

   Rows are 52px. The guidance floor is 44, and a menu is the one place on a
   site where a mis-tap costs the most.
   ========================================================================== */
.mnav > summary {
  display: flex; align-items: center; gap: 8px;
  list-style: none; cursor: pointer;
  font-family: var(--mono); font-size: 12.5px;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft);
  /* a 44px target without a 44px-looking control */
  padding: 14px 4px; margin: -14px -4px;
}
.mnav > summary::-webkit-details-marker { display: none; }
.mnav > summary:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* three bars that become a cross */
.mnav__bars {
  position: relative; display: block;
  width: 17px; height: 2px; background: currentColor;
  transition: background .18s ease;
}
.mnav__bars::before, .mnav__bars::after {
  content: ""; position: absolute; left: 0;
  width: 17px; height: 2px; background: currentColor;
  transition: transform .22s cubic-bezier(.3,.8,.3,1);
}
.mnav__bars::before { top: -5px; }
.mnav__bars::after  { top: 5px; }
.mnav[open] .mnav__bars { background: transparent; }
.mnav[open] .mnav__bars::before { transform: translateY(5px) rotate(45deg); }
.mnav[open] .mnav__bars::after  { transform: translateY(-5px) rotate(-45deg); }

/* the sheet: from under the header to the foot of the window */
.mnav__panel {
  position: fixed;
  left: 0; right: 0;
  top: var(--chrome);
  bottom: 0;
  /* the same limewash as the page, so the sheet reads as the page rather
     than as a panel laid over it. Same gradient stack as the ground layer. */
  background:
    radial-gradient(56% 48% at 12%  8%, rgba(255,252,244,.88), transparent 72%),
    radial-gradient(48% 44% at 88% 16%, rgba(244,232,206,.34), transparent 70%),
    radial-gradient(56% 50% at 74% 74%, rgba(252,245,228,.50), transparent 72%),
    radial-gradient(52% 48% at  6% 82%, rgba(240,227,198,.28), transparent 72%),
    radial-gradient(44% 40% at 46% 42%, rgba(255,254,250,.62), transparent 74%),
    var(--beige);
  padding: 8px var(--gut) calc(24px + env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
  display: flex; flex-direction: column;
  animation: mnav-in .22s ease both;
}
@keyframes mnav-in { from { opacity: 0; transform: translateY(-6px); } }
@media (prefers-reduced-motion: reduce) {
  .mnav__panel { animation: none; }
  .mnav__bars::before, .mnav__bars::after { transition: none; }
}

.mnav__panel ul { list-style: none; margin: 0; padding: 0; }
.mnav__panel li + li { border-top: 1px solid var(--rule-soft); }
.mnav__panel a:not(.btn) {
  display: flex; align-items: center;
  min-height: 52px;
  font-family: var(--text); font-size: 19px;
  color: var(--ink); text-decoration: none;
}
.mnav__panel a[aria-current="page"] {
  color: var(--oxblood);
}
.mnav__panel a[aria-current="page"]::after {
  content: ""; width: 5px; height: 5px; border-radius: 50%;
  background: var(--oxblood); margin-left: 10px;
}

@media (min-width: 1000px) { .mnav { display: none; } }

/* ==========================================================================
   The Why page body
   --------------------------------------------------------------------------
   Prose on the left, the four themes on the right and level with the top of
   it, so the themes read as a column of evidence beside the argument rather
   than as a block underneath it. One column on a phone, in document order.
   ========================================================================== */
.whygrid { display: grid; gap: clamp(26px, 3vw, 46px); }
.whygrid__head { margin-bottom: clamp(20px, 2.4vw, 30px); }
/* laid out with margins rather than a grid gap: as a grid the gap applied
   between the intro line and the first chip as well as between the cards,
   so that one space could not be tuned on its own */
.whygrid__themes { display: block; }
.whygrid__themes .card + .card { margin-top: clamp(22px, 2.4vw, 30px); }
.whygrid__say > p:first-child { margin-top: 0; }

@media (min-width: 900px) {
  .whygrid {
    grid-template-columns: minmax(0, 1fr) minmax(0, .92fr);
    align-items: start;
    column-gap: clamp(34px, 4vw, 64px);
  }
  /* the headline runs the width of both, so each column's first line of body
     text begins on the same baseline */
  .whygrid__head { grid-column: 1 / -1; }
}

/* the four themes: a square chip carries the name, so it reads as a label
   rather than as something to press. It is a paragraph, not a button. */
/* `.card h3` sets text-transform: none and out-weighs a bare class, which is
   why these four read in mixed case while every other typed label on the site
   is capitalised. Matching its weight here. 12px, not 10.5px: capitals are
   harder to read than lowercase, not easier, so this one cannot sit under the
   floor the rest of the site keeps to. */
.card h2.theme__tag, .card h3.theme__tag {
  display: block;
  font-family: var(--mono); font-size: 12px;
  letter-spacing: .14em; text-transform: uppercase; line-height: 1.7;
  color: var(--btn-fg); background: var(--btn-bg);
  border: 1px solid var(--btn-edge); border-radius: 0;
  padding: 11px 14px; margin: 0 0 14px;
}
.whygrid__themes .card { border-top: 0; padding-top: 0; }
.whygrid__intro { margin: 0 0 clamp(13px, 1.5vw, 18px); }
.whygrid__more { margin-top: clamp(22px, 2.6vw, 34px); }

/* ==========================================================================
   Contact
   --------------------------------------------------------------------------
   One address, so it is the page rather than a line inside it. People arrive
   knowing what they want; the job is to hand it over and get out of the way.
   ========================================================================== */
.contact__mail {
  margin-top: clamp(24px, 3.4vw, 38px);
  font-family: var(--disp);
  font-size: clamp(27px, 4.6vw, 50px);
  line-height: 1.15;
  word-break: break-word;
}
.contact__mail a {
  color: var(--ink);
  text-decoration: none;
  border-bottom: 2px solid var(--btn-bg);
  padding-bottom: 2px;
  transition: border-color .18s ease, color .18s ease;
}
.contact__mail a:hover { color: var(--forest); border-bottom-color: var(--forest); }
.contact__note { margin-top: clamp(18px, 2.2vw, 26px); max-width: 46em; }

/* The header CTA shortens on a phone. The full wording is 17 characters and,
   at a legible size, it plus the wordmark and the menu no longer fit across
   a 390px screen. The accessible name stays the full phrase either way. */
.btn__short { display: none; }
/* The short "Join" is kept only for the very narrowest screens. Everywhere
   else the full phrase shows, because "Join" on its own does not say what the
   button does. The header row is tightened to make the room. */
@media (max-width: 299px) {
  .btn__long { display: none; }
  .btn__short { display: inline; }
}

/* ==========================================================================
   About
   --------------------------------------------------------------------------
   What we are on the left, who we are on the right, level with each other.
   ========================================================================== */
.aboutgrid { display: grid; gap: clamp(30px, 3.4vw, 52px); }
.aboutgrid__say > p:first-child { margin-top: 0; }
/* the opening statement carries the weight, not a larger size: the page keeps
   one body size throughout */
.aboutgrid__lead { font-weight: 600; }
.aboutgrid__teamhead { margin-bottom: clamp(18px, 2vw, 24px); }
.aboutgrid__team .card + .card { margin-top: clamp(26px, 3vw, 36px); }

@media (min-width: 900px) {
  .aboutgrid {
    grid-template-columns: minmax(0, 1fr) minmax(0, .88fr);
    align-items: start;
    column-gap: clamp(34px, 4vw, 64px);
    row-gap: 0;
  }
  /* "Our team" takes a row of its own in the right column, so the prose and
     the first name below it start on the same line rather than the prose
     starting level with the heading. */
  .aboutgrid__teamhead { grid-area: 1 / 2; margin: 0 0 clamp(18px, 2vw, 24px); }
  .aboutgrid__say      { grid-area: 2 / 1; padding-top: 17px; }   /* the card's border and padding, less the difference in half-leading */
  .aboutgrid__team     { grid-area: 2 / 2; }
}

/* the founder's line, typed rather than set in the display italic. No
   measure on it: it is one sentence and it is meant to hold one line. */
.pull--typed {
  font-family: var(--mono);
  font-style: normal;
  font-size: clamp(13px, 1.5vw, 17px);
  line-height: 1.75;
  letter-spacing: .02em;
  color: var(--forest);
  max-width: none;
}

/* The founder's story runs in two columns on a wide screen and stacks on a
   phone. The heading and the question span both: the question has to hold
   one line, and splitting it across a column would break the thought. */
.storygrid { display: grid; }
.storygrid__head { margin: 0; }
.storygrid__quote { margin: clamp(18px, 2vw, 24px) 0 clamp(20px, 2.4vw, 28px); }
.storygrid__b { margin-top: clamp(18px, 2vw, 24px); }

@media (min-width: 900px) {
  .storygrid {
    grid-template-columns: 1fr 1fr;
    column-gap: clamp(34px, 4vw, 64px);
    align-items: start;
  }
  .storygrid__head,
  .storygrid__quote { grid-column: 1 / -1; }
  .storygrid__a { grid-column: 1; }
  .storygrid__b { grid-column: 2; margin-top: 0; }
}

/* the song sits at about a column's width rather than the full measure */
.ytlite { max-width: 520px; }

/* one body size down the page: the team bios come up off the card default to
   meet the prose, rather than the prose coming down to meet them */
.aboutgrid__team .card p { font-size: 17px; }

/* On the about page the team sits beside the prose, and the prose is short.
   Running the face above the name leaves the left column empty for half a
   screen, so here the face sits in the text and the bio wraps under it. */
@media (min-width: 760px) {
  .aboutgrid__team .card--person { display: flow-root; }
  .aboutgrid__team .card__face {
    float: left;
    width: 104px; height: 104px;
    margin: 2px 20px 10px 0;
  }
  .aboutgrid__team .card--person h3 { margin-top: 0; }
}

/* On the team cards the name is the thing a reader looks for, so it takes the
   reading serif and the role takes the typewriter, which is how a label reads
   everywhere else on the site. This is the one place h3 steps out of the
   heading convention, and it steps out deliberately. */
.aboutgrid__team .card--person h3 {
  font-family: var(--text);
  font-size: 19px;
  letter-spacing: normal;
  text-transform: none;
  line-height: 1.3;
  color: var(--ink);
  margin-bottom: 4px;
}
.aboutgrid__team .card--person .card__was {
  font-family: var(--mono);
  font-style: normal;
  font-size: 13px;
  letter-spacing: .13em;
  text-transform: uppercase;
  line-height: 1.6;
  color: var(--ink);
  margin: 0 0 14px;
}

/* ==========================================================================
   How it works
   --------------------------------------------------------------------------
   The three questions run as two columns of reading, and everything that is
   looked at rather than read sits full width underneath them.
   ========================================================================== */
.howgrid { display: grid; margin-top: clamp(22px, 2.6vw, 34px); gap: clamp(28px, 3.2vw, 44px); }
.howgrid__say > .ask:first-child { margin-top: 0; }

.howshow { margin-top: clamp(40px, 5vw, 76px); }
.howgrid__vessel { margin: clamp(26px, 3vw, 36px) 0 0; }
.howgrid__vessel figcaption { font-size: 12px; letter-spacing: .16em; text-align: center; }
/* Stacked, the caption introduces the plate rather than trailing it: there is
   no second column beside it to carry the explanation. */
@media (max-width: 859px) {
  .howgrid__vessel { display: flex; flex-direction: column; }
  .howgrid__vessel figcaption { order: -1; margin: 0 0 14px; }
}
.howshow__h { margin-bottom: clamp(22px, 2.6vw, 32px); }

@media (min-width: 860px) {
  .howgrid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: clamp(36px, 4.2vw, 68px);
    align-items: start;
  }
  /* The plate alternates sides, and with uneven columns that meant it landed
     in the wide column on odd steps and the narrow one on even steps: 677px
     against 484px. Swapping the columns rather than only the items keeps the
     plate in the same share of the row whichever side it is on. */
  .howshow .step { grid-template-columns: 1fr 1.4fr; }
  .howshow .step:nth-child(even) { grid-template-columns: 1.4fr 1fr; }
  /* the step copy is a sentence or two and does not want the whole share */
  .howshow .step__say { max-width: 52ch; }
  /* Step five is a tree, portrait, and cannot take the plates' landscape frame
     without losing its canopy. Capped by height instead, so it carries a
     similar weight to the plates rather than towering over them. */
  .howshow .step:last-child .step__art img { max-height: 360px; width: auto; }
}


/* ---- the timeline, on How it works --------------------------------------
   Drawn to scale, which is the entire argument: 49 days against 20 years is
   0.67% of the bar, so the second one is a sliver and its figure has to sit
   outside it. The min-width keeps that sliver visible rather than honest to
   the point of invisibility. */
.tline { margin-top: clamp(22px, 2.6vw, 30px); }
.tline__lab {
  font-family: var(--mono); font-size: 12px; letter-spacing: .06em;
  line-height: 1.5; color: var(--ink); margin: 0 0 8px;
}
.tline__lab ~ .tline__lab,
.tline__bar--long + .tline__lab { margin-top: clamp(18px, 2vw, 24px); }
.tline__bar {
  height: 34px; border-radius: 2px;
  background: var(--ink);
  display: flex; align-items: center; justify-content: flex-end;
}
.tline__bar--long { width: 100%; }
/* The light green reads only 1.86:1 against the ground, which is under the
   3:1 a meaningful graphic needs, so the burgundy edge carries the shape and
   the fill carries the colour. */
.tline__bar--short {
  width: .67%; min-width: 14px;
  background: var(--btn-bg);
  border: 1px solid var(--ink);
}
.tline__pair { display: flex; align-items: center; gap: 12px; }
.tline__fig {
  font-family: var(--mono); font-size: 12px; letter-spacing: .1em;
  color: var(--beige); padding-right: 14px; white-space: nowrap;
}
.tline__fig--beside { color: var(--ink); padding-right: 0; }

/* ---- a menu item with children ------------------------------------------
   Opens on hover and on keyboard focus, and the panel is padded rather than
   offset so the pointer never crosses a gap on the way down to it. With the
   stylesheet gone the children are simply a nested list, still reachable. */
.nav__drop { position: relative; }
.nav__sub {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%);
  z-index: 70;
  list-style: none; margin: 0;
  padding: 14px 0 0;                 /* the bridge, not a gap */
  min-width: 206px;
  opacity: 0; visibility: hidden;
  transition: opacity .14s ease, visibility 0s linear .14s;
}
.nav__drop:hover > .nav__sub,
.nav__drop:focus-within > .nav__sub {
  opacity: 1; visibility: visible;
  transition: opacity .14s ease, visibility 0s;
}
.nav__sub > li {
  background: var(--beige);
  border: 1px solid var(--rule);
}
.nav__sub > li + li { border-top: 0; }
.nav__sub > li:first-child { border-radius: 3px 3px 0 0; }
.nav__sub > li:last-child  { border-radius: 0 0 3px 3px; }
.nav__sub a {
  display: block;
  padding: 12px 16px;
  font-family: var(--mono); font-size: 12px;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink); text-decoration: none;
  white-space: nowrap;
}
.nav__sub a:hover,
.nav__sub a:focus-visible { background: var(--oat); }
.nav__ext { font-size: .9em; margin-left: .45em; opacity: .7; }

/* On a phone the children are listed under their parent, indented, with no
   second disclosure to find and open. */
/* Children in the sheet are rows like any other, not a shrunken aside.
   The old treatment set them at 86% size and 86% opacity behind a long rule,
   which put the targets under the 44px minimum and dropped their contrast for
   no reason. Hierarchy comes from the indent and the leading mark instead, so
   the text stays full strength and every row stays thumb-sized. */
.mnav__sub { list-style: none; margin: 0; padding: 0; }
.mnav__sub li:first-child { border-top: 1px solid var(--rule-soft); }

/* the label and its arrow share the row; the label keeps the full width it
   had, the arrow takes a target of its own on the right */
.mnav__row { display: flex; align-items: center; }
.mnav__row > a { flex: 1 1 auto; min-width: 0; }
.mnav__toggle {
  flex: none;
  width: 52px; min-height: 52px;
  display: grid; place-items: center;
  appearance: none; background: none; border: 0; padding: 0;
  color: var(--ink); cursor: pointer;
}
.mnav__chev {
  width: 9px; height: 9px;
  border-right: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform .18s ease;
}
.mnav__toggle[aria-expanded="true"] .mnav__chev { transform: translateY(2px) rotate(-135deg); }
.mnav__toggle:focus-visible { outline: 2px solid var(--oxblood); outline-offset: -4px; }
@media (prefers-reduced-motion: reduce) { .mnav__chev { transition: none; } }
.mnav__panel .mnav__sub a:not(.btn) {
  min-height: 48px;
  gap: 12px;
  font-size: 17px;
  color: var(--ink-soft);
}
.mnav__panel .mnav__sub a:not(.btn)::before {
  content: "";
  flex: none;
  width: 14px; height: 1px;
  background: var(--rule);
}

/* ==========================================================================
   Learn index
   --------------------------------------------------------------------------
   A reading list: one rule between entries, the whole card a target, and the
   search narrowing it in place. Shares the FAQ's field, renamed because it is
   no longer only the FAQ's.
   ========================================================================== */
.find { max-width: 420px; position: relative; }
.find__in {
  width: 100%; box-sizing: border-box;
  font-family: var(--mono); font-size: 13px; letter-spacing: .04em; color: var(--ink);
  background: transparent;
  border: 1px solid var(--oat); border-radius: 999px;
  padding: 12px 18px;
  transition: border-color .16s ease;
}
.find__in:focus { outline: none; border-color: var(--forest); }
.find__in::placeholder { color: var(--ink-soft); opacity: .62; }
.find__n {
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft);
  margin-top: 8px; min-height: 14px;
}
.find__none { color: var(--ink-soft); margin-top: 26px; }

.posts { list-style: none; margin: 0; padding: 0; }
.post { border-top: 1px solid var(--rule); }
.post:last-of-type { border-bottom: 1px solid var(--rule); }
.post__a {
  display: block;
  padding: clamp(26px, 3vw, 38px) 0;
  text-decoration: none; color: inherit;
}
.post__kind {
  font-family: var(--mono); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--oxblood);
}
.post__h {
  font-family: var(--disp); font-weight: 400;
  font-size: clamp(24px, 2.8vw, 34px); line-height: 1.14;
  letter-spacing: normal; text-transform: none;
  color: var(--ink);
  margin: 12px 0 0;
}
.post__a:hover .post__h,
.post__a:focus-visible .post__h { text-decoration: underline; text-underline-offset: .14em; }
.post__say {
  color: var(--ink-soft); margin-top: 12px; max-width: 62ch;
}
.post__go {
  font-family: var(--mono); font-size: 12px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--oxblood);
  margin-top: 16px;
}

/* ==========================================================================
   Environmental impact — the lifecycle chart and its table
   --------------------------------------------------------------------------
   Recreated from the pre-seed deck's slide, with the paper's own figures in
   place of the slide's indicative ones. Terramation is the only row given
   emphasis, as on the slide. Every bar carries a burgundy edge because the
   clay reads 1.86:1 against the ground, under the 3:1 a meaningful graphic
   needs; the fill carries the colour and the outline carries the shape.
   ========================================================================== */
.ecogrid { display: grid; gap: clamp(30px, 3.4vw, 46px); margin-top: clamp(26px, 3vw, 38px); }

.eco { margin: 0; padding: clamp(20px, 2.4vw, 28px); background: var(--panel, rgba(240,228,205,.5)); border: 1px solid var(--rule-soft); border-radius: 4px; }
.eco__h {
  font-family: var(--mono); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--oxblood);
  text-align: center; margin-bottom: clamp(18px, 2vw, 24px);
}
.eco__rows { list-style: none; margin: 0; padding: 0; }
.eco__row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 46px;
  align-items: center;
  gap: 6px 12px;
  padding: 9px 10px;
  border-radius: 3px;
}
.eco__row.is-ours { background: rgba(197,180,139,.38); }
.eco__name { font-family: var(--mono); font-size: 12px; letter-spacing: .05em; line-height: 1.45; }
.eco__q { opacity: .68; }
.eco__track { grid-column: 1; }
.eco__bar {
  height: 20px; border-radius: 999px;
  background: var(--ink); border: 1px solid var(--ink);
  min-width: 10px;
}
/* ours in the light green, the rest in the deep brown */
.eco__row.is-ours .eco__bar { background: var(--btn-bg); }
.eco__val {
  grid-column: 2; grid-row: 1 / span 2;
  font-family: var(--mono); font-size: 13px;
  text-align: right; color: var(--ink);
}
.eco__approx { opacity: .72; }
.eco__scale {
  font-family: var(--mono); font-size: 11px; line-height: 1.6;
  color: var(--ink-soft); margin-top: 16px;
}

/* at a comfortable width the label sits beside the bar rather than above it */
@media (min-width: 620px) {
  .eco__row { grid-template-columns: 14em minmax(0, 1fr) 46px; }
  .eco__name { grid-column: 1; }
  .eco__track { grid-column: 2; }
  .eco__val { grid-column: 3; grid-row: 1; }
}
/* The side-by-side split only once the chart column can still carry a usable
   track. At 1000px it left 111px for the bars, where 0.75 and 1.2 drew 10px
   and 11px and the chart stopped saying anything. */
@media (min-width: 1180px) {
  .ecogrid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); align-items: start; }
}

.eco__src {
  font-family: var(--mono); font-size: 11px; line-height: 1.7;
  color: var(--ink-soft); margin-top: clamp(22px, 2.6vw, 30px);
  max-width: 76ch; opacity: .86;
}

/* the library's empty state, where a term the articles do not cover is
   handed to the FAQ instead of to a dead end */
.find__none { margin-top: clamp(26px, 3vw, 36px); color: var(--ink-soft); }
.find__sug { list-style: none; margin: 14px 0 0; padding: 0; }
.find__sug li { border-top: 1px solid var(--rule-soft); }
.find__sug li:last-child { border-bottom: 1px solid var(--rule-soft); }
.find__sug a {
  display: block; padding: 13px 0;
  font-family: var(--mono); font-size: 13px; line-height: 1.5;
  color: var(--ink); text-decoration: none;
}
.find__sug a:hover, .find__sug a:focus-visible { text-decoration: underline; text-underline-offset: .2em; }

/* ---- question one: the written answer leads --------------------------- */
.choose__say { max-width: 560px; }
.choose__say .choose__write {
  width: 100%; box-sizing: border-box;
  /* typed, and at the same size as the "I'm not sure yet" beside it, so the
     two answers to the one question read as a pair */
  font-family: var(--mono); font-size: 10.5px;
  letter-spacing: .1em; text-transform: uppercase;
  color: var(--ink);
  background: rgba(255, 252, 244, .7);
  border: 1px solid var(--rule); border-radius: 0;
  padding: 14px 16px;
}
.choose__say .choose__write:focus-visible { outline: 2px solid var(--midnight); outline-offset: 2px; }
.choose__or {
  font-family: var(--mono); font-size: 12px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft);
  margin: 12px 0 10px;
}
.choose__inspo {
  margin: clamp(30px, 4vw, 44px) 0 clamp(16px, 2vw, 22px);
  /* no measure: one sentence, and it holds one line wherever there is room,
     rather than hanging its last words onto a second */
  max-width: none;
  text-wrap: balance;
  color: var(--ink-soft);
}

/* ---- selects, without the operating system's white furniture ----------
   The closed control is ours: the native arrow and panel are replaced by the
   same bottom rule the text fields use, plus a burgundy chevron. The opened
   list is drawn by the operating system and cannot be styled, so it will
   still look native on macOS however this is written. */
.field select {
  appearance: none; -webkit-appearance: none;
  width: 100%; max-width: none;
  font-family: var(--text); font-size: 17px; color: var(--ink);
  background-color: rgba(255, 252, 244, .7);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.6 6 6.4l5-4.8' fill='none' stroke='%234B0500' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 12px 8px;
  border: 1px solid var(--rule); border-radius: 0;
  padding: 14px 40px 14px 16px;
  cursor: pointer;
}
.field select:focus-visible { outline: 2px solid var(--midnight); outline-offset: 2px; }
/* honoured where the list is drawn by the browser rather than the OS */
.field select option { background: var(--beige); color: var(--ink); }

/* The possibilities are shown, not offered: they illustrate the answer rather
   than collecting it, so they keep the card but lose every interactive state.
   Same furniture as `.choose__opt`, without the pointer, the hover or the
   checked ring. The written answer above is the only thing being asked for. */
.choose__eg { display: flex; }
.choose__eg figure {
  display: block;
  flex: 1;
  margin: 0;
  padding: 10px 10px 12px;
  border: 1px solid var(--rule-soft);
  background: rgba(255, 252, 244, .5);
}
.choose__eg img {
  display: block;
  width: 100%;
  /* 12px shorter than the pickable cards were, which buys the third caption
     line that "part of regenerated bushland" needs without the card growing */
  height: 82px;
  object-fit: contain;
  object-position: bottom center;
  pointer-events: none;
}
.choose__eg figcaption {
  display: block;
  margin-top: 10px;
  /* three reserved, which is the longest caption, so every card is one height
     whatever the row holds */
  min-height: 4.5em;
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: .1em;
  text-transform: uppercase;
  line-height: 1.5;
  color: var(--ink-soft);
}

/* the question asked before a written answer is thrown away */
.choose__warn {
  margin-top: 16px;
  padding: 16px 18px;
  background: var(--win2-bg);
  color: #4B0500;
  border-radius: 3px;
  max-width: 560px;
}
.choose__warn:focus { outline: 2px solid var(--ink); outline-offset: 2px; }
.choose__warn-do { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 14px; }
.choose__warn .btn--ghost { color: #4B0500; border-color: #4B0500; }
.choose__warn .btn--ghost:hover { background: #4B0500; color: var(--beige); }

/* the sign-off, and the way out of the note into the whole story, on one line */
.note__foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px 18px;
  margin-top: 26px;
}
.note__paper .note__foot .note__sign { margin-top: 0; }
.note__more { margin: 0 0 0 auto; }   /* stays right even when it wraps below */
.note__more .btn { font-size: 11px; padding: 9px 15px; white-space: nowrap; }

/* the invitation sits above the memberships in the foot.
   `.site-foot a` sets a link colour and a 16px size, and being element plus
   class it out-weighs the button variants, which painted this one burgundy on
   burgundy and unreadable. Buttons in the foot keep their own styling. */
.site-foot a.btn { font-size: 12px; letter-spacing: .16em; color: var(--btn-fg); }
.site-foot a.btn--deep { color: var(--beige); }
.site-foot a.btn:hover, .site-foot a.btn:focus-visible { color: var(--ink); }


/* The arrow on a closing button. It drifts side to side on its own so the
   button reads as something to act on, and leans further when the pointer or
   keyboard reaches it. Decorative, so it is hidden from screen readers and the
   label still reads on its own. The gap is about two spaces of the typed face.
   Hover switches the loop off rather than fighting it: both write transform,
   and an animation wins over a transition. */
@keyframes go-drift {
  0%, 100% { transform: translateX(0); }
  50%      { transform: translateX(4px); }
}
.btn__go {
  display: inline-block;
  margin-left: 1.2em;
  transition: transform .18s cubic-bezier(.3,.8,.3,1);
  animation: go-drift 1.9s ease-in-out infinite;
}
.btn:hover .btn__go,
.btn:focus-visible .btn__go { animation: none; transform: translateX(7px); }
.btn:active .btn__go { animation: none; transform: translateX(4px); }
@media (prefers-reduced-motion: reduce) {
  .btn__go { transition: none; animation: none; }
  .btn:hover .btn__go, .btn:focus-visible .btn__go, .btn:active .btn__go { transform: none; }
}

/* A short lean, not a loop: two passes of a couple of pixels, then still.
   Driven from story.js when the closing beat comes into view. */
@keyframes cta-notice {
  0%, 100% { transform: translateX(0); }
  20%      { transform: translateX(-3px); }
  40%      { transform: translateX(3px); }
  60%      { transform: translateX(-2px); }
  80%      { transform: translateX(2px); }
}
.site-head__in > .btn.is-noticed { animation: cta-notice .62s ease-in-out 2; }
@media (prefers-reduced-motion: reduce) {
  .site-head__in > .btn.is-noticed { animation: none; }
}

/* The discussion paper button is the point of this page and it was landing
   171px below the fold on a 900px screen. Everything above it gives up a
   little: the section's own air, the gap under the headline, the space between
   the four themes, and the padding inside each tag. Desktop only, where the
   two columns exist and the fold is the thing being fought. */
@media (min-width: 900px) {
  .section:has(> .whygrid) { padding-top: clamp(18px, 1.8vw, 26px); }
  .whygrid { row-gap: clamp(16px, 1.6vw, 22px); }
  .whygrid__intro { margin-bottom: clamp(10px, 1.1vw, 13px); }
  .whygrid__themes .card + .card { margin-top: clamp(12px, 1.3vw, 17px); }
  .whygrid .theme__tag { padding-block: 7px; line-height: 1.5; }
  .whygrid__themes .card p { line-height: 1.6; }
  .whygrid__more { margin-top: clamp(14px, 1.5vw, 18px); }
}

/* ---- the form: answers are typed, errors are loud ----------------------
   Everything a person writes or picks is set in the typewriter, so an answer
   always looks like an answer and never like the page's own prose. */
/* The last question carries a box plus three consents, so the box matches the
   fields on the first screen rather than running as a page of its own: same
   width, same padding, same type, one line of height. */
.tf .q__input--short {
  /* height, not min-height: the rows attribute would otherwise set the floor
     and the box would sit taller than the fields it is matching */
  height: calc(clamp(18px, 2.2vw, 24px) * 1.45 + 30px);
  min-height: calc(clamp(18px, 2.2vw, 24px) * 1.45 + 30px);
  max-width: none;
  padding: 14px 16px;
  box-sizing: border-box;
  resize: vertical;
}
.tf .field input[type="text"],
.tf .field input[type="email"],
.tf .field textarea,
.tf .field select,
.tf .q__input {
  font-family: var(--mono);
  letter-spacing: .02em;
}
/* The select sets the size of its own option list, which at the boxes' type
   size was far too big once opened, so it takes a readable 17px. The two
   fields in a pair are then held to one height rather than each arriving at
   its own from its own type size. */
.tf .field select { font-size: 17px; }
.pair .field select,
.pair .field input[type="text"] {
  box-sizing: border-box;
  min-height: calc(clamp(18px, 2.2vw, 24px) * 1.45 + 30px);
}

/* The error was a line of text the same colour as everything else, which is
   easy to miss at the moment it matters. Coral is the warmest ground in the
   palette and carries burgundy at 6.45:1. */
.q__err:not([hidden]) {
  display: block;
  margin-top: 16px;
  padding: 12px 16px;
  background: var(--win2-bg);
  color: #4B0500;
  border: 1px solid #4B0500;
  border-radius: 3px;
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.55;
  max-width: 52ch;
}

/* ---- two fields on one line, where they belong together ---------------- */
.pair { display: grid; gap: clamp(18px, 2.2vw, 30px); }
@media (min-width: 720px) { .pair { grid-template-columns: 1fr 1fr; align-items: start; } }
.pair .field { margin: 0; }

/* the label and its "i", on one line */
.field__top { display: flex; align-items: center; gap: 8px; margin: 0 0 8px; }
.field__top label { margin-bottom: 0; }

/* "why we ask", the same affordance as the one in the messages strip */
.why { position: relative; flex: none; }
.why > summary {
  list-style: none; cursor: pointer;
  width: 15px; height: 15px; border-radius: 50%;
  border: 1px solid var(--oxblood); color: var(--oxblood);
  font-family: var(--mono); font-size: 9px; line-height: 13px;
  text-align: center;
  transition: background .16s ease, color .16s ease;
}
.why > summary::-webkit-details-marker { display: none; }
.why > summary:hover, .why[open] > summary { background: var(--oxblood); color: var(--beige); }
.why__body {
  position: absolute; top: calc(100% + 9px); left: 0;
  width: min(344px, 86vw); z-index: 50;
  background: var(--win2-bg); color: #4B0500;
  padding: 13px 15px; border-radius: 3px;
  box-shadow: 0 12px 38px rgba(75,5,0,.34);
  font-family: var(--text); font-size: 13.5px; line-height: 1.55;
  text-transform: none; letter-spacing: normal;
}
.why__body p { max-width: none; }

/* Checkboxes in the brand's brown rather than the browser's blue. */
input[type="checkbox"], input[type="radio"] { accent-color: var(--ink); }

/* The welcome holds one line: it is a greeting, and breaking "Evergrove
   Movement" across two lines reads as two thoughts. */
#q-who .q__ask { white-space: nowrap; font-size: clamp(22px, 3.4vw, 44px); }

/* ---- checkboxes drawn rather than borrowed -----------------------------
   The native control paints its accent colour as a hover and active fill, so
   with a near-black burgundy accent it looked like the box went black under
   the pointer. Drawing it means the only thing the colour does is the tick. */
.tf input[type="checkbox"],
.optout input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 17px; height: 17px; flex: none;
  margin: 0;
  border: 1px solid var(--ink);
  border-radius: 2px;
  background: transparent;
  display: inline-grid; place-content: center;
  cursor: pointer;
}
.tf input[type="checkbox"]::before,
.optout input[type="checkbox"]::before {
  content: "";
  width: 11px; height: 11px;
  transform: scale(0);
  background: var(--ink);
  clip-path: polygon(14% 44%, 0 65%, 50% 100%, 100% 16%, 80% 0%, 43% 62%);
}
.tf input[type="checkbox"]:checked::before,
.optout input[type="checkbox"]:checked::before { transform: scale(1); }
/* The notice at the top of the form: what we ask for and why, in plain sight
   rather than behind the "i", because beliefs are sensitive information and
   the Privacy Principles expect the notice at the point of collection. */
.q__intro {
  /* wide measure on purpose: this reads as a short notice above the fields,
     not as a paragraph of body copy, so it wants few long lines rather than
     many short ones */
  font-size: 14.5px; line-height: 1.55; color: var(--ink-soft);
  max-width: 100%; margin-top: 14px;
}
.q__intro a { color: var(--midnight); }

.tf input[type="checkbox"]:focus-visible,
.optout input[type="checkbox"]:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }

/* ---- no lingering ring after a click ----
   Clicking a tick box left an outline sitting on the row until you clicked
   somewhere else. Keyboard users still need that ring, so it is suppressed
   only when the last thing the person touched was a pointer. */
html[data-input="pointer"] .tf input:focus,
html[data-input="pointer"] .tf select:focus,
html[data-input="pointer"] .tf textarea:focus,
html[data-input="pointer"] .optout input:focus { outline: none; }
html[data-input="pointer"] .tf .choice:has(input:focus),
html[data-input="pointer"] .tf .choose__opt:has(input:focus),
html[data-input="pointer"] .tf .choice:has(input:focus-visible),
html[data-input="pointer"] .tf .choose__opt:has(input:focus-visible) { outline: none; }

/* ---- how far through you are ------------------------------------------- */
.progress-row {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: clamp(24px, 3.4vh, 40px);
}
/* a display declaration beats the hidden attribute, so the row needs this or
   it stays on screen through the thank-you */
.progress-row[hidden] { display: none; }
.progress {
  flex: 1 1 auto;
  height: 3px;
  background: var(--rule-soft);
  border-radius: 999px;
  overflow: hidden;
}
.progress__fill {
  display: block; height: 100%; width: 0;
  background: var(--ink);
  transition: width .3s cubic-bezier(.3,.8,.3,1);
}
.progress__pct {
  flex: none; margin: 0;
  font-family: var(--mono); font-size: 11px; letter-spacing: .14em;
  color: var(--ink-soft);
  min-width: 4ch; text-align: right;
}
@media (prefers-reduced-motion: reduce) { .progress__fill { transition: none; } }

/* the follow-up that only matters once the consent above it is given */
.choice__sub {
  display: flex; flex-wrap: wrap; gap: 10px 26px;
  padding: 0 0 15px 30px;
}
.choice__sub.is-off label { opacity: .45; cursor: default; }
.choice__sub input:disabled { cursor: default; }
.choice__sub label {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  font-family: var(--mono); font-size: 11px;
  letter-spacing: .1em; text-transform: uppercase; color: var(--ink-soft);
}
.choice__sub input { margin: 0; accent-color: var(--ink); }
