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

  Tokens mirror mobile/src/ui/tokens.ts 1:1 so the site and the app are
  unmistakably the same product. Dark is the original 2026-07-08 palette;
  light is palette A "Cool slate", approved by Matea 2026-08-07.

  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
    - rose = actions (tap it), lavender = signals (read it), never swapped
    - the window mark's three colours are LOCKED and identical in both themes
*/

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

:root {
  color-scheme: dark;

  --bg: #131a23;
  --surface: #1c2530;
  --surface-raised: #242f3c;
  --border: #303c4a;
  --ink: #f2f6fa;
  --ink-muted: #96a7b8;

  --primary: #f27ba0;
  --primary-pressed: #f79dba;
  --on-primary: #421324;
  --signal: #b39dff;
  --signal-bg: #232033;

  --success: #43d9a3;
  --success-bg: #16281f;
  --danger: #ff7a6e;
  --danger-bg: #33201c;
  --pending: #ffc46b;
  --pending-bg: #2e2517;

  --tint-stone: #a8adb8;
  --tint-steel: #7fa3c9;

  /* Focus ring reads on both canvases without being an accent. */
  --focus: #b39dff;

  /* Interactive boundaries only (inputs, icon buttons, ghost buttons).
     --border stays the app'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.38:1 against the card it sits on, which is not.
     #63788D measures 3.39:1 on --surface and 3.84:1 on the field's own
     fill, so it clears 3:1 against both of its neighbours. */
  --control-border: #63788d;
}

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

  --bg: #eff3f7;
  --surface: #ffffff;
  --surface-raised: #e4eaf1;
  --border: #c9d4de;
  --ink: #16202b;
  --ink-muted: #4e6172;

  --primary: #b93d6e;
  --primary-pressed: #9c3059;
  --on-primary: #ffffff;
  --signal: #6a50c7;
  --signal-bg: #ece7fb;

  --success: #177a55;
  --success-bg: #dff3ea;
  --danger: #b3362b;
  --danger-bg: #fbe5e2;
  --pending: #8a5d00;
  --pending-bg: #f7ecd7;

  /* City tints deepened for a white surface, same hue family as the app. */
  --tint-stone: #5c6270;
  --tint-steel: #35618f;

  --focus: #6a50c7;

  /* 3.40:1 on --surface (white), 3.05:1 on the page canvas. */
  --control-border: #7e8d9c;
}

: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;
  }
}
