/* ============================================================
   WeatherWindow.AI — Splash-only design system extensions
   Append-only after styles-foundation.css.
   Tokens and rules per DESIGN_SYSTEM_SPLASH.md (sections referenced inline).
   ============================================================ */

/* ─── §1 Splash-only token extensions ─────────────────────── */
:root {
  /* Marketing brand tones (not in App :root) */
  --brand-green:        #75ce91;   /* tagline "Wait" word, GO mirror */
  --brand-porthole:     #2b4a7a;

  /* Hero / section type (above in-app scale) */
  --fs-hero-lg:         4rem;      /* 64px — hero H1 only */
  --fs-section:         2.75rem;   /* 44px — section H2 */
  --fs-email-h3:        2rem;      /* 32px — email-band CTA */
  --fs-price:           3rem;      /* 48px — pricing figure (Ploy) */

  /* Card titles — prescribed sizes outside foundation scale (no clean foundation match) */
  --fs-card-h3:         1.5rem;    /* 24px — .ps-card h3 */
  --fs-card-h4:         1.125rem;  /* 18px — .step h4, .feat h4, .dir-a-meta-row .item .v */

  /* Splash spacing (above --s-12) */
  --s-section:          96px;
  --s-hero-top:         96px;
  --s-hero-bottom:      32px;
  --s-band:             56px;

  /* Mono-eyebrow tracking */
  --tracking-eyebrow-mono:       0.18em;
  --tracking-eyebrow-mono-tight: 0.10em;

  /* Hero / window elevation */
  --shadow-hero:        0 30px 80px rgba(0,0,40,0.6);

  /* Shape primitives outside foundation scale */
  --radius-pill:        999px;     /* status chip, .tag pill, etc. */
  --radius-bar:         2px;       /* carousel dot bar — smallest sensible radius */

  /* Ambient decorative washes (splash chrome only) */
  --ambient-glow-accent:   rgba(0,180,216,0.10);
  --ambient-glow-success:  rgba(46,196,182,0.06);
  --ambient-glow-strong:   rgba(0,180,216,0.15);

  /* Featured-pricing tile wash */
  --accent-tint-soft:   rgba(0,180,216,0.06);

  /* Status-chip tint */
  --accent-chip-bg:     rgba(0,180,216,0.06);
  --accent-chip-border: rgba(0,180,216,0.30);

  /* Data-source pill palette — one distinct hue per source. Tokens are stored
     in DISPLAY order (pill-N == the Nth chip), with hues spaced so adjacent
     chips sit ≥129° apart on the colour wheel — distinct chips, never a rainbow
     run. Vivid (L68/S90) so the chips pop; every hue still clears ≥4:1 contrast
     against the --bg as the chip text. */
  --pill-1:  #f78964;
  --pill-2:  #64f79e;
  --pill-3:  #b364f7;
  --pill-4:  #f7c864;
  --pill-5:  #64f7dd;
  --pill-6:  #f264f7;
  --pill-7:  #e7f764;
  --pill-8:  #64d2f7;
  --pill-9:  #f764bd;
  --pill-10: #a8f764;
  --pill-11: #6493f7;
  --pill-12: #f7647e;
  --pill-13: #69f764;
  --pill-14: #7464f7;
}

html.ww-light {
  --brand-green: #3a9a5e;
  --brand-gold:  #d99820;
  --ambient-glow-accent:  rgba(10,42,94,0.06);
  --ambient-glow-success: rgba(46,196,182,0.05);
  --ambient-glow-strong:  rgba(10,42,94,0.08);
  --accent-tint-soft:     rgba(10,42,94,0.04);
  --accent-chip-bg:       rgba(10,42,94,0.04);
  --accent-chip-border:   rgba(10,42,94,0.25);
}

/* ─── §6.1 Background ambience ─────────────────────────────── */
.dir-a {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  min-height: 100%;
  position: relative;
}
.dir-a-bg {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    radial-gradient(ellipse 1200px 600px at 80% -10%, var(--ambient-glow-accent), transparent 60%),
    radial-gradient(ellipse 800px 400px at 10% 30%, var(--ambient-glow-success), transparent 60%);
}
.dir-a-grid {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0.4;
  background-image:
    linear-gradient(var(--border-dim) 1px, transparent 1px),
    linear-gradient(90deg, var(--border-dim) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse 80% 60% at 50% 30%, black, transparent 80%);
}

/* ─── §6.2 Page shell ─────────────────────────────────────── */
.dir-a-shell {
  position: relative;
  max-width: 1280px;
  margin: 0 auto;
  padding: 0 var(--s-8);
}

/* ─── §6.3 Splash nav ─────────────────────────────────────── */
.dir-a-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Full-bleed navy. The sticky bar lives inside .dir-a-shell (padded --s-8 each
     side), so a plain background only paints the logo→CTA content span. The trust
     band below bleeds its lighter --surface to the shell edges via a -–s-8 negative
     margin, so as it scrolled under the sticky nav its lighter blue showed in the
     --s-8 side strips the navy didn't cover. Cancel the shell pad with a matching
     negative margin and re-pad internally so the navy reaches the shell edges
     (matching the trust band's width) while the logo/CTAs stay aligned at x=32. */
  margin: 0 calc(-1 * var(--s-8));
  padding: 22px var(--s-8);
  border-bottom: 1px solid var(--border-dim);
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--bg);
}
.dir-a-brand { display: flex; align-items: center; gap: 14px; }
.dir-a-brand img { height: 80px; width: auto; }
.dir-a-nav ul {
  display: flex;
  gap: var(--s-1);
  list-style: none;
  padding: 0;
  margin: 0;
}
.dir-a-nav ul a {
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text-dim);
  text-decoration: none;
  padding: 10px 16px;
  border-radius: var(--radius-sm);
}
.dir-a-nav ul a:hover { background: var(--surface); color: var(--text); }
.dir-a-actions { display: flex; gap: 10px; align-items: center; }
/* Nav CTA buttons match the nav-link font scale for visual weight parity. */
.dir-a-actions .btn { font-size: var(--fs-md); padding: 10px 18px; }
/* The desktop nav (80px logo ≈361px wide + 5-link menu + 2 CTAs) needs
   ~1070px to lay out, so it overflows every viewport below that. Collapse it:
   hide the in-page menu links (still reachable via the footer + page scroll),
   shrink + width-bound the logo (a smaller mark per §6.3/X9), and let the bar
   wrap so the logo and the Sign in / Start free CTAs always fit. */
@media (max-width: 1080px) {
  .dir-a-nav { flex-wrap: wrap; row-gap: var(--s-3); }
  .dir-a-nav ul { display: none; }
  .dir-a-nav .dir-a-brand img { height: 48px; max-width: 100%; }
}

/* ─── §6.4 Live status chip ────────────────────────────────── */
.dir-a-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--accent);
  padding: 4px 10px;
  border: 1px solid var(--accent-chip-border);
  border-radius: var(--radius-pill);
  background: var(--accent-chip-bg);
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.dir-a-status .dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
  animation: ww-pulse 2s ease-in-out infinite;
}
@keyframes ww-pulse {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.4; }
}
@media (prefers-reduced-motion: reduce) {
  .dir-a-status .dot { animation: none; }
}

/* ─── §6.5 Hero ───────────────────────────────────────────── */
.dir-a-hero {
  padding: var(--s-hero-top) 0 var(--s-hero-bottom);
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s-section);
  align-items: center;
  position: relative;
  z-index: 1;
}
.dir-a-eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--accent);
  /* Inter (sans) is proportional — the wide mono tracking read airy; use the
     tight value so the label reads intentional, not spaced-out. */
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  text-transform: uppercase;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 10px;
}
.dir-a-h1 {
  font-size: var(--fs-hero-lg);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.02em;
  margin: var(--s-6) 0 var(--s-8);
  text-wrap: balance;
}
.dir-a-h1 .em    { color: var(--accent); }
.dir-a-h1 .green { color: var(--brand-green); }
.dir-a-h1 .nowrap { white-space: nowrap; }
.dir-a-sub {
  font-size: var(--fs-md);
  line-height: 1.55;
  color: var(--text);
  max-width: 52ch;
  margin: 0 0 var(--s-10);
}
/* Verdict words in the hero subhead are colour-coded by tier. */
.dir-a-sub .v-go { color: var(--success); }
.dir-a-sub .v-caution,
.dir-a-sub .v-marginal { color: var(--warning); }
.dir-a-sub .v-nogo,
.dir-a-sub .v-divert { color: var(--danger); }
/* Inline phrase highlights used in the position-aware tagline/heading. */
.hl-warn { color: var(--warning); }
.hl-go { color: var(--success); }
.dir-a-cta { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.dir-a-cta-meta {
  /* Ploy: dim sans, 14px (not mono/dark). */
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-family: var(--font-sans);
  margin-top: var(--s-5);
  padding-left: 14px;
}

/* §6.20 Hero callout — captain's-judgment disclaimer
   Promoted from mono footnote → sans-serif body copy so it reads as
   marketing positioning rather than fine print. */
.dir-a-disclaim {
  font-size: var(--fs-base);
  color: var(--text-dim);
  font-family: var(--font-sans);
  margin-top: var(--s-5);
  max-width: 56ch;
  line-height: 1.6;
  border-left: 2px solid var(--accent);
  padding-left: 14px;
}

/* ─── §6.6 Hero verdict card ──────────────────────────────────
   The hero shows the verdict in a SINGLE .vcard (the redundant outer
   .vcard-hero frame was removed 2026-06-21 — a card inside a card). The card
   keeps the elevated hero shadow + 88px badge the frame used to provide; the
   verdict glow is applied per-kind below so it tracks the carousel. */
#hero-vcard {
  box-shadow: var(--shadow-hero);
}
#hero-vcard .vbadge {
  /* X8 — 88px in the hero; 92px elsewhere (foundation §3.4) */
  width: 88px;
  height: 88px;
}

/* Carousel dots */
.vdots {
  display: flex;
  justify-content: center;
  gap: 6px;
  margin-top: var(--s-5);
}
.vdots button {
  width: 24px;
  height: 4px;
  border-radius: var(--radius-bar);
  background: var(--border);
  border: 0;
  cursor: pointer;
  padding: 0;
  transition: background 200ms;
}
.vdots button.active { background: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .vdots button { transition: none; }
}

/* ─── §6.19 Browser-window mock (kept available for future use) ── */
.dir-a-window {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-hero);
  overflow: hidden;
}
.dir-a-window-bar {
  background: var(--bg-2);
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  gap: var(--s-2);
}
.dir-a-window-bar .dots { display: flex; gap: 6px; }
.dir-a-window-bar .dots span {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--surface-2);
}
.dir-a-window-bar .url {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-left: 12px;
  padding: 3px 10px;
  background: var(--surface);
  border-radius: var(--radius-sm);
  border: 1px solid var(--border);
}
.dir-a-window-body { padding: var(--s-6); }

/* ─── §6.7 Meta row ───────────────────────────────────────── */
.dir-a-meta-row {
  /* Ploy renders this as 5 equal columns spread across the full width
     (grid repeat(5)), not a left-packed flex row. */
  display: grid;
  /* 6 stats on one row in landscape (Jon, 2026-06-26); mobile stacks 2-up below.
     Columns are content-sized (not 1fr) and the free space is distributed EQUALLY
     between them via space-between, so the six stay left-aligned yet evenly spaced.
     Equal 1fr columns looked ragged: content of very different widths (46px "Global"
     vs 170px "Apparent & True Angles") left uneven trailing gutters, crowding the
     wide value against its right-hand neighbour ("Coverage"). --s-2 is the minimum
     gutter; the first item pins to x=32, the last to the right edge. */
  grid-template-columns: repeat(6, minmax(0, max-content));
  justify-content: space-between;
  gap: var(--s-2);
  padding: var(--s-6) 0;
  /* Dark breathing room below the stat strip, directly above the trust band
     ("Trusted data, not guesswork") — matched to the 136px section-transition
     spacing (var(--s-section) + var(--s-10)) so it's consistent everywhere. */
  margin-bottom: calc(var(--s-section) + var(--s-10));
  border-top: 1px solid var(--border-dim);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  position: relative;
  z-index: 1;
}
@media (max-width: 720px) {
  .dir-a-meta-row { grid-template-columns: repeat(2, 1fr); row-gap: var(--s-5); }
}
.dir-a-meta-row .item { display: flex; flex-direction: column; gap: 2px; }
.dir-a-meta-row .item .v { color: var(--text); font-family: var(--font-sans); font-size: var(--fs-base); font-weight: 600; }
.dir-a-meta-row .item .l {
  font-size: var(--fs-xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* ─── §6.8 Sidebar TOC (long-scroll layout) ───────────────── */
.splash-layout {
  display: grid;
  grid-template-columns: 156px 1fr;
  gap: 0 28px;
  align-items: start;
  position: relative;
  z-index: 1;
}
@media (max-width: 900px) {
  .splash-layout { display: block; }
  .splash-toc    { display: none; }
}
.splash-toc {
  position: sticky;
  top: 130px;
  max-height: calc(100vh - 150px);
  overflow-y: auto;
  scrollbar-width: none;
  padding: 2px 0;
}
.splash-toc::-webkit-scrollbar { display: none; }
@media (min-width: 1700px) {
  .splash-layout { display: block; }
  .splash-toc {
    position: fixed;
    left: max(20px, calc(50vw - 828px));
    top: 130px;
    width: 160px;
  }
}
.splash-toc-track {
  border-left: 2px solid var(--border);
  display: flex;
  flex-direction: column;
}
.splash-toc-item {
  display: flex;
  align-items: center;
  width: 100%;
  min-height: 36px;
  text-align: left;
  background: none;
  border: none;
  cursor: pointer;
  padding: 5px 4px 5px 12px;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  color: var(--text-dark);
  line-height: 1.3;
  position: relative;
  transition: color 0.15s;
}
.splash-toc-item::before {
  content: '';
  position: absolute;
  left: -5px;
  top: 50%;
  transform: translateY(-50%);
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--border);
  transition: background 0.15s;
}
.splash-toc-item:hover { color: var(--text-dim); }
.splash-toc-item:hover::before { background: var(--border-dim); }
.splash-toc-item.active {
  background: var(--accent-wash);
  color: var(--accent);
  font-weight: 600;
  border-radius: var(--radius-sm);
}
.splash-toc-item.active::before { background: var(--accent); }
.splash-main { min-width: 0; }

/* ─── §6.9 Section opener ─────────────────────────────────── */
.dir-a-section {
  padding: var(--s-section) var(--s-6);
  scroll-margin-top: 130px;
}
/* Inset alternating bands (Ploy reference) — surface-navy panels on alternating
   sections to structure the page; kept inside the main column so the TOC stays.
   Flat (no radius) so consecutive band sections read as one continuous band. */
.dir-a-section.band-alt {
  background: var(--surface);
  /* Lift the eyebrow/title up inside the band — 96px top read too low. */
  padding-top: calc(var(--s-section) - var(--s-8));
}
/* De-crowding (Jon, 2026-06-21): a dark (base) section that runs into a lighter
   band-alt section gets extra bottom space, so its content has room to breathe
   before the coloured band begins. Only fires at a base→band-alt transition. */
.dir-a-section:not(.band-alt):has(+ .band-alt) {
  padding-bottom: calc(var(--s-section) + var(--s-10));
}
/* …and the mirror: a dark (base) section emerging from a band-alt gets the same
   extra space at its TOP, so both sides of every coloured band get symmetric
   dark breathing room. Only fires at a band-alt→base transition. */
.dir-a-section.band-alt + .dir-a-section:not(.band-alt) {
  padding-top: calc(var(--s-section) + var(--s-10));
}
.dir-a-sectitle {
  /* Ploy eyebrows are cyan (--accent), weight 400 — not light. */
  font-size: var(--fs-base);
  color: var(--accent);
  font-family: var(--font-sans);
  /* tight tracking: proportional Inter reads airy at the wide mono value */
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  text-transform: uppercase;
  font-weight: 400;
  margin-bottom: var(--s-5);
}
.dir-a-sechead {
  /* Ploy renders section headings light (--text), reserving cyan for eyebrows
     + small accents. Was inheriting --accent (cyan); pin it to --text. */
  color: var(--text);
  font-size: var(--fs-section);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  margin: 0 0 var(--s-5);
}
/* A second section heading inside one #section (e.g. the "Meet the weather"
   engine statement under #why) needs a strong top break so it reads as its own
   beat, not a continuation of the prior paragraph. */
.dir-a-sechead--gap { margin-top: var(--s-section); }
.dir-a-secsub {
  font-size: var(--fs-md);
  color: var(--text-dim);
  line-height: 1.6;
  max-width: 56ch;
  margin: 0 0 var(--s-12);
}

/* Device showcase — Apple-bezel mockups. The transparent frame PNG paints on
   top (z-index 2); the media sits in the cut-out behind it. Cut-out insets are
   the measured transparent screen rect as a % of each frame image, so they hold
   at any rendered size. Captures are pre-matched to each cut-out's ratio
   (iPad 4:3, MacBook 1.547), so object-fit: cover seats them with no bars. */
#device-showcase { text-align: center; }
.device-stage {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--s-10);
  margin-top: var(--s-12);
}
.device { position: relative; margin: 0; line-height: 0; }
.device-frame {
  position: relative;
  z-index: 2;
  display: block;
  width: 100%;
  height: auto;
  pointer-events: none;
}
.device-screen {
  position: absolute;
  z-index: 1;
  overflow: hidden;
}
.device-screen > img,
.device-screen > video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.device--macbook { flex: 0 1 540px; }
.device--macbook .device-screen { left: 9.437%; top: 10.669%; width: 81.127%; height: 78.662%; }
.device--ipad { flex: 0 1 360px; }
.device--ipad .device-screen { left: 4.133%; top: 5.130%; width: 91.733%; height: 89.739%; }
@media (max-width: 760px) {
  .device-stage { gap: var(--s-8); }
  .device--macbook, .device--ipad { flex-basis: 100%; max-width: 520px; }
}

/* DEVICE SHOWCASE INTERACTIVE WRAPPERS :: START */
/* Clickable .feat-proof buttons in #device-showcase — flex sizing mirrors the
   plain figures they replaced; card-specific spacing overrides are reset. */
.showcase-proof--macbook { flex: 0 1 540px; }
.showcase-proof--ipad    { flex: 0 1 360px; }
.device-stage .feat-proof { margin-top: 0; padding: 0; }
/* MacBook screen starts at 10.7% from the top of the bezel figure, so the
   badge must be pushed inside the screen cutout (default 7% sits above it). */
.showcase-proof--macbook .feat-proof__open { top: 13%; right: 12%; }
@media (max-width: 760px) {
  .showcase-proof--macbook,
  .showcase-proof--ipad { flex-basis: 100%; max-width: 520px; }
}
/* DEVICE SHOWCASE INTERACTIVE WRAPPERS :: END */

/* Long-form prose inside a section (Origin story, Why-it-works paragraphs) */
.dir-a-prose {
  max-width: 64ch;
  font-size: var(--fs-md);
  line-height: 1.7;
  color: var(--text-dim);
}
.dir-a-prose p { margin: 0 0 var(--s-5); font-size: var(--fs-md); line-height: 1.7; }
.dir-a-prose p:last-child { margin: 0; color: var(--text); }
.dir-a-prose .lat { font-family: var(--font-mono); }

/* "Why it works" intro paragraphs */
.dir-a-why-p {
  /* Wrap at the same measure as the Origin prose (64ch), 18px. */
  color: var(--text-dim);
  max-width: 64ch;
  margin: var(--s-6) 0 0;
  line-height: 1.75;
  font-size: var(--fs-md);
}
.dir-a-why-p + .dir-a-why-p { margin-top: var(--s-4); }

/* ─── §6.10 Problem / Solution split ──────────────────────── */
.ps-grid { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-6); }
@media (max-width: 760px) {
  .ps-grid { grid-template-columns: 1fr; }
}
.ps-card {
  /* Ploy cards sit darker than the surface band behind them (#problem is a
     band-alt surface section), so use the base bg for contrast. */
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-8);
}
/* Option A (Jon, 2026-06-22): conform the WITHOUT/WITH labels to the page's
   eyebrow grammar (cf. .option-eyebrow) — small, dim, left-aligned, light weight.
   A big bold centered colored banner read as a "different dialect" against the
   rest of the splash; the before/after contrast now lives entirely on the ×/✓
   list markers, which keep the red/green. */
.ps-card .tag {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  text-transform: uppercase;
  display: block;
  margin-bottom: var(--s-2);
  font-weight: 400;
}
.ps-card h3 {
  font-size: var(--fs-card-h3);
  font-weight: 700;
  margin: 0 0 var(--s-4);
  line-height: 1.25;
  /* Both headings wrap to two lines — reserve exactly that so the bullet lists
     start at the same line without an empty third line under the heading. */
  min-height: calc(2 * 1.25 * var(--fs-card-h3));
}
.ps-card ul {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  gap: var(--s-2);
}
.ps-card li {
  font-size: var(--fs-md);
  color: var(--text-dim);
  line-height: 1.45;
  padding-left: 24px;
  position: relative;
  /* No per-bullet min-height: the Without/With lists are a thematic contrast,
     not a row-by-row comparison, so reserving 2 lines for every bullet only
     left blank gaps under the 1-line ones (read as ~2.5 line-spacing). Natural
     height + the list gap gives an even ~2.0 rhythm. */
}
.ps-card.before li::before {
  content: '×';
  position: absolute;
  left: 0;
  top: -2px;
  color: var(--danger);
  font-weight: 700;
  font-size: var(--fs-md);
}
.ps-card.after li::before {
  content: '✓';
  position: absolute;
  left: 0;
  top: -2px;
  color: var(--success);
  font-weight: 700;
}

/* ─── §6.15 Three-options grid ────────────────────────────── */
.option-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--s-5);
  margin-top: var(--s-10);
}
.option-card {
  /* Ploy: dark base cards on the surface "Three options" band (contrast). */
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 28px;
}
.option-card .option-eyebrow {
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  text-transform: uppercase;
  font-weight: 400;
  margin-bottom: var(--s-2);
}
.option-card h3 { margin-bottom: 12px; }
.option-card p {
  color: var(--text-dim);
  font-size: var(--fs-md);
  line-height: 1.65;
}
.option-card.option-feat {
  /* Ploy: featured Option C is the same dark base + an accent border (no tint). */
  border-color: var(--accent);
  position: relative;
}
.option-card.option-feat .option-eyebrow { color: var(--accent); }

/* ─── §6.11 Steps ─────────────────────────────────────────── */
.steps {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-6);
}
@media (max-width: 900px) { .steps { grid-template-columns: 1fr; max-width: 560px; margin-inline: auto; } }
.step {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: 20px;
  position: relative;
  transition: background 150ms ease;
}
.step:hover { background: var(--surface-2); }
.step .num {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--accent);
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  font-weight: 600;
  margin-bottom: var(--s-4);
}
.step h4 { font-size: var(--fs-card-h4); font-weight: 700; margin: 0 0 8px; }
.step p  { font-size: var(--fs-base); color: var(--text-dim); line-height: 1.55; margin: 0; }
/* Each step's thumbnail is the screen inside a silver iPad bezel (the same
   composite as #device-showcase / #features), pushed to the card bottom with
   margin-top:auto so all three bezels' tops align across the equal-height row.
   Hover lifts the device; the accent-wash→solid-cyan zoom badge pins to the
   screen's top-right. Clicking opens the iPad-bezel lightbox (splash.js); Step
   03 opens a dual Passage Report + Passage Map movie. */
.how-shot {
  position: relative;
  display: block;
  width: 100%;
  margin-top: auto;
  padding: var(--s-5) 0 0;
  background: none;
  border: none;
  cursor: pointer;
}
.how-shot__device {
  margin: 0;
  display: block;
  width: 100%;
  transition: transform 180ms ease;
}
.how-shot:hover .how-shot__device,
.how-shot:focus-visible .how-shot__device {
  transform: translateY(-4px) scale(1.02);
}
.how-shot:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius);
}
/* Zoom-in affordance anchored to the iPad SCREEN's top-right (percentages of the
   bezel so it tracks the cut-out at any size), above the bezel frame (z 3). */
.how-shot__open {
  position: absolute;
  top: 7%;
  right: 6%;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--s-8);
  height: var(--s-8);
  border-radius: var(--radius-sm);
  background: var(--accent-wash);
  color: var(--accent);
  opacity: 0.92;
  transform: scale(0.95);
  transition: opacity 180ms ease, transform 180ms ease, background 180ms ease, color 180ms ease;
}
.how-shot__open svg {
  width: 60%;
  height: 60%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.how-shot:hover .how-shot__open,
.how-shot:focus-visible .how-shot__open {
  opacity: 1;
  transform: scale(1);
  background: var(--accent);
  color: var(--text-on-accent);
}

/* ─── §6.12 Features ──────────────────────────────────────── */
.feat-eyebrow {
  font-size: var(--fs-xs);
  font-family: var(--font-sans);
  color: var(--text-dim);
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  text-transform: uppercase;
  margin-bottom: var(--s-4);
}
.feat-row {
  /* Ploy lays "What sets it apart" out 2×2, not 4-in-a-row. */
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--s-5);
  margin-bottom: var(--s-10);
}
@media (max-width: 720px) { .feat-row { grid-template-columns: 1fr; } }
.feat-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-5);
}
.feat-grid .feat {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
@media (max-width: 760px) { .feat-grid { grid-template-columns: 1fr; } }
.feat {
  /* Ploy: cards are dark base navy (#08111f) on the surface feature band,
     delineated by the --border outline — NOT the same colour as the band. */
  background: var(--bg);
  padding: 36px 28px;
}
.feat-row .feat {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  position: relative;
}
.feat-row .feat.feat-core {
  border: 1px solid var(--accent);
}
.feat .icon {
  /* Ploy: bordered cyan pill — cyan border, transparent fill, cyan mono-caps
     text (measured: 1px accent-tinted border, 4px radius, 4px 8px padding). */
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--accent);
  border: 1px solid var(--accent-chip-border);
  border-radius: var(--radius-sm);
  padding: 4px 8px;
  display: inline-block;
  margin-bottom: var(--s-5);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-weight: 600;
}
.feat h4 { font-size: var(--fs-card-h4); font-weight: 700; margin: 0 0 8px; line-height: 1.3; }
.feat p  { font-size: var(--fs-base); color: var(--text-dim); line-height: 1.55; margin: 0; }

/* FEATURES PROOF STRIP :: START */
/* Hero feature cards are flex columns so the iPad preview pins to the card
   bottom (margin-top:auto) — the previews then line up across each row. */
.feat-row .feat { display: flex; flex-direction: column; }
.feat-proof {
  position: relative;
  display: block;
  width: 100%;
  margin-top: auto;          /* push the preview to the bottom of the card */
  padding: var(--s-6) 0 0;
  background: none;
  border: none;
  cursor: pointer;
}
.feat-proof__device {
  margin: 0;
  display: block;
  width: 100%;
  transition: transform 180ms ease;
}
/* Hover lift + slight zoom — matches the "What a report looks like" cards, but
   WITHOUT their cyan border on the box. */
.feat-proof:hover .feat-proof__device,
.feat-proof:focus-visible .feat-proof__device {
  transform: translateY(-4px) scale(1.02);
}
.feat-proof:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--radius);
}
/* Open affordance pinned to the preview's top-right — same treatment as the
   report-section pop-out badge (accent-wash fill that goes solid cyan on hover),
   sized up so the diagonal arrow reads clearly. */
.feat-proof__open {
  /* Anchored to the iPad SCREEN's top-right corner (percentages of the bezel,
     so it tracks the screen cutout at any size). Lives inside the .device
     figure, above the bezel frame (z-index 3). */
  position: absolute;
  top: 7%;
  right: 6%;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--s-8);
  height: var(--s-8);
  border-radius: var(--radius-sm);
  background: var(--accent-wash);
  color: var(--accent);
  opacity: 0.9;
  transform: scale(0.95);
  transition: opacity 180ms ease, transform 180ms ease, background 180ms ease, color 180ms ease;
}
.feat-proof__open svg {
  width: 60%;
  height: 60%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.feat-proof:hover .feat-proof__open,
.feat-proof:focus-visible .feat-proof__open {
  opacity: 1;
  transform: scale(1);
  background: var(--accent);
  color: var(--text-on-accent);
}
/* FEATURES PROOF STRIP :: END */

/* FEATURE LIGHTBOX :: START */
.feature-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s-6);
}
.feature-lightbox[hidden] { display: none; }
.feature-lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(4px);
}
.feature-lightbox__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s-4);
  width: min(92vw, 1040px);
  max-height: 92vh;
  padding: var(--s-5);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;          /* iPad is sized to fit — no panel scroll */
}
.feature-lightbox__bar {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  gap: var(--s-4);
}
.feature-lightbox__title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text);
}
.feature-lightbox__close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--s-8);
  height: var(--s-8);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-dim);
  cursor: pointer;
  transition: color 150ms ease, background 150ms ease, border-color 150ms ease;
}
.feature-lightbox__close:hover { color: var(--text); background: var(--surface-2); border-color: var(--border); }
.feature-lightbox__close:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.feature-lightbox__stage {
  display: flex;
  flex: 1 1 auto;
  min-height: 0;
  align-items: center;
  justify-content: center;
}
/* A single bezel — iPad for #features, MacBook for #how. Cap the bezel by
   viewport height (minus the title bar + panel padding) so the whole device is
   visible without scrolling, on any viewport — short laptops included. A vh cap
   is used because a % max-height won't resolve against the flex stage's
   indefinite height. */
.feature-lightbox__stage .device { flex: 0 1 auto; width: auto; max-width: 100%; }
.feature-lightbox__stage .device .device-frame {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: calc(92vh - 140px);
}
/* Dual (Step 03 — Passage Report movie + Passage Map movie): two MacBook bezels
   side by side, each width-bound to ~half the (widened) panel and capped by a
   shorter vh so the pair fits without scrolling. Wraps to a stack on narrow
   viewports. */
.feature-lightbox__panel:has(.feature-lightbox__stage--dual) { width: min(96vw, 1280px); }
.feature-lightbox__stage--dual { gap: var(--s-5); flex-wrap: wrap; }
.feature-lightbox__stage--dual .device { flex: 1 1 0; min-width: min(100%, 420px); }
.feature-lightbox__stage--dual .device .device-frame {
  width: 100%;
  max-height: calc(88vh - 140px);
}
/* FEATURE LIGHTBOX :: END */

/* ─── §6.13 Sample assessments stack ──────────────────────── */
.samples { display: grid; gap: var(--s-4); }

/* ─── §6.14 Pricing ───────────────────────────────────────── */
.price-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
}
@media (max-width: 960px) { .price-grid { grid-template-columns: 1fr; } }
.price-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-8);
  position: relative;
  display: flex;
  flex-direction: column;
}
/* The cyan highlight is driven by .is-active (interactive) so it moves to the
   hovered/selected tier; .feat-tier only carries the ribbon now. */
.price-card .tier {
  /* Ploy: tier name is a big sans heading (24px/700), not a small mono label. */
  font-size: var(--fs-card-h3);
  color: var(--text);
  font-weight: 700;
  margin-bottom: 12px;
}
.price-card.feat-tier .tier { color: var(--text); }
.price-card .price {
  font-size: var(--fs-price);
  font-weight: 700;
  line-height: 1;
  margin: 0;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.price-card .price .per {
  font-size: var(--fs-sm);
  color: var(--text-dim);
  font-weight: 400;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}
.price-card .price-alt {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  margin-top: 6px;
  font-family: var(--font-mono);
}
.price-card .desc {
  font-size: var(--fs-base);
  color: var(--text-dim);
  margin: var(--s-4) 0 var(--s-6);
  line-height: 1.5;
  /* Reserve enough lines for the tallest tier description so the feature lists
     begin at the same vertical line across all three cards — the "invisible row"
     that holds the bullet lists level. The three descriptions are kept balanced
     in length (enforced by test_splash_frontend_cascade::TestPricingCardAlignment)
     so this reservation stays small; at the narrowest 3-col width the tallest
     wraps to 10 lines. Must use --fs-base — the unit the text renders at — or the
     reservation under-counts and a card's list drifts down. If you lengthen one
     description past the others, the alignment test fails BEFORE the bullets
     visibly drift (Jon has flagged this misalignment 5+ times). */
  min-height: calc(10 * 1.5 * var(--fs-base));
}
.price-card ul {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--s-6);
  display: grid;
  /* No row gap — the 1.5 line-height alone sets the item pitch to ~1.5× the
     font (Jon's target); any extra gap pushed it back toward double-spacing. */
  gap: 0;
  flex: 1;
  /* Pack bullets at the top of the stretched UL so the lists start level across
     tiers (the per-tier list-start is aligned via the .desc reservation). */
  align-content: start;
}
.price-card li {
  font-size: var(--fs-base);
  color: var(--text);
  padding-left: 22px;
  position: relative;
  /* ~1.5× line spacing, single line per feature — no 2-line per-row
     reservation (it left a blank line under every 1-line feature, reading as
     ~triple spacing). The list-start still aligns via the .desc reservation. */
  line-height: 1.5;
}
/* F3 — bullets are ✓ (success), not ◆ (verdict glyph) */
.price-card li::before {
  content: '✓';
  position: absolute;
  left: 0;
  color: var(--success);
  font-size: var(--fs-xs);
  top: 1px;
  font-weight: 700;
}
.price-card .ribbon {
  position: absolute;
  top: -1px;
  right: 24px;
  background: var(--accent);
  color: var(--text-on-accent);
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  padding: 4px 10px;
  border-radius: 0 0 var(--radius-sm) var(--radius-sm);
  text-transform: uppercase;
}
.price-card .lock {
  font-size: var(--fs-xs);
  color: var(--brand-gold);
  font-family: var(--font-sans);
  letter-spacing: 0.05em;
  margin-bottom: var(--s-4);
  display: flex;
  align-items: center;
  gap: 6px;
}
.price-card .lock.lock-spacer { visibility: hidden; }
.price-card .early-note {
  font-size: var(--fs-xs);
  font-family: var(--font-sans);
  color: var(--text-dark);
  margin-bottom: 8px;
}
.price-card .early-note.early-note-spacer { visibility: hidden; }
.price-card .cta-stack { display: grid; gap: var(--s-1); }
.price-card .cta-stack .btn { width: 100%; }
.price-card .cta-stack .btn-ghost { font-size: var(--fs-xs); }

/* ─── §6.16 Email signup band ─────────────────────────────── */
.email-band {
  background: linear-gradient(135deg, var(--surface) 0%, var(--bg-2) 100%);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-band) var(--s-12);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.email-band::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 600px 200px at 50% 100%, var(--ambient-glow-strong), transparent);
}
.email-band h3 {
  font-size: var(--fs-email-h3);
  font-weight: 800;
  margin: 0 0 12px;
  letter-spacing: -0.01em;
  position: relative;
}
.email-band p {
  font-size: var(--fs-base);
  color: var(--text-dim);
  margin: 0 0 var(--s-8);
  position: relative;
}
.email-form {
  display: flex;
  gap: 8px;
  max-width: 480px;
  margin: 0 auto;
  position: relative;
}
@media (max-width: 560px) {
  .email-form { flex-direction: column; }
  .email-form .btn { width: 100%; }
}
.email-form input {
  flex: 1;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 14px 16px;
  font-size: var(--fs-base);
  color: var(--text);
  font-family: var(--font-sans);
  outline: none;
}
.email-form input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-wash);
}

/* ─── §6.17 FAQ ───────────────────────────────────────────── */
/* FAQ — matches the app Help page (help.html) FAQ formatting: native browser
   disclosure triangle (no custom icon), surface card + --border outline,
   --radius, --s-3/--s-4 padding, summary weight 700 @ --fs-md. */
.faq-list { display: grid; gap: var(--s-3); }
.faq {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--s-3) var(--s-4);
}
.faq summary {
  cursor: pointer;
  font-weight: 700;
  font-size: var(--fs-md);
  color: var(--text);
}
.faq[open] summary { margin-bottom: var(--s-2); }
.faq p {
  font-size: var(--fs-base);
  color: var(--text-dim);
  line-height: 1.6;
  margin: 0;
}
.faq-more {
  margin: var(--s-6) 0 0;
  text-align: center;
  font-size: var(--fs-base);
  color: var(--text-dim);
}
.faq-more a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: none;
}
.faq-more a:hover { text-decoration: underline; }

/* ─── §6.18 Splash footer ─────────────────────────────────── */
.dir-a-footer {
  padding: var(--s-band) 0 var(--s-8);
  border-top: 1px solid var(--border);
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: var(--s-12);
  position: relative;
  z-index: 1;
}
@media (max-width: 760px) {
  /* Stack to a single column so the wide brand wordmark can't force a
     minmax(auto,1fr) track past a ~375px viewport and push the link
     columns off-screen. The logo is also width-bounded as a backstop. */
  .dir-a-footer { grid-template-columns: 1fr; }
  .dir-a-footer .col .dir-a-brand img { height: auto; max-width: 100%; }
}
.dir-a-footer .col h5 {
  /* Footer column headers are cyan sans (like eyebrows), weight 400. */
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
  font-weight: 400;
  color: var(--accent);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0 0 12px;
}
.dir-a-footer .col a {
  display: block;
  font-size: var(--fs-sm);
  color: var(--text-dim);
  text-decoration: none;
  padding: 4px 0;
}
.dir-a-footer .col a:hover { color: var(--accent); }
/* DESIGN_SYSTEM.md §3.1.10 — the 44px touch floor. These links render 28px
   tall (13px text + 4px padding each side), the densest tap column on the
   page. Grown with padding rather than line-height so the visual rhythm of
   the column is unchanged on pointer devices. */
@media (pointer: coarse) {
  .dir-a-footer .col a {
    min-height: 44px;
    padding: 12px 0;
    display: flex;
    align-items: center;
  }
}
.dir-a-footer .col .dir-a-brand { margin-bottom: var(--s-4); }
/* Scoped to >=761px on purpose. This rule is a same-specificity twin of the
   `height: auto` in the <=760px block above, and it sits LATER in the file —
   so at top level it wins by source order at every width, leaving the mobile
   `max-width: 100%` squeezing the wordmark's width against a fixed 68px
   height. Below ~375px the footer column is narrower than the lockup's
   natural 307px, so the clamp bound and the wordmark rendered squashed. */
@media (min-width: 761px) {
  .dir-a-footer .col .dir-a-brand img { height: 68px; }
}
.dir-a-footer .col .tagline {
  font-size: var(--fs-sm);
  color: var(--text);
  line-height: 1.55;
  max-width: 40ch;
  margin: 0;
}
.dir-a-fineprint {
  padding: var(--s-5) 0;
  border-top: 1px solid var(--border-dim);
  font-size: var(--fs-xs);
  color: var(--text-dim);
  font-family: var(--font-sans);
  display: flex;
  justify-content: space-between;
  position: relative;
  z-index: 1;
}

/* ─── Responsive — hero collapses on narrow viewports ─────── */
@media (max-width: 960px) {
  .dir-a-hero { grid-template-columns: 1fr; gap: var(--s-8); }
  /* Each headline line is kept on one row via .nowrap; at mobile sizes those
     phrases are wider than the viewport, so allow them to wrap (they only wrap
     when they don't fit). text-wrap:wrap overrides the desktop `balance`, which
     can optimize for even lines at a width a few px past a narrow container. */
  .dir-a-h1         { font-size: var(--fs-section); text-wrap: wrap; }
  .dir-a-h1 .nowrap { white-space: normal; }
}

/* ─── Legal Document Modal ──────────────────────────────────────
   Ports the .gps-modal-* + .legal-doc-body treatment from the app
   (css/styles.css ~2814-2908) into splash-scoped classes so the
   Privacy/Terms links open in-page instead of navigating to the
   raw HTML at app.weatherwindow.ai. Tokens used here are all in
   styles-foundation.css — no new tokens introduced. */
.legal-modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(8, 17, 31, 0.88);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  backdrop-filter: blur(4px);
}
.legal-modal-card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  width: min(860px, 96vw);
  max-height: 92vh;
  display: flex;
  flex-direction: column;
}
.legal-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  background: var(--bg-2);
  border-bottom: 1px solid var(--border);
  font-weight: 600;
  color: var(--accent);
}
.legal-modal-close {
  background: none;
  border: none;
  color: var(--text-dim);
  font-size: var(--fs-lg);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.legal-modal-close:hover { color: var(--text); background: var(--border); }

#legal-doc-body {
  overflow-y: auto;
  flex: 1;
  padding: 32px 40px;
}
.legal-doc-body h1 { color: var(--accent); margin-bottom: 8px; }
.legal-doc-body h2 { color: var(--text); margin-top: 36px; margin-bottom: 12px; }
.legal-doc-body h3 { color: var(--text); margin-top: 0; margin-bottom: 10px; font-size: 1rem; font-weight: 600; }
.legal-doc-body p,
.legal-doc-body li { line-height: 1.4; color: var(--text-dim); font-size: 0.95rem; }
.legal-doc-body .section-body { padding-left: 16px; }
.legal-doc-body .section-body > p,
.legal-doc-body .section-body > ul,
.legal-doc-body .section-body > table { margin-top: 8px; margin-bottom: 12px; }
.legal-doc-body .subsection {
  margin-top: 20px; padding: 12px 16px;
  border-left: 2px solid var(--border);
  background: rgba(255, 255, 255, 0.015);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
}
.legal-doc-body .subsection > p { margin-top: 8px; margin-bottom: 10px; }
.legal-doc-body ul { padding-left: 24px; margin: 8px 0 12px; }
.legal-doc-body ul li { margin-bottom: 6px; padding-left: 4px; }
.legal-doc-body a { color: var(--accent); }
.legal-doc-body .updated { font-size: 0.8rem; color: var(--text-dim); margin-bottom: 32px; }
.legal-doc-body table { width: 100%; border-collapse: collapse; margin-bottom: 16px; font-size: 0.9rem; }
.legal-doc-body th { text-align: left; padding: 8px 12px 8px 0; color: var(--text); border-bottom: 1px solid var(--border); }
.legal-doc-body td { padding: 8px 12px 8px 0; color: var(--text-dim); border-bottom: 1px solid var(--border); vertical-align: top; }
.legal-doc-body td:last-child,
.legal-doc-body th:last-child { padding-right: 0; }

/* ─── §6.21 Splash-review utility classes (CMA / CLO / CMO adjudication) ─────
   Hero tagline elevates the position-aware differentiator to above-the-fold.
   NOT-FOR-NAVIGATION strips repeat verbatim under the verdict carousel, above
   the pricing grid, and in the footer — plain text only (GLYPH-1: no ▲ ◆ ■).
   ───────────────────────────────────────────────────────────────────────── */

.dir-a-tagline {
  font-size: var(--fs-lg);
  font-weight: 600;
  line-height: 1.35;
  color: var(--text);
  margin: var(--s-5) 0 var(--s-6);
  max-width: 56ch;
  letter-spacing: -0.01em;
}
.dir-a-tagline .em { color: var(--accent); font-style: normal; }

.hero-nfn,
.pricing-nfn,
.legal-nfn {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  text-align: center;
  margin: var(--s-4) 0 0;
  padding-top: var(--s-3);
  border-top: 1px solid var(--border-dim);
}
.pricing-nfn { margin: 0 0 var(--s-5); border-top: 0; padding-top: 0; }
.legal-nfn   { margin: 0 0 var(--s-3); border-top: 0; padding-top: 0; }

.option-disclaim {
  font-size: var(--fs-xs);
  color: var(--text-dark);
  line-height: 1.5;
  margin-top: var(--s-3);
  padding-top: var(--s-3);
  border-top: 1px solid var(--border-dim);
}

.price-card .tier-fit {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  font-style: italic;
  margin: 4px 0 var(--s-3);
  line-height: 1.4;
  /* Reserve 4 lines: the longest fit-line (Sailor) wraps to 4 at the narrowest
     3-col width. This is the second "invisible row" — it must hold the tallest
     fit-line so the price/desc/bullets below it stay level across all tiers. */
  min-height: calc(4 * 1.4 * var(--fs-xs));
}

.price-card .cta-disclosure {
  display: grid;
  gap: 6px;
  margin: var(--s-3) 0 0;
  font-size: var(--fs-2xs);
  color: var(--text-dim);
  line-height: 1.5;
}
.price-card .cta-disclosure-line { display: block; }
.price-card .cta-disclosure a {
  color: var(--text-dim);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.price-card .cta-disclosure a:hover { color: var(--accent); }

.pricing-terms-shared {
  margin: var(--s-6) 0 0;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  line-height: 1.6;
  text-align: left;
}
.pricing-terms-shared a {
  color: var(--text-dim);
  text-decoration: underline;
  text-underline-offset: 2px;
}
.pricing-terms-shared a:hover { color: var(--accent); }

.samples-nfn {
  /* Ploy: plain dim text below the cards — no bordered box. */
  /* Full-width single run, no narrow column wrap (Jon, 2026-06-26). */
  margin: var(--s-5) 0 0;
  max-width: none;
  font-size: var(--fs-xs);
  color: var(--text-dim);
  line-height: 1.55;
}

.price-card .cta-disclosure .cta-disclosure-renewal {
  font-weight: 700;
  color: var(--text);
}

/* ── Pricing interval toggle (annual / quarterly) ── */
.pricing-interval-toggle {
  display: inline-flex;
  gap: 4px;
  margin: 0 auto var(--s-5);
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--surface);
  align-self: center;
  justify-content: center;
}
.dir-a-section#pricing { text-align: center; }
.dir-a-section#pricing > .dir-a-sectitle,
.dir-a-section#pricing > h2,
.dir-a-section#pricing > .dir-a-secsub,
.dir-a-section#pricing > .price-grid { text-align: left; }
.dir-a-section#pricing > .dir-a-secsub { margin-left: 0; }
.pricing-interval-toggle .interval-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  font-weight: 600;
  padding: 10px 20px;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  transition: background 150ms ease, color 150ms ease;
  letter-spacing: 0;
}
.pricing-interval-toggle .interval-btn:hover:not(.active) { color: var(--text); }
.pricing-interval-toggle .interval-btn.active {
  background: var(--accent-wash);
  color: var(--accent);
}
.pricing-interval-toggle .interval-save-badge {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 2px 8px;
  border-radius: 999px;
  background: var(--success);
  color: var(--text-on-accent, #000);
}

/* ── Sample Passage Report section (#report-sample) ── */
.report-mock {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-5);
  margin-top: var(--s-4);
}
@media (min-width: 1080px) {
  .report-mock { grid-template-columns: minmax(360px, 1fr) minmax(420px, 1.4fr); align-items: start; }
}
.report-verdict .vcard {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  box-shadow: var(--shadow-hero);
}
.report-verdict .vcard-content h4 {
  font-size: var(--fs-lg);
  line-height: 1.3;
  margin: 0 0 var(--s-3);
}
.report-verdict .vcard-content .r {
  font-size: var(--fs-sm);
  color: var(--text-dim);
  line-height: 1.55;
  margin: 0 0 var(--s-4);
}
/* Ploy renders the verdict-card reason line in mono (hero + samples + report). */
.vcard-content .r { font-family: var(--font-mono); }
.report-verdict .vmetrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
  gap: var(--s-3);
}
.report-map {
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-hero);
  display: flex;
  flex-direction: column;
}
.report-map-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border-dim);
  background: var(--bg-2);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.report-map-header .lbl { color: var(--accent); font-weight: 600; }
.report-map-header .report-map-time { color: var(--text-dim); letter-spacing: 0.05em; }
.report-map-svg,
.report-map-img {
  display: block;
  width: 100%;
  height: auto;
  background: var(--bg-2);
}
.report-map-img {
  /* Real in-app screenshot — preserve crisp pixel mapping on hidpi displays. */
  image-rendering: -webkit-optimize-contrast;
  /* biome-ignore lint/suspicious/noDuplicateProperties: deliberate progressive
     enhancement, not a mistake. Older WebKit/Blink understands only
     -webkit-optimize-contrast and ignores crisp-edges; modern browsers take
     crisp-edges as the later declaration. Both are required — dropping either
     degrades hidpi rendering on one class of browser, and the declaration order
     is load-bearing. See tests_live/test_css_intentional_duplicates.py */
  image-rendering: crisp-edges;
}
.report-map-scrubber {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: var(--s-3);
  align-items: center;
  padding: var(--s-3) var(--s-4);
  border-top: 1px solid var(--border-dim);
  background: var(--bg-2);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  letter-spacing: 0.05em;
}
.report-map-scrubber .lbl { color: var(--text-dim); letter-spacing: 0.08em; text-transform: uppercase; }
.report-map-scrubber .scrubber-track {
  position: relative;
  height: 4px;
  background: var(--surface);
  border-radius: 999px;
}
.report-map-scrubber .scrubber-fill {
  position: absolute;
  inset: 0 48% 0 0;
  background: linear-gradient(90deg, var(--success), var(--accent));
  border-radius: 999px;
}
.report-map-scrubber .scrubber-thumb {
  position: absolute;
  top: 50%;
  width: 14px;
  height: 14px;
  background: var(--accent);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 0 3px var(--accent-wash);
}
.report-map-scrubber .scrubber-time { color: var(--accent); }

.dir-a-legal {
  padding: var(--s-5) 0 var(--s-3);
  border-top: 1px solid var(--border-dim);
  text-align: center;
  position: relative;
  z-index: 1;
}
.legal-nonendorse {
  margin: 0 auto;
  max-width: 80ch;
  font-size: var(--fs-2xs);
  color: var(--text-dark);
  line-height: 1.55;
}

/* ─── Passage Demo — section thumbnails + Option-A modal chrome ──────────────
   Task 9. Light-DOM chrome only; the modal panes host Shadow DOM roots styled
   by css/passage-demo-app.css (the mirrored app stylesheet) — see
   js/passage-render/demo.js. Token-only per DESIGN_SYSTEM.md + _SPLASH.md:
   no inline hex / px font-size / px radius. The interactive demo (report/map)
   inside the shadow roots keeps the app's own treatment via the mirror.
   ───────────────────────────────────────────────────────────────────────── */

/* Thumbnail grid — two-up, collapses to one column on narrow screens. */
.demo-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--s-5);
  max-width: 64ch;
  margin: var(--s-6) auto 0;
}
@media (max-width: 720px) {
  .demo-grid { grid-template-columns: 1fr; }
}

/* Card — a button so it is keyboard-focusable and announces as actionable. */
.demo-card {
  display: flex;
  flex-direction: column;
  text-align: left;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  box-shadow: var(--shadow);
  cursor: pointer;
  overflow: hidden;
  transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}
.demo-card:hover,
.demo-card:focus-visible {
  transform: translateY(-4px) scale(1.012);
  box-shadow: var(--shadow-lg);
  border-color: var(--accent);
}
.demo-card:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Screenshot well + the pop-out badge that lives over its top-right corner. */
.demo-shot {
  position: relative;
  display: block;
  background: var(--surface-2);
}
.demo-shot img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  object-position: top center;
}
.demo-popout {
  position: absolute;
  top: var(--s-2);
  right: var(--s-2);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--s-6);
  height: var(--s-6);
  border-radius: var(--radius-sm);
  background: var(--accent-wash);
  color: var(--accent);
  opacity: 0.7;
  transform: scale(0.92);
  transition: opacity 180ms ease, transform 180ms ease, background 180ms ease;
}
.demo-popout svg {
  width: 60%;
  height: 60%;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.demo-card:hover .demo-popout,
.demo-card:focus-visible .demo-popout {
  opacity: 1;
  transform: scale(1);
  background: var(--accent);
  color: var(--text-on-accent);
}

/* Caption — title is always shown; the hint fades in on hover/focus. */
.demo-cap {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s-3);
  padding: var(--s-3) var(--s-4);
}
.demo-cap__title {
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text);
}
.demo-cap__hint {
  font-size: var(--fs-xs);
  font-family: var(--font-sans);
  color: var(--accent);
  opacity: 0;
  transition: opacity 180ms ease;
}
.demo-card:hover .demo-cap__hint,
.demo-card:focus-visible .demo-cap__hint {
  opacity: 1;
}

/* ─── Modal overlay ─────────────────────────────────────────────────────── */
.demo-modal {
  position: fixed;
  inset: 0;
  z-index: 1100;
  display: flex;
  align-items: stretch;
  justify-content: center;
  padding: var(--s-8);
}
.demo-modal[hidden] { display: none; }

.demo-modal__backdrop {
  position: absolute;
  inset: 0;
  /* Dim derived from the deep-background token rather than a raw rgba(). */
  background: color-mix(in srgb, var(--bg) 62%, transparent);
  backdrop-filter: blur(4px);
}

.demo-modal__panel {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100%;
  background: var(--bg);
  border: 2px solid rgba(255,255,255,0.55);
  border-radius: var(--radius-lg);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.6);
  overflow: hidden;
}

@media (max-width: 480px) {
  .demo-modal { padding: var(--s-4); }
}

.demo-modal__bar {
  display: flex;
  align-items: center;
  gap: var(--s-4);
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}
.demo-modal__title {
  flex: 1 1 auto;
  min-width: 0;
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.demo-modal__tabs {
  display: inline-flex;
  gap: var(--s-1);
  padding: var(--s-1);
  border: 1px solid var(--border);
  border-radius: var(--radius-pill);
  background: var(--bg-2);
}
.demo-tab {
  padding: var(--s-1) var(--s-4);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
  transition: color 150ms ease, background 150ms ease, border-color 150ms ease;
}
.demo-tab:hover { color: var(--text); background: rgba(255,255,255,0.08); }
.demo-tab:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.demo-tab[aria-selected="true"] {
  background: var(--accent);
  color: var(--text-on-accent);
  border-color: var(--accent);
}

.demo-modal__close {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--s-8);
  height: var(--s-8);
  border: 1px solid transparent;
  border-radius: var(--radius);
  background: transparent;
  color: var(--text-dim);
  font-size: var(--fs-md);
  cursor: pointer;
  transition: color 150ms ease, background 150ms ease, border-color 150ms ease;
}
.demo-modal__close:hover { color: var(--text); background: var(--surface-2); border-color: var(--border); }
.demo-modal__close:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* NFN banner — the .demo-nfn rules live in passage-render/demo.js
   injectShadowStyles(): the disclaimer is rendered INSIDE each pane's shadow
   root (so it scrolls with the report and is a static top banner on the map),
   and styles-splash.css does not reach the shadow tree. */

/* Pane — fills the remaining height; the shadow root inside scrolls itself. */
.demo-modal__pane {
  flex: 1 1 auto;
  min-height: 0;
  overflow: auto;
  background: var(--bg);
}
.demo-modal__pane[hidden] { display: none; }

/* ── Boat-popup portal (light-DOM, above shadow stacking context) ──────────
   The boat data popup is appended here rather than inside the shadow DOM so
   it reliably paints above .demo-modal__pane's overflow:auto stacking layer.
   pointer-events:none on the portal; popup itself restores auto. */
.demo-popup-portal {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 1200;
  overflow: hidden;
  /* Pin popup colors to the dark-navy app values regardless of page theme.
     styles-foundation.css defines these in :root but page-level overrides
     (html.ww-light, system prefers-color-scheme) could shift them. */
  --map-popup-bg:     #0d1f3c;
  --map-popup-text:   #c8e0f8;
  --map-popup-border: #2a6a9a;
}
.demo-popup-portal .passage-boat-popup-overlay {
  position: fixed;
  z-index: 1;
  pointer-events: auto;
  cursor: grab;
  user-select: none;
  font-family: var(--font-sans);
  font-size: var(--fs-sm);
  background: var(--map-popup-bg);
  color: var(--map-popup-text);
  border: 1px solid var(--map-popup-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  /* Fixed width prevents the popup from resizing as the user scrubs through
     hours with different sail configs. Sized to fit the widest row: "Sail Plan"
     label + full reef config pill + motor badge side-by-side (≈310px). */
  width: 310px;
}
.demo-popup-portal .passage-boat-popup-overlay:active { cursor: grabbing; }
.demo-popup-portal .passage-boat-popup-close {
  position: absolute;
  top: 2px;
  right: 5px;
  background: none;
  border: none;
  color: rgba(200,224,248,0.55);
  font-size: var(--fs-base);
  line-height: 1;
  cursor: pointer;
  padding: 0 2px;
}
.demo-popup-portal .passage-boat-popup-close:hover { color: var(--map-popup-text); }
.demo-popup-portal .tw-popup-inner { padding: 6px 2px; min-width: 200px; }
.demo-popup-portal .tw-popup-title {
  font-size: var(--fs-base);
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 4px;
}
.demo-popup-portal .tw-popup-coords {
  font-size: var(--fs-xs);
  color: var(--text-dim);
  font-family: var(--font-mono);
  margin-bottom: 6px;
}
.demo-popup-portal .tw-popup-row {
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-sm);
  padding: 2px 0;
  border-top: 1px solid var(--border-dim);
}
.demo-popup-portal .tw-popup-label { color: var(--text-dim); }
.demo-popup-portal .tw-popup-section {
  font-size: var(--fs-xs);
  font-weight: 700;
  color: var(--accent);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  margin: 7px 0 3px;
  padding-top: 5px;
  border-top: 1px solid var(--border-dim);
}
.demo-popup-portal .tw-popup-wind-table { width: 100%; border-collapse: collapse; font-size: var(--fs-xs); }
.demo-popup-portal .tw-popup-wind-table th { color: var(--text-dim); font-weight: 600; text-align: left; padding: 1px 4px 1px 0; }
.demo-popup-portal .tw-popup-wind-table td { padding: 1px 4px 1px 0; color: var(--map-popup-text); }
.demo-popup-portal .tw-popup-wind-table .tw-aw { color: var(--success); font-weight: 600; }
.demo-popup-portal .tw-popup-note { font-size: var(--fs-xs); color: var(--text-dim); margin-top: 4px; font-style: italic; }
.demo-popup-portal .tw-popup-elapsed { font-size: var(--fs-xs); font-weight: 400; color: var(--text-dim); letter-spacing: 0.01em; }
.demo-popup-portal .tw-popup-summary { font-size: var(--fs-xs); color: var(--map-popup-text); margin-top: 6px; padding-top: 5px; border-top: 1px solid var(--border-dim); line-height: 1.45; }
/* Port / starboard tack badges */
.demo-popup-portal .awa-ps { font-weight: 700; font-size: var(--fs-sm); padding: 2px 6px; border-radius: var(--radius-sm); white-space: nowrap; }
.demo-popup-portal .awa-p { background: var(--port-bg); color: var(--port-color); }
.demo-popup-portal .awa-s { background: var(--stbd-bg); color: var(--stbd-color); }
/* Sail plan pill badges */
.demo-popup-portal .reef-cell { font-weight: 700; padding: 2px 8px; border-radius: var(--radius-sm); font-size: var(--fs-xs); white-space: nowrap; display: inline-block; }
.demo-popup-portal .reef-full    { background: var(--stbd-bg);    color: var(--success); }
.demo-popup-portal .reef-1       { background: var(--accent-bg);  color: var(--accent);  }
.demo-popup-portal .reef-2       { background: var(--warning-bg); color: var(--warning); }
.demo-popup-portal .reef-3       { background: var(--danger-bg);  color: var(--danger);  }
.demo-popup-portal .reef-storm   { background: var(--danger); color: var(--text-on-accent); }
.demo-popup-portal .reef-undefined { background: var(--bg-raised); color: var(--text-dim); }
.demo-popup-portal .reef-motor-badge {
  display: inline-block; font-weight: 700; font-size: var(--fs-xs);
  padding: 1px 6px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--text-dark);
  border: 1px solid var(--border); margin-left: 4px;
  white-space: nowrap; vertical-align: middle;
}
/* Squall / lightning risk pills in the popup portal. The same pills are defined
   for :is(.samples, .range-card) above; the portal is a separate DOM context
   that needs its own scope. */
.demo-popup-portal .squall-pill,
.demo-popup-portal .lightning-pill {
  display: inline-block; font-family: var(--font-mono); font-variant-numeric: tabular-nums;
  font-weight: 700; font-size: var(--fs-sm); padding: 2px 7px;
  border-radius: var(--radius-sm); border: 1px solid transparent;
  white-space: nowrap; vertical-align: middle;
}
.demo-popup-portal .squall-pill.squall-low,
.demo-popup-portal .lightning-pill.lightning-negligible {
  background: var(--success-bg); color: var(--success); border-color: var(--success-border);
}
.demo-popup-portal .squall-pill.squall-moderate,
.demo-popup-portal .lightning-pill.lightning-isolated,
.demo-popup-portal .lightning-pill.lightning-scattered {
  background: var(--warning-bg); color: var(--warning); border-color: var(--warning-border);
}
.demo-popup-portal .squall-pill.squall-high,
.demo-popup-portal .lightning-pill.lightning-likely {
  background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border);
}
.demo-popup-portal .squall-pill.squall-severe,
.demo-popup-portal .lightning-pill.lightning-severe {
  background: var(--danger); color: var(--text-on-accent); border-color: var(--danger);
}
.demo-popup-portal .squall-pill.unknown,
.demo-popup-portal .lightning-pill.unknown {
  background: var(--bg-raised); color: var(--text-dim); border-color: var(--border);
}

/* TRUST BAND :: START */
/* Data-sources band — full-width strip between the hero meta-row and the
   scrollable section stack. Tokens only (no raw hex / rgba); cyan is rationed
   so the model chips stay neutral (surface + border, not accent). */
.trust-band {
  /* Ploy renders the trust band as a full-width surface band (verified on the
     15:27 ref). The shell pads --s-8 (32px) each side; cancel it with a
     negative margin and re-pad internally so the band bleeds to the shell
     edges while its content stays aligned with the hero/meta-row at x=32. */
  background: var(--surface);
  margin-left: calc(-1 * var(--s-8));
  margin-right: calc(-1 * var(--s-8));
  padding: var(--s-band) var(--s-8);
  text-align: left;
}
.trust-band .dir-a-sectitle { justify-content: flex-start; }
.trust-heading {
  margin: var(--s-3) 0 0;
  font-size: var(--fs-xl);
  font-weight: 800;
  line-height: 1.2;
  color: var(--text);
}
.trust-body {
  max-width: 64ch;
  margin: var(--s-3) 0 0;
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--text-dim);
}
.trust-models {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-start;
  gap: var(--s-2);
  margin: var(--s-6) 0 0;
  padding: 0;
  list-style: none;
}
.trust-model {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  /* Bold so the translucent-tint chips stay legible (Jon, 2026-06-20). */
  font-weight: 700;
  letter-spacing: var(--tracking-eyebrow-mono-tight);
  text-transform: uppercase;
  color: var(--text-dim);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--s-1) var(--s-3);
  white-space: nowrap;
}
/* Government-forecast sources sit on their own line under the forecast models. */
.tm-sources { margin-top: var(--s-3); }
/* One distinct hue per source. Each chip is a translucent TINT of its hue with a
   FULL-strength hue border (crisp coloured outline) and the vivid hue as bold
   text, so the colour reads as a defined, punchy chip rather than a faint wash.
   Hues are scoped per list (models 1–7, sources 8–14) so the two-row split can't
   shift the mapping; the palette keeps adjacent chips ≥129° apart (no rainbow). */
.tm-models  .trust-model:nth-child(1) { background: color-mix(in srgb, var(--pill-1)  15%, transparent); border-color: var(--pill-1);  color: var(--pill-1);  }
.tm-models  .trust-model:nth-child(2) { background: color-mix(in srgb, var(--pill-2)  15%, transparent); border-color: var(--pill-2);  color: var(--pill-2);  }
.tm-models  .trust-model:nth-child(3) { background: color-mix(in srgb, var(--pill-3)  15%, transparent); border-color: var(--pill-3);  color: var(--pill-3);  }
.tm-models  .trust-model:nth-child(4) { background: color-mix(in srgb, var(--pill-4)  15%, transparent); border-color: var(--pill-4);  color: var(--pill-4);  }
.tm-models  .trust-model:nth-child(5) { background: color-mix(in srgb, var(--pill-5)  15%, transparent); border-color: var(--pill-5);  color: var(--pill-5);  }
.tm-models  .trust-model:nth-child(6) { background: color-mix(in srgb, var(--pill-6)  15%, transparent); border-color: var(--pill-6);  color: var(--pill-6);  }
.tm-models  .trust-model:nth-child(7) { background: color-mix(in srgb, var(--pill-7)  15%, transparent); border-color: var(--pill-7);  color: var(--pill-7);  }
.tm-sources .trust-model:nth-child(1) { background: color-mix(in srgb, var(--pill-8)  15%, transparent); border-color: var(--pill-8);  color: var(--pill-8);  }
.tm-sources .trust-model:nth-child(2) { background: color-mix(in srgb, var(--pill-9)  15%, transparent); border-color: var(--pill-9);  color: var(--pill-9);  }
.tm-sources .trust-model:nth-child(3) { background: color-mix(in srgb, var(--pill-10) 15%, transparent); border-color: var(--pill-10); color: var(--pill-10); }
.tm-sources .trust-model:nth-child(4) { background: color-mix(in srgb, var(--pill-11) 15%, transparent); border-color: var(--pill-11); color: var(--pill-11); }
.tm-sources .trust-model:nth-child(5) { background: color-mix(in srgb, var(--pill-12) 15%, transparent); border-color: var(--pill-12); color: var(--pill-12); }
.tm-sources .trust-model:nth-child(6) { background: color-mix(in srgb, var(--pill-13) 15%, transparent); border-color: var(--pill-13); color: var(--pill-13); }
.tm-sources .trust-model:nth-child(7) { background: color-mix(in srgb, var(--pill-14) 15%, transparent); border-color: var(--pill-14); color: var(--pill-14); }
.trust-footnote {
  margin: var(--s-5) 0 0;
  font-size: var(--fs-2xs);
  line-height: 1.5;
  color: var(--text-dim);
}
@media (max-width: 640px) {
  .trust-heading { font-size: var(--fs-lg); }
}
/* TRUST BAND :: END */

/* MOTION :: START */
/* Homepage motion ported from Ploy, converted to tokens. Verdict glows reuse
   the existing --success/--warning/--danger -border tokens (no raw rgba at the
   usage site, per Jon's directive). Reveal + entrance are gated on
   .motion-ready, added by splash.js only when the visitor has NOT requested
   reduced motion — so no-JS and reduced-motion visitors get the full static
   page with every section visible. */

/* Scroll fade-and-rise reveal */
.motion-ready .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 600ms ease, transform 600ms ease;
}
.motion-ready .reveal.is-revealed {
  opacity: 1;
  transform: none;
}

/* Hero mount entrance — left column first, then the verdict card */
@keyframes ww-hero-entrance {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}
.motion-ready .hero-enter,
.motion-ready .hero-enter--card {
  opacity: 0;
  animation: ww-hero-entrance 600ms ease forwards;
}
.motion-ready .hero-enter--card { animation-delay: 180ms; }

/* Verdict glow + border on the CLICKABLE verdict chips (samples scale). The
   samples detail card does NOT glow (Jon: the glow belongs on the clickable
   5-level chips, not the detail). Hover border = the decision colour, never
   cyan. */
.vcard, .vchip { transition: box-shadow 200ms ease, border-color 200ms ease; }
.vchip.go:hover       { box-shadow: 0 0 24px var(--success-border); border-color: var(--success); }
.vchip.caution:hover,
.vchip.marginal:hover { box-shadow: 0 0 24px var(--warning-border); border-color: var(--warning); }
.vchip.nogo:hover,
.vchip.divert:hover   { box-shadow: 0 0 24px var(--danger-border); border-color: var(--danger); }
/* Hero verdict card — the glow is PERSISTENT and verdict-coloured (Jon,
   2026-06-21), so each card carries its own glow as the carousel cycles. The
   .vcard box-shadow transition cross-fades the colour on each verdict swap. */
#hero-vcard.go       { box-shadow: var(--shadow-hero), 0 0 28px var(--success-border); }
#hero-vcard.caution,
#hero-vcard.marginal { box-shadow: var(--shadow-hero), 0 0 28px var(--warning-border); }
#hero-vcard.nogo,
#hero-vcard.divert   { box-shadow: var(--shadow-hero), 0 0 28px var(--danger-border); }

/* Primary CTA nudge on hover */
.motion-ready .dir-a-cta .btn-primary { transition: transform 200ms ease; }
.motion-ready .dir-a-cta .btn-primary:hover { transform: translateY(-1px); }

/* Interactive pricing highlight — follows hover, locks on selection */
.price-card { transition: box-shadow 200ms ease, border-color 200ms ease; }
.price-card.is-active {
  border-color: var(--accent);
  background: linear-gradient(180deg, var(--accent-tint-soft), var(--surface));
  box-shadow: 0 0 0 3px var(--accent-wash);
}

@media (prefers-reduced-motion: reduce) {
  .reveal, .hero-enter, .hero-enter--card { opacity: 1; transform: none; animation: none; }
  .vcard, .price-card, .dir-a-cta .btn-primary { transition: none; }
}
/* MOTION :: END */

/* VERDICT SCALE :: START */
/* Ploy sample-assessments: a row of 5 compact verdict cards acting as a
   selector, plus a swappable detailed example below (#samples-stack). Verdict
   colours reuse the existing --success/--warning/--danger(-border) tokens. */
.samples-scale {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--s-3);
  margin: var(--s-6) 0 var(--s-8);
}
.vchip {
  display: flex;
  flex-direction: column;
  gap: var(--s-2);
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-5);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  transition: border-color 150ms ease, box-shadow 150ms ease;
}
.vchip-head {
  display: flex;
  align-items: center;
  gap: var(--s-2);
  font-family: var(--font-mono);
  font-weight: 700;
  letter-spacing: 0.04em;
}
.vchip .glyph { font-size: var(--fs-md); line-height: 1; }
.vchip .word { font-size: var(--fs-sm); }
.vchip .blurb { font-size: var(--fs-sm); color: var(--text-dim); line-height: 1.4; }
.vchip.go .vchip-head { color: var(--success); }
.vchip.go { border-color: var(--success-border); }
.vchip.caution .vchip-head,
.vchip.marginal .vchip-head { color: var(--warning); }
.vchip.caution,
.vchip.marginal { border-color: var(--warning-border); }
.vchip.nogo .vchip-head,
.vchip.divert .vchip-head { color: var(--danger); }
.vchip.nogo,
.vchip.divert { border-color: var(--danger-border); }
/* The selected chip (whose detail card is shown) keeps the verdict glow + a
   bright verdict border persistently — even after the mouse leaves. */
.vchip.is-selected.go { box-shadow: 0 0 24px var(--success-border); border-color: var(--success); }
.vchip.is-selected.caution,
.vchip.is-selected.marginal { box-shadow: 0 0 24px var(--warning-border); border-color: var(--warning); }
.vchip.is-selected.nogo,
.vchip.is-selected.divert { box-shadow: 0 0 24px var(--danger-border); border-color: var(--danger); }
@media (max-width: 720px) {
  .samples-scale { grid-template-columns: repeat(2, 1fr); }
  .vchip { padding-left: var(--s-4); padding-right: var(--s-6); }
}
/* Samples detail card carries five metrics (apparent wind · seas · comfort ·
   squall · lightning). The row wraps whole metrics (flex-wrap); each value is
   nowrap so a single metric — Seas especially — never breaks across two lines. */
.samples .vmetrics {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-4) var(--s-5);
}
.samples .vmetric { white-space: nowrap; }
.samples .vmetric .val {
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
/* Apparent wind + apparent wave direction → app's red/green Port/Starboard
   pill (mirrors .awa-ps in the app reefing table; tokens only). */
/* Scoped to both #samples and the #range cards (same pill components). */
:is(.samples, .range-card) .awa-ps {
  font-weight: 700;
  font-size: var(--fs-sm);
  padding: 2px 6px;
  border-radius: var(--radius-sm);
  white-space: nowrap;
  vertical-align: middle;
}
:is(.samples, .range-card) .awa-p { background: var(--port-bg); color: var(--port-color); }
:is(.samples, .range-card) .awa-s { background: var(--stbd-bg); color: var(--stbd-color); }
/* Squall + lightning 0–100 risk scores → app's coloured risk pills. Tier/band
   classes are derived from the score in splash.js with the app thresholds. */
:is(.samples, .range-card) .squall-pill,
:is(.samples, .range-card) .lightning-pill {
  display: inline-block;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: var(--fs-sm);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: middle;
}
:is(.samples, .range-card) .squall-pill.squall-low,
:is(.samples, .range-card) .lightning-pill.lightning-negligible {
  background: var(--success-bg); color: var(--success); border-color: var(--success-border);
}
:is(.samples, .range-card) .squall-pill.squall-moderate,
:is(.samples, .range-card) .lightning-pill.lightning-isolated,
:is(.samples, .range-card) .lightning-pill.lightning-scattered {
  background: var(--warning-bg); color: var(--warning); border-color: var(--warning-border);
}
:is(.samples, .range-card) .squall-pill.squall-high,
:is(.samples, .range-card) .lightning-pill.lightning-likely {
  background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border);
}
:is(.samples, .range-card) .squall-pill.squall-severe,
:is(.samples, .range-card) .lightning-pill.lightning-severe {
  background: var(--danger); color: var(--text-on-accent); border-color: var(--danger);
}
/* Comfort (vag_rating) → app's coloured motion badge. Calm/Mild green,
   Moderate amber, Rough/Severe red (Rough mapped to the danger token by
   project choice, in place of the app's standalone orange). */
:is(.samples, .range-card) .comfort-badge {
  display: inline-block;
  font-weight: 700;
  font-size: var(--fs-sm);
  padding: 2px 7px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  white-space: nowrap;
  vertical-align: middle;
}
:is(.samples, .range-card) .comfort-badge.comfort-calm,
:is(.samples, .range-card) .comfort-badge.comfort-mild {
  background: var(--success-bg); color: var(--success); border-color: var(--success-border);
}
:is(.samples, .range-card) .comfort-badge.comfort-moderate {
  background: var(--warning-bg); color: var(--warning); border-color: var(--warning-border);
}
:is(.samples, .range-card) .comfort-badge.comfort-rough,
:is(.samples, .range-card) .comfort-badge.comfort-severe {
  background: var(--danger-bg); color: var(--danger); border-color: var(--danger-border);
}
/* Cross-fade the detail card on each auto-rotate / chip swap (matches the
   hero carousel's .vcard-content fade). */
#samples-stack { transition: opacity 120ms ease-in; }
#samples-stack.updating { opacity: 0; }
@media (prefers-reduced-motion: reduce) {
  #samples-stack { transition: none; }
}
/* VERDICT SCALE :: END */

/* ─── #range passage-class cards — token-only (shared Passage Map visual
   language: two static stills + one featured animated map video) ──────── */
/* Subgrid so the five card rows (tier, route+distance, verdict+prose, metrics,
   iPad) align horizontally across all three cards regardless of prose length. */
.range-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(4, auto);
  column-gap: var(--s-6);
  row-gap: var(--s-4);
  margin-top: var(--s-8);
}
.range-card {
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--s-6);
  position: relative;
  overflow: hidden;
  display: grid;
  grid-row: span 4;
  grid-template-rows: subgrid;
  row-gap: var(--s-4);
}
/* Verdict badge + assessment prose, side by side. */
.range-verdict-row {
  display: flex;
  align-items: flex-start;
  gap: var(--s-4);
}
.range-verdict-row .vbadge { flex: none; }
.range-verdict-row .r { flex: 1 1 auto; min-width: 0; }
/* The passage class (Day sail / Weekend / Offshore) is the section's headline
   differentiator — render it prominent, brighter and larger than an eyebrow. */
.range-tier {
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text);
  line-height: 1.1;
}
/* Route + distance read as one tight unit (minimal gap between them). */
.range-head {
  display: flex;
  flex-direction: column;
  gap: var(--s-1);
}
.range-route {
  font-size: var(--fs-md);
  font-weight: 700;
  margin: 0;
  line-height: 1.3;
  text-wrap: balance;
}
.range-stat {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--text-dim);
}
/* Each card holds an iPad-bezel mockup (reuses the .device--ipad system).
   Neutralize the device-stage flex sizing so the iPad fills the card column. */
.range-device {
  flex: none;
  width: 100%;
  align-self: center;
}
/* The iPad is a click-to-expand lightbox trigger (.how-shot). Neutralize how-shot's
   margin-top:auto/top padding so it sits in the card's normal flow, not pinned bottom. */
.range-shot {
  margin-top: 0;
  padding-top: 0;
}
/* Verdict content (reasoning + the shared .vmetrics grid) — same content as the
   #samples cards, but the metric row must wrap inside the narrow 3-up column. */
.range-card .r {
  font-size: var(--fs-sm);
  color: var(--text-dim);
  line-height: 1.5;
  margin: 0;
}
/* Verdict as the shared circular badge (like #samples), sized for the card. */
.range-card .vbadge {
  width: 76px;
  height: 76px;
  border-width: 2px;
}
.range-card .vbadge .glyph { font-size: var(--fs-md); }
.range-card .vbadge .word  { font-size: var(--fs-2xs); }
.range-card.go       .vbadge { color: var(--success); border-color: var(--success); }
.range-card.caution  .vbadge,
.range-card.marginal .vbadge { color: var(--warning); border-color: var(--warning); }
.range-card.nogo     .vbadge,
.range-card.divert   .vbadge { color: var(--danger);  border-color: var(--danger); }

@media (max-width: 720px) {
  .range-grid { grid-template-columns: 1fr; }
}
