/* kurshalter.com — single shared stylesheet (emitted as /styles.css, the only render-blocking
   stylesheet). Colour and font tokens live in tokens.css (the app theme as custom properties;
   the prerender inlines the import so this stays one request). System sans for text,
   self-hosted IBM Plex Mono (the app's instrument face) for labels and readouts. */
/* kurshalter.com design tokens — the app theme (apps/mobile/src/theme/tokens.ts) and chart
   palette (packages/map-style/src/palette.ts) as CSS custom properties.

   Every colour value lives exactly once, in the PALETTE block (--day-*, --dusk-*, --night-*).
   The ROLE tokens (--surface, --text, --accent-ink, … — names mirror ThemeColors) are mapped
   from the palette three ways:
     :root                                  light scheme = app day
     @media (prefers-color-scheme: dark)    dark scheme  = app dusk
     [data-chart-mode='day' | 'dusk' | 'night']   the demo hero and the share page follow the
                                            chart mode the visitor picked, whatever the scheme
   demo.css aliases --k-* onto these roles. Contrast notes are WCAG 2.x ratios.

   Rules: --accent, --danger, --caution, --safe are FILLS and never carry text; text on them uses
   --foam/--sea (the CTA pair) or the matching *-ink token. Pink never carries text on pink. */

:root {
  /* ---- brand constants (scheme-independent) ---- */
  --sea: #0b2a4a; /* the navy field: hero, 404, the app card */
  --foam: #fcfbf8; /* 14.05 on sea — the CTA pair on the sea is foam fill / sea text */
  --course-on-sea: #de64a8; /* the plotted course on the navy field; kicker dash on the sea */
  --on-course: #0b2a4a; /* 4.50 on course pink — the only ink allowed on it */
  --sans:
    -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
  --mono: 'IBM Plex Mono', ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;

  /* ---- palette: app day ---- */
  --day-surface: #f8f5ec; /* page ground (chart paper) — the app land tone */
  /* floating chrome (strip, HUD, pills, FABs) — the app's `surface`. The app also has a lighter
     `surfaceTranslucent` blur tint (0.70/0.72); it is deliberately NOT mapped here, because text
     on chrome at that alpha misses 4.5:1 over the chart (night is opaque: glass wrecks night vision). */
  --day-surface-glass: rgba(252, 251, 248, 0.92);
  --day-surface-elevated: #ffffff; /* cards, sheets, the store-button ink on chrome */
  --day-text: #14273a; /* 13.95 / 13.4 on surface */
  --day-text-secondary: #5a6875; /* 5.25 / 6.9 on surface */
  --day-accent: #c21e80; /* FILL only: course line, kicker dash, region outlines — never text */
  --day-accent-ink: #c21e80; /* tappable text: links, kickers — 5.08 / 7.97 on surface */
  --day-accent-soft: rgba(194, 30, 128, 0.12); /* tonal wash: region fill, active FAB */
  --day-instrument: #0b2a4a; /* readout values (demo) */
  --day-instrument-dim: #56636f; /* placard labels — 5.95 on foam */
  --day-danger: #e4572e; /* FILL: speed-sign breach, stop wash */
  --day-danger-ink: #bb3a1b; /* red glyphs/text (the HUD stop) */
  --day-caution: #f2b134; /* FILL: draft-banner rule, warning chip ring */
  --day-caution-ink: #8a5c00; /* amber text */
  --day-caution-wash: rgba(242, 177, 52, 0.16); /* draft banner, pending marks */
  --day-safe: #2e9e6b; /* dot only (online, live) */
  --day-border: rgba(20, 39, 58, 0.12); /* chrome hairline (app value) */
  --day-hairline: rgba(20, 39, 58, 0.16); /* page rules and dividers */
  --day-code-wash: rgba(20, 39, 58, 0.06); /* recessed fills: code, phone-frame placeholder */
  --day-halo: rgba(255, 255, 255, 0.85); /* text halo over the chart */
  --day-coverage-sea: var(
    --day-surface
  ); /* Blattschnitt water (dark needs a cool sea against warm charcoal land) */
  --day-coverage-land-wash: var(--day-code-wash); /* Blattschnitt land panel wash */

  /* ---- palette: app dusk (= the site's dark scheme) ---- */
  --dusk-surface: #211e1a;
  --dusk-surface-glass: rgba(42, 38, 35, 0.9);
  --dusk-surface-elevated: #2c2823;
  --dusk-text: #eee6d9;
  --dusk-text-secondary: #b0a69a;
  --dusk-accent: #c8408f;
  --dusk-accent-ink: #ec9bc8;
  --dusk-accent-soft: rgba(200, 64, 143, 0.18);
  --dusk-instrument: #f5ecdd;
  --dusk-instrument-dim: #b3a89c;
  --dusk-danger: #e4572e;
  --dusk-danger-ink: #f58e70;
  --dusk-caution: #b8955a;
  --dusk-caution-ink: #f2b134;
  --dusk-caution-wash: rgba(184, 149, 90, 0.2);
  --dusk-safe: #55b98a;
  --dusk-border: rgba(238, 230, 217, 0.12);
  --dusk-hairline: rgba(238, 230, 217, 0.16);
  --dusk-code-wash: rgba(238, 230, 217, 0.08);
  --dusk-halo: rgba(0, 0, 0, 0.55);
  --dusk-coverage-sea: #141c27;
  --dusk-coverage-land-wash: rgba(238, 230, 217, 0.1);

  /* ---- palette: app night (demo chart mode only; red-only, no white) ---- */
  --night-surface: #110a08;
  --night-surface-glass: rgba(16, 9, 8, 0.94);
  --night-surface-elevated: #1a0f0c;
  --night-text: #e8a090;
  --night-text-secondary: #ad7a6e;
  --night-accent: #ff7088;
  --night-accent-ink: #ff7088;
  --night-accent-soft: rgba(255, 112, 136, 0.16);
  --night-instrument: #ffb3a3;
  --night-instrument-dim: #b07c70;
  --night-danger: #ff6a4d;
  --night-danger-ink: #ff6a4d;
  --night-caution: #f7b267;
  --night-caution-ink: #f7b267;
  --night-caution-wash: rgba(247, 178, 103, 0.16);
  --night-safe: #cfae7e;
  --night-border: rgba(255, 106, 77, 0.18);
  --night-hairline: rgba(255, 106, 77, 0.22);
  --night-code-wash: rgba(232, 160, 144, 0.07);
  --night-halo: rgba(0, 0, 0, 0.55);
  --night-coverage-sea: #141c27;
  --night-coverage-land-wash: rgba(232, 160, 144, 0.1);
}

/* ---- role mapping: page scheme ---- */
:root {
  --surface: var(--day-surface);
  --surface-glass: var(--day-surface-glass);
  --surface-elevated: var(--day-surface-elevated);
  --text: var(--day-text);
  --text-secondary: var(--day-text-secondary);
  --accent: var(--day-accent);
  --accent-ink: var(--day-accent-ink);
  --accent-soft: var(--day-accent-soft);
  --instrument: var(--day-instrument);
  --instrument-dim: var(--day-instrument-dim);
  --danger: var(--day-danger);
  --danger-ink: var(--day-danger-ink);
  --caution: var(--day-caution);
  --caution-ink: var(--day-caution-ink);
  --caution-wash: var(--day-caution-wash);
  --safe: var(--day-safe);
  --border: var(--day-border);
  --hairline: var(--day-hairline);
  --code-wash: var(--day-code-wash);
  --halo: var(--day-halo);
  --coverage-sea: var(--day-coverage-sea);
  --coverage-land-wash: var(--day-coverage-land-wash);
}

@media (prefers-color-scheme: dark) {
  :root {
    --surface: var(--dusk-surface);
    --surface-glass: var(--dusk-surface-glass);
    --surface-elevated: var(--dusk-surface-elevated);
    --text: var(--dusk-text);
    --text-secondary: var(--dusk-text-secondary);
    --accent: var(--dusk-accent);
    --accent-ink: var(--dusk-accent-ink);
    --accent-soft: var(--dusk-accent-soft);
    --instrument: var(--dusk-instrument);
    --instrument-dim: var(--dusk-instrument-dim);
    --danger: var(--dusk-danger);
    --danger-ink: var(--dusk-danger-ink);
    --caution: var(--dusk-caution);
    --caution-ink: var(--dusk-caution-ink);
    --caution-wash: var(--dusk-caution-wash);
    --safe: var(--dusk-safe);
    --border: var(--dusk-border);
    --hairline: var(--dusk-hairline);
    --code-wash: var(--dusk-code-wash);
    --halo: var(--dusk-halo);
    --coverage-sea: var(--dusk-coverage-sea);
    --coverage-land-wash: var(--dusk-coverage-land-wash);
  }
}

/* ---- role mapping: chart mode (the demo hero root, the share page) ---- */
[data-chart-mode='day'] {
  --surface: var(--day-surface);
  --surface-glass: var(--day-surface-glass);
  --surface-elevated: var(--day-surface-elevated);
  --text: var(--day-text);
  --text-secondary: var(--day-text-secondary);
  --accent: var(--day-accent);
  --accent-ink: var(--day-accent-ink);
  --accent-soft: var(--day-accent-soft);
  --instrument: var(--day-instrument);
  --instrument-dim: var(--day-instrument-dim);
  --danger: var(--day-danger);
  --danger-ink: var(--day-danger-ink);
  --caution: var(--day-caution);
  --caution-ink: var(--day-caution-ink);
  --caution-wash: var(--day-caution-wash);
  --safe: var(--day-safe);
  --border: var(--day-border);
  --hairline: var(--day-hairline);
  --code-wash: var(--day-code-wash);
  --halo: var(--day-halo);
  --coverage-sea: var(--day-coverage-sea);
  --coverage-land-wash: var(--day-coverage-land-wash);
}

[data-chart-mode='dusk'] {
  --surface: var(--dusk-surface);
  --surface-glass: var(--dusk-surface-glass);
  --surface-elevated: var(--dusk-surface-elevated);
  --text: var(--dusk-text);
  --text-secondary: var(--dusk-text-secondary);
  --accent: var(--dusk-accent);
  --accent-ink: var(--dusk-accent-ink);
  --accent-soft: var(--dusk-accent-soft);
  --instrument: var(--dusk-instrument);
  --instrument-dim: var(--dusk-instrument-dim);
  --danger: var(--dusk-danger);
  --danger-ink: var(--dusk-danger-ink);
  --caution: var(--dusk-caution);
  --caution-ink: var(--dusk-caution-ink);
  --caution-wash: var(--dusk-caution-wash);
  --safe: var(--dusk-safe);
  --border: var(--dusk-border);
  --hairline: var(--dusk-hairline);
  --code-wash: var(--dusk-code-wash);
  --halo: var(--dusk-halo);
  --coverage-sea: var(--dusk-coverage-sea);
  --coverage-land-wash: var(--dusk-coverage-land-wash);
}

[data-chart-mode='night'] {
  --surface: var(--night-surface);
  --surface-glass: var(--night-surface-glass);
  --surface-elevated: var(--night-surface-elevated);
  --text: var(--night-text);
  --text-secondary: var(--night-text-secondary);
  --accent: var(--night-accent);
  --accent-ink: var(--night-accent-ink);
  --accent-soft: var(--night-accent-soft);
  --instrument: var(--night-instrument);
  --instrument-dim: var(--night-instrument-dim);
  --danger: var(--night-danger);
  --danger-ink: var(--night-danger-ink);
  --caution: var(--night-caution);
  --caution-ink: var(--night-caution-ink);
  --caution-wash: var(--night-caution-wash);
  --safe: var(--night-safe);
  --border: var(--night-border);
  --hairline: var(--night-hairline);
  --code-wash: var(--night-code-wash);
  --halo: var(--night-halo);
  --coverage-sea: var(--night-coverage-sea);
  --coverage-land-wash: var(--night-coverage-land-wash);
}

/* Both cuts are declared: 500 Medium for placards and labels, 600 SemiBold for readouts and the
   stat/privacy display type. Without the 600 face the browser synthesises bold from the 500 and
   the instrument voice smears — scripts/build.mjs asserts dist/styles.css references both. */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-500.woff') format('woff');
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/ibm-plex-mono-600.woff') format('woff');
}

* {
  box-sizing: border-box;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--bar-h, 80px) + 1rem);
}

body {
  margin: 0;
  /* clip, not hidden: no scroll container, so fixed/sticky chrome keeps working and a stray
     overhang can never widen the layout viewport on a phone */
  overflow-x: clip;
  background: var(--surface);
  color: var(--text);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.65;
  text-rendering: optimizeLegibility;
}

::selection {
  background: rgba(222, 100, 168, 0.35);
}

:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 2px;
}
/* on the navy field the ring is foam (14.05); the magenta ring reads 2.6:1 there */
.bar-sea :focus-visible,
.sea :focus-visible,
.lost-sea :focus-visible,
.get-the-app-card :focus-visible {
  outline: 2px solid var(--foam);
  outline-offset: 3px;
}
.bar-sea.is-stuck :focus-visible {
  outline-color: var(--accent-ink);
}

a {
  color: var(--accent-ink);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* ---- top bar ------------------------------------------------------------------ */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 1.1rem clamp(1.25rem, 4vw, 2.5rem);
  color: var(--text);
}

.bar-sea {
  position: relative;
  z-index: 2;
  color: var(--foam);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.65rem;
  color: inherit;
  text-decoration: none;
  min-height: 2.75rem;
  min-width: 2.75rem;
}

.brand-word {
  height: 12px;
  width: auto;
  fill: currentColor;
  opacity: 0.92;
}

.bar-right {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
@media (max-width: 480px) {
  /* the mark alone identifies the bar; the wordmark is the first thing in the hero anyway */
  .bar .brand-word {
    display: none;
  }
  .bar-right {
    gap: 0.25rem;
  }
}

/* The CTA pair: text on surface on paper (13.95), foam on sea on the navy field (14.05). Pink
   never carries text — hover moves and shadows, it does not recolour. */
.bar-cta {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 1.1rem;
  border-radius: 999px;
  background: var(--text);
  color: var(--surface);
  font-size: 0.86rem;
  font-weight: 600;
  text-decoration: none;
  transition:
    transform 160ms ease,
    box-shadow 160ms ease;
}
.bar-sea .bar-cta {
  background: var(--foam);
  color: var(--sea);
}
.bar-cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 8px 18px -8px rgba(0, 0, 0, 0.5);
}
.bar-cta:active {
  transform: scale(0.97);
}

/* the language switch is the only language control on every page: 44 pt boxes */
.lang {
  display: inline-flex;
  align-items: center;
  font-family: var(--mono);
  font-size: 0.75rem;
  letter-spacing: 0.08em;
}
.lang > span {
  display: inline-flex;
  align-items: center;
}
.lang a,
.lang span[aria-current] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 2.75rem;
  min-height: 2.75rem;
  padding: 0;
  text-decoration: none;
}
.lang a {
  color: var(--text-secondary);
}
.bar-sea .lang a {
  color: rgba(252, 251, 248, 0.82); /* 9.85 on sea */
}
.bar-sea.is-stuck .lang a {
  color: var(--text-secondary);
}
.lang a:hover {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.3em;
}
.lang-sep {
  opacity: 0.35;
  margin: 0 -0.55rem;
}

/* ---- landing: the sea panel --------------------------------------------------- */

.sea {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: max(560px, min(92svh, 880px));
}
@media (max-width: 560px) {
  /* The first screen is the chart, and it stops just short of the fold: the sliver of paper
     under it is the only thing telling a phone visitor that the page continues. Capped so a
     tall narrow window does not stretch it. */
  .sea {
    min-height: min(97svh, 920px);
  }
}
.sea {
  background: var(--sea);
  overflow: clip; /* clip (not hidden): the bar inside goes position: fixed, which clip allows */
}
.hero-art {
  overflow: hidden;
}
.hero-static {
  overflow: hidden;
}

.hero-art {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.hero-art-tall {
  display: none;
}

@media (max-width: 700px) {
  .hero-art-wide {
    display: none;
  }

  .hero-art-tall {
    display: block;
  }

  /* The text column is always on flat navy. `preserveAspectRatio: slice` re-maps the tall art's
     viewBox differently at every phone width, so the course stroke cannot be kept off the copy by
     geometry alone — it used to run straight through the iPhone link and the "no substitute for
     official charts" line (2.59:1, and it read as a strikethrough). The art still shows at the
     right edge; TallArt's course is moved outboard as well. */
  .hero {
    background: linear-gradient(
      90deg,
      var(--sea) 0 62%,
      color-mix(in srgb, var(--sea) 70%, transparent) 80%,
      transparent 100%
    );
  }
}

.isobaths path {
  stroke: rgba(98, 160, 214, 0.17);
  stroke-width: 1.5;
}

.soundings {
  font-family: var(--mono);
  font-size: 14px;
  font-weight: 500;
  fill: rgba(252, 251, 248, 0.22);
}

.course {
  fill: none;
  stroke: var(--course-on-sea);
  stroke-width: 13;
  stroke-linecap: round;
}

.vessel {
  fill: var(--foam);
}

@media (prefers-reduced-motion: no-preference) {
  .course {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: course-draw 1.5s cubic-bezier(0.3, 0.5, 0.25, 1) 0.25s forwards;
  }

  .vessel {
    opacity: 0;
    animation: vessel-in 0.6s ease-out 1.45s forwards;
  }
}

@keyframes course-draw {
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes vessel-in {
  to {
    opacity: 1;
  }
}

.hero {
  position: relative;
  z-index: 1;
  margin: auto 0;
  padding: 3.5rem clamp(1.25rem, 8vw, 6.5rem) 4.5rem;
  max-width: 44rem;
}

.hero-word {
  margin: 0 0 1.6rem;
  color: var(--foam); /* wordmark paths fill currentColor */
}

.hero-word svg {
  display: block;
  width: clamp(150px, 20vw, 210px);
  height: auto;
  opacity: 0.92;
}

/* the sentence is the headline; the wordmark above it is the signature */
.hero-headline {
  margin: 0 0 1rem;
  max-width: 12em;
  font-size: clamp(2rem, 5.2vw, 3.6rem);
  line-height: 1.08;
  font-weight: 700;
  letter-spacing: -0.025em;
  color: var(--foam);
  text-wrap: balance;
}

.tagline {
  margin: 0 0 1.6rem;
  max-width: 30em;
  font-size: clamp(1.05rem, 1.7vw, 1.25rem);
  line-height: 1.5;
  font-weight: 400;
  color: rgba(252, 251, 248, 0.82);
  text-wrap: pretty;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
  margin: 0 0 1.8rem;
}

/* ---- store buttons (own design, no store logos) ------------------------------------- */
.stores {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1.4rem 2.2rem;
}
.store-buttons {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
}
.store-button {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  min-height: 3.25rem;
  padding: 0.55rem 1.15rem 0.55rem 0.9rem;
  border-radius: 14px;
  background: var(--foam);
  color: var(--sea);
  text-decoration: none;
  box-shadow: 0 10px 24px -12px rgba(0, 0, 0, 0.45);
  transition:
    transform 160ms ease,
    box-shadow 160ms ease,
    opacity 160ms ease;
}
a.store-button:hover {
  transform: translateY(-1px);
  box-shadow: 0 14px 28px -12px rgba(0, 0, 0, 0.5);
}
a.store-button:active {
  transform: scale(0.98);
}
.store-glyph {
  display: grid;
  place-items: center;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 10px;
  background: rgba(11, 42, 74, 0.08);
  color: inherit;
  flex: none;
}
.store-text {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}
.store-line1 {
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.02em;
  opacity: 0.72;
}
.store-line2 {
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: -0.01em;
}
/* A store without a link renders as a sentence with one real action, never as a dead or dimmed
   button — either store: `data-store` says which. It sits after the buttons; on the visitor's own
   platform it leads (the enhancer stamps the platform on <html>). */
.store-soon {
  margin: 0;
  max-width: 30em;
  font-size: 0.95rem;
  line-height: 1.45;
  color: var(--text-secondary);
  text-wrap: pretty;
}
.store-soon a {
  color: inherit;
  font-weight: 600;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}
.sea .store-soon,
.get-the-app-card .store-soon,
.lost-sea .store-soon {
  color: rgba(252, 251, 248, 0.82); /* 9.85 on sea */
}
html[data-platform='ios'] .store-soon[data-store='ios'],
html[data-platform='android'] .store-soon[data-store='android'] {
  order: -1;
}
.stores-lg .store-button {
  min-height: 3.6rem;
  padding: 0.65rem 1.35rem 0.65rem 1rem;
  border-radius: 16px;
}
.stores-lg .store-line2 {
  font-size: 1.1rem;
}
/* on the paper the buttons are text on surface (13.95 / 13.4) */
main .stores .store-button {
  background: var(--text);
  color: var(--surface);
}
main .stores .store-glyph {
  background: rgba(255, 255, 255, 0.12);
}
/* SPECIFICITY TRAP: the paper rule above carries a type selector (`main`, 0,2,1) and the closing
   card lives inside <main>, so a plain `.get-the-app-card .store-button` (0,2,0) LOSES and the
   card's own CTA paints --text on --sea (1.05:1, invisible). These two must keep the `main`
   prefix — and the paper rule must never be widened past `main .stores`. */
main .get-the-app-card .store-button {
  background: var(--foam);
  color: var(--sea);
}
main .get-the-app-card .store-glyph {
  background: rgba(11, 42, 74, 0.08);
}

/* the visitor's own platform only — but only once its own store has a link (the enhancer stamps
   data-own-store); until the App Store listing exists an iPhone keeps the Android button too */
html[data-own-store][data-platform='ios'] .store-button[data-store='android'],
html[data-own-store][data-platform='ios'] .store-soon[data-store='android'],
html[data-own-store][data-platform='android'] .store-button[data-store='ios'],
html[data-own-store][data-platform='android'] .store-soon[data-store='ios'] {
  display: none;
}

/* NO listing at all (`anyStoreLink()` false, components/store-buttons.tsx): the block turns into
   a column — one filled notify button in the store button's own place and shape, the two platform
   sentences quiet underneath. `order` keeps the button first and still lets the enhancer float the
   visitor's own platform to the top of the sentences (the rule above stays untouched: a sentence
   at order -1 lands between the button and the other platform, never above the CTA). */
.stores-notify {
  flex-direction: column;
  align-items: flex-start;
  gap: 0.7rem;
}
.stores-notify .store-buttons {
  order: -2;
}

/* the QR code: desktop only, next to the buttons */
.store-qr {
  display: none;
  align-items: center;
  gap: 0.8rem;
  color: inherit;
  text-decoration: none;
}
@media (hover: hover) and (pointer: fine) {
  .store-qr {
    display: inline-flex;
  }
}
html[data-platform='ios'] .store-qr,
html[data-platform='android'] .store-qr {
  display: none;
}
.store-qr-code {
  display: block;
  width: 5.2rem;
  height: 5.2rem;
  padding: 0.35rem;
  border-radius: 12px;
  background: #fff;
  box-shadow: 0 10px 24px -12px rgba(0, 0, 0, 0.45);
}
.store-qr-code svg {
  display: block;
  width: 100%;
  height: 100%;
}
.store-qr-label {
  max-width: 8em;
  font-size: 0.8rem;
  line-height: 1.35;
  opacity: 0.75;
}
.hero-stores {
  margin: 0.2rem 0 0.7rem;
}
.hero-beta {
  margin: 0 0 1.4rem;
  font-family: var(--mono);
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(252, 251, 248, 0.72); /* 8.3 on sea */
}
.get-the-app .hero-beta {
  color: var(--text-secondary);
  margin: 1.2rem 0 0;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 2.9rem;
  padding: 0 1.35rem;
  border-radius: 999px;
  font-size: 0.98rem;
  font-weight: 600;
  text-decoration: none;
  transition:
    transform 160ms ease,
    background-color 160ms ease,
    border-color 160ms ease;
}
.btn:active {
  transform: scale(0.98);
}
.btn-primary {
  background: var(--foam);
  color: var(--sea); /* 14.05 */
}
.btn-primary:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 22px -10px rgba(0, 0, 0, 0.55);
}
/* The bilingual shell pages put the English half INSIDE the pill (/get/'s notify button). The
   page-level `.lost-alt-inline` is foam on navy; on a foam pill it would be invisible, so inside a
   button it takes the button's own ink at 0.72 — 5.9:1 on foam, still the quieter half. */
.btn .lost-alt-inline {
  color: inherit;
  opacity: 0.72;
  /* a flex container strips the leading space of an anonymous item, so the gap is a margin */
  margin-left: 0.35em;
}
.btn-ghost {
  color: var(--foam);
  border: 1px solid rgba(252, 251, 248, 0.32);
}
.btn-ghost:hover {
  border-color: rgba(252, 251, 248, 0.7);
}

.status {
  margin: 0 0 1.4rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(252, 251, 248, 0.6);
}

/* the "not for navigation" line, set like a cautionary chart note (magenta-ruled) */
.chart-note {
  display: inline-block;
  margin: 0;
  padding: 0.6rem 0.9rem;
  border: 1px solid rgba(222, 100, 168, 0.7);
  font-family: var(--mono);
  font-size: 0.8rem; /* 12.8 px */
  letter-spacing: 0.02em;
  color: rgba(252, 251, 248, 0.9);
}

/* ---------------------------------------------------------------------------------------
   PHONES (≤ 560 px) — the static hero mirrors the live cartouche's layout.

   The island replaces this block with the live chart the moment the map is ready, so the two
   must agree on more than wording: the copy sits at the FOOT of the panel in both, at the same
   type sizes, so the swap is a crossfade and not a jump. The chart art keeps the upper half to
   itself, exactly where the live chart's clear window is.
   --------------------------------------------------------------------------------------- */
@media (max-width: 560px) {
  .hero {
    margin: auto 0 0; /* bottom-anchored, like the cartouche it becomes */
    max-width: none;
    padding: 2rem 1.75rem 1.7rem;
    /* Flat navy under the copy, the art above it. `slice` re-maps the tall art's viewBox at
       every width, so the stroke cannot be kept off the text by geometry alone. */
    background: linear-gradient(
      180deg,
      transparent 0,
      color-mix(in srgb, var(--sea) 72%, transparent) 8%,
      var(--sea) 18%
    );
  }
  .hero-word {
    margin-bottom: 0.65rem;
  }
  .hero-word svg {
    width: 104px;
  }
  /* the same clamp as the live cartouche (styles/demo.css), so the sentence does not resize
     when the island takes over */
  .hero-headline {
    margin-bottom: 0.5rem;
    max-width: none;
    font-size: clamp(1.5rem, 7vw, 2.25rem);
    line-height: 1.12;
  }
  .tagline {
    margin-bottom: 0.9rem;
    max-width: none;
    font-size: clamp(0.82rem, 4vw, 0.975rem);
    line-height: 1.42;
  }
  .sea .stores {
    flex-direction: column;
    align-items: stretch;
    gap: 0.65rem;
  }
  .sea .store-buttons {
    display: block;
  }
  .sea .store-button {
    display: flex;
    width: 100%;
    min-height: 3.25rem; /* 52 px */
    justify-content: center;
    gap: 0.6rem;
    padding: 0.5rem 1rem;
    border-radius: 14px;
  }
  .sea .store-line1 {
    display: none;
  }
  .sea .store-line2 {
    font-size: 1rem;
  }
  .sea .store-soon {
    font-size: 0.9rem;
    line-height: 1.6;
  }
  .sea .store-soon a {
    display: inline-block;
    padding: 0.5rem 0; /* ~39 px box on an inline link inside a sentence */
  }
  .hero-stores {
    margin: 0;
  }
  .hero-beta {
    margin: 0.65rem 0 0;
  }
  .chart-note {
    display: block;
    margin-top: 0.65rem;
    padding: 0.4rem 0.6rem;
    font-size: 0.72rem; /* 11.5 px — the same placard size the cartouche uses */
  }
}
@media (max-width: 560px) and (max-height: 720px) {
  .hero {
    padding: 1.4rem 1.6rem 1.4rem;
  }
  .hero-word svg {
    width: 92px;
  }
  .hero-headline {
    font-size: clamp(1.35rem, 6.2vw, 1.6rem);
  }
  .sea .store-button {
    min-height: 3rem;
  }
}

/* ---- landing: legend + credits ------------------------------------------------ */

.legend {
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) 1.5rem;
}

.legend-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 2.2rem 3rem;
  margin: 0;
}

.legend-item dt {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.legend-item dd {
  margin: 0.5rem 0 0;
  font-size: 0.98rem;
  line-height: 1.58;
  color: var(--text-secondary);
}

.open-data {
  max-width: 68rem;
  margin: 2rem auto 0;
  padding: 1.6rem clamp(1.25rem, 4vw, 2.5rem) 2.5rem;
  border-top: 1px solid var(--hairline);
}

.open-data .open-data-line {
  margin: 0;
  line-height: 1.7;
}

/* ---- footer ------------------------------------------------------------------- */

.site-foot {
  border-top: 1px solid var(--hairline);
  padding: 1.8rem clamp(1.25rem, 4vw, 2.5rem) 2.4rem;
  max-width: 68rem;
  margin: 0 auto;
}

.site-foot nav {
  display: flex;
  flex-wrap: wrap;
  /* no row gap: each link carries its own 44 pt box, which is the spacing */
  gap: 0 1.4rem;
  font-family: var(--mono);
  font-size: 0.78rem;
  letter-spacing: 0.03em;
}

/* the Impressum and the privacy policy: 44 pt targets that look like links without a hover */
.site-foot nav a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--hairline);
  text-underline-offset: 0.3em;
}

.site-foot nav a:hover {
  color: var(--accent-ink);
  text-decoration-color: currentColor;
}

.foot-note {
  margin: 1.1rem 0 0;
  font-size: 0.8rem;
  line-height: 1.6;
  color: var(--text-secondary);
  max-width: 62ch;
}

.foot-copy {
  margin: 0.5rem 0 0;
  font-size: 0.8rem;
  color: var(--text-secondary);
}

/* on document pages the footer aligns with the prose column */
.doc .site-foot {
  max-width: 44rem;
  padding-inline: clamp(1.25rem, 4vw, 2rem);
}

/* ---- document pages ----------------------------------------------------------- */

.prose {
  max-width: 44rem;
  margin: 0 auto;
  padding: 1.5rem clamp(1.25rem, 4vw, 2rem) 4rem;
}

.prose-kicker {
  margin: 1.4rem 0 0;
}

.prose h1 {
  font-size: clamp(1.9rem, 3.4vw, 2.5rem);
  line-height: 1.12;
  letter-spacing: -0.022em;
  margin: 0.6rem 0 1.4rem;
  text-wrap: balance;
}

.prose h2 {
  font-size: 1.28rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
  margin: 2.6em 0 0.7em;
  padding-top: 1.2em;
  border-top: 1px solid var(--hairline);
}

.prose h3 {
  font-size: 1.02rem;
  margin: 2em 0 0.6em;
}

.prose h2 + p,
.prose h3 + p {
  margin-top: 0;
}

.prose p,
.prose ul {
  margin: 0 0 1.05em;
}

.prose li {
  margin-bottom: 0.35em;
}

.prose blockquote {
  margin: 1.4em 0;
  padding: 0.1em 0 0.1em 1.1em;
  border-left: 3px solid var(--accent-soft);
  color: var(--text-secondary);
}

.prose blockquote p {
  margin-bottom: 0.5em;
}

.prose code {
  font-family: var(--mono);
  font-size: 0.84em;
  background: var(--code-wash);
  padding: 0.1em 0.35em;
  border-radius: 4px;
}

.table-scroll {
  overflow-x: auto;
  margin: 1.4em 0;
}

.table-scroll:focus-visible {
  outline: 2px solid var(--text);
  outline-offset: 4px;
}

.prose table {
  border-collapse: collapse;
  width: 100%;
  min-width: 34rem;
  font-size: 0.88rem;
  line-height: 1.5;
}

.prose th {
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-align: left;
  color: var(--text-secondary);
  padding: 0.45rem 0.9rem 0.45rem 0;
  border-bottom: 1.5px solid var(--hairline);
}

.prose td {
  vertical-align: top;
  padding: 0.55rem 0.9rem 0.55rem 0;
  border-bottom: 1px solid var(--hairline);
}

/* draft banner + pending fill-in marks (removed once the lawyer pass lands) */

.draft {
  margin: 1.2rem 0 0;
  padding: 0.75rem 1rem;
  border-left: 3px solid var(--caution);
  border-radius: 10px;
  background: var(--caution-wash);
  font-family: var(--mono);
  font-size: 0.78rem;
  line-height: 1.6;
}

mark.pending {
  background: var(--caution-wash);
  border-bottom: 1px dashed var(--caution);
  color: inherit;
  padding: 0 0.2em;
  border-radius: 2px;
}

/* ---- 404 ---------------------------------------------------------------------- */

.lost {
  max-width: 44rem;
  margin: 0 auto;
  padding: 4rem clamp(1.25rem, 4vw, 2rem);
}
.lost-sea {
  max-width: none;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 3rem clamp(1.25rem, 8vw, 6.5rem);
  background: var(--sea);
  color: var(--foam);
}
.lost-sea h1 {
  max-width: 14em;
  font-size: clamp(1.8rem, 4.6vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.022em;
  margin: 0 0 1.2rem;
  text-wrap: balance;
}
.lost-sea p {
  margin: 0 0 1.2rem;
  color: rgba(252, 251, 248, 0.82);
}
.lost-alt {
  display: block;
  font-weight: 500;
  color: rgba(252, 251, 248, 0.6);
}
.lost .code {
  font-family: var(--mono);
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  color: var(--foam);
}
.lost-links {
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem;
}
.lost-legal a {
  color: rgba(252, 251, 248, 0.7);
}
.lost-alt-inline {
  color: rgba(252, 251, 248, 0.6);
}
.lost-sea .store-soon {
  margin-top: 0.2rem;
}

/* ---- print -------------------------------------------------------------------- */

@media print {
  body {
    background: #fff;
    color: #000;
  }

  .bar,
  .site-foot nav,
  .foot-note {
    display: none;
  }

  .prose {
    max-width: none;
    padding: 0;
  }
}

/* ---- hero island mount ------------------------------------------------------------- */
/* #demo-root is prerendered with the static fallback inside; the live-demo island
   replaces its children client-side. Both variants fill the sea panel. */
#demo-root {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
  min-height: 0;
}
.hero-static {
  position: relative;
  flex: 1;
  display: flex;
  flex-direction: column;
}

/* ---- below-fold section devices ---------------------------------------------------- */
/* Magenta means "you can press this". Section eyebrows are labels, so they take the secondary
   ink (5.25 on paper) and keep the accent as the GRAPHIC dash in ::before — same rule as the
   app's ink-vs-fill contract. The same applies to .legend-item dt and .coverage-group h3. */
.section-kicker,
.section-title {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 0 0 0.9rem;
}
.section-kicker::before,
.section-title::before {
  content: '';
  display: inline-block;
  width: 1.1rem;
  height: 2px;
  background: var(--accent);
  margin-right: 0.55rem;
  vertical-align: 0.22em;
}
.section-heading {
  margin: 0 0 0.9rem;
  max-width: 18em;
  font-size: clamp(1.7rem, 3.6vw, 2.6rem);
  line-height: 1.1;
  font-weight: 700;
  letter-spacing: -0.022em;
  color: var(--text);
  text-wrap: balance;
}
.section-lead {
  font-size: clamp(1.02rem, 1.4vw, 1.15rem);
  line-height: 1.55;
  color: var(--text-secondary);
  max-width: 36em;
  margin: 0 0 2rem;
  text-wrap: pretty;
}

/* ---- stats strip: four facts in the instrument face -------------------------------- */
.hero-stats {
  list-style: none;
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(1.6rem, 4vw, 2.6rem) clamp(1.25rem, 4vw, 2.5rem) 0;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1rem 2rem;
}
.hero-stats li {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  padding: 1rem 0 0;
  border-top: 1px solid var(--hairline);
}
.stat-value {
  font-family: var(--mono);
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--text);
  font-variant-numeric: tabular-nums;
}
.stat-label {
  font-size: 0.86rem;
  color: var(--text-secondary);
}
@media (max-width: 700px) {
  .hero-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* ---- aboard: the product, in phone frames ------------------------------------------ */
.aboard {
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) 0;
}
.phones {
  list-style: none;
  margin: 0.5rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.2rem, 3vw, 2.4rem);
}
.phone-card figure {
  margin: 0;
}
.phone {
  /* a quiet bezel, not a device render: the screen is the point */
  position: relative;
  display: block;
  border-radius: clamp(26px, 5.5vw, 40px);
  padding: 10px;
  background: var(--sea);
  box-shadow:
    0 24px 48px -20px rgba(11, 42, 74, 0.45),
    0 0 0 1px rgba(255, 255, 255, 0.06) inset;
  cursor: zoom-in;
  transition:
    transform 260ms cubic-bezier(0.2, 0.7, 0.2, 1),
    box-shadow 260ms ease;
}
.phone:hover {
  transform: translateY(-4px);
  box-shadow:
    0 34px 60px -22px rgba(11, 42, 74, 0.55),
    0 0 0 1px rgba(255, 255, 255, 0.08) inset;
}
.phone.is-lifted img {
  visibility: hidden;
}

/* ---- lightbox (FLIP from the frame) -------------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 50;
  background: rgba(11, 22, 36, 0);
  -webkit-backdrop-filter: blur(0px);
  backdrop-filter: blur(0px);
  transition:
    background-color 320ms ease,
    backdrop-filter 320ms ease;
  cursor: zoom-out;
}
.lightbox.is-open {
  background: rgba(11, 22, 36, 0.82);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
}
.lightbox-img {
  position: fixed;
  display: block;
  max-width: 92vw;
  max-height: 88vh;
  object-fit: cover;
  border-radius: 22px;
  box-shadow: 0 40px 80px -30px rgba(0, 0, 0, 0.7);
  transition:
    left 380ms cubic-bezier(0.2, 0.8, 0.2, 1),
    top 380ms cubic-bezier(0.2, 0.8, 0.2, 1),
    width 380ms cubic-bezier(0.2, 0.8, 0.2, 1),
    height 380ms cubic-bezier(0.2, 0.8, 0.2, 1);
}
.lightbox-caption {
  position: fixed;
  left: 50%;
  bottom: max(1.2rem, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  margin: 0;
  max-width: 34rem;
  padding: 0 1rem;
  color: rgba(252, 251, 248, 0.85);
  font-size: 0.95rem;
  text-align: center;
  opacity: 0;
  transition: opacity 240ms ease 160ms;
}
.lightbox.is-open .lightbox-caption {
  opacity: 1;
}
.lightbox-close {
  position: fixed;
  top: max(1rem, env(safe-area-inset-top));
  right: 1rem;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  border: 0;
  background: rgba(252, 251, 248, 0.14);
  color: var(--foam);
  display: grid;
  place-items: center;
  cursor: pointer;
  opacity: 0;
  transition:
    opacity 240ms ease 160ms,
    background-color 160ms ease;
}
.lightbox.is-open .lightbox-close {
  opacity: 1;
}
.lightbox-close:hover {
  background: rgba(252, 251, 248, 0.26);
}
body.lightbox-open {
  overflow: hidden;
}
@media (prefers-reduced-motion: reduce) {
  .lightbox,
  .lightbox-img,
  .lightbox-caption,
  .lightbox-close,
  .phone {
    transition: none;
  }
}

/* ---- scroll reveals (enhancer adds .reveal, then .is-in) ---------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition:
    opacity 640ms cubic-bezier(0.2, 0.7, 0.2, 1) var(--reveal-delay, 0ms),
    transform 640ms cubic-bezier(0.2, 0.7, 0.2, 1) var(--reveal-delay, 0ms);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}
/* The enhancer is the only thing that hides these, and it is the only thing that may: it never
   hides a target nested inside another (the closing card's lead held an empty box for that
   reason), and a 3 s timeout shows anything its observer never reported. A scroll-driven
   `animation-timeline: view()` variant was tried and dropped — an animation drives opacity from
   a timeline this page cannot guarantee is ticking, and copy that stays at opacity 0 is the
   failure being fixed. */

/* ---- fixed glass bar once the sea has scrolled away (enhancer) ---------------------
   A sticky bar cannot leave its own section, so the bar goes fixed and the sea panel takes
   the bar's exact height as padding: no layout shift when the class lands. */
body.has-sticky-bar .bar-sea {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 20;
  transition:
    background-color 260ms ease,
    color 260ms ease,
    box-shadow 260ms ease;
}
body.has-sticky-bar .sea {
  /* --bar-h is measured from the live bar (enhance.ts); the literal is the computed height —
     2 × 1.1rem padding + the 2.75rem CTA — for the path where ResizeObserver is missing. */
  padding-top: var(--bar-h, 79px);
}
.bar-sea.is-stuck {
  background: color-mix(in srgb, var(--surface) 82%, transparent);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  color: var(--text);
  box-shadow: 0 1px 0 var(--hairline);
}
/* The stuck bar sits on paper, so the sea inks hand back to the page's own (the mark is reduced
   to its chevron at 26 px, so .mark-course / .mark-fix are not rendered there — named, not
   positional, so the reduction cannot silently repaint the wrong element). */
.bar-sea.is-stuck .brand .mark-course {
  stroke: var(--accent);
}
.bar-sea.is-stuck .brand .mark-fix,
.bar-sea.is-stuck .brand .mark-hull {
  fill: var(--text);
}
.bar-sea.is-stuck .bar-cta {
  background: var(--text);
  color: var(--surface);
}

/* ---- hero art drifts with the scroll (progressive: scroll-driven animations) ------- */
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .hero-art {
      animation: hero-drift linear both;
      animation-timeline: scroll();
      animation-range: 0 100vh;
    }
  }
}
@keyframes hero-drift {
  to {
    transform: translateY(12%) scale(1.04);
  }
}
.phone img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: clamp(18px, 4.2vw, 30px);
  background: var(--code-wash);
}
.phone-card figcaption {
  margin: 1rem 0.2rem 0;
  font-size: 0.95rem;
  line-height: 1.5;
  color: var(--text-secondary);
  text-wrap: pretty;
}
@media (max-width: 760px) {
  .phones {
    display: flex;
    gap: 1rem;
    margin-inline: calc(-1 * clamp(1.25rem, 4vw, 2.5rem));
    padding-inline: clamp(1.25rem, 4vw, 2.5rem);
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .phones::-webkit-scrollbar {
    display: none;
  }
  .phone-card {
    flex: 0 0 min(76vw, 320px);
    scroll-snap-align: center;
  }
}

/* legend entries carry the real seamark symbol (replaces the old route-line ::before) */
.legend-symbol {
  display: inline-flex;
  width: 30px;
  justify-content: center;
  flex: none;
}
.legend-icon {
  height: 27px;
  width: auto;
  display: block;
}

/* ---- coverage: the sheet-index diagram --------------------------------------------- */
.coverage {
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) 0;
}
/* the 28 outlines are the information; the diagram is capped and the pack list sits beside it */
.coverage-layout {
  display: grid;
  gap: clamp(1.4rem, 3.5vw, 3rem);
  align-items: start;
  margin-bottom: clamp(1.4rem, 3vw, 2.4rem);
}
.coverage-list {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.2rem clamp(1.4rem, 3.5vw, 3rem);
}
@media (min-width: 560px) and (max-width: 819px) {
  .coverage-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 820px) {
  .coverage-layout {
    grid-template-columns: minmax(0, 30rem) 1fr;
  }
}
@media (min-width: 1100px) {
  .coverage-list {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.coverage-map {
  width: 100%;
  max-width: 30rem;
  height: auto;
  border-radius: 20px;
  border: 1px solid var(--hairline);
  /* the panel itself is the land tone; the coastline path fills the sea */
  background:
    linear-gradient(0deg, var(--coverage-land-wash), var(--coverage-land-wash)), var(--surface);
}
.coverage-sea {
  fill: var(--coverage-sea);
  stroke: var(--hairline);
  stroke-width: 0.75;
}
.coverage-graticule {
  fill: none;
  stroke: var(--hairline);
  stroke-width: 1;
}
.coverage-grid-label {
  font-family: var(--mono);
  font-size: 6px; /* viewBox units: ~10 px on a 30 rem diagram */
  fill: var(--text-secondary);
}
.coverage-region {
  fill: var(--accent-soft);
  stroke: var(--accent);
  stroke-width: 1.1;
  stroke-linejoin: round;
}
.coverage-region:hover {
  fill: var(--accent);
  fill-opacity: 0.35;
}
.coverage-list {
  font-size: 0.92rem;
}
.coverage-group h3,
.coverage-group h4 {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-secondary);
  margin: 1.1rem 0 0.4rem;
}
.coverage-group h3,
.coverage-group h4 {
  margin-top: 0;
}
.coverage-group ul {
  list-style: none;
  margin: 0;
  padding: 0;
  columns: 1;
}
.coverage-group li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.18rem 0;
  border-bottom: 1px dotted var(--hairline);
}
.pack-size {
  font-family: var(--mono);
  font-size: 0.78rem;
  color: var(--text-secondary);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.coverage-note {
  font-size: 0.88rem;
  color: var(--text-secondary);
  margin-top: 1.4rem;
  max-width: 44em;
}

/* ---- open data / privacy / stores -------------------------------------------------- */
.open-data .open-data-line {
  font-size: 0.85rem;
  color: var(--text-secondary);
  max-width: 52em;
}
.privacy-stance {
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) 0;
}
.privacy-statement {
  font-family: var(--mono);
  font-size: clamp(1.4rem, 3.4vw, 2.4rem);
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.2;
  color: var(--text);
  margin: 0 0 1rem;
  text-wrap: balance;
}
.get-the-app {
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) 0;
}
.get-the-app-card {
  position: relative;
  overflow: hidden;
  padding: clamp(2rem, 5vw, 3.6rem) clamp(1.4rem, 4vw, 3rem);
  border-radius: 28px;
  background: var(--sea);
  color: var(--foam);
  box-shadow: 0 30px 60px -30px rgba(11, 42, 74, 0.5);
}
.get-the-app-card::after {
  /* a faint isobath, the chart's own texture */
  content: '';
  position: absolute;
  inset: auto -10% -40% auto;
  width: 60%;
  aspect-ratio: 1;
  border-radius: 50%;
  border: 1.5px solid rgba(98, 160, 214, 0.18);
  pointer-events: none;
}
/* on the navy card the eyebrow is foam like the lead (magenta text on sea is 2.6:1); the course
   pink stays as the GRAPHIC dash, the same ink-vs-fill split as everywhere else */
.get-the-app-card .section-kicker {
  color: rgba(252, 251, 248, 0.8); /* 9.45 on sea */
}
.get-the-app-card .section-kicker::before {
  background: var(--course-on-sea);
}
.get-the-app-card .section-heading {
  color: var(--foam);
  max-width: 16em;
}
.get-the-app-card .section-lead {
  color: rgba(252, 251, 248, 0.8);
  margin-bottom: 1.8rem;
}
.get-the-app-card .hero-beta {
  color: rgba(252, 251, 248, 0.72);
}
.site-foot {
  margin-top: clamp(3rem, 7vw, 5rem);
}
.foot-grid {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem 2rem;
  margin-bottom: 1.4rem;
}
.foot-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--text);
  font-weight: 700;
  letter-spacing: -0.01em;
}
.foot-trademarks {
  font-size: 0.78rem; /* 12.5 px, text-secondary at full opacity (5.25 / 6.9) */
}

/* Website navigation and disclosure: useful even before the island loads. */
.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 100;
  padding: 0.65rem 1rem;
  border-radius: 8px;
  background: var(--foam);
  color: var(--sea);
  transform: translateY(-200%);
}
.skip-link:focus {
  transform: none;
}
[id] {
  scroll-margin-top: calc(var(--bar-h, 80px) + 1rem);
}
.section-nav {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.25rem clamp(0.5rem, 3vw, 2rem);
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--hairline);
}
.section-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  padding: 0 0.5rem;
  color: var(--text);
  font-size: 0.9rem;
  font-weight: 600;
  text-decoration: none;
}
.section-nav a:hover {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 0.3em;
}
.faq {
  display: grid;
  gap: 1rem 3rem;
  max-width: 68rem;
  margin: 0 auto;
  padding: clamp(3.5rem, 8vw, 6rem) clamp(1.25rem, 4vw, 2.5rem) 0;
}
.faq details {
  border-bottom: 1px solid var(--hairline);
}
.faq details:first-child {
  border-top: 1px solid var(--hairline);
}
.faq summary {
  min-height: 2.75rem;
  padding: 1.15rem 0.25rem;
  color: var(--text);
  font-weight: 600;
  cursor: pointer;
}
.faq summary::marker {
  color: var(--accent-ink);
}
.faq summary:hover {
  color: var(--accent-ink);
}
.faq details p {
  margin: 0;
  padding: 0 0.25rem 1.3rem;
  color: var(--text-secondary);
  font-size: 1rem;
  line-height: 1.65;
}
@media (min-width: 820px) {
  .faq {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1.4fr);
  }
}
/* Text zoom must not make the fixed header wider than the viewport. */
.bar,
.bar-right {
  flex-wrap: wrap;
}
.prose,
.faq,
.coverage-list {
  overflow-wrap: anywhere;
}
.lightbox :focus-visible {
  outline-color: var(--foam);
}
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal {
    opacity: 1;
    transform: none;
  }
}
@media (prefers-reduced-transparency: reduce), (prefers-contrast: more) {
  .bar-sea.is-stuck {
    background: var(--surface);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  .lightbox.is-open {
    background: var(--sea);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
}
@media (prefers-contrast: more) {
  :root {
    --text-secondary: var(--text);
    --hairline: var(--text);
  }
}

.coverage-upcoming {
  margin-top: 2rem;
  padding: clamp(1.25rem, 3vw, 2rem);
  border: 1px solid var(--hairline);
  border-radius: 20px;
  background: var(--surface);
}
.coverage-upcoming > h3 {
  margin: 0;
  font-size: clamp(1.4rem, 3vw, 2rem);
}
.coverage-upcoming-lead {
  max-width: 58ch;
  color: var(--text-secondary);
  line-height: 1.6;
}
.coverage-upcoming-grid {
  display: grid;
  gap: 1.8rem;
  margin-top: 1.8rem;
}
@media (min-width: 640px) {
  .coverage-upcoming-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (min-width: 1000px) {
  .coverage-upcoming-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* Regional atlas: give names room, keep availability beside each region. */
.hero-stats {
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.atlas-overview {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  margin-bottom: 3rem;
}
.atlas-overview .coverage-map {
  width: 100%;
  max-height: 32rem;
}
.atlas-intro .section-lead {
  max-width: 42ch;
}
.atlas-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem 1.5rem;
  margin-top: 1.5rem;
  font-size: 0.85rem;
}
.atlas-legend > span {
  display: inline-flex;
  gap: 0.5rem;
  align-items: center;
}
.atlas-key {
  display: inline-block;
  width: 1.25rem;
  height: 0.8rem;
  border: 1.5px solid var(--accent-ink);
  background: color-mix(in srgb, var(--accent-ink) 12%, transparent);
}
.atlas-key-soon {
  border-style: dashed;
  background: transparent;
}
.coverage-map .coverage-region-soon {
  fill: transparent;
  stroke-dasharray: 4 3;
}
.atlas-groups {
  columns: 3;
  column-gap: 2rem;
}
.atlas-group {
  break-inside: avoid;
  margin: 0 0 2rem;
  padding: 1.25rem 0 0;
  border-top: 1px solid var(--hairline);
}
.atlas-group h3 {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-size: 1.05rem;
  margin: 0 0 0.85rem;
}
.atlas-group h3 > span {
  color: var(--text-secondary);
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 500;
}
.atlas-group ul {
  list-style: none;
  margin: 0;
  padding: 0;
}
.atlas-group li {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--hairline);
  font-size: 0.9rem;
  line-height: 1.5;
}
.atlas-group li > span:first-child {
  min-width: 0;
}
.atlas-group .pack-size,
.atlas-group .pack-status {
  flex-shrink: 0;
  font-size: 0.72rem;
  color: var(--text-secondary);
  white-space: nowrap;
}
.atlas-group .pack-status {
  font-family: inherit;
}
.atlas-group .coverage-note {
  margin: 0 0 0.75rem;
}
.atlas-note {
  max-width: 75ch;
}
@media (max-width: 900px) {
  .atlas-groups {
    columns: 2;
  }
}
@media (max-width: 600px) {
  .atlas-overview {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  .atlas-overview .coverage-map {
    max-height: 27rem;
  }
  .atlas-groups {
    columns: 1;
  }
  .hero-stats {
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 1rem;
  }
}

.atlas-group > summary {
  cursor: pointer;
  list-style: none;
}
.atlas-group > summary::-webkit-details-marker {
  display: none;
}
.atlas-group > summary h3 {
  align-items: center;
  min-height: 44px;
}
.atlas-group > summary h3::after {
  content: '+';
  color: var(--accent-ink);
  font-size: 1.25rem;
}
.atlas-group[open] > summary h3::after {
  content: '−';
}
.atlas-group > summary h3 > span {
  margin-left: auto;
}
.atlas-group > summary:focus-visible {
  outline: 2px solid var(--accent-ink);
  outline-offset: 4px;
}
@media (max-width: 600px) {
  .atlas-overview {
    margin-bottom: 1.5rem;
  }
  .atlas-overview .coverage-map {
    max-height: 230px;
  }
  .atlas-group {
    padding: 0;
    margin: 0;
  }
  .atlas-group > summary {
    padding: 5px 0;
  }
  .atlas-group > summary h3 {
    margin: 0;
    font-size: 0.95rem;
    gap: 0.75rem;
  }
  .atlas-group[open] {
    padding-bottom: 1rem;
  }
  .atlas-group ul {
    padding-left: 0.5rem;
  }
  .atlas-note {
    margin-top: 1.25rem;
  }
  .bar {
    padding-top: 0.5rem;
    padding-bottom: 0.5rem;
  }
}
