/* ============================================================
   Citizen Activate · site styles · Broadside system
   Tokens from the brand guide; ratios are WCAG contrast.
   ============================================================ */

/* Type scale
   ==========================================================================
   One closed set of sizes, one spelling each. Fluid display type stays in
   clamp(); these steps are its end points. */

/* Spacing
   ==========================================================================
   Two scales. --s-0..9 is RHYTHM, the space BETWEEN things: margins and gaps
   only, a 4px base doubling loosely (2 4 8 12 16 24 32 48 64 96). --pad-* is
   CONTROL, the space INSIDE a thing, paired y/x on the same base. --gutter is
   the page's side padding, stated once so anything aligning to .wrap can ask
   rather than restate the clamp. */
:root {
  --ca-red-50: #fcecec;
  --ca-red-100: #f7d0d2;
  --ca-red-300: #e4666c;
  --ca-red-500: #b3030d;
  --ca-red-700: #8c0209;
  --ca-red-900: #5c0105;
  --ca-navy-50: #eef2f8;
  --ca-navy-100: #d8e0ee;
  --ca-navy-300: #8a9cc4;
  --ca-navy-500: #1e4278;
  --ca-navy-700: #02204f;
  --ca-navy-900: #01132f;
  --ca-gold-50: #fdf6e3;
  --ca-gold-100: #f8e6b4;
  --ca-gold-300: #e8c267;
  --ca-gold-500: #d1952b;
  --ca-gold-700: #8f5e00;
  --ca-gold-900: #5e3d00;
  --ca-ink: #121826;
  --ca-charcoal: #2e3547;
  --ca-slate: #5a6377;
  --ca-steel: #8b93a6;
  --ca-limestone: #c9cfdb;
  --ca-fog: #e6e9f0;
  --ca-cream: #f6f4ec;
  --ca-paper: #f8f8f8;
  --ca-white: #ffffff;
  --ca-forest: #2a541e;
  --ca-plum: #362454;
  --ca-focus: var(--ca-gold-700);
  --ca-focus-dark: var(--ca-gold-500);

  /* Surfaces and inks
     ------------------------------------------------------------------
     The palette is the brand and does not move. What moves is which colour is
     the paper and which is the ink. Two palette tokens carry both jobs --
     navy-700 is the dark sections' ground and the light ones' ink, paper is the
     page's ground and the dark sections' ink -- so a theme cannot be a straight
     palette swap. Light values here are exactly the entries they replaced;
     tools/audit_theme.py proves it. */
  /* Named for the palette entry each one stands for, because that is what
     makes the light theme provably unchanged: --paper is the paper, --panel
     is the white. */
  --panel: var(--ca-white);
  --paper: var(--ca-paper);
  --cream: var(--ca-cream);
  --panel-2: var(--ca-navy-50);
  --panel-3: var(--ca-fog);
  /* The sections that are deliberately dark, in either theme. */
  --inverse: var(--ca-navy-700);
  --inverse-deep: var(--ca-navy-900);

  --ink: var(--ca-navy-700);
  --ink-deep: var(--ca-ink);
  --ink-2: var(--ca-charcoal);
  --ink-3: var(--ca-slate);
  /* A control's boundary, not a word: 1.4.11's 3.0, not 1.4.3's 4.5. Steel is
     3.08 on white and 2.53 on fog; a step darker holds on every light surface. */
  --edge: #7b8497;
  --ink-inverse: var(--ca-paper);
  --ink-inverse-2: var(--ca-navy-100);
  --ink-inverse-3: var(--ca-navy-300);

  --rule: var(--ca-limestone);
  --rule-soft: var(--ca-fog);
  --link: var(--ca-red-500);
  --link-hover: var(--ca-red-700);
  /* The gold that can carry text on the current ground: 700 on light. */
  --gold-ink: var(--ca-gold-700);
  --wash-gold: var(--ca-gold-50);
  --wash-red: var(--ca-red-50);
  /* The blue links: the punch card organisations and the power map's cross
     references. Navy-500 is 9.97 on white and 1.84 on the dark page, so it
     cannot be a constant. */
  --link-alt: var(--ca-navy-500);
  /* The unfilled part of the punch card's ring: a step off the ground it sits
     on rather than a colour of its own. The gold that fills it is what carries
     the value, and the count is written beside it, so this only has to be
     visible enough to show how far round there is to go. 1.16 here. */
  --track: var(--ca-navy-700);
  --plum-ink: var(--ca-plum);
  /* A modal is a sheet lifted off the page, and in dark it has to be lighter
     than what it covers or it disappears into it. */
  --dialog: var(--ca-paper);
  --scrim: rgba(1, 19, 47, 0.62);
  /* Painted into a data URI, so it cannot inherit a colour. Navy on light. */
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%2302204F' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --font-display: "Alfa Slab One", Rockwell, "Roboto Slab", serif;
  --font-text: "Barlow", "Helvetica Neue", Arial, sans-serif;
  /* The builder credit only, matched to the signature on the other sites it
     appears on. */
  --font-mono: "IBM Plex Mono", "SF Mono", Consolas, monospace;
  --font-accent: "Barlow Condensed", "Arial Narrow", sans-serif;
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-0: 0.125rem;
  --pad-2xs: var(--s-1) var(--s-2);
  --pad-xs: var(--s-2) var(--s-2);
  --pad-sm: var(--s-2) var(--s-3);
  --pad-md: var(--s-3) var(--s-4);
  --pad-lg: var(--s-4) var(--s-5);
  --gutter: clamp(1rem, 4vw, 2.5rem);
  /* one easing for the whole site */
  --ca-ease: cubic-bezier(0.2, 0.7, 0.3, 1);
  --t-1: 0.75rem; /* 12  micro labels, tags, definition terms */
  --t-2: 0.8125rem; /* 13  eyebrows, fine print, table heads */
  --t-3: 0.875rem; /* 14  small body, navigation, table cells */
  --t-4: 0.9375rem; /* 15  body */
  --t-5: 1rem; /* 16  lead body */
  --t-6: 1.0625rem; /* 17  buttons, sub-subsection headings */
  --t-7: 1.25rem; /* 20  card titles */
  --t-8: 1.5rem; /* 24  subsection headings */
  --t-9: 1.75rem; /* 28 */
  --t-10: 2rem; /* 32 */
  --t-11: 2.25rem; /* 36 */
  --t-12: 2.5rem; /* 40 */
  /* The right edge's tab column. The width was intrinsic (a 25.6px vertical
     line box, 8px padding a side, 1px border); stating it lets the two match. */
  --tab-w: 43px;
  /* The tab's height along its short side. Laid flat under 640 both tabs take
     it, so they match. */
  --tab-h: 40px;
  --tab-foot: clamp(1.25rem, 6vh, 3rem);
  --r-1: 3px;
  --r-2: 6px;
  --r-3: 12px;
  --e-2: 0 4px 14px rgba(2, 32, 79, 0.1);
  --e-3: 0 12px 32px rgba(2, 32, 79, 0.16);
  --wrap: 1180px;
  /* .site-header .wrap min-height 64px + its 2px gold rule. The hero
     measures itself against this so it fits under the header exactly. */
  --hdr: 66px;
  --map-water: #7fa6c9;
  --map-water-label: #5c86ad;
}
/* Dark
   ==========================================================================
   Said twice: data-theme="dark" is the reader's choice and must beat the
   system; data-theme="auto" follows it, live, because theme.js watches
   matchMedia. Nothing here is a colour that exists only in dark.
   
   Measured, on page #0d1424 / cream #171f2c / panel-2 #1b2540:
   ink 15.8 / 14.8 / 12.5   ink-3 8.6 / 8.0 / 6.8
   link 7.2 on the page     gold 10.8 on the page */
:root[data-theme="dark"] {
  color-scheme: dark;

  --panel: #0d1424;
  --paper: #111a2b;
  --cream: #171f2c;
  --panel-2: #1b2540;
  --panel-3: #212c48;
  --inverse: #060c17;
  --inverse-deep: #03070f;

  --ink: #e9eef7;
  --ink-deep: #f3f7fd;
  --ink-2: #cfd8e6;
  --ink-3: #a6b2c6;
  --edge: #8b97ab;
  --ink-inverse: #f1f4f9;
  --ink-inverse-2: #ccd6e6;
  --ink-inverse-3: #9aa8bf;

  --rule: #334566;
  --rule-soft: #1e2a40;
  /* Torch Red is 1.6 on this ground. The link keeps the family and takes the
     lightness it needs: 7.2 on the page. */
  --link: #ef8289;
  --link-hover: #f7d0d2;
  /* Gold-700 is the gold for text on paper. Here the paper is dark, so the
     gold that carries text is 300. */
  --gold-ink: var(--ca-gold-300);
  --wash-gold: #241d0e;
  --wash-red: #2a1215;
  --link-alt: #9dbdf0;
  --track: #16243f;
  --plum-ink: #c6b3e8;
  --dialog: #1f2b46;
  --scrim: rgba(0, 0, 0, 0.72);
  --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23E9EEF7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* The ring follows the ground: gold-700 disappears into this. */
  --ca-focus: var(--ca-gold-300);
}
@media (prefers-color-scheme: dark) {
  :root[data-theme="auto"] {
    color-scheme: dark;

    --panel: #0d1424;
    --paper: #111a2b;
    --cream: #171f2c;
    --panel-2: #1b2540;
    --panel-3: #212c48;
    --inverse: #060c17;
    --inverse-deep: #03070f;

    --ink: #e9eef7;
    --ink-deep: #f3f7fd;
    --ink-2: #cfd8e6;
    --ink-3: #a6b2c6;
    --edge: #8b97ab;
    --ink-inverse: #f1f4f9;
    --ink-inverse-2: #ccd6e6;
    --ink-inverse-3: #9aa8bf;

    --rule: #334566;
    --rule-soft: #1e2a40;
    /* Torch Red is 1.6 on this ground. The link keeps the family and takes the
       lightness it needs: 7.2 on the page. */
    --link: #ef8289;
    --link-hover: #f7d0d2;
    /* Gold-700 is the gold for text on paper. Here the paper is dark, so the
       gold that carries text is 300. */
    --gold-ink: var(--ca-gold-300);
    --wash-gold: #241d0e;
    --wash-red: #2a1215;
    --link-alt: #9dbdf0;
    --track: #16243f;
    --plum-ink: #c6b3e8;
    --dialog: #1f2b46;
    --scrim: rgba(0, 0, 0, 0.72);
    --select-chevron: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 6l4 4 4-4' fill='none' stroke='%23E9EEF7' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    /* The ring follows the ground: gold-700 disappears into this. */
    --ca-focus: var(--ca-gold-300);
  }
}

*,
*::before,
*::after {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
  scroll-padding-top: 84px;
}
body {
  margin: 0;
  background: var(--panel);
  color: var(--ink-deep);
  font-family: var(--font-text);
  font-size: var(--t-6);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img,
svg {
  max-width: 100%;
  display: block;
}
[hidden] {
  display: none !important;
}
h1,
h2,
h3,
h4 {
  margin: 0;
  text-wrap: balance;
}
p {
  margin: 0;
}
ul,
ol {
  margin: 0;
  padding: 0;
}
a {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  /* The underline is what marks a link, not the colour: Torch Red against the
     navy around it is 2.22, under the 3.0 that would let colour carry it. So
     the rule under it is a graphical object that conveys information, and
     wants 3.0 of its own. Gold-500 is 2.61 on white and 2.37 on cream -- it
     never had it. --gold-ink is the gold for the current ground: 5.57 on
     white in light, 10.80 on the page in dark. The dark sections state their
     own gold-300 further down, which is right there and wrong here. */
  text-decoration-color: var(--gold-ink);
  text-underline-offset: 0.2em;
}
a:hover {
  color: var(--link-hover);
  text-decoration-color: var(--ca-red-700);
}
:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
}
.on-dark :focus-visible,
.on-dark:focus-visible {
  outline-color: var(--ca-focus-dark);
}
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}
.skip {
  position: absolute;
  left: var(--s-4);
  top: -100px;
  z-index: 100;
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
  padding: var(--s-2) var(--s-4);
  border-radius: var(--r-1);
  font-family: var(--font-accent);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
.skip:focus {
  top: var(--s-3);
}
.wrap {
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.eyebrow {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.on-dark .eyebrow {
  color: var(--ca-gold-500);
}
.display {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2.75rem, 6vw, 4.75rem);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.h1 {
  font-family: var(--font-display);
  font-weight: 400;
  /* Section titles: 55px at the top, between the 24-28px subsection heads and
     the 76px hero and footer lines. */
  font-size: clamp(2.1rem, 5.2vw, 3.4375rem);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.h2 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.6rem, 3vw, 1.75rem);
  line-height: 1.1;
  color: var(--ink);
}
.h3 {
  font-family: var(--font-text);
  font-weight: 700;
  font-size: var(--t-8);
  line-height: 1.2;
  color: var(--ink);
}
.lead {
  font-size: var(--t-7);
  line-height: 1.5;
  color: var(--ink-2);
}
.small {
  font-size: var(--t-3);
  line-height: 1.5;
  color: var(--ink-3);
}.on-dark .h1,
.on-dark .h2,
.on-dark .h3,
.on-dark .display{
  color: var(--ink-inverse);
}
.on-dark .lead,
.on-dark p {
  color: var(--ink-inverse-2);
}
.on-dark .small {
  color: var(--ink-inverse-3);
}
.on-dark a {
  color: var(--ink-inverse);
  text-decoration-color: var(--ca-gold-500);
}
.on-dark a:hover {
  color: var(--ca-gold-300);
  text-decoration-color: var(--ca-gold-300);
}
.num {
  font-variant-numeric: tabular-nums;
}

/* ---------- Buttons (Ledger shape, Broadside labels) ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-5);
  border: 2px solid transparent;
  border-radius: var(--r-1);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-6);
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  cursor: pointer;
  white-space: nowrap;
  transition:
    background-color 0.15s,
    color 0.15s,
    border-color 0.15s;
  font-variant-numeric: tabular-nums;
  background: none;
}
.btn svg {
  width: 1em;
  height: 1em;
  flex: none;
}
.btn-primary {
  background: var(--ca-red-500);
  color: #fff;
}
.btn-primary:hover {
  background: var(--ca-red-700);
  color: #fff;
}
.btn-primary:active {
  background: var(--ca-red-900);
}
.btn-secondary {
  color: var(--ink);
  border-color: var(--ink);
}
.btn-secondary:hover {
  background: var(--panel-2);
  color: var(--ink);
}
.btn-secondary:active {
  background: var(--ca-navy-100);
}
.btn-tertiary {
  color: var(--link);
  padding-inline: var(--s-1);
  white-space: normal;
  text-align: left;
  line-height: 1.2;
  max-width: 100%;
  text-decoration: underline;
  text-decoration-color: var(--ca-gold-500);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.22em;
}
.btn-tertiary:hover {
  color: var(--link-hover);
  text-decoration-color: var(--ca-red-700);
}
.on-dark .btn-primary {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
.on-dark .btn-primary:hover {
  background: var(--ca-gold-300);
  color: var(--ca-navy-900);
}
.on-dark .btn-secondary {
  color: var(--ink-inverse);
  border-color: var(--ink-inverse);
}
.on-dark .btn-secondary:hover {
  background: rgba(255, 255, 255, 0.1);
  color: var(--ca-paper);
}
.on-dark .btn-tertiary {
  color: var(--ink-inverse);
}
.on-dark .btn-tertiary:hover {
  color: var(--ca-gold-300);
  text-decoration-color: var(--ca-gold-300);
}
.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  align-items: center;
}
@media (max-width: 480px) {
  .btn-row .btn-primary,
  .btn-row .btn-secondary {
    width: 100%;
    text-align: center;
  }
}
.chip {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  padding: var(--s-1) var(--s-2) var(--s-1) var(--s-2);
  border-radius: var(--r-1);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-1);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border: 1px solid var(--rule);
  background: var(--panel);
  color: var(--ink-deep);
  white-space: nowrap;
}
.chip i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: inline-block;
  flex: none;
}
.chip.solid {
  border-color: transparent;
  color: #fff;
}
.chip.solid.gold {
  background: var(--ca-gold-700);
}
.chip.solid.gold i {
  background: var(--ca-gold-500);
}
.chip.solid.red {
  background: var(--ca-red-500);
}
.chip.solid.red i {
  background: var(--panel);
}
.chip.solid.navy {
  background: var(--ca-navy-500);
}
.chip.solid.navy i {
  background: var(--panel);
}
.chip.solid.forest {
  background: var(--ca-forest);
}
.chip.solid.forest i {
  background: var(--panel);
}

/* ---------- Header / nav ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 60;
  background: var(--inverse);
  border-bottom: 2px solid var(--ca-gold-500);
  color: var(--ink-inverse);
}
.site-header .wrap {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  min-height: 64px;
}
/* Badge only in the header: the wordmark it used to sit beside is gone, and
   the link keeps its name from aria-label. The type rules went with it. */
.brand {
  display: flex;
  align-items: center;
  gap: var(--s-3);
  text-decoration: none;
  color: var(--ink-inverse);
  line-height: 1;
}
.brand img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--panel);
}
.brand span b {
  color: var(--ca-gold-500);
  font-weight: 700;
}
.nav-toggle {
  margin-left: auto;
  display: none;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
  padding: 0 var(--s-4);
  background: transparent;
  border: 2px solid var(--ink-inverse);
  border-radius: var(--r-1);
  color: var(--ink-inverse);
  font-family: var(--font-accent);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: var(--t-4);
  cursor: pointer;
}
.nav-toggle:focus-visible {
  outline-color: var(--ca-focus-dark);
}
.site-nav {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: var(--s-1);
}
.site-nav ul {
  list-style: none;
  display: flex;
  gap: var(--s-1);
}
.site-nav li a {
  display: block;
  padding: var(--s-2) var(--s-3);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-4);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-inverse);
  text-decoration: none;
  border-radius: var(--r-1);
}
.site-nav li a:hover {
  background: rgba(255, 255, 255, 0.1);
  color: var(--ca-paper);
}
.site-nav li a:focus-visible {
  outline-color: var(--ca-focus-dark);
}
.site-nav .btn {
  margin-left: var(--s-2);
}
.site-header .btn-primary {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
}
.site-header .btn-primary:hover {
  background: var(--ca-gold-300);
  color: var(--ca-navy-900);
}
/* The inline nav needs room for five labels and a button; below this it
   becomes a drawer instead of crowding. */
@media (max-width: 1149px) {
  .nav-toggle {
    display: inline-flex;
  }
  .site-nav {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    background: var(--inverse);
    border-bottom: 2px solid var(--ca-gold-500);
    padding: var(--s-3) var(--gutter) var(--s-5);
    margin: 0;
  }
  .site-nav.open {
    display: block;
  }
  .site-nav ul {
    flex-direction: column;
    gap: 0;
  }
  .site-nav li a {
    padding: var(--s-3) var(--s-2);
    font-size: var(--t-6);
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  }
  .site-nav .btn {
    margin: var(--s-4) 0 0;
    width: 100%;
  }
}

/* ---------- Hero ---------- */
.hero {
  background: var(--panel);
  padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(2.5rem, 6vw, 4rem);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.hero .wrap {
  display: grid;
  justify-items: center;
  gap: var(--s-5);
}

@media (prefers-reduced-motion: reduce) {
}
.hero h1 {
  max-width: 16ch;
  margin-inline: auto;
}
.hero .lead {
  max-width: 52ch;
  margin-inline: auto;
}
.hero .btn-row {
  justify-content: center;
}

/* ---------- Sections ---------- */
.sec {
  padding-block: clamp(3rem, 7vw, 5.5rem);
}
.sec.cream {
  background: var(--cream);
}
.sec.navy {
  background: var(--inverse-deep);
  color: var(--ink-inverse);
}
.sec.red {
  background: var(--ca-red-500);
  color: #fff;
}
.sec-head {
  max-width: 66ch;
  margin-bottom: var(--s-6);
}
.sec-head .lead {
  margin-top: var(--s-3);
}
.sec-head .h1 {
  margin-top: var(--s-2);
}
.grid3 {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--s-5);
}
@media (max-width: 900px) {
  .grid3 {
    grid-template-columns: minmax(0, 1fr);
  }
  }
.card {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  padding: var(--s-5);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-3);
  align-content: start;
}
.card .h3 {
  margin-top: var(--s-0);
}
.card p {
  color: var(--ink-2);
}
.card .btn-row {
  margin-top: var(--s-2);
}
.rule {
  height: 2px;
  background: var(--ca-gold-500);
  width: 64px;
}
.check {
  list-style: none;
  display: grid;
  gap: 0.6rem;
}
.check li {
  display: grid;
  grid-template-columns: 22px 1fr;
  gap: 0.6rem;
  align-items: start;
  color: var(--ink-2);
}
.check li svg {
  width: 22px;
  height: 22px;
  flex: none;
  margin-top: var(--s-0);
}
.on-dark .check li {
  color: var(--ink-inverse-2);
}

/* ---------- Map ---------- */
.map-layout {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(300px, 0.85fr);
  gap: var(--s-6);
  align-items: start;
}
@media (max-width: 900px) {
  .map-layout {
    grid-template-columns: 1fr;
  }
}
.map-stage {
  position: relative;
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--r-3);
  padding: var(--s-3);
  overflow: hidden;
}
/* The map keeps its own palette in both themes -- cream county, lavender
   neighbours, a blue river -- because it is a drawing of a place rather than
   a piece of the page's furniture. That is fine until you notice the
   neighbour polygons do not tile perfectly: there are slivers between them,
   and what shows through is whatever is behind the drawing. On white that was
   invisible. On the dark theme's #0d1424 it read as black spikes off the
   county's edges. The sea goes behind the whole drawing, so a gap is sea. */
.map-stage svg {
  width: 100%;
  height: auto;
  display: block;
  background: var(--ca-navy-50);
  border-radius: var(--r-2);
}
.map-stage .county {
  fill: var(--ca-cream);
  stroke: var(--ca-navy-700);
  stroke-width: 3;
  stroke-linejoin: round;
  transition: fill 0.2s;
}
.map-stage.is-metro .county {
  fill: var(--ca-gold-100);
}
.map-stage .neighbor {
  fill: var(--ca-navy-50);
  stroke: var(--ca-navy-100);
  stroke-width: 1.5;
}
.map-stage .river {
  fill: none;
  stroke: var(--map-water);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.9;
}
.map-stage .lbl {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-7);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  /* Slate, not steel: steel is 3.08 on the map's ground and these are words.
     5.68, and it matches every other secondary label on the site. */
  fill: var(--ink-3);
}
.map-stage .river-lbl {
  font-family: var(--font-text);
  font-style: italic;
  font-size: var(--t-7);
  fill: var(--map-water-label);
}
/* A texture on the county, not a second map. The fill is barely there but it
   is there: a shape filled with none takes no clicks. Clipped to the county
   outline in the markup -- the outline is a simplification and the real
   boundaries run past it in the north and the west. */
.map-stage .district {
  fill: rgba(2, 32, 79, 0.03);
  stroke: rgba(2, 32, 79, 0.3);
  stroke-width: 1;
  cursor: pointer;
}
.map-stage .district:hover {
  fill: rgba(209, 149, 43, 0.28);
}
.map-stage .district:hover,
.map-stage .district:focus {
  fill: var(--ca-gold-300);
}
/* A fill change alone is not a focus indicator: it reads as hover, and on a
   map the shape under the cursor is not obviously the focused one. */
.map-stage .district:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
}
.map-stage .district.active {
  fill: var(--ca-gold-500);
}
.marker {
  position: absolute;
  transform: translate(-15px, -50%);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: var(--s-1) var(--s-2) var(--s-1) var(--s-2);
  min-height: 32px;
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ca-navy-700);
  cursor: pointer;
  box-shadow: var(--e-2);
  white-space: nowrap;
  transition:
    transform 0.15s,
    background-color 0.15s;
}
.marker i {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--ca-red-500);
  border: 2px solid #fff;
  box-shadow: 0 0 0 1px var(--ca-red-500);
  flex: none;
}
.marker.civic i {
  background: var(--inverse);
  box-shadow: 0 0 0 1px var(--ca-navy-700);
}
.marker.metro i {
  background: var(--ca-gold-500);
  box-shadow: 0 0 0 1px var(--ca-gold-700);
}
.marker:hover,
.marker.active {
  background: var(--inverse);
  color: var(--ink-inverse);
  border-color: var(--inverse);
}
.marker:hover {
  transform: translate(-15px, -50%) scale(1.03);
}
.marker.side-l {
  flex-direction: row-reverse;
  padding: var(--s-1) var(--s-2) var(--s-1) var(--s-2);
  transform: translate(calc(-100% + 15px), -50%);
}
.marker.side-l:hover {
  transform: translate(calc(-100% + 15px), -50%) scale(1.03);
}
.marker.side-bl {
  flex-direction: row-reverse;
  padding: var(--s-1) var(--s-2) var(--s-1) var(--s-2);
  transform: translate(calc(-100% + 15px), -4px);
}
.marker.side-bl:hover {
  transform: translate(calc(-100% + 15px), -4px) scale(1.03);
}
.marker.side-tr {
  transform: translate(-15px, calc(-100% + 4px));
}
.marker.side-tr:hover {
  transform: translate(-15px, calc(-100% + 4px)) scale(1.03);
}
.marker.metro {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
  border-color: var(--ca-gold-700);
}
.marker.metro:hover,
.marker.metro.active {
  background: var(--inverse);
  color: var(--ink-inverse);
}
.place-list {
  display: none;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: var(--s-3);
}
.place-list button {
  min-height: 36px;
  padding: 0 var(--s-3) 0 var(--s-2);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
}
.place-list button i {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--ca-red-500);
  display: inline-block;
}
.place-list button.civic i {
  background: var(--inverse);
}
.place-list button.metro i {
  background: var(--ca-gold-500);
}
.place-list button[aria-pressed="true"] {
  background: var(--inverse);
  color: var(--ink-inverse);
  border-color: var(--inverse);
}
.map-stage .dot {
  fill: var(--ca-red-500);
  stroke: #fff;
  stroke-width: 3;
}
.map-stage .dot.civic {
  fill: var(--ca-navy-700);
}
.map-stage .dot.metro {
  fill: var(--ca-gold-500);
}
/* The chosen place, on the map itself. A ring rather than a bigger dot, so
   the point does not move off the thing it marks. */
.map-stage .dot {
  transition:
    r 0.18s ease,
    stroke 0.18s ease,
    stroke-width 0.18s ease;
}
.map-stage .dot.is-on {
  /* r is a CSS geometry property and not everything honours it, so the ring
     carries the state on its own: gold, and twice the width. */
  r: 11;
  stroke: var(--ca-gold-500);
  stroke-width: 6;
  paint-order: stroke;
}
@media (prefers-reduced-motion: reduce) {
  .map-stage .dot {
    transition: none;
  }
}
/* The dots are the markers only while the pills are down. With the pills up
   each carries its own, and these showed as a second pin under the two that
   are offset from their point. */
@media (min-width: 641px) {
  .map-stage .dot {
    display: none;
  }
}
/* Under 640 the pills come off the map: seven of them laid over a shape this
   size overlap each other and leave no map showing. The list below takes over,
   and the dots stay so the map still says where each one is -- which is why
   the dots carry data-place. */
@media (max-width: 640px) {
  .marker {
    display: none;
  }
  .place-list {
    display: flex;
  }
  /* 44, the target size, and wide enough that the labels do not wrap. */
  .place-list {
    gap: var(--s-2);
  }
  .place-list button {
    min-height: 44px;
    flex: 1 1 auto;
    justify-content: flex-start;
  }
}
.map-caption {
  margin-top: var(--s-3);
  font-size: var(--t-3);
  color: var(--ink-3);
}
.map-panel {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-4);
}
.info {
  background: var(--inverse);
  color: var(--ink-inverse);
  border-radius: var(--r-2);
  padding: var(--s-5);
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.6rem;
  min-height: 290px;
  align-content: start;
}
.info .eyebrow {
  color: var(--ca-gold-500);
}
.info .h2 {
  color: var(--ink-inverse);
  font-size: var(--t-8);
}
.info p {
  color: var(--ink-inverse-2);
}
.info ul {
  list-style: none;
  display: grid;
  gap: 0.3rem;
  /* Set in from the prose above it, the way a list is. */
  padding-left: var(--s-3);
  color: var(--ink-inverse-2);
  font-size: var(--t-4);
}
/* The dot takes a column of its own. Inline, a wrapped line came back to the
   dot's left edge instead of hanging under the first word. */
.info ul li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2);
}
.info ul li::before {
  content: "·";
  color: var(--ca-gold-500);
  font-weight: 700;
}
.info .facts {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: var(--s-1);
}
/* Tags, not buttons: filled gold at button proportions reads as something to
   press. Gold-300 on navy-700 is 9.34. */
.info .facts span {
  display: inline-flex;
  align-items: center;
  gap: var(--s-1);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ca-gold-300);
  /* The hairline is the gold at half strength: at full it is a second object
     as loud as the words inside it. */
  border: 1px solid color-mix(in srgb, var(--ca-gold-500) 55%, transparent);
  border-radius: var(--r-1);
  padding: var(--s-1) var(--s-2);
}
.info .facts span::before {
  content: "";
  flex: none;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--ca-gold-500);
}
.info a {
  color: var(--ink-inverse);
}
.picker {
  background: var(--panel);
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  padding: var(--s-4) var(--s-5);
  display: grid;
  gap: 0.6rem;
}
.picker label {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink);
}
.picker .row {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
}
select {
  font: inherit;
  font-family: var(--font-text);
  min-height: 44px;
  padding: 0 2.2rem 0 0.8rem;
  border: 2px solid var(--edge);
  border-radius: var(--r-1);
  background: var(--panel)
    var(--select-chevron)
    no-repeat right 0.7rem center/16px;
  appearance: none;
  -webkit-appearance: none;
  color: var(--ink-deep);
  flex: 1 1 180px;
}
select:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
  border-color: var(--ink);
}
/* The key belongs on the map. The stage already clips and is positioned, so
   it sits in the bottom-left corner, which the county shape leaves clear. */
.map-stage .legend {
  position: absolute;
  left: var(--s-4);
  bottom: var(--s-4);
  z-index: 3;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--s-1);
  padding: var(--s-3) var(--s-4);
  background: rgba(255, 255, 255, 0.92);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  font-size: var(--t-2);
}
/* Under 640 the key stops floating over the county and takes a line of its
   own, where it costs nothing and hides nothing. After the rules it
   overrides, not before: same specificity, so source order decides. */
@media (max-width: 640px) {
  .map-stage .legend {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    gap: var(--s-2) var(--s-4);
    margin-top: var(--s-3);
    border: 0;
    padding: 0;
    background: none;
    box-shadow: none;
  }
}

.legend {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  font-size: var(--t-3);
  color: var(--ink-3);
  align-items: center;
}
.legend i {
  display: inline-block;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  margin-right: var(--s-2);
  vertical-align: -1px;
}

/* ---------- Who can run ---------- */
.basics {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
}
@media (max-width: 900px) {
  .basics {
    grid-template-columns: minmax(0, 1fr);
  }
}
.key {
  display: grid;
  gap: 0.75rem;
}
.key div {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.75rem;
  align-items: start;
}
.key p {
  font-size: var(--t-4);
  color: var(--ink-2);
}
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: var(--s-5) 0 var(--s-3);
}
.filters button {
  min-height: 36px;
  padding: 0 var(--s-4);
  border: 2px solid var(--ink);
  border-radius: var(--r-1);
  background: var(--panel);
  color: var(--ink);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  cursor: pointer;
}
.filters button[aria-pressed="true"] {
  background: var(--inverse);
  color: var(--ink-inverse);
}
.filters button:hover {
  background: var(--panel-2);
}
.filters button[aria-pressed="true"]:hover {
  background: var(--inverse-deep);
}
.tbl-wrap {
  overflow-x: auto;
  min-width: 0;
  border: 1px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--panel);
}
.tbl-wrap:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
}
table.qb {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-4);
}
.qb th {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-inverse);
  background: var(--inverse);
  text-align: left;
  padding: var(--s-3) var(--s-3);
  white-space: nowrap;
}
.qb th.n,
.qb td.n {
  text-align: right;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.qb td {
  padding: var(--s-3) var(--s-3);
  border-bottom: 1px solid var(--rule-soft);
  vertical-align: top;
  color: var(--ink-2);
}
.qb td.office {
  font-weight: 700;
  color: var(--ink);
  white-space: nowrap;
}
.qb tbody tr:nth-child(even) td {
  background: var(--cream);
}
.qb tr[hidden] {
  display: none;
}
@media (max-width: 700px) {
  table.qb {
    min-width: 760px;
  }
}
.qb caption {
  caption-side: bottom;
  text-align: left;
  font-size: var(--t-2);
  color: var(--ink-3);
  padding: var(--s-3) 0.85rem;
}
.fit {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s-3);
  margin-top: var(--s-3);
}
.fit button {
  text-align: left;
  padding: var(--s-4);
  border: 2px solid var(--rule);
  border-radius: var(--r-2);
  background: var(--panel);
  cursor: pointer;
  font: inherit;
  color: var(--ink-deep);
  display: grid;
  gap: 0.25rem;
  min-height: 44px;
}
.fit button b {
  font-family: var(--font-accent);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
}
.fit button span {
  font-size: var(--t-3);
  color: var(--ink-3);
}
.fit button:hover {
  border-color: var(--ink-inverse-3);
}
.fit button[aria-pressed="true"] {
  border-color: var(--inverse);
  background: var(--panel-2);
}
.fit-out {
  margin-top: var(--s-4);
  background: var(--inverse);
  color: var(--ink-inverse);
  border-radius: var(--r-2);
  padding: var(--s-5);
  display: grid;
  gap: 0.5rem;
}
.fit-out .eyebrow {
  color: var(--ca-gold-500);
}
.fit-out p {
  color: var(--ink-inverse-2);
}
.fit-out .h3 {
  color: var(--ink-inverse);
}

/* ---------- Ballot / timeline ---------- */
.cycles {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 0.9fr);
  gap: var(--s-6);
  align-items: start;
}
@media (max-width: 900px) {
  .cycles {
    grid-template-columns: minmax(0, 1fr);
  }
}
.timeline {
  list-style: none;
  display: grid;
  gap: 0;
  border-left: 3px solid var(--ca-gold-500);
  margin-left: var(--s-2);
}
.timeline li {
  padding: 0 0 var(--s-5) var(--s-5);
  position: relative;
}
.timeline li::before {
  content: "";
  position: absolute;
  left: -10px;
  top: 0.45rem;
  width: 17px;
  height: 17px;
  border-radius: 50%;
  background: var(--inverse-deep);
  border: 3px solid var(--ca-gold-500);
}
.timeline li.now::before {
  background: var(--ca-gold-500);
}
.timeline .when {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ca-gold-500);
}
.timeline .what {
  font-family: var(--font-text);
  font-size: var(--t-7);
  line-height: 1.15;
  color: var(--ink-inverse);
  margin-top: var(--s-0);
  font-weight: 700;
}
.timeline p {
  margin-top: var(--s-1);
  color: var(--ink-inverse-2);
  font-size: var(--t-4);
}
.steps {
  list-style: none;
  display: grid;
  gap: var(--s-3);
  counter-reset: step;
}
.steps li {
  display: grid;
  grid-template-columns: 44px 1fr;
  gap: var(--s-3);
  align-items: start;
  background: var(--inverse);
  border-radius: var(--r-2);
  padding: var(--s-4);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.steps li::before {
  counter-increment: step;
  content: counter(step);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--ca-gold-500);
  color: var(--ca-navy-900);
  font-family: var(--font-text);
  font-size: var(--t-7);
  display: grid;
  place-items: center;
  font-weight: 700;
}
.steps b {
  display: block;
  font-family: var(--font-text);
  font-weight: 700;
  color: var(--ink-inverse);
  font-size: var(--t-6);
}
.steps p {
  color: var(--ink-inverse-2);
  font-size: var(--t-4);
  margin-top: var(--s-1);
}
.terms {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--t-4);
  margin-top: var(--s-4);
}
.terms th {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-2);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ca-gold-500);
  text-align: left;
  padding: var(--s-2) var(--s-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}
.terms td {
  padding: var(--s-2) var(--s-2);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  color: var(--ink-inverse-2);
  vertical-align: top;
}
.terms td:first-child {
  color: var(--ink-inverse);
  font-weight: 600;
}
.terms tr.next td {
  color: var(--ink-inverse);
}
.terms tr.next td:first-child::after {
  content: "next";
  font-family: var(--font-accent);
  font-size: var(--t-1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ca-navy-900);
  background: var(--ca-gold-500);
  padding: var(--s-0) var(--s-2);
  border-radius: 3px;
  margin-left: var(--s-2);
  vertical-align: middle;
}

/* ---------- CTA ---------- */
@media (max-width: 900px) {
  }

/* Footer
   ============================================================
   Pitch band with the torch, links on cream, stars and legal line. */
.site-footer {
  background: var(--inverse-deep);
  color: var(--ink-inverse-2);
  padding: 0;
  border-top: 0;
}
.site-footer .wrap {
  display: block;
}
.site-footer .ft-cols p {
  max-width: none;
  font-size: var(--t-5);
}

/* 1 · pitch band: navy-700 between two gold rules, so the red panel above
   never meets navy and the cream below gets its own edge */
.ft-band {
  /* Not a grid: one in-flow child and no tracks, and as a grid the child's
     margin-inline:auto suppressed its stretch, so .wrap shrank to its content. */
  display: block;
  position: relative;
  overflow: hidden;
  background: var(--inverse);
  border-top: 3px solid var(--ca-gold-500);
  border-bottom: 2px solid var(--ca-gold-500);
  min-height: 300px;
}
.site-footer .ft-band .wrap {
  position: relative;
  z-index: 1;
  display: grid;
  justify-items: start;
  gap: var(--s-5);
  padding-block: var(--s-7);
  padding-right: calc(var(--gutter) + 170px);
}
.ft-band-copy {
  position: relative;
  display: grid;
  gap: var(--s-3);
}
.ft-band-actions {
  position: relative;
}
.ft-band-lead {
  margin: 0;
  max-width: 52ch;
  font-size: var(--t-6);
  line-height: 1.5;
  color: var(--ink-inverse-2);
}
.ft-pitch {
  font-family: var(--font-display);
  font-weight: 400;
  /* The same size as the hero's headline, which is what this line answers. */
  font-size: clamp(2.65rem, 5.8vw, 4.75rem);
  line-height: 1.1;
  color: var(--ink-inverse);
  max-width: 24ch;
  margin: 0;
  text-wrap: balance;
}

/* One SVG across the band. The viewBox is extended left rather than the
   element narrowed, so scale stays driven by the band's height: same torch at
   any width, only the rays are cut. */
.ft-torch {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  pointer-events: none;
  z-index: 0;
}
/* The flames morph with SVG's own animation in the markup. A CSS transform on
   top of that put a skew over a morph and read as neither. */
.ft-flame-core {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: ft-flicker-in 1.7s ease-in-out infinite;
}
.ft-glow {
  animation: ft-glow 4.8s ease-in-out infinite;
}
@keyframes ft-flicker-in {
  0%,
  100% {
    transform: scale(1, 1);
  }
  38% {
    transform: scale(0.93, 1.08);
  }
  70% {
    transform: scale(1.05, 0.95);
  }
}
@keyframes ft-glow {
  0%,
  100% {
    opacity: 0.72;
  }
  50% {
    opacity: 1;
  }
}
/* animation-play-state reaches the CSS animations only. The morph is SVG's own
   animation and is stopped by pauseAnimations() on the element, in footer.js. */
.ft-torch.is-paused * {
  animation-play-state: paused;
}
/* Stops the CSS half. The morph needs pauseAnimations(), which footer.js calls
   under the same query: animation:none does not reach SVG's own animation. */
@media (prefers-reduced-motion: reduce) {
  .ft-torch * {
    animation: none;
  }
}

/* Pause, Stop, Hide (2.2.2). 45% still puts the mark at 3.45:1 on the band;
   the 3:1 a control needs is measured on the mark, not the box round it. */
.ft-pause {
  position: absolute;
  right: var(--gutter);
  bottom: var(--s-4);
  z-index: 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  border: 2px solid currentColor;
  border-radius: var(--r-1);
  background: none;
  color: var(--ink-inverse-2);
  opacity: 0.45;
  cursor: pointer;
  transition: opacity 0.2s;
}
.ft-pause:hover,
.ft-pause:focus-visible {
  opacity: 1;
}
.ft-pause:focus-visible {
  outline: 3px solid var(--ca-focus-dark);
  outline-offset: 2px;
}
.ft-pause svg {
  width: 12px;
  height: 12px;
  fill: currentColor;
}
.ft-pause .ft-pause-play {
  display: none;
}
.ft-pause[aria-pressed="true"] .ft-pause-bars {
  display: none;
}
.ft-pause[aria-pressed="true"] .ft-pause-play {
  display: block;
}

/* 2 · links on cream */
.ft-cols {
  background: var(--cream);
  color: var(--ink-2);
}
.site-footer .ft-cols .wrap {
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 0;
  padding-block: var(--s-7);
}
.ft-col {
  display: grid;
  align-content: start;
  gap: var(--s-4);
  border-left: 1px solid var(--rule);
  padding-left: var(--s-6);
}
.ft-col:first-child {
  border-left: 0;
  padding-left: 0;
  padding-right: var(--s-6);
  gap: var(--s-5);
}
.ft-cols .eyebrow {
  color: var(--link);
  margin: 0;
}
.ft-rule {
  width: 36px;
  height: 2px;
  background: var(--ca-gold-500);
  margin-top: calc(-1 * var(--s-2));
}
.ft-mark {
  display: flex;
  align-items: center;
  gap: var(--s-4);
}
.ft-badge {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  flex: none;
}
.ft-blurb {
  color: var(--ink-2);
  line-height: 1.6;
  max-width: 46ch;
}
.ft-write {
  display: grid;
  gap: var(--s-1);
  justify-items: start;
}
/* Same monoline as the rest of the site's glyphs -- 24px box, 1.6 stroke,
   currentColor -- so they take the link's colour with the label. */
.ft-social {
  list-style: none;
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
}
.site-footer .ft-social-link {
  display: inline-flex;
  align-items: center;
  gap: var(--s-3);
  font-weight: 600;
  font-size: var(--t-6);
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--ca-gold-500);
  text-underline-offset: 0.25em;
  text-decoration-skip-ink: none;
}
.ft-social-i {
  width: 1.15em;
  height: 1.15em;
  flex: none;
  /* Outside the underline, which the label owns. */
  text-decoration: none;
}
.site-footer .ft-social-link:hover {
  color: var(--link-hover);
  text-decoration-color: var(--ca-red-700);
}
.site-footer .ft-links {
  list-style: none;
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  font-size: var(--t-5);
}
.ft-links li {
  display: flex;
  align-items: baseline;
  gap: var(--s-2);
}
.ft-num {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-2);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold-ink);
  font-variant-numeric: tabular-nums;
  min-width: 1.4em;
}
.site-footer .ft-links a {
  color: var(--ink);
  font-weight: 500;
  line-height: 1.35;
  text-decoration: none;
  padding-block: var(--s-0);
}
.site-footer .ft-links a:hover {
  color: var(--link);
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--ca-gold-500);
  text-underline-offset: 0.22em;
}
.ft-ext {
  display: inline;
  width: 11px;
  height: 11px;
  margin-left: 0.3em;
  vertical-align: -1px;
  opacity: 0.7;
}

/* 3 · stars and legal line on navy-900 */
.ft-legal-band {
  background: var(--inverse-deep);
  border-top: 3px solid var(--ca-gold-500);
}
.site-footer .ft-legal-band .wrap {
  display: grid;
  gap: var(--s-4);
  padding-block: var(--s-5) var(--s-6);
}
.ft-legal {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3) var(--s-6);
  font-size: var(--t-2);
  line-height: 1.5;
  color: var(--ink-inverse-3);
}
/* The notes take the whole row. This used to reserve space for the signature
   laid over its right end, which only worked while the signature was folded
   down to the mark. */
.ft-legal-text {
  flex: 1 1 100%;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--s-2) var(--s-6);
}
.ft-legal span:first-child {
  color: var(--ink-inverse-2);
}

@media (max-width: 900px) {
  .ft-torch,
  .ft-pause {
    display: none;
  }
  .ft-band {
    min-height: 0;
  }
  .site-footer .ft-band .wrap {
    padding-right: var(--gutter);
  }
  .site-footer .ft-cols .wrap {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-6);
  }
  .ft-col,
  .ft-col:first-child {
    border-left: 0;
    padding-left: 0;
    padding-right: 0;
  }
}
@media (max-width: 480px) {
  .ft-mark {
    flex-direction: column;
    align-items: flex-start;
  }
  .ft-pitch {
    font-size: var(--t-10);
  }
}

/* A button label stays on one line: where it will not fit, the type comes
   down a step and the padding in. Below this width every filled button is
   full-bleed anyway, so they step together. .btn-tertiary is excluded -- it is
   link-shaped with long labels in narrow cards, and wraps between words. */
@media (max-width: 380px) {
  .btn,
  .ca-ev-btn,
  .ca-what-pb-tab {
    font-size: var(--t-4);
    letter-spacing: 0.06em;
    padding-inline: var(--s-4);
  }
  }

/* ---------- Quick Book tab + drawer ---------- */
.qb-tab {
  position: fixed;
  right: 0;
  bottom: var(--tab-foot);
  width: var(--tab-w);
  z-index: 70;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  writing-mode: vertical-rl;
  text-orientation: mixed;
  background: var(--ca-red-500);
  color: #fff;
  border: 1px solid #fff;
  border-right: 0;
  border-top: 4px solid var(--ca-gold-500);
  border-radius: var(--r-1) 0 0 var(--r-1);
  padding: var(--s-4) var(--s-2);
  font-family: var(--font-accent);
  font-weight: 700;
  font-size: var(--t-5);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  box-shadow: 0 18px 55px rgba(1, 19, 47, 0.48);
  transition:
    background-color 0.15s,
    padding 0.15s,
    opacity 0.3s,
    transform 0.3s;
}
.qb-tab:hover {
  background: var(--ca-red-700);
  padding-right: var(--s-3);
}
.qb-tab:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
}
/* Barlow Condensed: ascent 1.0em, descent 0.2em, so the line-box centre sits
   0.05em block-start of the cap centre. In vertical-rl that is the right, so
   the mark shifts 0.05em left. translate, not transform, which the rotation
   already owns. */
.qb-tab svg {
  width: 1.1em;
  height: 1.1em;
  flex: none;
  transform: rotate(90deg);
  translate: -0.05em 0;
}
/* The payoff card lands in this corner, so the tab slides off while it is up.
   Only while the hero is on screen: the card keeps .show once a scene is
   finished, and gating on that alone hid the tab on every section below. */
body:has(#rebuild-story.on-screen .payoff.show) .qb-tab {
  opacity: 0;
  transform: translateX(110%);
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .qb-tab {
    transition:
      background-color 0.15s,
      padding 0.15s;
  }
}
@media (max-width: 640px) {
  /* Both tabs read their foot from the one token; a literal here would put them
     apart. */
  :root {
    --tab-foot: 14px;
  }
  /* Laid on its side the tab is as wide as its words. The base width is a
     vertical tab's thickness, which wrapped QUICK BOOK onto two lines. */
  /* The mark alone. The words are the length of a phone's whole thumb reach
     lying across the foot of the screen, and the book already says which tab
     this is -- it is the same mark the nav link carries. The button keeps
     aria-label="Quick Book", so the name does not change with the width. */
  .qb-tab-word {
    display: none;
  }
  /* Both tabs are the same square. --tab-w is the thickness of a vertical
     tab, which is 43; laid flat beside the signature they are 40 by 40. */
  .qb-tab,
  .ss-egg {
    width: var(--tab-h);
  }
  .qb-tab {
    justify-content: center;
    white-space: nowrap;
    writing-mode: horizontal-tb;
    /* Standing up the gold is the leading edge. Laid down that is the left side,
       the right having run off the screen. */
    border-top: 1px solid #fff;
    border-left: 4px solid var(--ca-gold-500);
    border-radius: var(--r-1) 0 0 var(--r-1);
    /* Height off the token, not padding, so it matches the signature exactly.
       Border-box, so the gold edge and hairlines sit inside the 40. */
    height: var(--tab-h);
    padding: 0;
  }
  .qb-tab svg {
    width: 20px;
    height: 20px;
    transform: none;
    translate: 0;
  }
}
.drawer {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: none;
}
.drawer.open {
  display: block;
}
.drawer .scrim {
  position: absolute;
  inset: 0;
  background: rgba(1, 19, 47, 0.6);
}
.drawer .sheet {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: min(440px, 92vw);
  background: var(--panel);
  box-shadow: var(--e-3);
  display: grid;
  grid-template-rows: auto 1fr auto;
  border-left: 6px solid var(--ca-gold-500);
}
.drawer .sheet header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-4) var(--s-5);
  background: var(--inverse);
  color: var(--ink-inverse);
}
.drawer .sheet header .h3 {
  color: var(--ink-inverse);
  font-family: var(--font-text);
  font-weight: 400;
  font-size: var(--t-7);
}
.drawer .close {
  min-width: 44px;
  min-height: 44px;
  border: 2px solid var(--ink-inverse);
  border-radius: var(--r-1);
  background: transparent;
  color: var(--ink-inverse);
  cursor: pointer;
  display: grid;
  place-items: center;
}
.drawer .close:focus-visible {
  outline-color: var(--ca-focus-dark);
}
.drawer .close svg {
  width: 18px;
  height: 18px;
}
.toc {
  overflow: auto;
  padding: var(--s-4) var(--s-5) var(--s-5);
  display: grid;
  gap: 0.5rem;
  align-content: start;
}
.toc p {
  font-size: var(--t-4);
  color: var(--ink-3);
  margin-bottom: var(--s-1);
}
.toc a {
  display: grid;
  grid-template-columns: 12px 1fr auto;
  gap: 0.7rem;
  align-items: center;
  padding: var(--s-3) var(--s-3) var(--s-3) var(--s-2);
  border: 1px solid var(--rule);
  border-left-width: 6px;
  border-radius: var(--r-1);
  text-decoration: none;
  color: var(--ink-deep);
  font-weight: 600;
  background: var(--panel);
}
.toc a small {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-1);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.toc a:hover {
  background: var(--panel-2);
  color: var(--ink);
}
.toc a i {
  width: 12px;
  height: 12px;
  border-radius: 2px;
  display: inline-block;
}
.drawer .sheet footer {
  padding: var(--s-4) var(--s-5) var(--s-5);
  border-top: 1px solid var(--rule-soft);
  display: grid;
  gap: 0.5rem;
}

/* ---------- Punch card ----------
   Holes read as unpunched stock until marked, then a Ray Gold star stamps
   through. All of it stops under prefers-reduced-motion. */
.punchcard {
  background: var(--inverse-deep);
  color: var(--ink-inverse);
  overflow: hidden;
}
.punchcard .wrap {
  display: grid;
  grid-template-columns: minmax(0, 22rem) minmax(0, 1fr);
  gap: var(--s-7);
  align-items: start;
}
@media (max-width: 900px) {
  .punchcard .wrap {
    grid-template-columns: minmax(0, 1fr);
    gap: var(--s-5);
  }
}
/* The headline is sized against its column. A wider column buys it 44px, but
   below about 1088px the card drops to one cell across and runs to sixteen
   rows, so the column only widens where there is room for both. */
@media (min-width: 1200px) {
  .punchcard .wrap {
    grid-template-columns: minmax(0, 26rem) minmax(0, 1fr);
  }
}

.pc-head {
  display: grid;
  gap: var(--s-3);
  position: sticky;
  top: 84px;
  /* the headline is sized against this column, below */
  container-type: inline-size;
}
@media (max-width: 900px) {
  .pc-head {
    position: static;
  }
}
.punchcard .display {
  color: var(--ink-inverse);
  /* "Real momentum." is 9.1em of Alfa Slab One, so it is measured against the
     column rather than the viewport to hold the two lines it is written as. */
  font-size: min(clamp(2rem, 4.2vw, 3.4375rem), 10.5cqi);
}
.punchcard .eyebrow {
  color: var(--ca-gold-500);
}
.punchcard .lead {
  color: var(--ink-inverse-2);
  max-width: 40ch;
}
.punchcard .pc-note {
  color: var(--ink-inverse-3);
  max-width: 38ch;
}

/* Progress: a ring that fills, and a number that carries the news. */
.pc-meter {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  margin-top: var(--s-2);
}
.pc-ring {
  width: 84px;
  height: 84px;
  flex: none;
  transform: rotate(-90deg);
}
.pc-ring circle {
  fill: none;
  stroke-width: 8;
  stroke-linecap: round;
}
.pc-ring-bg {
  stroke: var(--track);
}
.pc-ring-fg {
  stroke: var(--ca-gold-500);
  stroke-dasharray: 226;
  stroke-dashoffset: 226;
  transition: stroke-dashoffset 0.5s cubic-bezier(0.2, 0.8, 0.2, 1);
}
.pc-count {
  display: grid;
  line-height: 1.1;
}
.pc-count b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-12);
  color: var(--ca-gold-500);
  font-variant-numeric: tabular-nums;
}
.pc-count span {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-inverse-2);
}
.punchcard .pc-status {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-6);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ca-gold-500);
  min-height: 1.4em;
}
.pc-status:empty {
  display: none;
}

/* The card stock, with a perforated tear-off edge. */
.pc-card {
  position: relative;
  background: var(--paper);
  border-radius: var(--r-3);
  padding: var(--s-5) var(--s-5) var(--s-5) var(--s-6);
  box-shadow: var(--e-3);
}
.pc-rail {
  position: absolute;
  inset: 0 auto 0 var(--s-4);
  width: 2px;
  background: repeating-linear-gradient(
    var(--ca-limestone) 0 6px,
    transparent 6px 12px
  );
}
@media (max-width: 560px) {
  .pc-card {
    padding: var(--s-4);
  }
  .pc-rail {
    display: none;
  }
}

/* Bleeds past the card's padding to the corners, and sits above the rail: the
   rail is positioned, so it paints over static content unless this is too. */
.pc-card-head {
  position: relative;
  z-index: 1;
  margin:
    calc(-1 * var(--s-5))
    calc(-1 * var(--s-5))
    var(--s-5)
    calc(-1 * var(--s-6));
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: var(--s-2) var(--s-5);
  padding: var(--s-4) var(--s-5);
  border-radius: var(--r-3) var(--r-3) 0 0;
  background: var(--inverse);
  color: var(--ink-inverse);
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  line-height: 1.3;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}
.pc-card-head b {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: var(--t-9);
  line-height: 1.1;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ca-white);
}
.pc-card-head span:last-child {
  color: var(--ca-gold-500); /* 6.09 on navy-700 */
}
.pc-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  grid-auto-rows: 1fr;
  gap: var(--s-2);
}
/* The organisation links inside the label cost two things, both paid for: a
   click on one would also tick the box, except that HTML says a label does
   nothing for events aimed at interactive content inside it; and the link
   text would fold into the box's name, so those nine inputs carry aria-label. */
.pc-cell {
  display: flex;
  flex-direction: column;
  min-height: 64px;
  padding: var(--s-3);
  border: 1px dashed var(--rule);
  border-radius: var(--r-2);
  background: var(--panel);
  transition:
    border-color 0.18s ease,
    background 0.18s ease;
}
.pc-cell label {
  flex: 1;
}
/* .pc-cell, not .pc-text a alone: .on-dark a is a class and an element and
   outranks a single class. The link was taking --ca-paper on white, 1.06:1. */
.pc-cell .pc-text a {
  /* Blue against the navy of the line it sits in, and it holds on all three
     grounds a cell can have: 9.97 on white, 9.25 on the gold hover, 8.71 on
     the red of a punched cell. */
  color: var(--link-alt);
  /* The underline does the work, not the colour: navy-500 against the navy-700
     around it is 1.59. That makes the rule a meaningful graphic, wanting 3.0 --
     gold-500 is 2.61 on white, so this is gold-700 at 5.57. */
  text-decoration: underline;
  text-decoration-thickness: 2px;
  text-decoration-color: var(--ca-gold-700);
  text-underline-offset: 0.2em;
}
.pc-cell .pc-text a:hover,
.pc-cell .pc-text a:focus-visible {
  color: var(--ink);
  text-decoration-thickness: 3px;
}
.pc-cell label {
  display: flex;
  align-items: flex-start;
  gap: var(--s-3);
  cursor: pointer;
}
.pc-cell:hover {
  border-color: var(--ca-gold-500);
  background: var(--wash-gold);
}
.pc-cell input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.pc-cell:focus-within {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
}

/* The hole: a punched-out disc that a star stamps into. */
.pc-hole {
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--panel-3);
  box-shadow: inset 0 2px 4px rgba(2, 32, 79, 0.22);
  display: grid;
  place-items: center;
  transition:
    background 0.18s ease,
    box-shadow 0.18s ease;
}
.pc-hole svg {
  width: 20px;
  height: 20px;
  fill: var(--ca-gold-500);
  transform: scale(0) rotate(-40deg);
  opacity: 0;
  transition:
    transform 0.34s cubic-bezier(0.34, 1.56, 0.64, 1),
    opacity 0.2s ease;
}
.pc-text {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-5);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  line-height: 1.2;
}

/* A repeated activity: a solid left edge so the set reads as one thing, and a
   count, which is the cue that does not rely on colour. */
.pc-cell[data-set] {
  border-left: 3px solid var(--ca-gold-500);
}
.pc-cell[data-set] .pc-text small {
  display: inline-block;
  margin-top: var(--s-2);
  padding: var(--s-0) var(--s-2);
  border-radius: 999px;
  background: var(--wash-gold);
  color: var(--gold-ink); /* 5.17 on gold-50 */
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-1);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The "1 of 4" on the repeated activities: grey, small and on its own line
   under the activity, out of the label's caps and tracking. */
.pc-text small {
  display: block;
  font-family: var(--font-text);
  font-weight: 400;
  font-size: var(--t-2);
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink-3);
  margin-top: var(--s-1);
}
.pc-cell:has(input:checked) {
  border-style: solid;
  border-color: var(--link);
  background: var(--wash-red);
}
.pc-cell:has(input:checked) .pc-hole {
  background: var(--inverse-deep);
  box-shadow: inset 0 0 0 2px var(--ca-gold-500);
}
.pc-cell:has(input:checked) .pc-hole svg {
  transform: scale(1) rotate(0);
  opacity: 1;
}

.pc-reset {
  margin-top: var(--s-4);
  background: none;
  border: 0;
  padding: var(--s-2) 0;
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
  cursor: pointer;
  border-bottom: 2px solid var(--rule);
}
.pc-reset:hover {
  color: var(--link);
  border-bottom-color: var(--link);
}

/* ---------- Send the card in ----------
   A native dialog, so Escape, the backdrop and the focus trap are the
   browser's. */
.pc-dialog {
  position: fixed;
  width: min(34rem, calc(100vw - var(--s-6)));
  /* vh first and dvh second, because a browser that does not understand dvh
     drops that line and keeps this one. With no max-height at all the sheet
     grows past the screen, nothing scrolls it because nothing is over-full,
     and the page behind is locked -- which is a trap rather than a dialog.
     That is what this was on a phone.

     The cap needs somewhere to put what it cuts, hence overflow. Contained,
     so a flick that reaches the end of the form does not carry on into the
     page behind it. */
  max-height: calc(100vh - var(--s-6));
  max-height: calc(100dvh - var(--s-6));
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  overscroll-behavior: contain;
  padding: 0;
  border: 0;
  border-radius: var(--r-3);
  background: var(--dialog);
  color: var(--ink);
  box-shadow: var(--e-3);
}
/* On a phone the form is taller than the screen whatever is done to it, so it
   stops pretending to be a centred card: full width against the bottom edge,
   where a thumb is, with the top two corners rounded and the rest of the
   screen showing the page it came from. inset and margin are stated rather
   than left to the user agent, which centres a modal and would fight this. */
@media (max-width: 640px) {
  .pc-dialog {
    inset: 0;
    width: 100%;
    max-width: none;
    max-height: 86vh;
    max-height: 86dvh;
    margin: auto auto 0;
    border-radius: var(--r-3) var(--r-3) 0 0;
  }
  .pc-form {
    padding: var(--s-4) var(--s-4) var(--s-5);
  }
  /* The form is taller than the sheet, so the two buttons ride the bottom
     edge rather than waiting under it. Negative margins take them out to the
     sheet's own sides; the background is the sheet's, or the form would show
     through as it passes underneath. Both buttons are here, so the way out is
     as reachable as the way on. */
  .pc-form-actions {
    position: sticky;
    bottom: calc(var(--s-5) * -1);
    z-index: 1;
    margin: var(--s-1) calc(var(--s-4) * -1) calc(var(--s-5) * -1);
    padding: var(--s-3) var(--s-4);
    border-top: 1px solid var(--rule);
    background: var(--dialog);
  }
  .pc-form-actions .btn {
    flex: 1 1 auto;
  }
}

/* The page behind a modal holds still. Stated with :has rather than toggled
   from script: there is no restore step to get wrong, and no second thing
   fighting over body.style.overflow the way the drawer does. */
body:has(.pc-dialog[open]) {
  overflow: hidden;
}
.pc-dialog::backdrop {
  background: var(--scrim);
}
.pc-form {
  position: relative;
  display: grid;
  gap: var(--s-3);
  padding: var(--s-5);
}
/* Nothing in here inherits. The dialog is out of the punch card section now,
   but a modal is a surface of its own and it should not be one section's
   change away from unreadable again. */
.pc-dialog,
.pc-dialog h2,
.pc-dialog p,
.pc-dialog li,
.pc-dialog label {
  color: var(--ink);
}
.pc-dialog a {
  color: var(--link); /* 7.15 on paper */
  text-decoration-thickness: 2px;
  text-underline-offset: 0.2em;
}
.pc-dialog a:hover,
.pc-dialog a:focus-visible {
  color: var(--link-hover);
}
.pc-form-head {
  display: grid;
  gap: var(--s-2);
  /* clear of the close button */
  padding-right: var(--s-6);
}
.pc-form-head .eyebrow {
  color: var(--gold-ink); /* 5.57 on paper */
}
.pc-form-head h2 {
  margin: 0;
  font-family: var(--font-display);
  font-size: var(--t-11); /* 36px, and the slab's floor is 24 */
  line-height: 1.05;
  color: var(--ink); /* 15.88 on paper */
}
.pc-form-head p {
  margin: 0;
  font-size: var(--t-5);
  color: var(--ink-2); /* 12.28 on paper, against the slate it was */
}
/* The close X. A dialog closes on Escape and on the backdrop already; this is
   the one a reader can see. */
.pc-form-x {
  position: absolute;
  top: var(--s-3);
  right: var(--s-3);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: var(--r-1);
  background: none;
  color: var(--ink-3);
  cursor: pointer;
}
.pc-form-x svg {
  width: 20px;
  height: 20px;
}
.pc-form-x:hover {
  color: var(--link);
  background: var(--panel-3);
}
.pc-form-x:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
}
/* What is going in the envelope, said in full rather than as a number. */
.pc-form-tally {
  padding: var(--s-3);
  border-left: 3px solid var(--ca-gold-500);
  background: var(--wash-gold);
}
.pc-form-count {
  margin: 0;
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-4);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--gold-ink); /* 5.16 on gold-50 */
}
.pc-form-list {
  list-style: none;
  margin: var(--s-2) 0 0;
  padding: 0;
  display: grid;
  gap: var(--s-1);
  font-size: var(--t-4);
  color: var(--ink-2); /* 11.6 on gold-50 */
}
.pc-form-list li {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--s-2);
}
.pc-form-list li::before {
  content: "★";
  color: var(--gold-ink);
}
.pc-form-list li span {
  color: var(--ink-3);
}
.pc-form-list.is-empty li::before {
  content: "·";
}
.pc-field {
  display: grid;
  gap: var(--s-1);
}
.pc-field label {
  font-family: var(--font-accent);
  font-weight: 600;
  font-size: var(--t-3);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink);
}
/* The optional marker rides on the label rather than taking a line. */
.pc-field label span {
  font-weight: 500;
  letter-spacing: 0.04em;
  text-transform: none;
  color: var(--ink-3);
}
.pc-field input,
.pc-field textarea {
  min-height: 44px;
  padding: var(--s-2) var(--s-3);
  border: 1px solid var(--rule);
  border-radius: var(--r-1);
  background: var(--panel);
  font-family: var(--font-text);
  font-size: var(--t-5);
  color: var(--ink-deep);
}
.pc-field textarea {
  resize: vertical;
  line-height: 1.5;
}
.pc-field input:focus-visible,
.pc-field textarea:focus-visible {
  outline: 3px solid var(--ca-focus);
  outline-offset: 2px;
  border-color: var(--ink);
}
.pc-form-status:empty {
  display: none;
}
.pc-form-status {
  margin: 0;
  font-size: var(--t-4);
  color: var(--link-hover); /* 9.87 on paper, and it is the only thing it says */
}
.pc-form-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-1);
}
/* The honeypot. Off the page rather than display:none, which some bots skip. */
.pc-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Cells deal in as the card scrolls into view. */
.pc-card[data-pc] .pc-cell {
  opacity: 0;
  transform: translateY(10px);
}
.pc-card.is-dealt .pc-cell {
  opacity: 1;
  transform: none;
  transition:
    opacity 0.4s ease calc(var(--i) * 28ms),
    transform 0.4s cubic-bezier(0.2, 0.8, 0.2, 1) calc(var(--i) * 28ms);
}

/* A finished card says so. */
.pc-card.is-complete {
  box-shadow:
    0 0 0 3px var(--ca-gold-500),
    var(--e-3);
}
.punchcard.is-complete .pc-count b {
  color: var(--ca-gold-300);
}

@media (prefers-reduced-motion: reduce) {
  .pc-card[data-pc] .pc-cell {
    opacity: 1;
    transform: none;
  }
  .pc-card.is-dealt .pc-cell {
    transition: none;
  }
  .pc-hole svg {
    transition: none;
  }
  .pc-ring-fg {
    transition: none;
  }
}

/* ---------- Header bar ----------
   Breaks out of the 1180px .wrap cap so the two ends sit at the screen edges.
   Scoped above the drawer breakpoint, which stacks these in a column. */
@media (min-width: 1150px) {
  .site-header .wrap {
    max-width: none;
    gap: var(--s-6);
  }
  .site-nav {
    margin-left: 0;
    flex: 1 1 auto;
    min-width: 0;
  }
  .site-nav ul {
    flex: 1 1 auto;
    /* A set gap, not space-evenly, which handed the labels whatever the track had
       spare and pushed them 25px apart at the narrow end of this tier. */
    justify-content: center;
    gap: var(--s-3);
    /* On very wide screens an unbounded track flings the group into the far
       corners, so hold it together, centred between the badge and the button. */
    max-width: 900px;
    margin-inline: auto;
  }
  .site-nav li a {
    white-space: nowrap;
  }
  .site-nav .btn {
    flex: none;
    margin-left: var(--s-6);
  }
}

/* Between the drawer breakpoint and a wide bar the five labels and the button
   are tight, so trim the padding and tracking rather than let them collide. */
@media (min-width: 1150px) and (max-width: 1319px) {
  .site-header .wrap {
    gap: var(--s-4);
  }
  .site-nav ul {
    gap: var(--s-2);
  }
  .site-nav li a {
    padding: var(--s-2) var(--s-2);
    font-size: var(--t-3);
    letter-spacing: 0.04em;
  }
  .site-nav .btn {
    margin-left: var(--s-3);
    padding: 0 var(--s-4);
  }
}

/* The Quick Book nav link carries the same book mark as the floating tab, so
   the two ways into the docs read as one thing. */
/* Ranged left. On the bar the row shrink-wraps; in the drawer this anchor is
   the full width of the panel and centring left it out of line. */
.site-nav .nav-book {
  display: flex;
  align-items: center;
  justify-content: flex-start;
  gap: 0.45rem;
}
.site-nav .nav-book svg {
  width: 1.05em;
  height: 1.05em;
  flex: none;
  /* All-caps labels fill only the cap box, so a centred icon sits low. Barlow
     Condensed: ascent 1.0em, descent 0.2em, cap 0.7em -- lift by 0.05em. */
  transform: translateY(0.08em);
}

/* Builder signature
   ==========================================================================
   A tab under the Quick Book one: same width, edge and foot, left corners
   rounded, right side off screen. Folded to the mark until reached for. Up
   only while the footer is on screen, which footer.js watches. */
.ss-egg {
  position: fixed;
  right: 0;
  bottom: var(--tab-foot);
  z-index: 69;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--tab-w);
  height: var(--tab-h);
  padding: 0;
  border: 1px solid #fff;
  border-right: 0;
  border-radius: var(--r-1) 0 0 var(--r-1);
  background: #0d1218;
  box-shadow: 0 18px 55px rgba(1, 19, 47, 0.48);
  opacity: 0;
  pointer-events: none;
  color: #a9b7c6;
  /* IBM Plex Mono 600, tracked 0.08em. 10.5px is off this site's scale, which
     floors at 12; the signature is the same size wherever it appears. */
  font-family: var(--font-mono);
  font-weight: 600;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  transition:
    opacity 0.35s,
    width 0.45s var(--ca-ease),
    color 0.3s;
}
/* Only in the footer. Without the class -- without script -- it stays down. */
.site-footer.on-screen .ss-egg {
  opacity: 1;
  pointer-events: auto;
}
/* Reaching for it slides the wordmark out of the edge. */
.site-footer.on-screen .ss-egg:hover,
.site-footer.on-screen .ss-egg:focus-visible,
.site-footer.on-screen .ss-egg.is-open {
  width: 190px;
  justify-content: flex-start;
  padding: 0 11px;
}
.ss-egg:hover,
.ss-egg:focus-visible,
.ss-egg.is-open {
  /* The mark's own orange, not the site's gold: the signature is set the same
     wherever it appears. */
  color: #ff6a2c;
}
.ss-egg:focus-visible {
  outline: 3px solid var(--ca-focus-dark);
  outline-offset: 3px;
}
/* The mark's own margins were for sitting in a line of text; here the flexbox
   centres it and the word owns the gap. */
.ss-egg .stackmark {
  margin: 0;
}
.ss-egg-word {
  max-width: 0;
  padding-left: 0;
  overflow: hidden;
  transition:
    max-width 0.45s var(--ca-ease),
    padding-left 0.45s;
}
.ss-egg:hover .ss-egg-word,
.ss-egg:focus-visible .ss-egg-word,
.ss-egg.is-open .ss-egg-word {
  max-width: 190px;
  padding-left: 6px;
}

/* The Quick Book tab sits on top of it, at every width. */
.qb-tab {
  bottom: calc(var(--tab-foot) + var(--tab-h) + var(--s-2));
}

/* ---------- Light · Dark · Auto ----------
   The segmented control from ezwastenc.com, in Ray Gold. Same geometry: a
   1px accent outline, 4px of padding, 2px between the segments. Body type at
   its own weight
   rather than the site's tracked caps, which is what makes it read as a
   setting rather than a call to action.

   Their filled segment is white on a deeper orange, because white on the
   display orange does not clear AA. Gold has the same problem -- white on
   gold-500 is 2.05 -- so this takes the pair the site already uses for a
   filled control on a dark ground: navy-900 on gold-500, 7.09. Unfilled is
   gold-500 on the band at the same 7.09.

   A fieldset of radios, so arrow keys and roving focus come free; the inputs
   are moved off screen rather than display:none, which would take them out of
   the tab order with them. */
.theme-switch {
  display: flex;
  width: fit-content;
  align-items: center;
  gap: 2px;
  /* Ranged right under the last column, so it sits with the edge of the grid
     rather than starting a fourth column of its own. */
  margin: var(--s-5) 0 0 auto;
  padding: var(--s-1);
  border: 1px solid var(--ca-gold-500);
  border-radius: var(--r-1);
}
.theme-switch label {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* the 24px floor 2.5.8 puts under a target */
  min-height: 24px;
  padding: var(--s-1) var(--s-3);
  border-radius: var(--r-1);
  font-family: var(--font-text);
  font-weight: 500;
  font-size: var(--t-1);
  line-height: 1;
  color: var(--ca-gold-500); /* 7.09 on navy-900 */
  cursor: pointer;
  transition:
    background-color 0.2s,
    color 0.2s;
}
.theme-switch input {
  position: absolute;
  width: 100%;
  height: 100%;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}
.theme-switch label:hover {
  background: color-mix(in srgb, var(--ca-gold-500) 14%, transparent);
}
.theme-switch label:has(input:checked) {
  background: var(--ca-gold-500);
  color: var(--ca-navy-900); /* 7.09 on gold-500 */
}
.theme-switch label:has(input:focus-visible) {
  outline: 3px solid var(--ca-focus-dark);
  outline-offset: 2px;
}
@media (prefers-reduced-motion: reduce) {
  .theme-switch label {
    transition: none;
  }
}

/* Three stacked bars with the top one lit: the StoryStack mark. */
.stackmark {
  display: inline-block;
  position: relative;
  width: 11px;
  height: 11px;
  margin: 0 var(--s-1) -1px 0;
}
.stackmark span {
  position: absolute;
  left: 0;
  height: 2px;
  border-radius: 1px;
  background: #7d8b9c;
}
.stackmark span:nth-child(1) {
  top: 1px;
  width: 70%;
  background: #ff6a2c;
}
.stackmark span:nth-child(2) {
  top: 5px;
  width: 100%;
}
.stackmark span:nth-child(3) {
  top: 9px;
  width: 55%;
}
/* The bars land bottom-first, the lit one last, each on an arc. Top and
   bottom come from the left, the middle from the right, so they alternate. */
@keyframes stack-drop {
  /* every step lists translate/rotate/scaleX in the same order, or the browser
     has nothing to interpolate between */
  0% {
    transform: translate(-11px, -6px) rotate(-14deg) scaleX(1);
    opacity: 0;
    animation-timing-function: cubic-bezier(0.2, 0.6, 0.4, 1);
  }
  28% {
    transform: translate(-6px, -8px) rotate(-9deg) scaleX(1);
    opacity: 1;
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.5);
  }
  62% {
    transform: translate(0, 0) rotate(0deg) scaleX(1);
    opacity: 1;
    animation-timing-function: ease-out;
  }
  75% {
    transform: translate(0, 0) rotate(0deg) scaleX(1.14);
    opacity: 1;
  }
  100% {
    transform: translate(0, 0) rotate(0deg) scaleX(1);
    opacity: 1;
  }
}
@keyframes stack-drop-right {
  0% {
    transform: translate(11px, -6px) rotate(14deg) scaleX(1);
    opacity: 0;
    animation-timing-function: cubic-bezier(0.2, 0.6, 0.4, 1);
  }
  28% {
    transform: translate(6px, -8px) rotate(9deg) scaleX(1);
    opacity: 1;
    animation-timing-function: cubic-bezier(0.55, 0, 0.85, 0.5);
  }
  62% {
    transform: translate(0, 0) rotate(0deg) scaleX(1);
    opacity: 1;
    animation-timing-function: ease-out;
  }
  75% {
    transform: translate(0, 0) rotate(0deg) scaleX(1.14);
    opacity: 1;
  }
  100% {
    transform: translate(0, 0) rotate(0deg) scaleX(1);
    opacity: 1;
  }
}
/* the bars are flush left, so the squash spreads right rather than pulling the
   stack off its edge */
.stackmark span {
  transform-origin: left center;
}
.ss-egg:hover .stackmark span,
.ss-egg:focus-visible .stackmark span,
.ss-egg.is-open .stackmark span {
  /* backwards, so a bar waiting out its delay stays up and invisible rather
     than sitting in place and then jumping back up to fall again */
  animation: stack-drop 0.56s backwards;
}
.ss-egg:hover .stackmark span:nth-child(3),
.ss-egg:focus-visible .stackmark span:nth-child(3),
.ss-egg.is-open .stackmark span:nth-child(3) {
  animation-delay: 0s;
}
.ss-egg:hover .stackmark span:nth-child(2),
.ss-egg:focus-visible .stackmark span:nth-child(2),
.ss-egg.is-open .stackmark span:nth-child(2) {
  animation-name: stack-drop-right;
  animation-delay: 0.16s;
}
.ss-egg:hover .stackmark span:nth-child(1),
.ss-egg:focus-visible .stackmark span:nth-child(1),
.ss-egg.is-open .stackmark span:nth-child(1) {
  animation-delay: 0.32s;
}

@media (prefers-reduced-motion: reduce) {
  .ss-egg:hover .stackmark span,
  .ss-egg:focus-visible .stackmark span {
    animation: none;
  }
  .ss-egg,
  .ss-egg-word {
    transition: none;
  }
}

/* 404
   ==========================================================================
   Its own page: no header, no footer, nothing to navigate but the two ways
   back. */
.error-page {
  min-height: 100svh;
  display: grid;
  align-content: center;
  background: var(--inverse-deep);
  color: var(--ink-inverse);
  padding-block: var(--s-7);
  text-align: center;
}
.error-page .wrap {
  display: grid;
  justify-items: center;
  gap: var(--s-3);
  max-width: 44rem;
}
.error-seal {
  width: clamp(112px, 17vw, 196px);
  height: auto;
  margin-bottom: var(--s-2);
  filter: drop-shadow(0 10px 26px rgba(1, 19, 47, 0.6));
}
.error-page .display {
  font-size: clamp(2.25rem, 6vw, 3.5rem);
}
.error-page .lead {
  max-width: 46ch;
}
.error-actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  justify-content: center;
  margin-top: var(--s-3);
}
@media (max-width: 520px) {
  .error-actions {
    width: 100%;
  }
  .error-actions .btn {
    width: 100%;
  }
}

/* The book mark turns a page on hover
   ==========================================================================
   The third path is the right leaf, drawn over the cover, so at rest it is
   invisible. Pivoting on the spine rather than the icon's centre is the
   trick, hence transform-box. */
.nav-book svg .pg,
.qb-tab svg .pg {
  opacity: 0;
  transform-box: view-box;
  transform-origin: 8px 8px;
}
@keyframes book-turn {
  0% {
    transform: scaleX(1);
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  88% {
    opacity: 1;
  }
  100% {
    transform: scaleX(-1);
    opacity: 0;
  }
}
.nav-book:hover svg .pg,
.nav-book:focus-visible svg .pg,
.qb-tab:hover svg .pg,
.qb-tab:focus-visible svg .pg {
  animation: book-turn 0.6s cubic-bezier(0.4, 0, 0.3, 1);
}

@media (prefers-reduced-motion: reduce) {
  .nav-book:hover svg .pg,
  .nav-book:focus-visible svg .pg,
  .qb-tab:hover svg .pg,
  .qb-tab:focus-visible svg .pg {
    animation: none;
  }
}

/* Phone landscape
   ==========================================================================
   Section padding is set from vw, which a landscape phone has plenty of and no
   height for: at 844x390 that is 59px top and bottom. Height gets a say here.
   The drawer is the other one: at 568x320 it needed 296px under a 64px header
   with 256px to give, so the last items were unreachable. It scrolls now. */
@media (orientation: landscape) and (max-height: 520px) {
  .sec,
  .ca-what,
  .ca-ev {
    padding-block: clamp(1.5rem, 5vh, 2.5rem);
  }
  .site-footer {
    padding-block: var(--s-6) var(--s-5);
  }
  .site-nav.open {
    max-height: calc(100svh - 64px);
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .error-page {
    padding-block: var(--s-6);
  }
  .error-seal {
    width: clamp(72px, 12vh, 112px);
  }
}
