/* ============================================================
   The PTO App — "Midnight Coral" design tokens & base styles
   Single hand-authored stylesheet, no framework. Mobile-first.
   This is the product's own skin (see design spec §4) — the site
   wears the app's palette so product and site read as one thing.
   Header/nav/hero/footer/sections arrive in later tasks; tokens +
   type + primitives below are the foundation they build on.
   ============================================================ */

/* ---- 1. Design tokens (spec §4 — verbatim) ----
   --brand / --brand-deep / --navy / --hero-1..3 / category tints
   are IDENTICAL in light and dark (the coral holds in both themes
   by design) so they live once in :root. Only --brand-soft, --bg,
   --surface, --ink, --ink-soft, --line flip — those are restated in
   the dark override AND the prefers-color-scheme fallback so all
   three blocks agree before any toggle click. */
:root {
  --brand:#FF6A55; --brand-deep:#D94B38; --navy:#0A0F28;
  --hero-1:#1B2B6E; --hero-2:#0B1437; --hero-3:#0A0F28;
  --p-events:#3FA6A5; --p-volunteer:#F2B441; --p-fundraising:#E74C8A;
  --p-resources:#7C83DB; --p-surveys:#58BA8E;

  --brand-soft:#FFD5CE;
  --bg:#FAFBFC; --surface:#FFFFFF; --ink:#0A0F28; --ink-soft:#5B6168; --line:#E2E5E9;

  --font-body:"Plus Jakarta Sans",system-ui,sans-serif;
  --font-display:"Fraunces",Georgia,serif;
}
:root[data-theme="dark"] {
  --brand-soft:#3A2430;
  --bg:#0B0E1A; --surface:#141830; --ink:#ECEEF6; --ink-soft:#A0A6C0; --line:#262B45;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --brand-soft:#3A2430;
    --bg:#0B0E1A; --surface:#141830; --ink:#ECEEF6; --ink-soft:#A0A6C0; --line:#262B45;
  }
}

/* ---- 2. Supplemental tokens ----
   Fixed values that don't flip between themes, plus one derived
   token: --brand-ink mixes --brand toward the CURRENT --ink. Since
   --ink itself already flips (near-navy in light, near-white in
   dark), this one formula self-adjusts for both themes with no
   separate dark-mode override block — see the ghost-button note
   in §7 for why plain --brand text can't be used directly. */
:root {
  --radius-sm: 10px;
  --radius-lg: 16px;
  --shadow-card: 0 1px 2px rgba(10,15,40,.06), 0 14px 32px -18px rgba(10,15,40,.35);
  --ease: cubic-bezier(.4,0,.2,1);
  --brand-ink: color-mix(in srgb, var(--brand) 50%, var(--ink) 50%);
  /* AI newsletter pillar (§17): coral mixed toward the resources indigo —
     avoids a third solid-coral pillar (announcements, chat already are)
     while staying in the family palette. Both inputs are theme-invariant
     (spec §4: category tints + brand hold identical light/dark), so this
     derived token needs no separate dark override either. */
  --p-ai: color-mix(in srgb, var(--brand) 55%, var(--p-resources) 45%);
  /* Task 18 a11y fix: plain --brand-deep on --bg measured 4.042:1 in light
     mode (just under the 4.5:1 text floor; dark was already 4.592:1). Same
     color-mix-toward-current-theme's--ink formula as --brand-ink (§ above),
     but a lighter 88/12 mix so the eyebrow keeps reading as "coral", just
     darkened enough in light / lightened enough in dark. Measured (sRGB
     relative luminance): 4.918:1 light, 5.277:1 dark — both clear 4.5:1 with
     real margin (not a razor-thin pass). --brand-ink is untouched, so
     .section--tint's override (below, ~5.8:1 light / ~7.7:1 dark) still
     applies unchanged. */
  --eyebrow-ink: color-mix(in srgb, var(--brand-deep) 88%, var(--ink) 12%);
  color-scheme: light dark;
}
:root[data-theme="light"] { color-scheme: light; }
:root[data-theme="dark"] { color-scheme: dark; }

/* ---- 3. Base element resets ---- */
* { box-sizing:border-box; }
html { scroll-behavior:smooth; scroll-padding-top:4.5rem; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior:auto; } *,*::before,*::after { animation:none!important; transition:none!important; } }
body { margin:0; background:var(--bg); color:var(--ink); font-family:var(--font-body); line-height:1.6; -webkit-font-smoothing:antialiased; }
img, picture, svg { max-width:100%; display:block; }
button, input, textarea, select { font:inherit; color:inherit; }
h1, h2, h3, p, ul, ol, figure { margin:0 0 1em; }
::selection { background:var(--brand-soft); color:var(--brand-deep); }

/* Single focus treatment, reused by every interactive element below.
   --brand-ink (not plain --brand) is used here on purpose: plain
   --brand measures only ~2.7:1 against --bg in light mode (see the
   ghost-button contrast note in §7) — nowhere near the 3:1 floor a
   focus ring needs against arbitrary page backgrounds. --brand-ink
   clears >=5.8:1 against every ground it lands on (bg, surface,
   card, brand-soft) in both themes, so it's the safe universal
   choice for "on brand" focus visibility. */
:focus-visible { outline:3px solid var(--brand-ink); outline-offset:3px; border-radius:4px; }

/* ---- 4. Typography scale ----
   Fraunces (display) only on display/h1/h2 for editorial weight;
   Plus Jakarta Sans everywhere else, including h3 — it reads as a
   "sub-head" rather than another display line. */
h1, h2, .text-display {
  font-family:var(--font-display);
  font-optical-sizing:auto;
  color:var(--ink);
  font-weight:600;
}
.text-display, h1 { line-height:1.08; letter-spacing:-0.015em; }
.text-display { font-size:clamp(2.75rem, 2.05rem + 3vw, 4.75rem); }
h1 { font-size:clamp(2.25rem, 1.85rem + 1.8vw, 3.25rem); }
h2 { font-size:clamp(1.75rem, 1.5rem + 1.1vw, 2.375rem); font-weight:500; line-height:1.2; letter-spacing:0; }

h3 {
  font-family:var(--font-body);
  font-size:clamp(1.1875rem, 1.1rem + 0.4vw, 1.375rem);
  font-weight:700;
  line-height:1.35;
  color:var(--ink);
}

p { font-size:1.0625rem; line-height:1.65; }

.eyebrow {
  display:block;
  font-family:var(--font-body);
  font-size:.8125rem;
  font-weight:700;
  letter-spacing:.09em;
  text-transform:uppercase;
  color:var(--eyebrow-ink);
  margin:0 0 .75em;
}

a {
  color:var(--brand-deep);
  text-decoration-thickness:1.5px;
  text-underline-offset:.15em;
}
a:hover, a:focus-visible { text-decoration-thickness:2.5px; }

/* ---- 5. Layout primitives ---- */
.container { width:min(1160px,92vw); margin-inline:auto; }
.section { padding-block:clamp(3.5rem, 6vw, 6rem); }
.section + .section { border-top:1px solid var(--line); }

/* ---- 6. Reveal-on-scroll ---- */
.reveal { opacity:0; transform:translateY(16px); transition:opacity .6s ease, transform .6s ease; }
.reveal.is-visible { opacity:1; transform:none; }

/* ============================================================
   7. Buttons
   ============================================================ */
.btn {
  display:inline-flex;
  align-items:center;
  justify-content:center;
  gap:.5em;
  padding:.875rem 1.75rem;
  border-radius:999px;
  border:2px solid transparent;
  font-family:var(--font-body);
  font-size:1rem;
  font-weight:600;
  line-height:1;
  text-decoration:none;
  cursor:pointer;
  transition:background-color .2s var(--ease), border-color .2s var(--ease), color .2s var(--ease), transform .15s var(--ease);
}
.btn:active { transform:translateY(1px); }

/* Primary — coral fill, --navy text. Unlike the warpededu reference,
   --brand/--brand-deep/--navy here are IDENTICAL in light and dark
   (spec §4: "the coral holds in both"), so — deliberately, unlike
   the reference — there is NO :root[data-theme="dark"] .btn override
   here: there is nothing for one to correct. The reference's
   :not(.btn--accent):not(.btn--ghost) cascade-guard existed because
   a *theme-scoped* selector (higher specificity than a plain variant
   class) had to be stopped from leaking onto other variants; with no
   theme-scoped rule at all for the primary variant, that failure mode
   can't occur. Measured (sRGB relative luminance, see task-3 report):
   navy-on-brand (rest) = 6.696:1, navy-on-brand-deep (hover) = 4.509:1
   — both clear the 4.5:1 text floor in both themes (the colors don't
   change between themes, so the ratio doesn't either). Variant rules
   below still fully restate background/color rather than patching the
   base, so source order alone resolves them — no specificity fight to
   guard against. */
.btn {
  background:var(--brand);
  color:var(--navy);
}
.btn:hover { background:var(--brand-deep); }

/* Ghost — plain --brand text measures only ~2.7:1 against a light
   --bg (fails 4.5:1 badly) even though it clears ~6.8:1 against the
   dark --bg — so per the brief, adjust with a color-mix toward --ink.
   --brand-ink (§2) mixes 50/50 toward the CURRENT theme's --ink, which
   pushes it dark in light mode and light in dark mode — exactly the
   direction each theme needs, from one formula. Measured floor across
   rest (on --bg) and hover (on --brand-soft) in both themes is
   ~5.16:1 (light hover, the tightest case) — see task-3 report for
   the full table. */
.btn--ghost {
  background:transparent;
  border-color:var(--brand-ink);
  color:var(--brand-ink);
}
.btn--ghost:hover { background:var(--brand-soft); }

/* ---- 8. Card ---- */
.card {
  background:var(--surface);
  border:1px solid var(--line);
  border-radius:var(--radius-lg);
  padding:1.75rem;
  box-shadow:var(--shadow-card);
}

/* ============================================================
   9. Device — iPhone bezel class family
   The hero's centerpiece (spec §6): a phone that looks like a plain
   marketing screenshot until touched. This is the shared frame that
   hosts either a poster <img> now or the live demo <iframe> later
   (task 13) — only the frame is defined here; positioning/size in
   any given placement is the caller's job.
   --device-radius / --device-bezel are exposed as custom properties
   so a later task can size a smaller/larger phone without forking
   the rule (e.g. a proof-rail thumbnail vs. the full hero phone).
   ============================================================ */
.device {
  --device-radius: 54px;
  --device-bezel: 14px;
  position:relative;
  display:block;
  border-radius:var(--device-radius);
  padding:var(--device-bezel);
  background:linear-gradient(158deg, #2E3350 0%, #05060D 55%, #1B1E2C 100%);
  box-shadow:
    0 1px 2px rgba(10,15,40,.08),
    0 44px 90px -32px color-mix(in srgb, var(--brand) 32%, rgba(10,15,40,.6));
}
.device img,
.device iframe,
.device__screen {
  display:block;
  width:100%;
  height:100%;
  border:0;
  border-radius:calc(var(--device-radius) - var(--device-bezel));
  background:#C7CBD6; /* placeholder "screen" grey until real content loads */
}
.device__screen { aspect-ratio:393 / 852; } /* iPhone 16 Pro logical px, per spec §7 */

/* ============================================================
   10. Skip link
   ============================================================ */
.skip-link {
  position:fixed; top:.75rem; left:.75rem; z-index:200;
  padding:.7rem 1.1rem; border-radius:999px;
  background:var(--brand); color:var(--navy); font-weight:700;
  text-decoration:none;
  transform:translateY(-160%);
  transition:transform .18s var(--ease);
}
.skip-link:focus-visible { transform:none; }

/* ============================================================
   11. Site header + primary nav
   Sticky and transparent while it floats over the hero, then a
   blurred, hairline-ruled surface bar once the page scrolls
   (.is-scrolled toggled in site.js). Reduced-motion users still
   get the state change — only the transition is dropped globally.
   ============================================================ */
.site-header {
  position:sticky; top:0; z-index:100;
  background:transparent;
  border-bottom:1px solid transparent;
  transition:background-color .25s var(--ease), border-color .25s var(--ease), backdrop-filter .25s var(--ease);
}
.site-header.is-scrolled {
  background:color-mix(in srgb, var(--bg) 82%, transparent);
  border-bottom-color:var(--line);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
  backdrop-filter:blur(14px) saturate(1.4);
}
.nav {
  display:flex; align-items:center; gap:1rem;
  min-height:4.25rem;
  padding-block:.65rem;
}

/* Wordmark — inline SVG lockup (coral app-icon mark + "The PTO App"
   letterforms), inlined verbatim here and in the footer. Letters inherit
   currentColor so they flip with the theme (navy in the nav, light on the
   footer's navy band); the coral mark stays literal. It's inlined rather
   than <use>d from a shared <symbol> on purpose: currentColor in a <use>
   instance resolves from the symbol's definition context, not each call
   site, which would leave the footer's letters navy-on-navy. */
.wordmark {
  display:inline-flex; align-items:center;
  /* Pad the tap target to >=44px tall without shifting surrounding layout:
     the padding grows the link's hit box; the equal negative margin pulls
     its footprint back to the mark's own visual height. */
  padding-block:.6rem; margin-block:-.6rem;
  margin-right:auto; line-height:0;
  color:var(--ink); text-decoration:none;
}
.wordmark__mark { height:1.6rem; width:auto; display:block; }
.wordmark:hover, .wordmark:focus-visible { text-decoration:none; }
.wordmark:hover .wordmark__mark { opacity:.85; }

/* Nav menu — inline row on desktop, drop-down sheet on mobile (§16). */
.nav__menu { display:flex; align-items:center; gap:.35rem; }
.nav__link {
  display:inline-flex; align-items:center; justify-content:center;
  min-height:44px;
  padding:.5rem .85rem; border-radius:999px;
  font-weight:600; font-size:.95rem;
  color:var(--ink); text-decoration:none;
  transition:background-color .2s var(--ease), color .2s var(--ease);
}
.nav__menu a:not(.btn):hover,
.nav__menu a:not(.btn):focus-visible {
  color:var(--brand-deep); background:var(--brand-soft); text-decoration:none;
}
.nav__cta { margin-left:.5rem; min-height:44px; padding:.6rem 1.2rem; font-size:.95rem; }

.nav__actions { display:flex; align-items:center; gap:.5rem; }
.icon-button {
  width:44px; height:44px; border-radius:999px;
  border:1px solid var(--line); background:var(--surface); color:var(--ink);
  cursor:pointer; display:grid; place-items:center; font-size:1.15rem; line-height:1;
  box-shadow:var(--shadow-card);
  transition:transform .15s var(--ease), background-color .2s var(--ease);
}
.icon-button:hover { transform:translateY(-1px); background:var(--brand-soft); }

/* Hamburger (mobile only; shown in §16). */
.nav-toggle {
  display:none;
  width:44px; height:44px; border-radius:999px;
  border:1px solid var(--line); background:var(--surface); cursor:pointer;
  place-items:center;
  box-shadow:var(--shadow-card);
}
.nav-toggle__bars, .nav-toggle__bars::before, .nav-toggle__bars::after {
  content:""; display:block;
  width:18px; height:2px; border-radius:2px; background:var(--ink);
  transition:transform .2s var(--ease), opacity .2s var(--ease);
}
.nav-toggle__bars { position:relative; }
.nav-toggle__bars::before { position:absolute; top:-6px; }
.nav-toggle__bars::after  { position:absolute; top:6px; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars { background:transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::before { top:0; transform:rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bars::after  { top:0; transform:rotate(-45deg); }

/* ============================================================
   12. Hero — copy column
   The star is the phone (§13); the copy is set quiet and confident
   around it. The coral "promise" line is the one place the type
   raises its voice, staking the claim the phone then proves.
   ============================================================ */
.hero {
  position:relative;
  display:grid; align-items:center;
  padding-block:clamp(2.5rem, 5vh, 4.5rem);
  overflow:hidden;
}
/* One soft, STATIC coral wash behind the phone — enough to lift the
   navy bezel off --bg. Deliberately not animated: a screenshot that
   glowed or pulsed would give the disguise away before the tap. */
.hero::before {
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(42% 46% at 78% 42%,
    color-mix(in srgb, var(--brand) 15%, transparent), transparent 72%);
}
.hero__grid {
  position:relative; z-index:1;
  display:grid;
  grid-template-columns:minmax(0, 1fr) auto;
  align-items:center;
  gap:clamp(1.5rem, 4vw, 4rem);
}

.hero__copy { max-width:34rem; }
.hero__title {
  font-family:var(--font-display);
  font-optical-sizing:auto; font-weight:600;
  font-size:clamp(2.6rem, 1.7rem + 3vw, 4rem);
  line-height:1.02; letter-spacing:-0.025em;
  text-wrap:balance;
  margin:0 0 .5rem;
}
/* The promise — same editorial serif as the headline, coral, one size
   down, so it reads as the headline's second breath rather than a label. */
.hero__promise {
  font-family:var(--font-display);
  font-weight:500;
  font-size:clamp(1.35rem, 1.05rem + 1vw, 1.9rem);
  line-height:1.15; letter-spacing:-0.01em;
  color:var(--brand-deep);
  text-wrap:balance;
  margin:0 0 1.1rem;
}
.hero__sub {
  color:var(--ink-soft);
  font-size:clamp(1.02rem, 0.98rem + 0.3vw, 1.15rem);
  line-height:1.6; max-width:40ch; margin:0 0 1.7rem;
}
.hero__cta { display:flex; flex-wrap:wrap; gap:.8rem; margin-bottom:1.35rem; }
.beta {
  display:inline-flex; align-items:center; gap:.55rem;
  font-size:.9rem; font-weight:600; color:var(--ink-soft); margin:0;
}
.beta__dot {
  width:9px; height:9px; border-radius:999px; background:var(--p-surveys);
  box-shadow:0 0 0 4px color-mix(in srgb, var(--p-surveys) 22%, transparent);
}
@keyframes betapulse {
  0%,100% { box-shadow:0 0 0 4px color-mix(in srgb, var(--p-surveys) 22%, transparent); }
  50%     { box-shadow:0 0 0 7px color-mix(in srgb, var(--p-surveys) 6%, transparent); }
}
@media (prefers-reduced-motion:no-preference) { .beta__dot { animation:betapulse 2.6s var(--ease) infinite; } }

/* ============================================================
   13. Hero — the phone (poster over live demo)
   The stage (.device__screen) is the positioning context. The live
   <iframe> sits underneath; the poster <picture> is stacked on top
   and cross-fades to nothing on {type:'ready'} (site.js adds .is-swapped).
   Aspect ratios match 393:852 exactly, so the self-scaling demo fills
   the stage with no letterbox. If the demo never readies, the poster
   simply stays — a graceful static fallback.
   ============================================================ */
.hero__stage { display:flex; flex-direction:column; align-items:center; }
.hero-device { width:min(400px, 86vw); }

.hero-stage { position:relative; overflow:hidden; background:var(--navy); }
.hero-stage > .hero-demo,
.hero-stage > .hero-poster {
  position:absolute; inset:0;
  width:100%; height:100%;
  border:0; border-radius:inherit;
}
.hero-demo { z-index:1; background:transparent; }
.hero-poster {
  z-index:2; display:block; overflow:hidden;
  transition:opacity .25s var(--ease);
}
.hero-poster img {
  width:100%; height:100%;
  object-fit:cover; object-position:top center;
  border-radius:0;
}
.hero-poster.is-swapped { opacity:0; pointer-events:none; }

/* ============================================================
   14. Hero — liveness cue pill + quiet demo tools
   ============================================================ */
.hero-cue {
  margin:1.1rem 0 0;
  display:inline-flex; align-items:center; gap:.45rem;
  padding:.5rem 1rem; border-radius:999px;
  background:var(--brand-soft); color:var(--brand-deep);
  font-size:.9rem; font-weight:700;
  box-shadow:var(--shadow-card);
  opacity:0; transform:translateY(6px);
  transition:opacity .3s var(--ease), transform .3s var(--ease);
}
.hero-cue.is-in { opacity:1; transform:none; }

.hero-tools {
  display:flex; flex-wrap:wrap; justify-content:center; gap:.35rem 1.25rem;
  margin-top:1rem;
}
.hero-tools__btn {
  display:inline-flex; align-items:center; justify-content:center; gap:.4rem;
  min-height:44px;
  background:none; border:0; padding:.35rem .6rem; cursor:pointer;
  font-family:var(--font-body); font-size:.85rem; font-weight:600;
  color:var(--ink-soft); text-decoration:none;
  border-radius:999px;
  transition:color .2s var(--ease);
}
.hero-tools__btn:hover, .hero-tools__btn:focus-visible { color:var(--brand-deep); }
.hero-tools__status {
  min-height:1.2em; margin:.4rem 0 0;
  font-size:.8rem; font-weight:600; color:var(--brand-deep);
  text-align:center; opacity:0;
  transition:opacity .2s var(--ease);
}
.hero-tools__status.is-shown { opacity:1; }

/* ============================================================
   15. Footer — a quiet navy band that anchors the page on --navy in
   BOTH themes (the one region that deliberately doesn't flip), so the
   site ends on the app's own midnight ground. Text is set light; every
   link clears 4.5:1 on navy (measured). The wordmark's letters ride
   currentColor (light here); its coral mark stays literal. Focus rings
   switch to coral (>=3:1 on navy, unlike the page-default --brand-ink).
   ============================================================ */
.site-footer {
  background:var(--navy);
  color:#EEF0F8;
  padding-block:clamp(3rem, 5vw, 4.5rem);
}
.site-footer :focus-visible { outline-color:var(--brand); }
.site-footer__inner {
  display:grid; grid-template-columns:1fr;
  gap:2.5rem clamp(1.5rem, 3vw, 3rem);
}
@media (min-width:560px) { .site-footer__inner { grid-template-columns:repeat(2, 1fr); } }
@media (min-width:900px) { .site-footer__inner { grid-template-columns:1.7fr 1fr 1fr 1.15fr; } }

/* -- Brand block -- */
.footer-brand { max-width:24rem; }
/* Same padding-block:.6rem tap-target pad as the base .wordmark rule;
   margins here net out to the original 0 (top) / 1.1rem (bottom) visual
   gaps once that padding is subtracted back out. */
.footer-brand .wordmark { color:#EEF0F8; margin:-.6rem 0 .5rem; }
.footer-brand .wordmark__mark { height:1.85rem; }
.footer-tagline { margin:0 0 1rem; color:#C7CCE0; font-size:1rem; line-height:1.55; }
.footer-beta {
  display:inline-flex; align-items:center; gap:.55rem; margin:0;
  font-size:.85rem; font-weight:600; color:#C7CCE0;
}
.footer-beta__dot {
  width:9px; height:9px; border-radius:999px; background:var(--p-surveys);
  box-shadow:0 0 0 4px color-mix(in srgb, var(--p-surveys) 26%, transparent);
}

/* -- Link columns -- */
.footer-col__title {
  margin:0 0 1rem;
  font-size:.75rem; font-weight:700; letter-spacing:.09em; text-transform:uppercase;
  color:#9AA0BE;
}
.footer-col ul { list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:.7rem; }
.footer-link { color:#C7CCE0; text-decoration:none; font-size:.95rem; line-height:1.4; }
.footer-link:hover, .footer-link:focus-visible { color:var(--brand); text-decoration:underline; }
/* external-destination cue — decorative, so the arrow is aria-hidden in markup */
.footer-link__ext { margin-left:.32em; font-size:.85em; opacity:.75; }
.footer-email {
  display:inline-block; margin-top:1.1rem;
  font-weight:700; color:#EEF0F8; text-decoration:none; font-size:1.0625rem;
}
.footer-email:hover, .footer-email:focus-visible { color:var(--brand); text-decoration:underline; }

/* -- Legal line -- */
.site-footer__legal {
  margin-top:clamp(2.25rem, 4vw, 3rem);
  padding-top:1.5rem;
  border-top:1px solid color-mix(in srgb, #EEF0F8 14%, transparent);
}
.site-footer__legal p { margin:0; font-size:.8125rem; color:#9AA0BE; line-height:1.5; }

/* ============================================================
   16. Responsive — mobile nav sheet + stacked hero
   ============================================================ */
@media (max-width:880px) {
  .nav-toggle { display:grid; }
  .nav__menu {
    position:absolute; top:100%; left:0; right:0;
    flex-direction:column; align-items:stretch; gap:.25rem;
    padding:1rem clamp(1rem, 4vw, 2rem) 1.25rem;
    background:var(--surface);
    border-bottom:1px solid var(--line);
    box-shadow:var(--shadow-card);
    opacity:0; visibility:hidden; transform:translateY(-8px);
    pointer-events:none;
    transition:opacity .2s var(--ease), transform .2s var(--ease), visibility .2s var(--ease);
  }
  .nav__menu.is-open { opacity:1; visibility:visible; transform:none; pointer-events:auto; }
  .nav__link { padding:.7rem .85rem; font-size:1.02rem; }
  .nav__cta { margin:.35rem 0 0; width:100%; }
}

@media (max-width:900px) {
  .hero__grid {
    grid-template-columns:1fr; gap:2rem;
    text-align:center; justify-items:center;
  }
  .hero__copy { max-width:40rem; }
  .hero__sub { max-width:46ch; margin-inline:auto; }
  .hero__cta { justify-content:center; }
  .beta { justify-content:center; text-align:center; }
  .hero__stage { order:2; }
  .hero__copy { order:1; }
}

@media (max-width:430px) {
  .hero__cta .btn { width:100%; }
}

/* ============================================================
   17. Section head — shared eyebrow + h2 (+ optional intro lead)
   used by every content section from here down. Left-aligned,
   readable measure on the intro line only (the h2 itself is
   allowed to run the container's full width).
   ============================================================ */
.section-head { max-width:46rem; margin-bottom:clamp(2rem, 4vw, 3rem); }
.section-head h2 { margin:0 0 .65rem; }
.section-head__intro {
  color:var(--ink-soft);
  font-size:clamp(1.05rem, 1rem + 0.3vw, 1.2rem);
  line-height:1.6; max-width:42ch; margin:0;
}

/* ============================================================
   18. How it works (#how) — a genuine 3-step sequence (claim, then
   invite, then run), so the numbering is information, not decor. A
   hairline connector bridges each gap at the 3-up breakpoint only,
   reinforcing "this is an order" without competing with the phone
   above for attention.
   ============================================================ */
.steps {
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:1fr; gap:1.85rem;
}
.step { position:relative; }
.step__num {
  display:inline-flex; align-items:center; justify-content:center;
  width:2.75rem; height:2.75rem; border-radius:999px;
  font-family:var(--font-display); font-weight:600; font-size:1.2rem;
  background:var(--brand-soft); color:var(--brand-ink);
  margin-bottom:1rem;
}
.step__title { margin:0 0 .4rem; }
.step__desc { margin:0; color:var(--ink-soft); font-size:.975rem; line-height:1.6; max-width:30ch; }

@media (min-width:760px) {
  .steps { grid-template-columns:repeat(3, 1fr); gap:1.75rem; }
  .step:not(:last-child)::after {
    content:""; position:absolute; top:1.375rem; left:100%;
    width:1.75rem; height:2px; background:var(--line);
  }
}

/* ============================================================
   19. Feature pillars (#tour-of-features) — 10 truthful cards, each
   wearing its category's tint on a soft icon chip (identical formula
   to the app's own taxonomy) plus a "See it in the demo →" control
   that scrolls back to the phone and drives it live (site.js
   [data-demo-goto]). Cards stretch to equal height so every link
   lands on the same baseline across a row.
   ============================================================ */
.pillars {
  list-style:none; margin:0; padding:0;
  display:grid;
  grid-template-columns:repeat(auto-fit, minmax(min(100%, 17rem), 1fr));
  gap:1.15rem;
}
.pillar { padding:1.75rem; display:flex; flex-direction:column; }
.pillar__title { margin:0 0 .5rem; }
.pillar__desc { margin:0; color:var(--ink-soft); font-size:.975rem; line-height:1.6; }

/* Soft category chip — same accessible formula as the ghost-button /
   badge tokens above: chip mixes --pc 16% toward --surface, the glyph
   mixes --pc 60% toward --ink, so the glyph is always pushed away from
   the chip's own lightness in whichever theme is active. */
.pillar__icon {
  width:2.75rem; height:2.75rem; border-radius:13px;
  display:grid; place-items:center; margin-bottom:1.1rem;
  background:color-mix(in srgb, var(--pc) 16%, var(--surface));
  color:color-mix(in srgb, var(--pc) 60%, var(--ink));
  transition:background-color .25s var(--ease);
}
.pillar__icon svg {
  width:1.55rem; height:1.55rem;
  fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
}

.pillar {
  transition:transform .18s var(--ease), box-shadow .25s var(--ease), border-color .25s var(--ease);
}
.pillar:hover {
  transform:translateY(-4px);
  border-color:color-mix(in srgb, var(--pc) 42%, var(--line));
  box-shadow:0 1px 2px rgba(10,15,40,.06),
             0 22px 44px -22px color-mix(in srgb, var(--pc) 55%, rgba(10,15,40,.4));
}
.pillar:hover .pillar__icon { background:color-mix(in srgb, var(--pc) 24%, var(--surface)); }
.pillar:nth-child(2n) { transition-delay:.05s; }
.pillar:nth-child(3n) { transition-delay:.1s; }

/* Per-card category accents (spec §4 tints; chat = brand coral per
   the app's own chat color; AI newsletter = --p-ai §2; sponsors is
   deliberately neutral — wishlist already owns the volunteer amber). */
.pillar--events     { --pc:var(--p-events); }
.pillar--announce   { --pc:var(--brand); }
.pillar--fund        { --pc:var(--p-fundraising); }
.pillar--chat        { --pc:var(--brand); }
.pillar--surveys    { --pc:var(--p-surveys); }
.pillar--resources  { --pc:var(--p-resources); }
.pillar--newsletter { --pc:var(--p-ai); }
.pillar--wishlist    { --pc:var(--p-volunteer); }
.pillar--sponsors    { --pc:var(--ink-soft); }
.pillar--theming     { --pc:var(--brand); }

/* Per-school theming's icon is a 2x2 cluster of category dots (a literal
   "multi-color chip") instead of a line glyph — the one pillar where the
   chip itself demonstrates the claim. */
.dot-quad { display:grid; grid-template-columns:repeat(2, 1fr); gap:3px; width:1.05rem; height:1.05rem; }
.dot-quad__i { border-radius:999px; }
.dot-quad__i--1 { background:var(--p-events); }
.dot-quad__i--2 { background:var(--p-fundraising); }
.dot-quad__i--3 { background:var(--p-volunteer); }
.dot-quad__i--4 { background:var(--p-surveys); }

.pillar__link {
  display:inline-flex; align-items:center; gap:.35rem;
  margin-top:auto; padding-top:1.1rem;
  font-weight:700; font-size:.925rem;
  color:var(--brand-deep); text-decoration:none;
}
.pillar__link:hover, .pillar__link:focus-visible { text-decoration:underline; }
.pillar__link span { display:inline-block; transition:transform .18s var(--ease); }
.pillar__link:hover span, .pillar__link:focus-visible span { transform:translateX(3px); }

/* ============================================================
   20. Boards vs parents (#boards) — asymmetric split; the board
   card carries the visual weight (accent rule + the #beta CTA)
   since boards are the primary audience (spec §3).
   ============================================================ */
.split-grid {
  display:grid; grid-template-columns:1fr; gap:clamp(1.25rem, 3vw, 2rem);
  align-items:stretch;
}
@media (min-width:768px) { .split-grid { grid-template-columns:3fr 2fr; } }

.split-card { display:flex; flex-direction:column; height:100%; }
.split-card--board { border-top:4px solid var(--brand); padding-top:calc(1.75rem - 3px); }

.split-card__badge {
  display:inline-flex; align-self:flex-start;
  padding:.35rem .85rem; border-radius:999px;
  font-size:.8125rem; font-weight:700; letter-spacing:.01em;
  margin-bottom:1rem;
}
/* Both badges use --brand-ink (not --brand-deep, and not a lighter
   brand/ink mix): at .8125rem/700 this text is too small to qualify as
   "large text" under WCAG (needs >=18.66px bold), so it needs the plain
   4.5:1 text floor rather than the 3:1 graphical floor — measured 6.0+:1
   here in both themes vs. ~3.1-3.4:1 with the lighter mixes first tried. */
.split-card__badge--board { background:color-mix(in srgb, var(--brand) 20%, var(--surface)); color:var(--brand-ink); }
.split-card__badge--parents { background:var(--brand-soft); color:var(--brand-ink); }

.split-card__title { margin:0 0 .9rem; }

.split-list { list-style:none; margin:0 0 1.5rem; padding:0; display:flex; flex-direction:column; gap:.65rem; }
.split-list__item { display:flex; align-items:flex-start; gap:.65rem; font-size:.975rem; line-height:1.5; color:var(--ink-soft); }

.split-list__icon { flex:none; width:1.3rem; height:1.3rem; margin-top:.15rem; color:var(--brand-deep); }
.split-list__icon svg { width:100%; height:100%; fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; }

.split-list__dot {
  flex:none; width:9px; height:9px; margin-top:.5rem; border-radius:999px;
  background:var(--pc); box-shadow:0 0 0 4px color-mix(in srgb, var(--pc) 20%, transparent);
}
.split-list__dot--events    { --pc:var(--p-events); }
.split-list__dot--volunteer { --pc:var(--p-volunteer); }
.split-list__dot--fund      { --pc:var(--p-fundraising); }
.split-list__dot--brand     { --pc:var(--brand); }

.split-note { margin:0; font-style:italic; color:var(--ink-soft); }
.split-card__cta { margin-top:auto; padding-top:.25rem; }

/* ============================================================
   21. Trust (#trust) — a compact honest-signal row on a
   brand-soft tint band. Icons sit in a surface chip so they read
   as a floating signal, not a category (these four claims are
   equally weighted, unlike the pillar taxonomy above).
   ============================================================ */
.section--tint { background:var(--brand-soft); }
/* The shared .eyebrow color (--eyebrow-ink, §2) measures a comfortable
   4.9+:1 against the plain --bg every other section sits on (matching the
   hero's own eyebrow), but drops well below 4.5:1 here since this is the
   one section sitting on the brand-soft tint itself — two colors from the
   same family read closer together. --brand-ink (same fix as the ghost
   button / badges above, a heavier 50/50 mix) restores a measured 5.8+:1
   in both themes on this tint. */
.section--tint .eyebrow { color:var(--brand-ink); }

.trust-row {
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:1fr; gap:1.75rem;
}
@media (min-width:600px) { .trust-row { grid-template-columns:repeat(2, 1fr); } }
@media (min-width:1040px) { .trust-row { grid-template-columns:repeat(4, 1fr); gap:1.5rem; } }

.trust-item { display:flex; flex-direction:column; gap:.6rem; }
.trust-item__icon {
  width:2.5rem; height:2.5rem; border-radius:12px;
  display:grid; place-items:center;
  background:var(--surface); color:var(--brand-deep);
  box-shadow:var(--shadow-card);
}
.trust-item__icon svg { width:1.4rem; height:1.4rem; fill:none; stroke:currentColor; stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.trust-item__title { margin:0; font-family:var(--font-body); font-size:1rem; font-weight:700; color:var(--ink); }
.trust-item__desc { margin:0; font-size:.925rem; line-height:1.55; color:var(--ink-soft); }

/* ============================================================
   22. FAQ (#faq) — native <details>/<summary> accordions: free
   keyboard support + screen-reader semantics, styled plus/minus
   indicator (a rotating "+"), generous 44px+ tap target on the
   whole question row.
   ============================================================ */
.faq-list { display:flex; flex-direction:column; gap:.75rem; max-width:44rem; }
.faq-item {
  border:1px solid var(--line); border-radius:var(--radius-lg);
  background:var(--surface); overflow:hidden;
}
.faq-item__q {
  display:flex; align-items:center; justify-content:space-between; gap:1rem;
  min-height:44px; padding:1.15rem 1.35rem;
  cursor:pointer; list-style:none;
  font-weight:700; font-size:1.02rem; color:var(--ink);
  transition:color .2s var(--ease);
}
.faq-item__q::-webkit-details-marker { display:none; }
.faq-item__q::marker { content:""; }
.faq-item__q:hover, .faq-item__q:focus-visible { color:var(--brand-deep); }

.faq-item__toggle { position:relative; flex:none; width:1.15rem; height:1.15rem; }
.faq-item__toggle::before, .faq-item__toggle::after {
  content:""; position:absolute; top:50%; left:50%;
  width:1.15rem; height:2px; background:var(--brand-deep);
  transform:translate(-50%, -50%);
  transition:transform .2s var(--ease);
}
.faq-item__toggle::after { transform:translate(-50%, -50%) rotate(90deg); }
.faq-item[open] .faq-item__toggle::after { transform:translate(-50%, -50%) rotate(0deg); }

.faq-item__a { padding:0 1.35rem 1.35rem; color:var(--ink-soft); }
.faq-item__a p { margin:0; font-size:.975rem; line-height:1.6; }
.faq-item__a a { color:var(--brand-deep); }

/* ============================================================
   23. New-sections narrow-screen tuning
   ============================================================ */
@media (max-width:520px) {
  .split-card__cta .btn { width:100%; }
}

/* ============================================================
   24. Beta signup (#beta) — the page's conversion finale: a single
   centered column, header and form both, on an ambient wash that
   mirrors the hero's own radial glow (§12) from the opposite
   corner — the one deliberate visual callback that bookends the
   page, rather than a new decorative device.
   ============================================================ */
.section--beta { position:relative; overflow:hidden; }
.section--beta::before {
  content:""; position:absolute; inset:0; z-index:0; pointer-events:none;
  background:radial-gradient(46% 56% at 20% 88%,
    color-mix(in srgb, var(--brand) 15%, transparent), transparent 72%);
}
.beta-grid { position:relative; z-index:1; max-width:36rem; margin-inline:auto; }

.beta-intro { text-align:center; margin-bottom:clamp(1.75rem, 4vw, 2.5rem); }
.beta-intro h2 { text-wrap:balance; }
.beta-intro__lead {
  color:var(--ink-soft);
  font-size:clamp(1.05rem, 1rem + 0.3vw, 1.2rem);
  line-height:1.6; max-width:38ch; margin:0 auto;
}

/* -- Form card -- */
.beta-form { padding:clamp(1.75rem, 3vw, 2.5rem); }

.form-row { display:grid; grid-template-columns:1fr; gap:0 1rem; }
@media (min-width:480px) { .form-row { grid-template-columns:1fr 1fr; } }

.form-field { display:flex; flex-direction:column; gap:.4rem; margin-bottom:1.35rem; }
.form-field label { font-weight:600; font-size:.95rem; }
.form-field__optional { font-weight:400; color:var(--ink-soft); }

/* Inputs sit a shade darker/lighter than the card's own --surface (both
   draw from --bg), reading as a recessed "well" against the card in both
   themes without any extra color token. --line alone measures ~1.2:1
   against --bg (built for hairlines between similarly-toned surfaces, not
   a standalone control boundary) — mixing in --ink pushes it to >=3:1
   (WCAG 1.4.11) without looking like a heavy, off-brand box. */
.form-field input, .form-field select, .form-field textarea {
  width:100%; min-height:2.75rem; /* >=44px touch target */
  padding:.7rem .9rem;
  border-radius:var(--radius-sm);
  border:1.5px solid color-mix(in srgb, var(--ink) 45%, var(--line));
  background:var(--bg);
  color:var(--ink);
  font-size:1rem; /* >=16px: keeps iOS Safari from zooming in on focus */
  line-height:1.3;
  transition:border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.form-field textarea { min-height:7rem; resize:vertical; }
.form-field input::placeholder, .form-field textarea::placeholder { color:var(--ink-soft); opacity:.75; }
.form-field input:hover, .form-field select:hover, .form-field textarea:hover {
  border-color:color-mix(in srgb, var(--brand) 35%, var(--line));
}
/* :focus-visible outline is the shared global treatment (§3); this just
   also deepens the border itself so the "well" reads focused at a glance. */
.form-field input:focus-visible, .form-field select:focus-visible, .form-field textarea:focus-visible {
  border-color:var(--brand);
}

/* Honeypot: clipped to 1px and taken out of both the tab order (via the
   [tabindex="-1"] in the markup) and the a11y tree (via [aria-hidden]) —
   deliberately NOT display:none, since some bots skip hidden/display:none
   fields but still fill in a "visually hidden" one. */
.visually-hidden {
  position:absolute!important;
  width:1px; height:1px;
  padding:0; margin:-1px;
  overflow:hidden;
  clip:rect(0,0,0,0);
  white-space:nowrap;
  border:0;
}

.beta-form__actions { display:flex; align-items:center; flex-wrap:wrap; gap:1.1rem; }
.beta-form__status { margin:0; font-size:.95rem; font-weight:600; color:var(--ink-soft); min-height:1.4em; }

@media (max-width:520px) {
  .beta-form__actions .btn { width:100%; }
}

/* ============================================================
   25. Utility pages (privacy/terms/404) — a page-head title block
   and a narrow "prose" column for plain-language policy copy, both
   leaning on tokens/primitives already defined above (.section,
   .container, .eyebrow, h1/h2 type scale) rather than a parallel
   system built just for these three pages.
   ============================================================ */

/* -- Title block: eyebrow + h1 + a small effective-date line, same
   rhythm as .section-head (§17) but built for a page's one h1. -- */
.page-head { max-width:46rem; margin-bottom:clamp(2rem, 4vw, 3rem); }
.page-head h1 { margin:0 0 .5rem; }
.page-head__meta { margin:0; color:var(--ink-soft); font-size:.95rem; }

/* -- Prose: a readable measure for running policy copy. Headings
   keep the global Fraunces h2 look; only spacing is added here. -- */
.prose { max-width:70ch; }
.prose h2 { margin:2.25rem 0 .65rem; }
.prose h2:first-child { margin-top:0; }
.prose p, .prose li { color:var(--ink-soft); }
.prose ul, .prose ol { margin:0 0 1em; padding-left:1.3rem; }
.prose li { margin-bottom:.5em; line-height:1.6; }
.prose li:last-child { margin-bottom:0; }
.prose li::marker { color:var(--brand-deep); }
.prose strong { color:var(--ink); }
.prose a { font-weight:600; }

/* ============================================================
   26. 404 — a single quiet, centered moment between header and
   footer. Signature element: a miniature, inert replica of the
   app's own RSVP segmented control (§19 "Events & RSVPs" pillar —
   "Going, Maybe, Can't make it, all in one tap"), permanently stuck
   on "Can't make it" — the one deliberate callback to the product's
   own UI language, rather than a new illustration built just for
   this page.
   ============================================================ */
.notfound { min-height:56vh; display:flex; align-items:center; }
.notfound__inner { max-width:34rem; margin-inline:auto; text-align:center; }
.notfound__line {
  color:var(--ink-soft);
  font-size:clamp(1.05rem, 1rem + 0.3vw, 1.2rem);
  line-height:1.6;
  margin:0 0 2rem;
}

/* Miniature RSVP control — visually matches the real segmented
   control's shape/rhythm but is inert (no button semantics, no
   click handlers): a prop, not a functioning control. */
.rsvp-echo {
  display:inline-flex; gap:.4rem;
  padding:.35rem; margin:0 0 1.75rem;
  border-radius:999px;
  background:var(--surface);
  border:1px solid var(--line);
  box-shadow:var(--shadow-card);
}
.rsvp-echo__opt {
  padding:.5rem 1.1rem;
  border-radius:999px;
  font-size:.9rem; font-weight:700;
  color:var(--ink-soft);
}
.rsvp-echo__opt--active {
  background:var(--brand); color:var(--navy);
}
@media (max-width:520px) { .notfound__inner .btn { width:100%; } }
