/*
  Crewside: the landing page. One stylesheet, no build step, no web fonts.

  PALETTE: Dusk, both modes, since 2026-09-14 (Matea's ruling, operations/
  decisions.md 2026-09-14: the public brand goes Dusk, website first, because
  social is already posted in the Dusk browns). The values are read off the
  "Crewside Dusk" board (colour-system board + the Gallery artboards, 2026-09-09),
  not invented; the handful the board does not carry are derived and named in
  michelangelo-to-leonardo-2026-09-14-website-dusk.md, each with its measured
  contrast. The APP does not move yet: mobile/src/ui/tokens.ts still ships the
  blue-slate dark and the cool-slate light, deliberately, until the Dusk client
  sitting after submission. So the 1:1 mirror this file used to claim is
  suspended, not broken, and this file is the first surface on the new palette.

  Dark is the site's default (ruled 2026-08-19). Light exists because older
  crew reported dark is hard to read (ruled 2026-08-07), which is why every
  light value here is held to AA on the rendered page rather than to the board.

  Rules carried from the app:
    - no raw hex in rules below this block, tokens only
    - depth = lighter surface + hairline border, never shadows; 2 levels max
    - gold = actions (tap it), the warm city hue = signals (read it), teal =
      success; never swapped. The old rose/lavender pair retired with the
      blue-slate palette.
    - the window mark's three colours are LOCKED and identical in both themes
      (#B39DFF / #FFC46B / #F27BA0, ruled 2026-08-07, re-ruled 2026-09-14).
      mark.svg, favicon.svg and .wm-dot are NOT part of this palette and a warm
      restyle does not get to re-tint them to match.
*/

/* ---------------------------------------------------------------- tokens */

:root {
  color-scheme: dark;

  /* Dusk dark. Canvas, card, chip and hairline straight off the board. */
  --bg: #151210;
  --surface: #211c18;
  --surface-raised: #2a241e;
  --border: #332c25;
  --ink: #f4ece0;
  --ink-muted: #a3968a;

  /* Gold is the action colour (the board's "Add layover" / "Continue with
     Apple" fill, and its link colour). Pressed goes lighter on dark. The
     pressed step is not on the board. */
  --primary: #ddbb88;
  --primary-pressed: #e9cda3;
  --on-primary: #1b150c;

  /* The signal is the board's warm city hue (Bangkok coral): the code on the
     card and its "Chat open" line share it. Its ground is Gallery's city
     tint, the one hex the kickoff carried. */
  --signal: #ffb197;
  --signal-bg: #3d261f;

  /* Success teal is the board's "Crew only" shield. The other three states
     are not on the board and are derived: danger keeps the coral family but
     goes redder, pending is the board's Singapore amber. Each -bg is its
     accent laid over --surface at roughly 15%, then measured. */
  --success: #63c3ae;
  --success-bg: #17302b;
  --danger: #ff9a8a;
  --danger-bg: #3b211d;
  --pending: #f2bf79;
  --pending-bg: #33281a;

  /* City tints for the phone mock. The class names in index.html are still
     --stone and --steel (the old cool tints); the VALUES are now the board's
     Bangkok coral and Singapore amber. The board assigns no hue to LHR or
     FRA, so this pairing is ours. */
  --tint-stone: #ffb197;
  --tint-steel: #f2bf79;

  /* Focus ring is the action gold: reads on both canvases without being a
     second accent. */
  --focus: #ddbb88;

  /* Interactive boundaries only (inputs, icon buttons, ghost buttons).
     --border stays the board's hairline and is used for cards, which are
     decorative grouping. This one is a WCAG 1.4.11 target: a field the
     visitor is meant to type in has to be findable as a field, and the
     hairline measures 1.23:1 against the card it sits on, which is not.
     #7A6C5C measures 3.32:1 on --surface and 3.67:1 on the field's own
     fill, so it clears 3:1 against both of its neighbours. Not on the board. */
  --control-border: #7a6c5c;
}

:root[data-theme="light"] {
  color-scheme: light;

  /* Dusk light. Canvas, card, chip, hairline and both inks off the board. */
  --bg: #f3ece1;
  --surface: #fffbf5;
  --surface-raised: #ebe1d3;
  --border: #e0d4c3;
  --ink: #211a14;
  --ink-muted: #5f5346;

  /* The board's light gold is #9A6B2A. It measures 3.97:1 on the page canvas,
     which is below AA for the link text that sits there (footer, legal back
     links, fineprint), so the site deepens it one step to #8A5E22: 4.83:1 on
     the canvas, 5.50:1 on a card, and 5.50:1 under the button label. Same
     hue. Pressed goes darker on light. */
  --primary: #8a5e22;
  --primary-pressed: #6f4a19;
  --on-primary: #fffbf5;

  /* Bangkok coral in its light lightness map, on Gallery's light tint. */
  --signal: #993613;
  --signal-bg: #ffe5dc;

  /* The board's light shield teal #1E7F6B measures 4.16:1 on the canvas and
     4.24:1 on a pale teal ground, so it is deepened to #1B7462 (4.81 / 4.90).
     Danger and pending derived as on dark; pending is Singapore's light amber
     straight off the board. */
  --success: #1b7462;
  --success-bg: #e1f3ec;
  --danger: #a6382a;
  --danger-bg: #fbe3dd;
  --pending: #874a00;
  --pending-bg: #f7e6cc;

  /* Same hue per city in both modes: coral is coral with the lights on. */
  --tint-stone: #993613;
  --tint-steel: #874a00;

  --focus: #8a5e22;

  /* 3.91:1 on --surface, 3.44:1 on the page canvas. Not on the board. */
  --control-border: #8c7c6a;
}

:root {
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-8: 32px;
  --space-10: 40px;
  --space-12: 48px;
  --space-16: 64px;
  --space-20: 80px;
  --space-24: 96px;

  --radius-sm: 10px;
  --radius-md: 14px;
  --radius-lg: 22px;
  --radius-xl: 28px;
  --radius-pill: 999px;

  /* System stack only. No Google Fonts request, no third-party processor,
     and the app ships in the same faces. */
  --font: -apple-system, BlinkMacSystemFont, "SF Pro Display", "SF Pro Text",
    "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --fs-hero: clamp(2.5rem, 1.6rem + 4.2vw, 4.25rem);
  --fs-display: clamp(1.85rem, 1.4rem + 2.2vw, 2.75rem);
  --fs-title: clamp(1.2rem, 1.1rem + 0.5vw, 1.4rem);
  --fs-lead: clamp(1.075rem, 1rem + 0.4vw, 1.25rem);
  --fs-body: 1.0625rem;
  --fs-caption: 0.8125rem;

  --lh-tight: 1.08;
  --lh-body: 1.6;
  --ls-display: -0.02em;

  --maxw: 1080px;
  --maxw-prose: 68ch;
  --touch: 48px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur: 180ms;
}

/* ----------------------------------------------------------------- base */

*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  /* iOS Safari inflates font sizes on pages it decides are "wide" (text
     autosizing), and it skips tiny transformed inline-blocks like the
     wordmark's dotless-i span while inflating the letters around it. That
     is how the sun dot ended up over different letters at different widths
     in Matea's 08-18 screenshots, and how the grown wordmark painted into
     the theme toggle. Pin the ratio: the page sets its own sizes. */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

h1,
h2,
h3 {
  margin: 0;
  letter-spacing: var(--ls-display);
  line-height: 1.15;
  text-wrap: balance;
}

p {
  margin: 0;
}

a {
  color: var(--primary);
  text-underline-offset: 3px;
}

a:hover {
  color: var(--primary-pressed);
}

img,
svg {
  max-width: 100%;
}

:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: var(--space-1);
}

.container {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--space-5);
}

.section {
  padding-block: clamp(var(--space-16), 9vw, var(--space-24));
}

.section--tight {
  padding-block: clamp(var(--space-12), 6vw, var(--space-16));
}

.muted {
  color: var(--ink-muted);
}

.lead {
  font-size: var(--fs-lead);
  color: var(--ink-muted);
}

.h-display {
  font-size: var(--fs-display);
  font-weight: 800;
}

.h-title {
  font-size: var(--fs-title);
  font-weight: 700;
}

.prose {
  max-width: var(--maxw-prose);
}

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

.skip-link {
  position: absolute;
  left: var(--space-4);
  top: calc(var(--space-4) * -6);
  z-index: 20;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  color: var(--ink);
  text-decoration: none;
  transition: top var(--dur) var(--ease);
}

.skip-link:focus-visible {
  top: var(--space-4);
}

/* ------------------------------------------------------------ the brand */

/* Wordmark: lowercase, dotless i (U+0131) carrying its own dot, so the sun
   can be recoloured at all. You cannot recolour a real tittle.

   EVERY NUMBER BELOW IS THE RULED ONE, ported from the approved board
   (crewside-animation-preview.html, blessed by Matea 2026-08-11) rather than
   re-derived. The board renders at 36px, so the pixel values there convert:
     dot        7.92px / 36  = 0.22em   <- one of the two numbers Matea locked
     dot bottom 24.70px / 36 = 0.686em
   line-height:1 is load-bearing. The dot is positioned from the bottom of the
   inline box, so an inherited line-height would move it. */
.wordmark {
  font-weight: 700;
  letter-spacing: 0.01em;
  line-height: 1;
  display: inline-block;
  color: var(--ink);
  white-space: nowrap;
}

.wm-i {
  position: relative;
  display: inline-block;
}

/* scaleY, not a smaller font-size: shrinking the glyph thins the stroke and
   narrows the letter, transforming keeps full weight and the same advance
   width so nothing around it reflows. */
.wm-stem {
  display: inline-block;
  transform: scaleY(0.9);
  transform-origin: 50% 84.78%;
}

/* Amber in BOTH themes, with the glow, exactly as approved. This is the
   sun that leaves the window in the app's opening animation, so it is brand
   geometry and sits outside the palettes like the window mark itself.
   WCAG 1.4.3 exempts logotypes from the contrast floor, which is why this
   survives on the light canvas where amber body text never would. */
.wm-dot {
  position: absolute;
  left: 50%;
  bottom: 0.686em;
  transform: translateX(-50%);
  width: 0.22em;
  height: 0.22em;
  border-radius: 50%;
  display: block;
  background: #ffc46b;
  box-shadow:
    0 0 0.187em 0.066em rgba(255, 196, 107, 0.55),
    0 0 0.44em 0.165em rgba(255, 196, 107, 0.24);
}

.lockup {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  text-decoration: none;
  color: var(--ink);
}

.lockup__mark {
  width: 34px;
  height: 34px;
  flex: none;
  display: block;
}

.lockup__word {
  font-size: 1.4rem;
}

/* --------------------------------------------------------------- header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: 68px;
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

/* ------------------------------------------------------------- controls */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--touch);
  padding: 0 var(--space-6);
  border: 1px solid transparent;
  border-radius: var(--radius-pill);
  background: var(--primary);
  color: var(--on-primary);
  font: inherit;
  font-weight: 700;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--dur) var(--ease);
  /* A pill's label never wraps: a two-line "Join the waitlist" inflated the
     whole header bar on phones (08-18). Tight widths shorten the label
     instead - see the header tiers at the bottom of this file. */
  white-space: nowrap;
}

.btn:hover {
  background: var(--primary-pressed);
  color: var(--on-primary);
}

.btn--secondary {
  background: transparent;
  border-color: var(--control-border);
  color: var(--ink);
}

.btn--secondary:hover {
  background: var(--surface-raised);
  color: var(--ink);
}

.btn--block {
  width: 100%;
}

.btn[disabled] {
  opacity: 0.65;
  cursor: progress;
}

.theme-toggle {
  display: inline-grid;
  place-items: center;
  width: var(--touch);
  height: var(--touch);
  border: 1px solid var(--control-border);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--ink);
  cursor: pointer;
  padding: 0;
}

.theme-toggle:hover {
  background: var(--surface-raised);
}

.theme-toggle svg {
  width: 20px;
  height: 20px;
  display: block;
}

/* Show the icon for the mode you would switch TO. */
:root:not([data-theme="light"]) .theme-toggle__sun {
  display: none;
}

:root[data-theme="light"] .theme-toggle__moon {
  display: none;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--signal-bg);
  color: var(--signal);
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0.02em;
}

.trust {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  color: var(--ink-muted);
  font-size: var(--fs-caption);
  line-height: 1.5;
}

.trust__badge {
  flex: none;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--signal-bg);
  color: var(--signal);
  font-size: 12px;
  font-weight: 800;
}

/* ----------------------------------------------------------------- hero */

.hero {
  padding-top: clamp(var(--space-12), 7vw, var(--space-20));
  padding-bottom: clamp(var(--space-12), 7vw, var(--space-20));
}

.hero__grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(var(--space-8), 6vw, var(--space-20));
  align-items: center;
}

.hero__slogan {
  font-size: var(--fs-hero);
  font-weight: 800;
  line-height: var(--lh-tight);
  margin-top: var(--space-5);
}

.hero__subline {
  margin-top: var(--space-5);
  max-width: 46ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-8);
}

.hero__fineprint {
  margin-top: var(--space-4);
  font-size: var(--fs-caption);
}

.hero__art {
  display: flex;
  justify-content: center;
}

/* The phone echoes the app's layover list. Same visual language, not a
   screenshot: a screenshot dates the moment the app changes. */
.phone {
  width: min(340px, 100%);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--radius-xl);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

:root[data-theme="light"] .phone {
  background: var(--surface-raised);
}

.phone__label {
  font-size: 1.25rem;
  font-weight: 800;
  color: var(--ink);
  letter-spacing: -0.02em;
}

.lo-card {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-4) var(--space-5);
}

.lo-card__code {
  font-size: 1.75rem;
  font-weight: 800;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}

/* City tints live here as classes, NOT as inline style attributes. Our own
   CSP is `style-src 'self'`, which blocks a style="" attribute outright, so
   an inline tint silently renders as inherited ink. That shipped once and was
   only caught on the real host, because a local static server sends no CSP.
   Any future tint goes in this block. */
.lo-card__code--stone {
  color: var(--tint-stone);
}

.lo-card__code--steel {
  color: var(--tint-steel);
}

.lo-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.lo-card__city {
  color: var(--ink);
  font-size: 0.9rem;
}

/* flex-start, not center: when the status wraps to two lines the dot would
   otherwise float halfway down the block instead of sitting with the first
   word it belongs to. */
.lo-card__status {
  display: inline-flex;
  align-items: flex-start;
  gap: var(--space-2);
  font-size: 0.75rem;
  font-weight: 700;
}

.lo-card__status--open {
  color: var(--signal);
}

.lo-card__status--soon {
  color: var(--pending);
}

.live-dot {
  flex: none;
  width: 8px;
  height: 8px;
  /* centres the dot on the cap height of the first line */
  margin-top: 0.32em;
  border-radius: 50%;
  background: var(--signal);
  animation: pulse 1.6s var(--ease) infinite;
}

@keyframes pulse {
  0%,
  100% {
    opacity: 1;
  }
  50% {
    opacity: 0.35;
  }
}

/* -------------------------------------------------------------- mission */

.mission__p + .mission__p {
  margin-top: var(--space-5);
}

.mission__note {
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
  margin-top: var(--space-8);
  max-width: var(--maxw-prose);
  border-color: color-mix(in srgb, var(--signal) 35%, var(--border));
}

.mission__note .trust__badge {
  width: 28px;
  height: 28px;
  font-size: 14px;
}

/* ------------------------------------------------------------------ how */

.how__heading {
  margin-bottom: var(--space-10);
  max-width: 20ch;
}

.how__steps {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-5);
}

.how__step {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.how__num {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border-radius: var(--radius-md);
  background: var(--signal-bg);
  color: var(--signal);
  font-weight: 800;
  font-size: 1.1rem;
  font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------- waitlist */

.waitlist__grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(var(--space-8), 5vw, var(--space-16));
  align-items: start;
}

.waitlist__intro {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.wl-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.wl-form[hidden],
.wl-success[hidden],
.wl-status[hidden],
.field__error[hidden] {
  display: none;
}

.wl-form__fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.field__label {
  font-size: var(--fs-caption);
  font-weight: 700;
  color: var(--ink);
}

.field__input {
  min-height: var(--touch);
  border-radius: var(--radius-md);
  border: 1px solid var(--control-border);
  background: var(--bg);
  color: var(--ink);
  padding: 0 var(--space-4);
  font-family: inherit;
  font-size: 1rem;
  transition: border-color var(--dur) var(--ease);
}

:root[data-theme="light"] .field__input {
  background: var(--surface);
}

.field__input::placeholder {
  color: var(--ink-muted);
}

.field__input:focus-visible {
  border-color: var(--primary);
}

.field__input[aria-invalid="true"] {
  border-color: var(--danger);
}

.field__error {
  font-size: var(--fs-caption);
  color: var(--danger);
}

/* The city question's supporting line. Sits between label and input so it is
   read before typing; wired to the input via aria-describedby. */
.field__hint {
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--ink-muted);
}

.field__consent {
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--ink-muted);
}

.banner {
  border-radius: var(--radius-md);
  padding: var(--space-3) var(--space-4);
  font-size: var(--fs-caption);
  line-height: 1.5;
}

.banner--danger {
  background: var(--danger-bg);
  color: var(--danger);
}

.banner--pending {
  background: var(--pending-bg);
  color: var(--pending);
}

.wl-success {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: flex-start;
  border-color: color-mix(in srgb, var(--success) 40%, var(--border));
}

.wl-success__check {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--success-bg);
  color: var(--success);
  font-size: 22px;
  font-weight: 800;
}

/* ------------------------------------------------------------------ faq */

.faq__heading {
  margin-bottom: var(--space-8);
}

.faq__list {
  max-width: var(--maxw-prose);
}

.faq__item {
  border-bottom: 1px solid var(--border);
}

.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  min-height: var(--touch);
  padding: var(--space-4) 0;
  cursor: pointer;
  font-weight: 700;
  color: var(--ink);
  list-style: none;
}

.faq__q::-webkit-details-marker {
  display: none;
}

.faq__chevron {
  flex: none;
  width: 11px;
  height: 11px;
  border-right: 2px solid var(--ink-muted);
  border-bottom: 2px solid var(--ink-muted);
  transform: rotate(45deg);
  transition: transform var(--dur) var(--ease);
}

.faq__item[open] .faq__chevron {
  transform: rotate(-135deg);
}

.faq__a {
  padding-bottom: var(--space-5);
  color: var(--ink-muted);
}

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

.site-footer {
  border-top: 1px solid var(--border);
  padding-block: var(--space-12);
}

.site-footer__grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-6);
  justify-content: space-between;
  align-items: flex-start;
}

.site-footer__claim {
  font-weight: 700;
  color: var(--ink);
}

.site-footer__line {
  margin-top: var(--space-2);
  color: var(--ink-muted);
  font-size: var(--fs-caption);
  max-width: 46ch;
}

.site-footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  align-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-footer__links a {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  font-size: var(--fs-caption);
  font-weight: 700;
}

/* ------------------------------------------------------------ legal doc */

.legal {
  padding-block: clamp(var(--space-12), 7vw, var(--space-20));
}

.legal__doc {
  max-width: var(--maxw-prose);
}

.legal__doc h1 {
  font-size: var(--fs-display);
  font-weight: 800;
}

.legal__doc h2 {
  font-size: var(--fs-title);
  font-weight: 700;
  margin-top: var(--space-10);
}

.legal__doc p {
  margin-top: var(--space-4);
  color: var(--ink-muted);
}

.legal__doc .legal__address {
  color: var(--ink);
}

.legal__back {
  display: inline-flex;
  align-items: center;
  min-height: var(--touch);
  margin-top: var(--space-10);
  font-weight: 700;
}

/* Lead paragraph on /terms and /privacy: the one-line orientation under the
   h1. Full --ink rather than the --ink-muted the rest of .legal__doc p uses,
   and a shade larger, so it reads as the opening of a document rather than as
   the first item of body copy. */
.legal__doc .legal__lead {
  margin-top: var(--space-5);
  color: var(--ink);
  font-size: var(--fs-lead, 1.125rem);
  line-height: 1.55;
}

/* Lists inside a legal document. The .legal__doc block styled h1/h2/p only,
   because the Impressum is unbroken prose; both interim pages lean on lists
   because "what we hold about you" is a list in reality and prose would be
   softening it. */
.legal__list {
  margin-top: var(--space-4);
  padding-left: var(--space-5);
  color: var(--ink-muted);
  list-style: disc;
}
.legal__list li {
  margin-top: var(--space-2);
  padding-left: var(--space-1);
}
.legal__list li::marker {
  color: var(--signal);
}
.legal__list strong {
  color: var(--ink);
}
.legal__doc .legal__interim strong {
  color: var(--ink);
}

.legal__updated {
  margin-top: var(--space-10);
  font-size: var(--fs-caption);
}

/* -------------------------------------------------------------- status */

.status-page {
  min-height: 70vh;
  display: grid;
  place-items: center;
  padding-block: var(--space-16);
}

.status-card {
  max-width: 48ch;
  /* the grid centres .container, not the card inside it */
  margin-inline: auto;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
}

.status-card__icon {
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  font-size: 26px;
  font-weight: 800;
  background: var(--signal-bg);
  color: var(--signal);
}

.status-card__icon--success {
  background: var(--success-bg);
  color: var(--success);
}

.status-card__icon--pending {
  background: var(--pending-bg);
  color: var(--pending);
}

/* ------------------------------------------- confirm / unsubscribe gate */

/*
  The one-click interstitial (/confirm, /unsubscribe). Three mutually exclusive
  states live in the markup at once and link.js picks one on <html> before the
  first paint, so nothing flashes:

    (no attribute) -> "nojs"    JavaScript is off, or link.js failed to load
    data-link="ok"      -> the POST button, the only thing that mutates anything
    data-link="missing" -> the link reached us without a usable 64-hex token

  "nojs" is the default in the markup rather than a state the script has to
  reach, so a visitor whose browser never runs link.js is told what happened and
  given a way out instead of meeting a button that would silently do nothing.
*/
.link-gate {
  width: 100%;
}

.link-gate > [data-gate] {
  display: none;
}

.link-gate > [data-gate="nojs"] {
  display: block;
}

[data-link] .link-gate > [data-gate="nojs"] {
  display: none;
}

[data-link="ok"] .link-gate > [data-gate="form"] {
  display: block;
}

[data-link="missing"] .link-gate > [data-gate="missing"] {
  display: block;
}

/*
  Heading and promise follow the state too. A page that says "One last click."
  above a paragraph explaining that the link is broken is a page arguing with
  itself, and the visitor whose mail client wrapped the URL is exactly the
  person least able to tell which half to believe.
*/
.g-missing {
  display: none;
}

[data-link="missing"] .g-ok {
  display: none;
}

[data-link="missing"] .g-missing {
  display: inline;
}

[data-link="missing"] .g-hide-missing {
  display: none;
}

.link-note {
  margin: 0;
  color: var(--ink-muted);
  text-align: left;
}

.link-why {
  margin: 0;
  color: var(--ink-muted);
  font-size: var(--fs-caption);
}

/*
  The card is bilingual in the markup and switches on <html data-lang>, because
  the language belongs to the EMAIL the visitor came from, not to the site: the
  site is English-only (ruled 2026-08-13) and its header and footer stay English
  here. `lang="de"` therefore sits on the German spans themselves, so a screen
  reader changes voice on exactly the words that changed and on nothing else.
*/
.t-de {
  display: none;
}

[data-lang="de"] .t-de {
  display: inline;
}

[data-lang="de"] .t-en {
  display: none;
}

/* --------------------------------------------------------- responsive */

@media (max-width: 900px) {
  .hero__grid,
  .waitlist__grid {
    grid-template-columns: 1fr;
  }
  .hero__art {
    order: -1;
  }
  .how__steps {
    grid-template-columns: 1fr;
  }
}

/* Header at phone widths (Matea's 08-18 screenshots): the bar must never
   wrap, overlap, or push the page wider than the viewport. Three tiers,
   each budgeted against measured text widths with >= 8px slack at the
   ruled test widths 320/375/390/430:

     <= 560px  compact lockup + smaller CTA, full label
               390pt: 122.9 + 12 + 48 + 8 + 149.5 = 340.4 of 350 available
     <= 385px  label shortens to "Join waitlist"
               375pt: 122.9 + 12 + 48 + 8 + 121.9 = 312.8 of 335
     <= 345px  label shortens to "Waitlist", lockup tightens one more step
               320pt: 113 + 8 + 48 + 8 + 81.1 = 258.1 of 280

   The theme toggle stays 48px in every tier: touch targets do not shrink.
   The three labels live in the markup as sibling spans; only one is ever
   displayed, and the anchor carries a constant aria-label so the accessible
   name does not change with the viewport. */
@media (max-width: 560px) {
  .site-header__inner {
    gap: var(--space-3);
  }
  .lockup {
    gap: var(--space-2);
  }
  .lockup__mark {
    width: 28px;
    height: 28px;
  }
  .lockup__word {
    font-size: 1.25rem;
  }
  .header-actions {
    gap: var(--space-2);
  }
  .header-actions .btn {
    padding: 0 var(--space-4);
    font-size: 0.9375rem;
  }
}

.btn__label--mid,
.btn__label--min {
  display: none;
}

@media (max-width: 385px) {
  .header-actions .btn__label--full {
    display: none;
  }
  .header-actions .btn__label--mid {
    display: inline;
  }
}

@media (max-width: 345px) {
  .site-header__inner {
    gap: var(--space-2);
  }
  .lockup__mark {
    width: 24px;
    height: 24px;
  }
  .lockup__word {
    font-size: 1.15rem;
  }
  .header-actions .btn {
    padding: 0 var(--space-3);
  }
  .header-actions .btn__label--mid {
    display: none;
  }
  .header-actions .btn__label--min {
    display: inline;
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
