/* =============================================================================
   THUNDER ROLLS — DESIGN TOKENS  (sqrt(phi) type scale · Fibonacci spacing)
   Math is inspectable, not just asserted in prose:
     --ratio-sqrt-phi (1.27202) is the type-scale step; --fs-* below = 17 * 1.27202^n.
     --sp-* spacing values are consecutive Fibonacci integers (8,13,21,34,55,89,144).

   SCOPE OF THE TOKEN CLAIM (honest, not absolute): every TYPE size and every
   rhythm/SPACING value flows from the tokens above. A small set of constants is
   deliberately OFF the scale because it answers to external geometry, not rhythm —
   each is tokenized below and/or carries an inline "off-scale on purpose" note:
     · --layout-max (1200px container) and the responsive breakpoints
       (560/760/900/980/1100px) — content-measure / device thresholds, not rhythm steps;
     · icon glyph geometry (hamburger 24x2 + 5px gap, hero bolt 54x130,
       age-gate bolt 34x55, placeholder bolt 48x60) — fixed SVG aspect ratios;
     · grid column floors (--col-min-* minmax values), --hero-tube-max (540px),
       and component max-widths (cookie/newsletter) — layout breakpoints for wrapping;
     · 4px chip/checkbox insets — optical hit-area tuning;
     · fluid-type clamp() MIDDLE terms (the "Npx + Nvw" slope/intercept anchors in
       --fluid-hero-wordmark/-hero-sub/-h1/-body-lead/-manifesto) — these are the linear
       viewport-interpolation geometry BETWEEN two scale rungs; both the clamp FLOOR and
       CEILING are √φ scale tokens (--fs-*), only the interpolation slope is a bare px/vw
       constant. The size the user sees is always token-bounded; the slope is not a rhythm step;
     · the skip-link off-screen hide offset (top:-200px) — a functional "park it out of view"
       value, not a rhythm step (the visible focused position uses --sp-8).

   FONT exceptions to the Ultra/Archivo/Space-Mono-only hard rule (both intentional, not drift):
     · 'Ultra Fallback' @font-face (below) — a metric-compatible CLS swap shim, NOT a
       user-visible font family. It maps to local Georgia/Times with size-adjust + ascent/
       descent overrides so the hero box doesn't jolt before Ultra finishes loading; once Ultra
       settles the user never sees it. Display layer is still Ultra-only.
     · --font-legal (Arial, Helvetica, Calibri) — OMMA packaging/labeling rules MANDATE a
       standard sans (Arial/Helvetica/Calibri) for the statutory warning copy; an approved sans is
       listed FIRST so the warnings never fall back to the display/body face. This is a regulatory
       exception to the display-font rule and applies ONLY to legal/warning text.
   These are documented exceptions; the scale governs everything that carries rhythm. */
/* Metric-compatible fallback for Ultra (the hero/display slab). Loaded async via media="print"
   swap, so before it settles the browser uses this override-tuned local serif. size-adjust +
   ascent/descent overrides bring Georgia's box close to Ultra's so the swap doesn't jolt the hero
   wordmark and <h1> (CLS). Values tuned to Ultra's heavy slab proportions. */
@font-face{
  /* CLS shim only: a metric-compatible local serif so Ultra's display box doesn't jolt on load — the
     user never sees this face once Ultra settles, so it is NOT a violation of the Ultra/Archivo/
     Space-Mono font hard rule. Full rationale in the token-header FONT-exceptions note above. */
  font-family:'Ultra Fallback';
  src:local('Georgia'),local('Times New Roman'),local('serif');
  font-display:swap;
  size-adjust:108%;
  ascent-override:88%;
  descent-override:22%;
  line-gap-override:0%;
}

:root{
  /* Math constants (the scale rationale, as inspectable tokens) */
  --ratio-phi:1.618034;        /* φ — also the body line-height (--lh-body) */
  --ratio-sqrt-phi:1.27202;    /* √φ — the type-scale step ratio */

  /* Fonts */
  --font-display:'Ultra', 'Ultra Fallback';
  --font-body:'Archivo';
  --font-data:'Space Mono';
  --font-legal:Arial, Helvetica, Calibri, sans-serif; /* OMMA legal: approved standard sans FIRST (statutory warning copy), not the display/body face */

  /* Brand color invariants */
  --color-navy:#0A2540;
  --color-bone:#F5F1E6;
  --color-indica:#21407F;
  --color-sativa:#C13A26;
  --color-hybrid:#7E4A86;
  --color-ink:#0A2540;
  --color-ink-muted:#3A5470;
  --color-rule:#D4CCB8;
  --color-rule-dark:#1C3A5A;
  --color-card-dark:#0C2A48; /* recurring dark-card surface (cards/edu/locator input/results) — one shade, one token */
  --color-focus:#0A6FB8;
  /* placeholder on the dark fields (#0C2A48): bone at .6 alpha = ~4.9:1, clears WCAG AA (4.5:1) */
  --color-placeholder-dark:rgba(245,241,230,.6);

  /* Type scale — 17px * --ratio-sqrt-phi^n  (i.e. 17 * 1.27202^n).
     The large rungs (4xl..7xl) are computed LIVE off the previous rung * --ratio-sqrt-phi so the
     whole √φ ladder is inspectable end-to-end and cannot silently drift from the asserted math:
       4xl = 44.51 * 1.27202 ≈ 56.62 · 5xl ≈ 72.02 · 6xl ≈ 91.61 · 7xl ≈ 116.53px. */
  --fs-2xs:10.51px; --fs-xs:13.36px; --fs-base:17px; --fs-lg:21.62px;
  --fs-xl:27.51px; --fs-2xl:34.99px; --fs-3xl:44.51px;
  --fs-4xl:calc(var(--fs-3xl) * var(--ratio-sqrt-phi));
  --fs-5xl:calc(var(--fs-4xl) * var(--ratio-sqrt-phi));
  --fs-6xl:calc(var(--fs-5xl) * var(--ratio-sqrt-phi));
  --fs-7xl:calc(var(--fs-6xl) * var(--ratio-sqrt-phi));

  /* Fluid type (built from tokens, 375->1440 viewport) */
  /* wordmark floor lowered to --fs-3xl so Ultra "THUNDER" never overflows a 360px viewport (both ends are tokens) */
  --fluid-hero-wordmark:clamp(var(--fs-3xl), 30.0px + 6.0vw, var(--fs-7xl));
  /* hero-sub floor at --fs-2xl (not --fs-3xl) so the Ultra slab "fazes him." never touches the
     hero frame inset at ~360px — same scrutiny the wordmark got; still a scale token. */
  --fluid-hero-sub:clamp(var(--fs-2xl), 27.93px + 4.422vw, var(--fs-6xl));
  /* ceiling at --fs-4xl (the next live scale rung) so section headings keep climbing the
     √φ ladder on wide viewports instead of stalling at --fs-3xl — uses the otherwise-spare slot */
  --fluid-h1:clamp(var(--fs-xl), 20.1px + 2.5vw, var(--fs-4xl));
  --fluid-body-lead:clamp(var(--fs-base), 15.37px + 0.434vw, var(--fs-lg));
  --fluid-manifesto:clamp(var(--fs-2xl), 16.0px + 5.4vw, var(--fs-5xl));

  /* Spacing — Fibonacci px */
  --sp-8:8px; --sp-13:13px; --sp-21:21px; --sp-34:34px; --sp-55:55px; --sp-89:89px; --sp-144:144px;

  /* Semantic spacing aliases */
  --pad-card:var(--sp-34);
  --pad-section-x:var(--sp-34);
  --gap-cols:var(--sp-34);
  --gap-cards-row:var(--sp-55);
  --pad-section-y-sm:var(--sp-55);
  --pad-section-y-md:var(--sp-89);
  --pad-section-y-lg:var(--sp-144);
  --gap-hero-content:var(--sp-89);
  --pad-btn:var(--sp-13) var(--sp-34);
  --gap-stack:var(--sp-21);
  --gap-tag:var(--sp-13);
  --gap-icon:var(--sp-8);

  /* Off-scale layout constants (deliberately NOT on the type/rhythm scale — see header).
     Named here so the values are tokens, not bare literals scattered through the rules. */
  --layout-max:1200px;        /* container measure — content width cap, not a rhythm step */
  --hero-tube-max:540px;      /* LCP tube render height — the controlled axis (width follows) */
  --hero-tube-w:149px;        /* = round(540 * 700/2540): deterministic width from the tube's intrinsic 700x2540, kills first-paint reflow */
  --hero-tube-clamp-max:300px;/* hero tube responsive-width CEILING (the clamp upper bound) — layout cap on the controlled width axis, not a rhythm step */
  --hero-horse-max:240px;     /* decorative hero horse max-width — layout cap on a background mascot, not a rhythm step */
  --col-min-card:280px;       /* card-grid / help wrap floor (~content min before reflow) */
  --col-min-storm:250px;      /* storm-grid wrap floor */
  --col-min-edu:260px;        /* edu-grid / results wrap floor */
  --measure-cookie:760px;     /* cookie banner max measure */
  --measure-newsletter:520px; /* newsletter column max measure */

  /* Off-scale depth/affordance tokens (px shadows, focus ring, input floor are optical, not rhythm
     — named here so the values are documented tokens rather than bare literals in the rules) */
  --shadow-hero-tube:0 30px 40px rgba(10,37,64,.18); /* LCP tube lift */
  --shadow-product:0 12px 20px rgba(0,0,0,.3);       /* product image lift on dark media */
  --shadow-cookie:0 10px 40px rgba(10,37,64,.25);    /* cookie banner elevation over content */
  --outline-focus:3px;        /* focus-ring thickness (visibility floor, not a rhythm step) */
  --locator-input-min:180px;  /* ZIP input min-width before the locator row wraps */

  /* Line heights / letter spacing  (--lh-body = φ = --ratio-phi) */
  --lh-display:0.92; --lh-h1:1.05; --lh-h2h3:1.15;
  --lh-body:var(--ratio-phi); --lh-fine:1.5;
  /* Off-scale display line-heights (named so they aren't bare literals): the Ultra slab needs
     sub-1.0 leading to stack tightly — these answer to the heavy slab's optical metrics, not rhythm. */
  --lh-wordmark:0.9;     /* hero/footer wordmark — tighter than --lh-display for the stacked lockup */
  --lh-manifesto:1.04;   /* manifesto display line — single optical step off --lh-h1 */
  --lh-storm-name:1.0;   /* storm-card name — Ultra slab tight optical stack (off-scale, like the two above) */
  --ls-display:-0.03em; --ls-h1:-0.02em; --ls-h2h3:-0.01em; --ls-body:0;
  --ls-mono:0.06em; --ls-fine:0.08em; --ls-ui:0.12em;
  --ls-btn-hover:0.14em; /* solid-button hover spreads one notch past --ls-ui (0.12) — optical, not a scale step */
}

/* ---- Per-state accent theme (default OK). Toggle [data-state] on <html>. ----
   --accent-foreground = text color for solid buttons whose fill is --accent. Navy text on the
   CA/NV/NY accents fails WCAG AA (≈2.4–2.9:1), so those states force bone text (≥4.5:1). */
:root,html[data-state='ok']{
  /* --accent-secondary-dark = small text on the dark cards (#0C2A48). OK vermilion at full
     saturation is only 4.25:1 there, so OK lightens to #F4773F (5.25:1); CA/NV/NY already pass. */
  --accent-primary:#0A6FB8; --accent-secondary:#EE5A24; --accent-secondary-dark:#F4773F; --accent:#EE5A24; --accent-foreground:var(--color-navy);
}
html[data-state='ca']{
  /* Lakers white-led (approved CW _shared.jsx 'lakersWhite'): Royal purple #552583 (links/large, 9.8:1 on bone)
     + gold #FDB927 pop. Gold fails on bone → on-bone small use falls back to purple; gold pop takes dark text. */
  --accent-primary:#552583; --accent-secondary:#FDB927; --accent-secondary-dark:#552583; --accent:#FDB927; --accent-foreground:#28143F;
}
html[data-state='nv']{
  /* mustard #D4A017 on navy #0A2540 = 6.54:1 (on dark card #0C2A48 = 6.14:1) — clears AA (4.5:1)
     for the underlined responsible-strip links and small-text uses; same tone safe as text + fill. */
  --accent-primary:#8B5E0B; --accent-secondary:#D4A017; --accent-secondary-dark:#D4A017; --accent:#0A6FB8; --accent-foreground:var(--color-bone);
}
html[data-state='ny']{
  /* Yankees home white (approved CW _shared.jsx 'yankees'): navy #0C2340 (links/large, 13.99:1 on bone)
     + brass #B8924A pop + soft-navy pinstripe field. Brass fails on bone → on-bone small falls back to navy. */
  --accent-primary:#0C2340; --accent-secondary:#B8924A; --accent-secondary-dark:#0C2340; --accent:#B8924A; --accent-foreground:#0C2340;
}
/* Smooth accent transition on state flip (reduced-motion guarded globally) */
.btn,.state-btn,.nav__state,.storm,.card__label,.wordmark .spark svg,.hero__bolt{
  transition:background .3s ease,border-color .3s ease,color .3s ease,fill .3s ease;
}

/* =============================================================================
   RESET + BASE
   ============================================================================= */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%}
body{
  font-family:var(--font-body); font-size:var(--fs-base);
  line-height:var(--lh-body); color:var(--color-ink);
  background:var(--color-bone); overflow-x:hidden;
  -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
}
img{display:block;max-width:100%;height:auto}
a{color:inherit;text-decoration:none}
button{font:inherit;cursor:pointer;border:none;background:none;color:inherit}
ul{list-style:none}
:focus-visible{outline:var(--outline-focus) solid var(--color-focus);outline-offset:var(--sp-8)}
.section--dark :focus-visible,.footer :focus-visible,.agegate :focus-visible,.nav__menu :focus-visible{outline-color:var(--color-bone)}

.skip-link{position:absolute;left:var(--sp-8);top:-200px;z-index:3000;background:var(--color-navy);color:var(--color-bone);padding:var(--sp-13) var(--sp-21);font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-ui);text-transform:uppercase}
.skip-link:focus{top:var(--sp-8)}

/* =============================================================================
   TYPOGRAPHY ROLE CLASSES
   ============================================================================= */
.t-h1{font-family:var(--font-body);font-size:var(--fluid-h1);line-height:var(--lh-h1);letter-spacing:var(--ls-h1);font-weight:700}
.t-body-lead{font-family:var(--font-body);font-size:var(--fluid-body-lead);line-height:var(--lh-body);letter-spacing:var(--ls-body);font-weight:400}
.t-body{font-family:var(--font-body);font-size:var(--fs-base);line-height:var(--lh-body);letter-spacing:var(--ls-body)}
.t-fine{font-family:var(--font-data);font-size:var(--fs-2xs);line-height:var(--lh-fine);letter-spacing:var(--ls-fine)}
.kicker{font-family:var(--font-data);font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:var(--ls-ui);color:var(--color-ink-muted)}

/* =============================================================================
   LAYOUT PRIMITIVES
   ============================================================================= */
.wrap{max-width:var(--layout-max);margin-inline:auto;padding-inline:var(--pad-section-x)}
.section{padding-block:var(--pad-section-y-sm)}
@media(min-width:760px){.section{padding-block:var(--pad-section-y-md)}}
@media(min-width:1100px){.section{padding-block:var(--pad-section-y-lg)}}
.section--dark{background:var(--color-navy);color:var(--color-bone)}
.section--dark .kicker{color:rgba(245,241,230,.65)}
.section-head{max-width:62ch;margin-bottom:var(--sp-55)}
.section-head .kicker{display:block;margin-bottom:var(--sp-13)}
.section-head h2{margin-bottom:var(--sp-21)}
.section-head p{color:var(--color-ink-muted);max-width:54ch}
.section--dark .section-head p{color:rgba(245,241,230,.80)}

/* Buttons */
.btn{display:inline-flex;align-items:center;gap:var(--gap-icon);font-family:var(--font-body);font-size:var(--fs-xs);font-weight:700;letter-spacing:var(--ls-ui);text-transform:uppercase;padding:var(--pad-btn);border:2px solid var(--color-navy)}
/* demo-state CTA (e.g. the locator "Reserve" button before reservations are wired).
   Targets BOTH the native `disabled` property and `[aria-disabled='true']` — the locator Reserve
   button uses aria-disabled (not disabled) so it stays keyboard-focusable and its explanatory
   aria-label is reachable, but it must still LOOK inert. Hover stays inert (no accent light-up);
   cursor:not-allowed signals it can't complete an action. */
.btn:disabled,.btn:disabled:hover,
.btn[aria-disabled='true'],.btn[aria-disabled='true']:hover,.btn[aria-disabled='true']:focus-visible{opacity:.5;cursor:not-allowed;background:var(--accent);border-color:var(--accent);color:var(--accent-foreground);letter-spacing:var(--ls-ui)}
.btn--solid{background:var(--accent);border-color:var(--accent);color:var(--accent-foreground)}
.btn--solid:hover,.btn--solid:focus-visible{background:var(--color-navy);border-color:var(--color-navy);color:var(--color-bone);letter-spacing:var(--ls-btn-hover)}
.btn--ghost{background:transparent;color:var(--color-navy)}
.btn--ghost:hover,.btn--ghost:focus-visible{background:var(--color-navy);color:var(--color-bone)}
.section--dark .btn--ghost{color:var(--color-bone);border-color:var(--color-bone)}
.section--dark .btn--ghost:hover,.section--dark .btn--ghost:focus-visible{background:var(--color-bone);color:var(--color-navy)}

.bolt-svg{width:1em;height:1.4em}
.footnote{margin-top:var(--sp-34);max-width:70ch;color:var(--color-ink-muted)}
.section--dark .footnote{color:rgba(245,241,230,.70)}

/* =============================================================================
   AGE GATE
   ============================================================================= */
.agegate{position:fixed;inset:0;z-index:2500;display:grid;place-items:center;overflow-y:auto;background:var(--color-navy);padding:var(--sp-34);padding-top:calc(var(--sp-34) + env(safe-area-inset-top));padding-bottom:calc(var(--sp-34) + env(safe-area-inset-bottom))}
.agegate[hidden]{display:none}
.agegate__panel{max-width:48ch;text-align:center;color:var(--color-bone)}
.agegate__bolt{width:34px;height:55px;color:var(--accent);margin:0 auto var(--sp-21)} /* 34x55: fixed bolt-glyph aspect, off the spacing scale on purpose */
.agegate .kicker{color:rgba(245,241,230,.6);display:block;margin-bottom:var(--sp-21)}
.agegate h2{font-family:var(--font-display);font-size:var(--fluid-h1);line-height:var(--lh-display);letter-spacing:var(--ls-display);margin-bottom:var(--sp-21)}
.agegate p{color:rgba(245,241,230,.85);margin-bottom:var(--sp-21)}
.agegate__q{font-weight:700;color:var(--color-bone)}
.agegate__btns{display:flex;gap:var(--gap-tag);justify-content:center;flex-wrap:wrap;margin-bottom:var(--sp-34)}
/* JS-off: the Yes/No buttons are dead without JS. app.js removes html.no-js, so the buttons show
   only when JS can drive them (CSP-safe — replaces the blocked inline <noscript><style>). */
.no-js #agegate-default .agegate__btns{display:none}
.agegate__fine{color:rgba(245,241,230,.55)!important}
.agegate__exit{color:var(--accent);text-decoration:underline;font-family:var(--font-data);font-size:var(--fs-xs)}

/* =============================================================================
   NAV
   ============================================================================= */
.nav{position:sticky;top:0;z-index:900;background:rgba(245,241,230,.94);backdrop-filter:blur(8px);border-bottom:1px solid var(--color-rule)}
.nav__inner{max-width:var(--layout-max);margin-inline:auto;padding:var(--sp-13) var(--pad-section-x);display:flex;align-items:center;justify-content:space-between;gap:var(--sp-21)}
.nav__brand{display:inline-flex;align-items:center;padding:0;line-height:0}
/* Phase 2: SVG wordmark replaces Ultra-font text. Nav height constraint: 40px. SVG is 520×392
   so height-constrained to 40px → width = 520*(40/392) ≈ 53px. Keep aspect-ratio:auto. */
.nav__wordmark{display:block;height:40px;width:auto;max-width:none}
/* Retain legacy bolt-svg rule in case any other use-site remains (agegate, etc.) */
.nav__brand .bolt-svg{color:var(--accent);height:1em}
.nav__links{display:none;align-items:center;gap:var(--sp-21)}
.nav__links a{font-family:var(--font-body);font-size:var(--fs-xs);font-weight:600;letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--color-ink-muted);transition:color .15s}
.nav__links a:hover{color:var(--accent-primary)}
.nav__state{display:none;font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);text-transform:uppercase;color:var(--color-navy);border:1px solid var(--accent-primary);padding:var(--sp-8) var(--sp-13);white-space:nowrap}
@media(min-width:560px){.nav__state{display:inline-block}}
.nav__cta{display:none}
.nav__toggle{display:inline-flex;flex-direction:column;gap:5px;padding:var(--sp-8)} /* 5px: optical hamburger gap, off-scale on purpose */
.nav__toggle span{width:24px;height:2px;background:var(--color-navy);display:block} /* 24x2: fixed icon-bar geometry, not a rhythm value */
.nav__menu{display:none}
@media(min-width:980px){.nav__links{display:flex}.nav__cta{display:inline-flex}.nav__toggle{display:none}}
.nav__menu[data-open='true']{display:block;position:fixed;inset:0;z-index:901;background:var(--color-navy);padding:calc(var(--sp-55) + var(--sp-34)) var(--sp-34) var(--sp-34)}
.nav__menu ul{display:flex;flex-direction:column;gap:var(--sp-21)}
.nav__menu a{font-family:var(--font-body);font-size:var(--fs-xl);font-weight:700;color:var(--color-bone);text-transform:uppercase;letter-spacing:var(--ls-h2h3)}
.nav__menu .btn{margin-top:var(--sp-34)}
.nav__menu-close{position:absolute;top:var(--sp-34);right:var(--sp-34);color:var(--color-bone);font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-ui)}
/* Sound toggle — unobtrusive speaker icon in the nav. Default OFF: the slash (mute) shows and the
   waves are hidden; aria-pressed='true' flips to playing (waves on, slash off). 22x22: fixed icon
   geometry, off the spacing scale on purpose. */
.nav__sound{display:inline-flex;align-items:center;justify-content:center;padding:var(--sp-8);color:var(--color-ink-muted);border:1px solid transparent;transition:color .15s,border-color .15s}
.nav__sound:hover,.nav__sound:focus-visible{color:var(--accent-primary)}
.nav__sound-icon{width:22px;height:22px}
.nav__sound .nav__sound-wave{display:none}
.nav__sound[aria-pressed='true']{color:var(--accent)}
.nav__sound[aria-pressed='true'] .nav__sound-wave{display:inline}
.nav__sound[aria-pressed='true'] .nav__sound-mute{display:none}

/* =============================================================================
   HERO
   ============================================================================= */
.hero{position:relative;background:var(--color-bone);padding-block:var(--sp-55) var(--sp-34);overflow:hidden}
.hero__frame{position:absolute;inset:var(--sp-21);border:1px solid var(--color-rule-dark);pointer-events:none;z-index:1}
.hero__inner{position:relative;z-index:2;max-width:var(--layout-max);margin-inline:auto;padding-inline:var(--pad-section-x);display:grid;gap:var(--gap-hero-content);align-items:center}
@media(min-width:900px){.hero__inner{grid-template-columns:1.1fr .9fr}}
.hero__kicker{display:block;margin-bottom:var(--sp-21);color:var(--color-ink-muted)}
.wordmark{display:block;margin-bottom:var(--sp-13)}
/* Phase 2: real SVG wordmark. Fluid width from 280px (mobile) up to 520px (desktop max).
   Aspect ratio locked; SVG canvas is 520×392. */
.wordmark__svg{display:block;width:clamp(240px,70vw,520px);height:auto}
@media(max-width:360px){.wordmark__svg{width:240px}}
/* Retain legacy .spark rule for any remaining use-sites */
.wordmark span{display:block}
.wordmark .spark{display:inline-flex;vertical-align:baseline}
.wordmark .spark svg{width:.42em;height:.78em;color:var(--accent);margin-left:.04em}
.hero__head{font-family:var(--font-display);color:var(--color-navy);font-size:var(--fluid-hero-sub);line-height:var(--lh-display);letter-spacing:var(--ls-display);margin:var(--sp-21) 0 var(--sp-34)}
.hero__head span{display:block}
.hero__deck{max-width:40ch;color:var(--color-ink-muted);margin-bottom:var(--sp-21)}
/* heroMicro is a <button> (keyboard-reachable easter egg) styled to read as inline italic text */
.hero__micro{display:inline-block;text-align:left;background:none;border:none;padding:0;font-style:italic;color:var(--color-navy);font-family:var(--font-body);font-size:var(--fs-lg);margin-bottom:var(--sp-34);cursor:pointer}
.hero__cta{display:flex;gap:var(--gap-tag);flex-wrap:wrap}
.hero__media{position:relative;display:flex;justify-content:center;align-items:flex-end}
/* Deterministic LCP box: aspect-ratio (= intrinsic 700/2540) + the img's own width/height attrs
   reserve the footprint from first paint, so the responsive width below causes NO reflow on load.
   width is a token-anchored clamp: floors at --hero-tube-w (~149px) on the smallest screens and
   grows with the viewport to a real hero scale (>=240px by the 900px two-column breakpoint) instead
   of floating thumbnail-sized in the desktop media column. height/max-height kept as the cap. */
.hero__tube{width:clamp(var(--hero-tube-w), 30vw, var(--hero-tube-clamp-max));aspect-ratio:700/2540;height:auto;max-height:var(--hero-tube-max);object-fit:contain;filter:drop-shadow(var(--shadow-hero-tube))}
.hero__horse{position:absolute;left:-4%;bottom:-2%;width:46%;max-width:var(--hero-horse-max);opacity:.10;z-index:-1;pointer-events:none}
.hero__bolt{position:absolute;right:18%;top:6%;width:54px;height:130px;color:var(--accent);z-index:3;opacity:0} /* 54x130: fixed bolt-glyph aspect, intentionally off the spacing scale */
@media(prefers-reduced-motion:no-preference){
  .hero__bolt{animation:strike 2600ms ease-out 600ms 1 forwards}
  @keyframes strike{0%{opacity:0}6%{opacity:1}14%{opacity:.2}20%{opacity:.9}30%{opacity:0}100%{opacity:0}}
}
@media(prefers-reduced-motion:reduce){.hero__bolt{opacity:.55}}

.compliance-strip{background:var(--color-navy);color:rgba(245,241,230,.85);text-align:center}
.compliance-strip p{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);padding:var(--sp-13) var(--sp-34);max-width:90ch;margin-inline:auto}

/* =============================================================================
   MANIFESTO
   ============================================================================= */
.manifesto{background:var(--color-bone);text-align:center;padding-block:var(--sp-144)}
.manifesto .kicker{display:block;margin-bottom:var(--sp-34)}
.manifesto p{font-family:var(--font-display);color:var(--color-navy);font-size:var(--fluid-manifesto);line-height:var(--lh-manifesto);letter-spacing:var(--ls-display);max-width:18ch;margin-inline:auto}

/* =============================================================================
   CARD GRID (value / why $9)
   ============================================================================= */
.card-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--col-min-card),1fr));gap:var(--gap-cards-row) var(--gap-cols);align-items:stretch}
.card{display:flex;flex-direction:column;padding:var(--pad-card);height:100%;background:var(--color-card-dark);border:1px solid var(--color-rule-dark)}
.card__label{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--accent-secondary-dark);margin-bottom:var(--sp-13)}
/* Reserve two display lines (mirrors .storm__name's two-line reserve) so the body/footer rows
   start at a shared Y across the three cards even when titles wrap to different line counts.
   The reserve uses --lh-h2h3 which IS this title's rendered line-height, so a 2-line title fills
   the reserve exactly and a 1-line title leaves the second line empty — body tops then align. */
.card__title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-family:var(--font-body);font-size:var(--fs-xl);line-height:var(--lh-h2h3);letter-spacing:var(--ls-h2h3);font-weight:700;color:var(--color-bone);margin-bottom:var(--sp-13);min-height:calc(var(--lh-h2h3) * var(--fs-xl) * 2)}
.card__body{--card-body-lines:3;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--card-body-lines);overflow:hidden;color:rgba(245,241,230,.80);line-height:var(--lh-body);min-height:calc(var(--lh-body) * var(--fs-base) * var(--card-body-lines))}
.card__footer{margin-top:auto;padding-top:var(--gap-stack);font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-mono);color:var(--accent-secondary-dark);border-top:1px solid var(--color-rule-dark)}

/* =============================================================================
   STORM LINEUP
   ============================================================================= */
.storm-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--col-min-storm),1fr));gap:var(--sp-21);align-items:stretch}
.storm{display:flex;flex-direction:column;height:100%;background:var(--color-bone);border:1px solid var(--color-rule);border-top:3px solid var(--lane);padding:var(--pad-card)}
.storm[data-lane='indica']{--lane:var(--color-indica)}
.storm[data-lane='sativa']{--lane:var(--color-sativa)}
.storm[data-lane='hybrid']{--lane:var(--color-hybrid)}
.storm--featured{border:1px solid var(--color-navy);border-top:3px solid var(--lane);box-shadow:inset 0 0 0 1px var(--color-navy)}
@media(prefers-reduced-motion:no-preference){.storm{transition:transform .2s ease,border-top-width .2s ease}.storm:hover,.storm:focus-within{transform:translateY(-3px);border-top-width:5px}}
@media(prefers-reduced-motion:reduce){.storm:focus-within{border-top-width:5px}}
/* Reserve the flagship-tag slot on EVERY storm card so the pill row aligns column-to-column.
   .storm__feat-tag uses --fs-2xs (10.51) * --lh-fine spacing; reserve that exact band + margin. */
/* Wider reserve band (--sp-13 not --sp-8): adds ~5px slack above the pill so a FOUT metric shift
   in Ultra/Space Mono can't let "Flagship" kiss the pill before web fonts settle. */
.storm::before{content:"";display:block;height:calc(var(--fs-2xs) + var(--sp-13));flex:none}
/* Explicit coords inside the ::before reserved band (top:pad-card, left:pad-card) so "Flagship"
   sits in the gap ABOVE the pill and never falls onto the pill via static-position resolution.
   Fixed line-height pins its line-box height so a taller fallback metric can't grow it downward. */
.storm__feat-tag{position:absolute;top:var(--pad-card);left:var(--pad-card);font-family:var(--font-data);font-size:var(--fs-2xs);line-height:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--accent)}
.storm{position:relative}
.storm__pill{align-self:flex-start;font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--color-bone);background:var(--lane);padding:var(--sp-8) var(--sp-13);margin-bottom:var(--sp-21)}
/* overflow-wrap:anywhere guards a future long single-token strain name from overflowing horizontally
   at the --col-min-storm wrap floor; the 2-line reserve covers today's names (max 2 lines @250px).
   -webkit-line-clamp:2 caps it at 2 lines (matching .card__title) so a future name longer than ~10
   Ultra chars can't wrap to 3 lines and blow past the reserve, breaking the forecast-row alignment. */
.storm__name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-family:var(--font-display);font-size:var(--fs-xl);line-height:var(--lh-storm-name);letter-spacing:var(--ls-display);color:var(--color-navy);margin-bottom:var(--sp-13);min-height:calc(var(--lh-storm-name) * 2 * var(--fs-xl));overflow-wrap:anywhere}
.storm__forecast{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;overflow:hidden;color:var(--color-ink-muted);line-height:var(--lh-body);min-height:calc(var(--lh-body) * var(--fs-base) * 3)}
.storm__data{margin-top:auto;padding-top:var(--sp-21);border-top:1px solid var(--color-rule);font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-mono);color:var(--color-navy)}
/* Forecast roast (opt-in brand voice, injected by app.js). The roast swaps IN PLACE inside the
   reserved .storm__forecast box (still -webkit-line-clamp:3, same min-height) so toggling never
   reflows the row — peer cards keep equal height. Roast state italicizes + darkens = "the horse
   talking." .storm__ask is a link-styled <button>; navy on bone clears AA, accent on hover/focus. */
.storm__forecast--roast{color:var(--color-navy);font-style:italic}
.storm__ask{align-self:flex-start;margin:var(--sp-13) 0 0;padding:0;background:none;border:0;cursor:pointer;font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--color-navy);text-decoration:underline;text-underline-offset:3px}
.storm__ask:hover,.storm__ask:focus-visible{color:var(--accent-primary)}

/* =============================================================================
   PRODUCT / RESERVE
   ============================================================================= */
.product-grid{display:grid;grid-template-columns:1fr;gap:var(--sp-55);align-items:stretch}
@media(min-width:760px){.product-grid{grid-template-columns:1fr 1fr}}
.product{display:flex;flex-direction:column;height:100%;background:var(--color-bone);border:1px solid var(--color-rule)}
.product__media{position:relative;background:var(--color-navy);display:grid;place-items:center;aspect-ratio:4/3;overflow:hidden;border-bottom:1px solid var(--color-rule)}
.product__media img{max-height:88%;width:auto;filter:drop-shadow(var(--shadow-product))}
.anno{position:absolute;font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-mono);text-transform:uppercase;color:var(--color-bone);background:rgba(10,37,64,.72);border:1px solid var(--accent-secondary);padding:4px var(--sp-8)} /* 4px: tight chip inset, deliberate optical exception */
.anno--a{top:8%;left:6%}.anno--b{top:30%;right:6%}.anno--c{bottom:24%;left:6%}.anno--d{bottom:8%;right:6%}
/* aspect-ratio:4/3 matches .product__media so the 5-pack media slot is the SAME height as the
   single-tube image slot — keeps the two product cards' bodies starting at a shared Y. */
.box-placeholder{position:relative;background:var(--color-bone);display:grid;place-items:center;text-align:center;gap:var(--sp-13);padding:var(--sp-34);aspect-ratio:4/3}
.box-placeholder .bolt-svg{width:48px;height:60px;color:var(--accent);margin-inline:auto}
.box-placeholder p{font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-mono);text-transform:uppercase;color:var(--color-ink-muted)}
.product__body{padding:var(--pad-card);display:flex;flex-direction:column;flex:1}
.product__eyebrow{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--accent-primary);margin-bottom:var(--sp-13)}
/* Two-line reserve (mirrors .card__title / .storm__name): at mid-range widths where the 2-col
   product grid is active (~760-900px) "1g Pre-Roll Tube" wraps to 2 lines while "5-Pack" stays on 1,
   so without a reserve the spec/CTA rows start at different Y across the row. --lh-h2h3 * --fs-2xl is
   this title's rendered line-box; reserving 2 of them + clamping to 2 lines equalizes the title band. */
.product__title{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-family:var(--font-body);font-size:var(--fs-2xl);font-weight:700;line-height:var(--lh-h2h3);letter-spacing:var(--ls-h2h3);color:var(--color-navy);margin-bottom:var(--sp-13);min-height:calc(var(--lh-h2h3) * var(--fs-2xl) * 2)}
/* Clamp the description to a fixed 3 lines + reserve that height so the spec/CTA footer starts at
   the SAME Y across both product cards even when the two descriptions differ in length (card-grid
   box-math: peer rows must align across the row, not just equal card height). */
.product__desc{--product-desc-lines:3;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--product-desc-lines);overflow:hidden;color:var(--color-ink-muted);margin-bottom:var(--sp-21);min-height:calc(var(--lh-body) * var(--fs-base) * var(--product-desc-lines))}
/* Group spec + CTA into one auto footer so both pin to the same bottom baseline across the row. */
.product__foot{margin-top:auto}
.product__spec{font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-mono);color:var(--color-navy);padding-top:var(--sp-13);border-top:1px solid var(--color-rule);margin-bottom:var(--sp-21)}
.product-anno-caption{text-align:center;font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);color:rgba(245,241,230,.7);position:absolute;bottom:var(--sp-8);left:0;right:0}
.reserve-explainer{margin-top:var(--sp-55);max-width:70ch;color:var(--color-ink-muted)}

/* =============================================================================
   EDUCATION
   ============================================================================= */
.edu-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--col-min-edu),1fr));gap:var(--sp-21);align-items:stretch}
.edu{display:flex;flex-direction:column;height:100%;border-left:3px solid var(--accent-secondary);padding:var(--sp-21) var(--sp-34);background:var(--color-card-dark)}
/* TITLE gets a two-line reserve (mirrors .card__title) so every .edu__body starts at a shared Y
   across the row even when one title wraps to 2 lines and its row-peer is 1 line. --lh-h2h3 is this
   title's rendered line-height (fs-base/700), so a 2-line title fills the reserve exactly and a
   1-line title leaves the 2nd line empty — body tops then align. This reserves HEIGHT only; it does
   NOT clamp/truncate the legal BODY copy below. (Card-grid alignment hard rule: measure body tops.) */
.edu__title{font-family:var(--font-body);font-size:var(--fs-base);font-weight:700;line-height:var(--lh-h2h3);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--color-bone);margin-bottom:var(--sp-13);min-height:calc(var(--lh-h2h3) * var(--fs-base) * 2)}
/* NO line-clamp on the BODY: these cards carry verbatim OMMA-mandated warning language (pregnancy,
   contaminant testing, keep-out-of-reach) that must NEVER be truncated mid-sentence at the narrow
   wrap floor. The title reserve above aligns the body tops; the body itself stays unclamped so the
   legally-required copy is always shown in full. */
.edu__body{color:rgba(245,241,230,.82);line-height:var(--lh-body);font-size:var(--fs-base)}
.responsible-strip{margin-top:var(--sp-55);text-align:center;border:1px solid var(--accent-secondary);padding:var(--sp-21) var(--sp-34)}
.responsible-strip p{font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-mono);color:var(--color-bone)}
.responsible-strip a{color:var(--accent-secondary);text-decoration:underline}

/* =============================================================================
   HELP LINES
   ============================================================================= */
.help-list{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--col-min-card),1fr));gap:var(--sp-21);align-items:stretch}
.help{display:flex;flex-direction:column;height:100%;border:1px solid var(--color-rule);padding:var(--sp-34);gap:var(--sp-8)}
/* NAME reserves 1 line, SUB reserves 2 lines (mirrors the card-grid reserve pattern) so the
   .help__foot (number + link) drops to a shared bottom baseline across every card in the row even
   when names/subs differ in length. --lh-h2h3 / --lh-body are the respective rendered line-heights,
   so the reserve fills exactly. Verify by measuring .help__foot tops across the row (hard rule). */
.help__name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:1;overflow:hidden;font-family:var(--font-body);font-weight:700;color:var(--color-navy);font-size:var(--fs-base);line-height:var(--lh-h2h3);min-height:calc(var(--lh-h2h3) * var(--fs-base) * 1)}
.help__sub{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;color:var(--color-ink-muted);font-size:var(--fs-base);line-height:var(--lh-body);min-height:calc(var(--lh-body) * var(--fs-base) * 2)}
/* Footer (number + link) pinned to the bottom so it aligns across the row regardless of name/sub height. */
.help__foot{margin-top:auto;display:flex;flex-direction:column;gap:var(--sp-8)}
.help__num{font-family:var(--font-data);font-size:var(--fs-lg);font-weight:700;color:var(--accent-primary);letter-spacing:var(--ls-mono);padding-top:var(--sp-8)}
.help__num a{color:inherit}
.help__link{font-family:var(--font-data);font-size:var(--fs-xs);color:var(--color-ink-muted);text-decoration:underline}
.help-close{margin-top:var(--sp-34);max-width:60ch;color:var(--color-ink-muted);font-style:italic}

/* =============================================================================
   FIND / LOCATOR + STATE SWITCHER
   ============================================================================= */
.state-switcher{display:flex;gap:var(--gap-tag);flex-wrap:wrap;margin-bottom:var(--sp-34)}
.state-btn{font-family:var(--font-body);font-size:var(--fs-xs);font-weight:600;letter-spacing:var(--ls-ui);text-transform:uppercase;padding:var(--sp-8) var(--sp-21);border:2px solid var(--accent-secondary);background:transparent;color:var(--accent-secondary);display:inline-flex;align-items:center}
.state-btn[aria-checked='true'],.state-btn:hover{background:var(--accent-secondary);color:var(--color-navy)}
/* No opacity dim: at .7 this status label ("Live"/"Rolling in") fell below WCAG AA (≈2.8–3.3:1)
   on the OK/CA fills; full color clears AA (≥4.53:1) selected + unselected. Hierarchy is held by
   the smaller size, looser tracking, and text-transform:none — not by dimming. */
.state-tag{font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);margin-left:var(--sp-8);text-transform:none}
.find__label{display:block;font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:rgba(245,241,230,.6);margin-bottom:var(--sp-13)}
/* Clamp + reserve a FIXED 5-line block (not a 2-line floor): every state body is longer than two
   lines, so a 2-line min-height alone never equalized them and the locator form below shifted on
   each state flip. Five lines covers the longest body at 360px; identical reserved height across all
   four states keeps the form top Y constant. */
.find__state-body{--state-body-lines:5;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:var(--state-body-lines);overflow:hidden;color:rgba(245,241,230,.85);margin-bottom:var(--sp-34);max-width:60ch;min-height:calc(var(--lh-body) * var(--fs-base) * var(--state-body-lines))}
.locator{display:flex;gap:var(--gap-tag);flex-wrap:wrap;align-items:stretch;margin-bottom:var(--sp-21)}
.locator input{flex:1;min-width:var(--locator-input-min);font-family:var(--font-data);font-size:var(--fs-base);padding:var(--sp-21);background:var(--color-card-dark);border:1px solid var(--color-rule-dark);color:var(--color-bone)}
.locator input::placeholder{color:var(--color-placeholder-dark)}
.find__helper{font-family:var(--font-data);font-size:var(--fs-xs);color:rgba(245,241,230,.65)}
.results{display:grid;grid-template-columns:repeat(auto-fit,minmax(var(--col-min-edu),1fr));gap:var(--sp-21);margin-top:var(--sp-34);align-items:stretch}
.result{display:flex;flex-direction:column;height:100%;background:var(--color-card-dark);border:1px solid var(--color-rule-dark);padding:var(--sp-34)}
/* Locator results are JS-generated with variable-length dispensary names/addresses. Clamp name to 2
   lines and meta to 2 lines + reserve that height so the Reserve CTA footer pins to a shared Y across
   the row (card-grid alignment hard rule — peer footers must line up even when text length differs). */
.result__name{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-family:var(--font-body);font-size:var(--fs-lg);line-height:var(--lh-h2h3);font-weight:700;color:var(--color-bone);margin-bottom:var(--sp-13);min-height:calc(var(--lh-h2h3) * var(--fs-lg) * 2)}
.result__meta{display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow:hidden;font-family:var(--font-data);font-size:var(--fs-2xs);line-height:var(--lh-body);letter-spacing:var(--ls-mono);color:rgba(245,241,230,.72);margin-bottom:var(--sp-21);min-height:calc(var(--lh-body) * var(--fs-2xs) * 2)}
.result__cta{margin-top:auto}
.result__micro{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);color:rgba(245,241,230,.55);margin-top:var(--sp-13)}
.find__compliance{margin-top:var(--sp-34);font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);color:rgba(245,241,230,.6);max-width:70ch}

/* =============================================================================
   NEWSLETTER
   ============================================================================= */
.newsletter-form{display:grid;gap:var(--sp-21);max-width:var(--measure-newsletter);margin-top:var(--sp-34)}
.newsletter-form label{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:var(--color-ink-muted);display:block;margin-bottom:var(--sp-8)}
.newsletter-form input[type=email],.newsletter-form select{width:100%;font-family:var(--font-data);font-size:var(--fs-base);padding:var(--sp-13) var(--sp-21);background:var(--color-bone);border:1px solid var(--color-navy);color:var(--color-navy)}
.consent-row{display:flex;align-items:flex-start;gap:var(--sp-13)}
.consent-row input{margin-top:4px;width:18px;height:18px;flex:none;accent-color:var(--accent-primary)} /* 18x18 + 4px: fixed checkbox hit-area, off-scale on purpose */
.consent-row label{text-transform:none;letter-spacing:0;font-family:var(--font-body);font-size:var(--fs-xs);color:var(--color-ink-muted);margin:0}
.demo-notice{border:1px dashed var(--accent-primary);padding:var(--sp-21);margin-top:var(--sp-21);max-width:var(--measure-newsletter);color:var(--color-ink-muted)}
.demo-notice strong{color:var(--color-navy)}
/* min-height:1.4em reserves one status line so the form doesn't shift when nlMsg fills — em-relative
   to this element's own font, a functional reserve (not a rhythm step), off-scale on purpose. */
.newsletter-msg{font-family:var(--font-data);font-size:var(--fs-xs);color:var(--accent-primary);margin-top:var(--sp-13);min-height:1.4em}
.privacy-micro{margin-top:var(--sp-21);max-width:var(--measure-newsletter);color:var(--color-ink-muted)}

/* =============================================================================
   FOOTER
   ============================================================================= */
.footer{background:var(--color-navy);color:var(--color-bone);padding-block:var(--pad-section-y-sm)}
.footer__brand{font-family:var(--font-display);font-size:var(--fs-2xl);letter-spacing:var(--ls-display);color:var(--color-bone);margin-bottom:var(--sp-13)}
.footer__tag{font-family:var(--font-data);font-size:var(--fs-xs);letter-spacing:var(--ls-mono);color:rgba(245,241,230,.7);margin-bottom:var(--sp-34)}
.footer__nav{display:flex;flex-wrap:wrap;gap:var(--sp-21);margin-bottom:var(--sp-55)}
.footer__nav a{font-family:var(--font-body);font-size:var(--fs-xs);font-weight:600;letter-spacing:var(--ls-ui);text-transform:uppercase;color:rgba(245,241,230,.8);transition:color .15s}
.footer__nav a:hover{color:var(--accent-secondary)}
.warnings{border-top:1px solid var(--color-rule-dark);border-bottom:1px solid var(--color-rule-dark);padding-block:var(--sp-34);margin-bottom:var(--sp-34)}
.warnings__title{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;color:rgba(245,241,230,.6);margin-bottom:var(--sp-21)}
.warnings ul{display:grid;gap:var(--sp-13);max-width:90ch}
.warnings li{font-family:var(--font-legal);font-size:var(--fs-xs);line-height:var(--lh-fine);font-weight:700;color:rgba(245,241,230,.92)}
/* General legal/privacy PROSE (producer/license line, privacy+cookie copy) — NOT verbatim OMMA
   statutory warnings, so it does NOT take the --font-legal mandate (that exception is scoped to the
   six-item .warnings list only). Use the body face to keep it consistent with surrounding footer copy. */
.legal-note{font-family:var(--font-body);font-size:var(--fs-2xs);line-height:var(--lh-fine);color:rgba(245,241,230,.66);max-width:90ch;margin-bottom:var(--sp-21)}
/* Cookie-settings control rendered inline in the privacy note — styled as an underlined link
   (it IS a <button> for correct semantics: it triggers an action, not navigation). */
.privacy__cookie-settings{font:inherit;color:var(--accent-secondary);text-decoration:underline;background:none;border:none;padding:0;cursor:pointer}
.privacy__cookie-settings:hover,.privacy__cookie-settings:focus-visible{color:var(--color-bone)}
.copyright{font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-fine);color:rgba(245,241,230,.55)}

/* Inactive state uses visibility:hidden (not just opacity:0) so the button leaves the tab order —
   keyboard users can't Tab into an invisible control near the top of the page. */
.totop{position:fixed;right:calc(var(--sp-21) + env(safe-area-inset-right));bottom:calc(var(--sp-21) + env(safe-area-inset-bottom));z-index:500;background:var(--color-navy);color:var(--color-bone);border:1px solid var(--accent);padding:var(--sp-13) var(--sp-21);font-family:var(--font-data);font-size:var(--fs-2xs);letter-spacing:var(--ls-ui);text-transform:uppercase;opacity:0;visibility:hidden;pointer-events:none;transition:opacity .25s,visibility .25s}
.totop[data-show='true']{opacity:1;visibility:visible;pointer-events:auto}
/* while the cookie banner occupies the bottom of the viewport, suppress the back-to-top button
   so the two fixed elements never crowd the bottom-right corner on narrow screens */
body[data-cookie-open='true'] .totop{display:none}

/* The grievance — pinned brand-voice marginalia (decorative; app.js swaps the line per scroll-beat).
   Self-contained bone surface so it reads at AA contrast over BOTH bone and dark sections; bottom-
   LEFT (opposite the back-to-top button, no corner collision); --accent border ties it to the live
   state theme. Desktop-only — hidden under the layout-max breakpoint to avoid mobile crowding. */
.grievance{position:fixed;left:var(--sp-21);bottom:calc(var(--sp-21) + env(safe-area-inset-bottom));z-index:400;max-width:200px;padding:var(--sp-13) var(--sp-21);background:rgba(245,241,230,.92);border-left:2px solid var(--accent);pointer-events:none}
.grievance__line{margin:0;font-family:var(--font-data);font-style:italic;font-size:var(--fs-2xs);line-height:var(--lh-fine);letter-spacing:var(--ls-mono);color:var(--color-ink-muted);opacity:.85}
@media(prefers-reduced-motion:no-preference){.grievance__line{transition:opacity .22s ease}.grievance__line.is-fading{opacity:0}}
/* Only surface the grievance once the viewport is wide enough that the 1200px content column leaves
   a real left gutter (≈210px) for it — otherwise it overlaps the leftmost storm card. Below that it
   stays hidden (it's decorative). Final placement is part of the pending brand-visual pass. */
.grievance{display:none}
@media(min-width:1640px){.grievance{display:block}}

/* =============================================================================
   COOKIE CONSENT
   ============================================================================= */
.cookie{position:fixed;left:var(--sp-21);right:var(--sp-21);bottom:calc(var(--sp-21) + env(safe-area-inset-bottom));z-index:1500;background:var(--color-bone);border:2px solid var(--color-navy);padding:var(--sp-21) var(--sp-34);display:flex;flex-wrap:wrap;gap:var(--sp-21);align-items:center;justify-content:space-between;max-width:var(--measure-cookie);margin-inline:auto;box-shadow:var(--shadow-cookie)}
.cookie[hidden]{display:none}
/* while the modal mobile menu (aria-modal) is open, hide the cookie banner so its higher
   z-index:1500 can't paint over the menu on first-visit mobile (the banner lives outside
   .nav's sticky stacking context) */
body[data-menu-open='true'] .cookie{display:none}
.cookie p{font-family:var(--font-body);font-size:var(--fs-xs);color:var(--color-ink-muted);max-width:46ch}
.cookie a{color:var(--accent-primary);text-decoration:underline}
.cookie__btns{display:flex;gap:var(--gap-tag);flex-wrap:wrap}
.cookie .btn{font-size:var(--fs-2xs);padding:var(--sp-8) var(--sp-21)}

/* 1px box: the canonical visually-hidden / screen-reader-only clip (a11y idiom, not a rhythm value). */
.vh{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* Reduced-motion master guard */
@media(prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;scroll-behavior:auto!important}
}
