/* STRLL Landing Page. Design system per website/DESIGN.md. Follow your curiosity. Fonts: css/fonts.css */

:root {
  --bg: #F5F5F7;          /* page, never pure white */
  --surface: #FFFFFF;     /* cards, image frames */
  --ink: #1F2641;         /* navy: text, wordmark, dark surfaces */
  --ink-deep: #0D1129;    /* scrim and footer */
  --ink-muted: #5B6472;   /* secondary text, 5.6:1 on --bg */
  --accent: #00B1EA;      /* blue: ONLY primary action and active states. Text on it is always --ink */
  --accent-hover: #33C1EE;
  --mint: #71D0C5;        /* small accents: eyebrow on photos, markers, tags. Never a fill or button */
  --border: #E2E4EA;

  --font-display: 'Outfit', -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: 'Libre Franklin', -apple-system, BlinkMacSystemFont, sans-serif;

  /* 8px grid */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-5: 48px;
  --space-6: 64px;
  --space-7: 96px;
  --space-8: 128px;

  /* type scale 14 / 16 / 19 / 24 / 32 / 44 / 64 */
  --fs-14: 0.875rem;
  --fs-16: 1rem;
  --fs-19: 1.1875rem;
  --fs-24: 1.5rem;
  --fs-32: 2rem;
  --fs-44: 2.75rem;
  --fs-64: 4rem;
  /* hero headline only: the one deliberate step above the scale (decided 2026-10-13) */
  --fs-hero: clamp(3rem, 8.4vw, 5.5rem);

  --container-max: 1180px;

  --radius: 20px;
  --radius-pill: 999px;
  /* the only shadow: under elements that float over a photo (device frame, video panel) */
  --shadow-float: 0 8px 24px rgba(31, 38, 65, 0.10);
  --motion-reveal: 400ms cubic-bezier(0.22, 0.61, 0.36, 1);
  --motion-fast: 180ms ease;
}

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

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-16);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

h1, h2, h3, .lede { text-wrap: balance; }
h1, h2, h3 { font-family: var(--font-display); font-weight: 700; line-height: 1.1; margin: 0; color: var(--ink); }
h1 { font-size: clamp(2.5rem, 5.5vw, var(--fs-64)); font-weight: 800; }
h2 { font-size: clamp(var(--fs-32), 3.6vw, var(--fs-44)); }
h3 { font-size: var(--fs-24); line-height: 1.2; }
p { margin: 0; color: var(--ink); }
img { max-width: 100%; height: auto; }
a { color: inherit; }
.text-muted { color: var(--ink-muted); }

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  background: var(--ink);
  color: #fff;
  padding: var(--space-2) var(--space-3);
  z-index: 200;
  border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; }

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 3px;
}

.container {
  max-width: var(--container-max);
  margin: 0 auto;
  padding: 0 var(--space-3);
}
/* Left inset that matches where .container's own centering lands its content, so flush
   full-bleed blocks (hero below) align with container-wrapped sections instead of sitting
   at the viewport edge. Collapses to --space-3 once the viewport is narrower than --container-max. */
:root { --container-inset-left: max(var(--space-3), calc((100vw - var(--container-max)) / 2 + var(--space-3))); }

section { padding: var(--space-7) 0; }
section[id] { scroll-margin-top: 64px; }
@media (max-width: 640px) { section { padding: var(--space-6) 0; } }

.eyebrow {
  display: inline-block;
  font-size: var(--fs-14);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: var(--space-2);
}

.lede {
  font-size: var(--fs-19);
  line-height: 1.6;
  color: var(--ink-muted);
  max-width: 56ch;
}

/* Buttons. Text on the blue primary is ALWAYS navy (white on #00B1EA is 2.48:1). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 14px 28px;
  border-radius: var(--radius-pill);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-16);
  line-height: 1.3;
  text-decoration: none;
  border: 2px solid transparent;
  cursor: pointer;
  transition: background var(--motion-fast), border-color var(--motion-fast), color var(--motion-fast);
  min-height: 44px;
}
.btn-primary { background: var(--accent); color: var(--ink); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-glass {
  background: rgba(255, 255, 255, 0.14);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-color: rgba(255, 255, 255, 0.55);
  color: #fff;
}
.btn-glass:hover { background: rgba(255, 255, 255, 0.26); }
.btn-row { display: flex; align-items: center; gap: var(--space-2) var(--space-3); flex-wrap: wrap; }

/* Secondary text link next to a button; adapts to photo (white) or light (navy) surfaces */
.link-text {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-weight: 600;
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 5px;
  text-decoration-thickness: 2px;
  text-decoration-color: currentColor;
  transition: text-decoration-color var(--motion-fast);
}
.link-text:hover { text-decoration-color: var(--mint); }

/* Logo: compass mark (ring + needle from the app icon) as inline SVG, plus wordmark */
.logo { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; color: inherit; }
.logo svg { display: block; }
.logo-word { font-family: var(--font-display); font-weight: 800; font-size: var(--fs-24); letter-spacing: 0.04em; line-height: 1; }

/* Nav: transparent over the hero, solid once the page scrolls */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  color: #fff;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background var(--motion-fast), border-color var(--motion-fast), color var(--motion-fast);
}
.nav.is-scrolled {
  background: rgba(245, 245, 247, 0.94);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  border-bottom-color: var(--border);
  color: var(--ink);
}
.nav .container { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); padding-top: 12px; padding-bottom: 12px; }
.nav-menu { display: flex; align-items: center; gap: var(--space-4); }
.nav-links { display: flex; align-items: center; gap: var(--space-4); list-style: none; margin: 0; padding: 0; }
.nav-links a { text-decoration: none; font-weight: 600; font-size: var(--fs-14); color: inherit; }
.nav-links a:not(.btn):hover { text-decoration: underline; text-underline-offset: 5px; }
.nav-links .btn { font-size: var(--fs-14); padding: 10px 20px; min-height: 44px; color: var(--ink); }
.nav-lang { display: flex; gap: 4px; font-size: var(--fs-14); font-weight: 600; }
.nav-lang a { color: inherit; opacity: 0.75; text-decoration: none; padding: 8px; border-radius: 8px; }
.nav-lang a[aria-current="true"] { opacity: 1; }
.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  cursor: pointer;
}
.nav-toggle svg { display: block; }
.nav-toggle svg path { stroke: currentColor; }

@media (max-width: 960px) {
  .nav-menu {
    display: none;
    position: absolute;
    top: 100%;
    left: var(--space-2);
    right: var(--space-2);
    margin-top: 8px;
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-2);
    background: var(--surface);
    color: var(--ink);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: var(--space-3);
    box-shadow: var(--shadow-float);
  }
  .nav-menu.is-open { display: flex; }
  .nav-links { flex-direction: column; align-items: flex-start; gap: var(--space-1); }
  .nav-links a { font-size: var(--fs-16); display: inline-flex; align-items: center; min-height: 44px; }
  .nav-links .btn { margin-top: var(--space-1); }
  .nav-toggle { display: inline-flex; }
}

/* Scroll reveal: fade in + 12px up, 400ms. Content stays visible unless JS opts in
   (class reveal-ready on <html>), so no-JS, reduced motion and ?static=1 all show everything. */
.reveal-ready .reveal:not(.is-visible) { opacity: 0; transform: translateY(12px); }
.reveal-d1 { --reveal-delay: 120ms; }
.reveal-d2 { --reveal-delay: 240ms; }
.reveal-ready .reveal { transition: opacity var(--motion-reveal), transform var(--motion-reveal); transition-delay: var(--reveal-delay, 0ms); }

/* Hero: full-bleed photo, bottom-left copy, device frame on the right from 1024px up.
   Photo is enlarged to 125% and anchored left on desktop so the couple (43% from the left in the
   source) sits right of the text column instead of behind it. Mobile uses the portrait poster. */
.hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 100vh;
  min-height: 100svh;
  padding: 0;
  overflow: hidden;
  color: #fff;
}
.hero-bg { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
.hero-bg picture { display: block; width: 100%; height: 100%; }
.hero-bg img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; }
@media (min-width: 1024px) {
  .hero-bg img { width: 125%; max-width: none; object-position: 0% 70%; }
}
/* Almost no scrim: a bottom gradient under the copy and a light top fade for the nav.
   Darkening over a photo is the only gradient the page uses. */
.hero-scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(0deg, rgba(13,17,41,0.88) 0%, rgba(13,17,41,0.66) 28%, rgba(13,17,41,0) 58%),
    linear-gradient(180deg, rgba(13,17,41,0.84) 0%, rgba(13,17,41,0.7) 7%, rgba(13,17,41,0) 26%);
}
.hero-content {
  position: relative; z-index: 2;
  width: 100%;
  max-width: calc(620px + var(--container-inset-left));
  padding: 160px var(--space-3) var(--space-6) var(--container-inset-left);
}
.hero-content h1 { color: #fff; font-size: var(--fs-hero); max-width: 10ch; margin: 0 0 var(--space-3); }
.hero-content .lede { color: rgba(255, 255, 255, 0.92); margin: 0 0 var(--space-4); max-width: 44ch; }

/* Device: black bezel, real screenshot, cross-fade via .slideshow-bg (js/main.js).
   No CSS-drawn notch: the screenshots already show the real Dynamic Island. */
.device-bezel {
  position: relative;
  background: #0a0a0a;
  border-radius: 32px;
  padding: 8px;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.12), var(--shadow-float);
}
.device-screen {
  position: relative;
  border-radius: 24px;
  overflow: hidden;
  aspect-ratio: 1206 / 2622;
  background: #000;
}
.device-screen img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* Hero device: hidden below 1024px */
.hero-device-frame { display: none; }
@media (min-width: 1024px) {
  .hero-device-frame {
    display: block;
    position: absolute; z-index: 2;
    right: max(var(--space-3), calc((100vw - var(--container-max)) / 2 + var(--space-3)));
    top: 50%;
    transform: translateY(-42%);
    width: 210px;
  }
  .hero-device-frame .device-bezel { padding: 12px; border-radius: 42px; }
  .hero-device-frame .device-screen { border-radius: 32px; }
}
@media (min-width: 1280px) { .hero-device-frame { width: 248px; } }
/* Desktop hero is cropped to ~72% of the viewport so the first section peeks in; copy and phone sit on the middle line. */
@media (min-width: 1024px) {
  .hero { align-items: center; min-height: 620px; height: 72vh; height: 72svh; max-height: 780px; }
  .hero-content { padding-top: 96px; padding-bottom: var(--space-6); }
}

/* Slideshow: cross-fade between stacked images (js/main.js toggles .is-active) */
.slideshow-bg img { position: absolute; inset: 0; opacity: 0; transition: opacity 1800ms ease; }
.slideshow-bg img.is-active { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .slideshow-bg img { transition: none; } }

/* ---- Hero with intro video. Scoped to .hero--video so the photo hero is unaffected. ----
   Photo stays as background; after ~1.5s a 9:16 video panel pops out of it. Desktop: full-height panel on
   the right, photo dims. <1024px: video opens as a fullscreen overlay (nothing cropped), closable with the X.
   Swapping the device frame for the panel is a class on the hero, not a rebuild. */
.hero--video .hero-device-frame { display: none; }
.hero--video .hero-bg img {
  opacity: 1; filter: brightness(1); transition: opacity 700ms ease, filter 700ms ease, transform 220ms cubic-bezier(.3,0,.2,1);
}
.hero--video .hero-bg.is-punching img { transform: scale(1.04); }
.hero--video .hero-bg.is-playing img { opacity: 0.4; filter: brightness(0.6); }
.hero-video-panel {
  position: absolute; z-index: 2; top: 0; bottom: 0;
  /* mirrors .container centering so the right edges line up */
  right: max(var(--space-3), calc((100vw - var(--container-max)) / 2));
  height: 100%; aspect-ratio: 9 / 16; overflow: hidden; background: #000;
  box-shadow: var(--shadow-float);
  opacity: 0; transform: scale(0.1); transform-origin: 50% 55%;
  transition: opacity 460ms ease, transform 460ms cubic-bezier(.2,.85,.3,1.25);
}
.hero-video-panel.is-revealed { opacity: 1; transform: scale(1); }
.hero-video-panel video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* Browsers block unmuted autoplay: video starts muted, this button is the gesture that unlocks sound. */
.hero-video-sound {
  position: absolute; z-index: 3; left: 50%; bottom: 20px; transform: translateX(-50%);
  display: flex; align-items: center; gap: 6px;
  background: rgba(13,17,41,0.78); color: #fff; border: 1px solid rgba(255,255,255,0.3); border-radius: var(--radius-pill);
  padding: 10px 16px; min-height: 44px; font-family: var(--font-body); font-size: var(--fs-14); font-weight: 600;
  cursor: pointer; opacity: 0; pointer-events: none; transition: opacity 300ms ease;
}
.hero-video-panel.is-revealed .hero-video-sound { opacity: 1; pointer-events: auto; }
.hero-video-sound[data-unmuted] { border-color: var(--mint); }
.hero-video-close { display: none; }
@media (max-width: 1023px) {
  .hero--video .hero-bg.is-playing img { opacity: 1; filter: none; }
  .hero-video-panel {
    position: fixed; z-index: 1000; inset: 0; right: auto; width: 100%; height: 100dvh;
    aspect-ratio: auto; background: #000; box-shadow: none;
    transform: scale(0.6); transform-origin: 50% 35%; visibility: hidden; pointer-events: none;
    transition: opacity 400ms ease, transform 500ms cubic-bezier(.2,.85,.3,1), visibility 0s linear 500ms;
  }
  .hero-video-panel.is-revealed { transform: scale(1); visibility: visible; pointer-events: auto; transition-delay: 0s; }
  .hero-video-panel video { object-fit: contain; }
  .hero-video-sound { left: 16px; bottom: max(20px, env(safe-area-inset-bottom)); transform: none; }
  .hero-video-close {
    display: flex; align-items: center; justify-content: center;
    position: absolute; z-index: 3; top: max(16px, env(safe-area-inset-top)); right: 16px;
    width: 44px; height: 44px; border: 1px solid rgba(255,255,255,0.3); border-radius: 50%;
    background: rgba(13,17,41,0.78); color: #fff; font-size: 22px; line-height: 1; cursor: pointer;
  }
}
@media (prefers-reduced-motion: reduce) {
  .hero--video .hero-bg img, .hero-video-panel { transition: none; }
  .hero-video-panel { display: none; }
}
@media (max-width: 1023px) {
  /* Mobile hero: photo band on top (nothing covers the faces), headline and copy on navy below it,
     small phone with the rotating app screens to the right, bleeding ~32px off the edge.
     The headline's cap line sits on the top edge of the phone screen. */
  .hero {
    display: grid; grid-template-columns: minmax(0, 1fr) 100px; grid-template-rows: auto auto auto auto 1fr;
    column-gap: 14px; align-items: start;
    background: var(--ink-deep); min-height: 0; padding: 0 var(--space-3) 28px;
  }
  .hero-bg { position: relative; inset: auto; grid-column: 1 / -1; margin: 0 calc(var(--space-3) * -1); height: 36vh; height: 36svh; min-height: 270px; }
  .hero-bg img { object-position: 50% 20%; }
  .hero-scrim {
    inset: 0 0 auto 0; height: 36vh; height: 36svh; min-height: 270px;
    background: linear-gradient(180deg, rgba(13,17,41,0.8) 0%, rgba(13,17,41,0) 24%, rgba(13,17,41,0) 48%, rgba(13,17,41,1) 100%);
  }
  .hero-content { display: contents; }
  /* 42px, but shrinking on narrow screens so the first line ("Follow your", about 5.4em wide) always ends before the phone.
     The top margin compensates the cap offset (0.2em) so the cap line stays flush with the phone screen top. */
  .hero-content h1 {
    --hero-h1: min(42px, calc((100vw - 156px) / 5.4));
    grid-column: 1 / -1; grid-row: 2; font-size: var(--hero-h1);
    margin: calc(24px + 0.2 * (42px - var(--hero-h1))) 0 12px;
  }
  .hero-content .lede { grid-column: 1; font-size: 16px; line-height: 1.5; margin: 0 0 14px; }
  /* A longer label (German) wraps inside the text column instead of pushing the phone off the screen. */
  /* The button sits in the last row, its bottom edge flush with the bottom of the phone screen (7px bezel). */
  .hero-content .btn { grid-column: 1; grid-row: 5; align-self: end; margin-bottom: 7px; justify-self: start; max-width: 100%; font-size: 13px; line-height: 1.2; min-height: 44px; padding: 10px 14px; text-align: center; }
  .hero-device-frame {
    display: block; position: relative; z-index: 2; grid-column: 2; grid-row: 2 / span 4; justify-self: start;
    width: 156px; margin-top: 26px; margin-left: 8px;
  }
  .hero-device-frame .device-bezel { padding: 7px; border-radius: 26px; }
  .hero-device-frame .device-screen { border-radius: 20px; }
}

/* ---------- Sections ---------- */
.section-head { max-width: 760px; margin: 0 auto var(--space-6); text-align: center; }
.section-head h2 { margin-bottom: var(--space-2); }
.section-head .lede { margin: 0 auto; }
@media (max-width: 640px) { .section-head { margin-bottom: var(--space-5); } }

/* 2 Steps slideshow: one slide per step, left to right: photo, text, device frame with the app screenshot.
   Horizontal scroll-snap track = native swipe; js/main.js adds auto-advance and the step buttons and sets
   .is-ready. Without JS the slides simply stack and the buttons stay hidden. */
.steps-show { --step-gap: var(--space-5); --step-device-w: 208px; }
.steps-track { display: grid; gap: var(--space-7); }
.step-slide { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--step-device-w); gap: var(--step-gap); align-items: center; padding: 0 var(--space-3) var(--space-5) 0; }
/* Photo stretches to the height of the device frame, so every slide has the same frame */
.step-media { align-self: stretch; min-height: 320px; position: relative; border-radius: var(--radius); overflow: hidden; background: var(--border); }
.step-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.step-media--portrait img { object-position: 50% 30%; }
/* The device frame is the one floating element, so it carries the only shadow */
.step-device .device-bezel { padding: 10px; border-radius: 38px; }
.step-device .device-screen { border-radius: 28px; }
.step-num { font-family: var(--font-display); font-weight: 800; font-size: var(--fs-64); line-height: 1; color: var(--ink); display: block; }
.step-num::after { content: ""; display: block; width: 48px; height: 4px; margin: var(--space-2) 0 var(--space-3); background: var(--mint); border-radius: 2px; }
.step-text h3 { font-size: clamp(var(--fs-24), 2.6vw, var(--fs-32)); margin-bottom: var(--space-2); }
.step-text p { color: var(--ink-muted); font-size: var(--fs-19); max-width: 44ch; }

.steps-controls { display: none; }
.steps-show.is-ready .steps-track {
  display: flex; gap: 0; overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scrollbar-width: none;
}
.steps-show.is-ready .steps-track::-webkit-scrollbar { display: none; }
.steps-show.is-ready .step-slide { flex: 0 0 100%; scroll-snap-align: start; scroll-snap-stop: always; }
/* Same columns as the slides, so the buttons sit under the text column */
.steps-show.is-ready .steps-controls {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) var(--step-device-w); gap: var(--step-gap); margin-top: var(--space-2); padding-right: var(--space-3);
}
.steps-nav { grid-column: 2; display: flex; align-items: center; gap: var(--space-1); }
.steps-dot {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  border-radius: var(--radius-pill); border: 2px solid var(--border);
  background: var(--surface); color: var(--ink);
  font-family: var(--font-body); font-size: var(--fs-16); font-weight: 600; line-height: 1; cursor: pointer;
  transition: background var(--motion-fast), border-color var(--motion-fast);
}
.steps-dot:hover { border-color: var(--ink); }
/* Blue marks the active step only */
.steps-dot[aria-current="true"] { background: var(--accent); border-color: var(--accent); }
.steps-dot[aria-current="true"]:hover { background: var(--accent-hover); border-color: var(--accent-hover); }

@media (max-width: 1100px) {
  .steps-show { --step-gap: var(--space-3); --step-device-w: 184px; }
}
@media (max-width: 860px) {
  /* Photo on top, below it text left and device frame right in one row */
  .steps-show { --step-gap: var(--space-2); --step-device-w: 144px; }
  .step-slide { grid-template-columns: minmax(0, 1fr) var(--step-device-w); align-items: start; row-gap: var(--space-3); padding: 0 var(--space-1) var(--space-3) 0; }
  .step-media { grid-column: 1 / -1; align-self: auto; min-height: 0; aspect-ratio: 16 / 10; }
  .step-device .device-bezel { padding: 6px; border-radius: 24px; }
  .step-device .device-screen { border-radius: 18px; }
  .step-num { font-size: var(--fs-44); }
  .step-num::after { margin: var(--space-1) 0 var(--space-2); }
  .step-text h3 { font-size: var(--fs-19); margin-bottom: var(--space-1); }
  .step-text p { font-size: var(--fs-16); }
  .steps-show.is-ready .steps-controls { grid-template-columns: 1fr; padding-right: 0; }
  .steps-nav { grid-column: 1; }
}

/* Photo layers shared by the pre-registration band (.waitlist) */
.bleed-bg { position: absolute; inset: 0; z-index: 0; }
.bleed-bg img { width: 100%; height: 100%; object-fit: cover; display: block; }
.bleed-scrim { position: absolute; inset: 0; z-index: 1; }

/* 4 Gallery: one row of equal photo tiles, 3 visible (2 on tablets, 1 plus a slice of the next on phones).
   Same mechanics as the steps slideshow: scroll-snap track, native swipe, js/main.js adds auto-advance and the
   prev/next buttons and sets .is-ready. Without JS it stays a plain scrollable row. The track clips inside the
   container on tablet and desktop and runs to the viewport edges on phones so the next tile peeks out. */
.gallery { --tile-gap: var(--space-2); --tile-w: calc((100% - 2 * var(--tile-gap)) / 3); }
.gallery-track {
  list-style: none; margin: 0; padding: 0; display: flex; gap: var(--tile-gap);
  overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory; scrollbar-width: none;
}
.gallery-track::-webkit-scrollbar { display: none; }
.gallery-track:focus-visible { outline-offset: 4px; border-radius: var(--radius); }
.tile { position: relative; flex: 0 0 var(--tile-w); aspect-ratio: 4 / 5; margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--ink); scroll-snap-align: start; }
.tile img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.tile-caption { position: absolute; left: 0; right: 0; bottom: 0; z-index: 1; padding: var(--space-6) var(--space-3) var(--space-3); color: #fff; background: linear-gradient(0deg, rgba(13,17,41,0.92) 0%, rgba(13,17,41,0.84) 55%, rgba(13,17,41,0) 100%); }
.tile-caption h3 { color: #fff; font-size: var(--fs-24); margin-bottom: 4px; }
.tile-caption p { color: rgba(255,255,255,0.92); font-size: var(--fs-16); line-height: 1.4; }
.gallery-controls { display: none; }
.gallery.is-ready .gallery-controls { display: flex; justify-content: center; gap: var(--space-2); margin-top: var(--space-3); }
.gallery-btn {
  position: relative; width: 44px; height: 44px; padding: 0; cursor: pointer;
  border-radius: 50%; border: 2px solid var(--border); background: var(--surface); color: var(--ink);
  transition: border-color var(--motion-fast);
}
.gallery-btn:hover { border-color: var(--ink); }
/* Chevron drawn with borders, no icon set */
.gallery-btn::before {
  content: ""; position: absolute; top: 50%; left: 50%; width: 10px; height: 10px;
  border: solid currentColor; border-width: 0 2px 2px 0;
}
.gallery-btn--prev::before { transform: translate(-30%, -50%) rotate(135deg); }
.gallery-btn--next::before { transform: translate(-70%, -50%) rotate(-45deg); }
@media (max-width: 1023px) {
  .gallery { --tile-w: calc((100% - var(--tile-gap)) / 2); }
}
@media (max-width: 640px) {
  /* 76% of the container width (viewport minus both page margins) */
  .gallery { --tile-w: calc((100vw - 2 * var(--space-3)) * 0.76); }
  .gallery-track { margin: 0 calc(var(--space-3) * -1); padding: 0 var(--space-3); scroll-padding-left: var(--space-3); }
}

/* 5 Pre-registration: photo band with a form card floating on it */
.waitlist { position: relative; display: flex; align-items: center; min-height: 90vh; padding: var(--space-7) 0; overflow: hidden; }
.waitlist .bleed-bg img { object-position: 50% 40%; }
.waitlist .bleed-scrim { background: linear-gradient(0deg, rgba(13,17,41,0.55) 0%, rgba(13,17,41,0.35) 100%); }
.waitlist .container { position: relative; z-index: 2; display: flex; justify-content: flex-end; }
.form-card { background: var(--surface); color: var(--ink); border-radius: var(--radius); padding: var(--space-5); width: 100%; max-width: 520px; box-shadow: var(--shadow-float); }
.form-card .eyebrow { margin-bottom: var(--space-1); }
.form-card h2 { margin-bottom: var(--space-2); }
.form-card > p { color: var(--ink-muted); margin-bottom: var(--space-4); }
.field { display: grid; gap: 6px; margin-bottom: var(--space-3); }
.field label { font-weight: 600; font-size: var(--fs-14); }
.field input {
  min-height: 48px; padding: 10px 14px; font: inherit; color: var(--ink);
  background: var(--bg); border: 1px solid #8A92A3; border-radius: 12px; width: 100%;
}
.field input:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; border-color: var(--ink); }
/* Platform choice: two equal radio options, native radios kept (visually hidden, still focusable) */
.field-choice { border: 0; padding: 0; margin: 0 0 var(--space-3); min-width: 0; }
.field-choice legend { padding: 0; margin-bottom: 6px; font-weight: 600; font-size: var(--fs-14); }
.choice-row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-1); }
.choice { position: relative; display: block; cursor: pointer; }
.choice input { position: absolute; opacity: 0; inset: 0; width: 100%; height: 100%; margin: 0; cursor: pointer; }
.choice span {
  display: flex; align-items: center; justify-content: center; gap: 10px; min-height: 48px; padding: 10px 12px;
  font-weight: 600; color: var(--ink); background: var(--bg);
  border: 1px solid #8A92A3; border-radius: 12px; transition: border-color var(--motion-fast), box-shadow var(--motion-fast);
}
/* Radio mark: empty ring, filled ring with a check when selected (shape change, not colour alone) */
.choice span::before { content: ""; flex: 0 0 18px; width: 18px; height: 18px; box-sizing: border-box; border: 2px solid #8A92A3; border-radius: 50%; }
.choice:hover span { border-color: var(--ink); }
.choice input:checked + span { border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); background: var(--surface); }
.choice input:checked + span::before {
  border-color: var(--ink); background: var(--ink);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 14 14'%3E%3Cpath d='M3 7.5l2.8 2.8L11 4.5' fill='none' stroke='%23fff' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-size: 100% 100%;
}
.choice input:focus-visible + span { outline: 3px solid var(--accent); outline-offset: 2px; }
.field-choice[aria-invalid="true"] .choice span { border-color: #A3281C; }
.field .hint { color: var(--ink-muted); font-weight: 400; }
/* Honeypot: off-screen for sighted users, hidden from assistive tech (aria-hidden in markup) */
.hp { position: absolute !important; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form-card .btn { width: 100%; }
.btn[disabled] { opacity: 0.65; cursor: not-allowed; }
.form-msg { font-weight: 600; margin: 0; }
.form-msg:not(:empty) { margin-top: var(--space-2); }
.form-msg--error { color: #A3281C; }
.form-note { margin-top: var(--space-3); font-size: var(--fs-14); color: var(--ink-muted); line-height: 1.5; }
.form-note a { color: var(--ink); text-underline-offset: 3px; }
@media (max-width: 760px) {
  .waitlist { min-height: 0; padding: var(--space-6) 0; }
  .waitlist .container { justify-content: center; }
  .form-card { padding: var(--space-3); }
}

/* Footer: brand block plus link columns, copyright line below. Structure and proportions after TSTE. */
.footer { background: var(--ink-deep); color: rgba(255,255,255,0.82); padding: var(--space-6) 0 var(--space-4); }
.footer-grid { display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-6); }
.footer-brand { max-width: 320px; display: flex; flex-direction: column; gap: var(--space-2); }
.footer .logo { color: #fff; }
.footer-brand p { color: rgba(255,255,255,0.82); font-size: var(--fs-16); line-height: 1.5; }
.footer-cols { display: flex; flex-wrap: wrap; gap: var(--space-6); flex: 1; justify-content: flex-end; }
.footer-col { display: flex; flex-direction: column; min-width: 160px; }
.footer-title { margin: 0 0 var(--space-1); font-size: var(--fs-14); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--mint); }
.footer-col a { display: flex; align-items: center; min-height: 44px; color: inherit; text-decoration: none; font-size: var(--fs-16); }
.footer-col a:hover { color: #fff; text-decoration: underline; text-underline-offset: 4px; }
.footer-bottom { margin-top: var(--space-5); }
.footer-copy { padding-top: var(--space-3); border-top: 1px solid rgba(255,255,255,0.16); font-size: var(--fs-14); color: rgba(255,255,255,0.82); }
@media (max-width: 640px) {
  .footer-grid, .footer-cols { flex-direction: column; gap: var(--space-4); }
  .footer-cols { justify-content: flex-start; }
}

/* 3 Cities: Europe map (Natural Earth 50m, public domain, images/europe.svg) with one pin per city.
   Ported from the TSTE city section: faint photo, copy left, map right, polaroid card that follows
   the active pin. Pin positions are generated from each city's coordinates (same Mercator
   projection as the map) and live at the end of this block. */
.city-section { position: relative; overflow: hidden; }
.city-section-bg { position: absolute; inset: 0; z-index: 0; }
.city-section-bg img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 40%; display: block; }
/* Navy scrim over the photo: the only gradient allowed besides the hero (darkening over a photo). Darkest where the white copy sits. */
.city-section-bg::after { content: ""; position: absolute; inset: 0; background: linear-gradient(90deg, rgba(13,17,41,0.88) 0%, rgba(13,17,41,0.76) 55%, rgba(13,17,41,0.62) 100%); }
.city-section .container { position: relative; z-index: 1; }
.city-grid { display: grid; grid-template-columns: 1fr 1.05fr; gap: var(--space-6); align-items: center; }
.city-copy h2 { margin-bottom: var(--space-2); color: #fff; }
.city-copy .lede { margin-bottom: var(--space-4); color: rgba(255, 255, 255, 0.92); }
.city-map-wrap { width: 100%; max-width: 540px; justify-self: end; }
.city-stage { position: relative; }
.city-map { position: relative; width: 100%; aspect-ratio: 1000 / 1189.3; }
.city-map-svg { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
/* The map is cut out of the frame (land only). Land that runs into the frame edge (Russia, Turkey) fades out
   instead of ending in a hard line. */
.city-map-svg {
  -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 76%, transparent 98%), linear-gradient(180deg, #000 0%, #000 84%, transparent 99%);
  mask-image: linear-gradient(90deg, #000 0%, #000 76%, transparent 98%), linear-gradient(180deg, #000 0%, #000 84%, transparent 99%);
  -webkit-mask-composite: source-in; mask-composite: intersect;
}
.city-pin {
  all: unset; position: absolute; z-index: 1; width: 24px; height: 24px;
  margin: -12px 0 0 -12px; /* centre the dot on the geographic coordinate */
  cursor: pointer; border-radius: 50%;
}
.city-pin-dot {
  position: absolute; left: 50%; top: 50%; width: 10px; height: 10px; margin: -5px 0 0 -5px;
  border-radius: 50%; background: #fff; box-shadow: 0 0 0 2px var(--ink);
  transition: background var(--motion-fast), width var(--motion-fast), height var(--motion-fast), margin var(--motion-fast);
}
.city-pin-ring {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  width: 24px; height: 24px; border-radius: 50%; background: var(--accent); opacity: 0;
}
.city-pin.is-active { z-index: 3; }
.city-pin.is-active .city-pin-dot { width: 14px; height: 14px; margin: -7px 0 0 -7px; background: var(--accent); box-shadow: 0 0 0 2px #fff, 0 0 0 3px var(--ink); }
.city-pin.is-active .city-pin-ring { animation: city-pin-pulse 2200ms ease-out infinite; }
@keyframes city-pin-pulse {
  0% { opacity: 0.4; transform: translate(-50%, -50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) scale(2.4); }
}
@media (prefers-reduced-motion: reduce) { .city-pin-ring { animation: none !important; } }
.city-pin:hover, .city-pin:focus-visible { z-index: 4; }
.city-pin:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
/* Label only for the active pin and on hover/focus */
.city-pin-label {
  display: none; position: absolute; top: 50%; transform: translateY(-50%); white-space: nowrap; pointer-events: none;
  font-size: var(--fs-14); font-weight: 600; line-height: 1; color: #fff; background: var(--ink); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.55);
  padding: 6px 10px; border-radius: var(--radius-pill);
}
.city-pin.is-active .city-pin-label, .city-pin:hover .city-pin-label, .city-pin:focus-visible .city-pin-label { display: block; }
.city-pin-label.label-right, .label-right .city-pin-label { left: calc(100% + 2px); }
.label-left .city-pin-label { right: calc(100% + 2px); }

/* Photo card, polaroid style, lying on the ocean top left of the map. The only shadow on the page
   besides device frames (it floats over the map). */
.city-card {
  position: absolute; left: -3%; top: 0; z-index: 5; width: 200px;
  background: var(--surface); padding: 10px 10px 14px; border-radius: 12px;
  box-shadow: var(--shadow-float); transform: rotate(-3deg); transform-origin: center top;
}
.city-card-img { display: block; width: 100%; aspect-ratio: 560 / 500; object-fit: cover; border-radius: 6px; background: var(--border); }
.city-card.is-revealing { animation: city-polaroid-drop 480ms cubic-bezier(0.22, 0.61, 0.36, 1); }
@keyframes city-polaroid-drop {
  0% { opacity: 0; transform: translateY(-22px) rotate(3deg) scale(0.94); }
  100% { opacity: 1; transform: translateY(0) rotate(-3deg) scale(1); }
}
@media (prefers-reduced-motion: reduce) { .city-card.is-revealing { animation: none !important; } }
.city-card-label { display: grid; gap: 2px; margin-top: 10px; }
.city-card-name { font-family: var(--font-display); font-weight: 700; font-size: var(--fs-19); line-height: 1.2; color: var(--ink); }
.city-card-country, .city-card-count { font-size: var(--fs-14); color: var(--ink-muted); line-height: 1.3; }
.city-card-count { font-weight: 600; color: var(--ink); }
@media (max-width: 900px) {
  /* copy spans the full width here, so the scrim is flat and dark everywhere */
  .city-section-bg::after { background: rgba(13, 17, 41, 0.8); }
  .city-grid { grid-template-columns: 1fr; gap: var(--space-5); }
  .city-map-wrap { justify-self: center; max-width: 560px; }
  /* card leaves the map and sits below it */
  .city-card { position: relative; left: auto; top: auto; width: 220px; margin: var(--space-4) auto 0; }
}

/* Per-pin position: percent of the map box, generated from lat/lon */
.p-amsterdam { left: 27.9%; top: 62.4%; }
.p-antalya { left: 73.18%; top: 94.76%; }
.p-antwerp { left: 27.02%; top: 65.13%; }
.p-athens { left: 60.93%; top: 92.74%; }
.p-barcelona { left: 23.1%; top: 86.21%; }
.p-bari { left: 48.9%; top: 86.74%; }
.p-basel { left: 32.61%; top: 73.43%; }
.p-berlin { left: 42.82%; top: 62.03%; }
.p-bratislava { left: 49.31%; top: 72.14%; }
.p-brussels { left: 26.93%; top: 66.0%; }
.p-budapest { left: 52.7%; top: 73.57%; }
.p-gdansk { left: 52.01%; top: 57.49%; }
.p-dublin { left: 8.32%; top: 60.0%; }
.p-dubrovnik { left: 51.04%; top: 83.7%; }
.p-edinburgh { left: 13.7%; top: 53.35%; }
.p-florence { left: 39.05%; top: 81.44%; }
.p-hamburg { left: 36.83%; top: 59.5%; }
.p-heidelberg { left: 34.51%; top: 69.34%; }
.p-helsinki { left: 63.05%; top: 41.58%; }
.p-heraklion { left: 63.41%; top: 97.6%; }
.p-innsbruck { left: 39.31%; top: 74.07%; }
.p-istanbul { left: 70.14%; top: 86.95%; }
.p-copenhagen { left: 41.35%; top: 54.08%; }
.p-krakow { left: 54.29%; top: 67.82%; }
.p-lisbon { left: 3.26%; top: 91.35%; }
.p-london { left: 19.07%; top: 64.45%; }
.p-luebeck { left: 38.05%; top: 58.71%; }
.p-madrid { left: 12.8%; top: 88.11%; }
.p-milan { left: 35.42%; top: 77.93%; }
.p-malaga { left: 11.54%; top: 95.08%; }
.p-marbella { left: 10.73%; top: 95.47%; }
.p-munich { left: 39.62%; top: 72.17%; }
.p-murcia { left: 17.31%; top: 92.72%; }
.p-naples { left: 44.33%; top: 87.26%; }
.p-oslo { left: 38.16%; top: 42.34%; }
.p-paris { left: 23.42%; top: 70.56%; }
.p-pisa { left: 37.55%; top: 81.53%; }
.p-porto { left: 4.16%; top: 86.66%; }
.p-prague { left: 44.63%; top: 67.8%; }
.p-rome { left: 41.22%; top: 85.19%; }
.p-segovia { left: 12.09%; top: 87.08%; }
.p-seville { left: 8.8%; top: 93.85%; }
.p-split { left: 48.14%; top: 81.97%; }
.p-stockholm { left: 51.0%; top: 44.04%; }
.p-strasbourg { left: 32.9%; top: 71.2%; }
.p-stuttgart { left: 35.41%; top: 70.74%; }
.p-valencia { left: 18.64%; top: 89.93%; }
.p-venice { left: 40.9%; top: 77.97%; }
.p-verona { left: 38.58%; top: 77.98%; }
.p-warsaw { left: 56.16%; top: 62.73%; }
.p-vienna { left: 48.02%; top: 72.01%; }
.p-zurich { left: 34.28%; top: 73.83%; }
