/* ==========================================================================
   RouteFeed — the website in the app's own chrome (2026-09-12)

   Every value here is an app token, so the site and the app read as one
   product (route_feed/lib/core/theme/*): the light palette from AppColors,
   the floating surface from FloatingChromeSurface (surface at the frosted
   opacity, hairline border, pill radius, AppShadows.floating), radii from
   AppRadii (12 / 18 / 26 / pill), the type scale from AppTextStyles.

   Colour discipline (APP_IDEA § Color Discipline): teal is discovery and
   trust, purple the expressive secondary, the teal→purple sweep only on
   brand moments (the wordmark's "o", the one hero button); coral ONLY on
   the working Go. Brand colours never paint the map itself.

   Two type voices, as in the app: Space Grotesk for everything (display,
   body, controls); Fraunces italic only where the app uses it — place
   names and the tagline.

   THE STAGE: the hero and the tour are ONE block over ONE sticky map. The
   hero is the first screen; from the first stop on, the same map is
   clipped into a rounded frame on the left (a clip-path animation, no
   re-rendering), the phone rises on the right and the stops scroll past
   in the middle, one screen each. js/hero-map.js flips
   .stage[data-state] between "hero" and "tour"; js/main.js pages one stop
   per wheel gesture while the stage is on screen.
   ========================================================================== */

:root {
  --base: #F8FAFC;           /* AppColors.lightBase */
  --surface: #FFFFFF;        /* AppColors.lightSurface */
  --elevated: #EDF2F8;       /* AppColors.lightElevatedSurface */
  --primary: #0D9488;        /* AppColors.lightPrimary */
  --secondary: #7C3AED;      /* AppColors.lightSecondary */
  --go: #E14B75;             /* AppColors.lightAction — the one coral */
  --text: #14202A;           /* AppColors.lightTextPrimary */
  --text-2: #5B6B7E;         /* AppColors.lightTextSecondary */
  --border: #D8E1EC;         /* AppColors.lightBorder */
  --sweep: linear-gradient(135deg, var(--primary), var(--secondary)); /* OrbPainting: top-left teal → bottom-right purple */
  --glass: rgba(255, 255, 255, 0.8);     /* surface at AppOpacities.glassChrome (panels) */
  --frosted: rgba(255, 255, 255, 0.94);  /* surface at AppOpacities.frosted (controls) */
  --glass-veil: rgba(255, 255, 255, 0.6); /* AppOpacities.glassVeil */
  --shadow-floating: 0 1px 3px rgba(0, 0, 0, 0.08), 0 8px 18px rgba(0, 0, 0, 0.12); /* AppShadows.floating */
  --shadow-dock: 0 2px 4px rgba(0, 0, 0, 0.09), 0 12px 24px rgba(0, 0, 0, 0.16);    /* AppShadows.dock */
  --halo: 0 0 14px rgba(13, 148, 136, 0.3); /* AppGlows.halo: primary at navOrbHalo 0.3, chromeGlowBlur 14 */
  --r-small: 12px;           /* AppRadii.small */
  --r-medium: 18px;          /* AppRadii.medium */
  --r-large: 26px;           /* AppRadii.large */
  --r-pill: 999px;           /* AppRadii.pill */
  --night-base: #0A101F;     /* AppColors.darkCinemaBase */
  --night-scrim: #060A14;    /* AppColors.darkCinemaScrim */
  --night-glass: rgba(13, 20, 36, 0.8); /* darkGlass at glassChrome */
  --night-text: #F2F5F4;     /* AppColors.darkTextPrimary */
  --night-text-2: #94A3B8;   /* AppColors.darkTextSecondary */
  --night-primary: #14BBA6;  /* AppColors.darkPrimary */
  --sans: "Space Grotesk", system-ui, -apple-system, sans-serif;
  --serif: "Fraunces", Georgia, serif;
  --gutter: clamp(20px, 4vw, 56px);
  --bar-h: 64px;
  --wrap: 1180px;           /* widened at 1600 / 1900 / 2400 px below */
  --ease-out: cubic-bezier(0.2, 0.8, 0.2, 1);
  --morph: 0.8s;            /* the hero → tour shrink */
  color-scheme: light;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
[hidden] { display: none !important; }
html { scroll-behavior: smooth; }
html.is-snapping { scroll-snap-type: y mandatory; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--base);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

a { color: inherit; text-decoration: none; }
p a, .credit a { text-decoration: underline; text-underline-offset: 3px; text-decoration-color: var(--border); }
p a:hover, .credit a:hover { text-decoration-color: currentColor; }
img { max-width: 100%; display: block; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; border-radius: 4px; }
.maplibregl-canvas:focus { outline: none; }
.maplibregl-canvas:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }
.maplibregl-canvas-container.maplibregl-interactive { cursor: default; }
[id] { scroll-margin-top: var(--bar-h); }

/* Shared pieces --------------------------------------------------------- */
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 var(--gutter); }

/* The floating surface: FloatingChromeSurface, translated. */
.glass {
  background: var(--glass);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-floating);
}

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  height: 30px;
  padding: 0 12px;
  border-radius: var(--r-pill);
  background: var(--surface);
  border: 1px solid var(--border);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-2);
  white-space: nowrap;
}
.chip__dot { width: 7px; height: 7px; border-radius: 50%; background: var(--primary); box-shadow: var(--halo); }

/* Pill buttons: the app's control shape (pill radius, 44px tall). */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  height: 44px;
  padding: 0 22px;
  border-radius: var(--r-pill);
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.01em;
  transition: transform 0.15s ease, box-shadow 0.15s ease, filter 0.15s ease;
  white-space: nowrap;
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: none; }
/* The one brand-sweep button on the page (a hero CTA is a sanctioned
   gradient moment). */
.btn--sweep { background: var(--sweep); color: #fff; box-shadow: var(--shadow-floating); }
.btn--sweep:hover { filter: brightness(1.06); }
.btn--sweep.is-on { background: var(--surface); color: var(--text); border: 1px solid var(--border); }
/* Coral is the app's Go and nothing else: this button, and its picture
   inside the phone (.phone__route). */
.btn--go { background: var(--go); color: #fff; min-width: 108px; }
.btn--go:hover { filter: brightness(1.05); }

.eyebrow {
  display: inline-block;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--primary);
  margin-bottom: 14px;
}
.h1 {
  font-weight: 700;
  font-size: clamp(34px, 4.6vw, 60px);
  line-height: 1.02;
  letter-spacing: -0.035em;
  text-wrap: balance;
}
.credit { font-size: 12px; line-height: 1.4; color: var(--text-2); }

/* --------------------------------------------------------------------------
   Top bar — floating over everything, the app's frosted chrome
   -------------------------------------------------------------------------- */
.bar {
  position: sticky;
  top: 0;
  z-index: 50;
  height: var(--bar-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 var(--gutter);
  background: var(--frosted);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}
.wordmark {
  display: inline-flex;
  align-items: center;
  font-weight: 700;
  font-size: 21px;
  letter-spacing: -0.02em;
  line-height: 1;
  white-space: nowrap;
}
/* The Waypoint O (decision 0002): the earth orb wearing the route ring is
   the wordmark's "o". */
.wordmark__o { display: inline-block; height: 1.14em; width: auto; margin: 0 -0.06em 0 -0.02em; transform: translateY(0.02em); }
.wordmark--small { font-size: 18px; }
/* The one link in the bar: a quiet byline in the app's secondary ink. */
.bar__by { font-size: 14px; font-weight: 600; color: var(--text-2); white-space: nowrap; transition: color 0.15s ease; }
.bar__by:hover { color: var(--text); }
.bar__by span { display: inline-block; margin-left: 2px; transition: transform 0.15s ease; }
.bar__by:hover span { transform: translate(1px, -1px); }

/* --------------------------------------------------------------------------
   The stage — one sticky map; the hero, then the tour
   -------------------------------------------------------------------------- */
.stage {
  --stage-text: clamp(240px, 24vw, 420px);
  --stage-phone: clamp(220px, 16vw, 360px);
  --stage-gap: clamp(28px, 3vw, 64px);
  --frame-inset: 24px;
  /* the frame's right edge: gutter + phone column + gap + text column + gap */
  --frame-right: calc(var(--gutter) + var(--stage-phone) + var(--stage-gap) + var(--stage-text) + var(--stage-gap));
  position: relative;
  background: var(--base);
  scroll-snap-align: start;
}
.stage__sticky {
  position: sticky;
  top: var(--bar-h);
  height: calc(100vh - var(--bar-h));
  height: calc(100svh - var(--bar-h));
  overflow: hidden;
  z-index: 1;
  background: var(--elevated);
}
/* The map: full screen in the hero; clipped into the frame in the tour.
   Animating a clip-path costs nothing — the canvas itself never resizes;
   js/hero-map.js gives the map padding instead so the camera centres in
   the visible part. */
.stage__map {
  position: absolute;
  inset: 0;
  opacity: 0;
  clip-path: inset(0 0 0 0 round 0);
  transition: opacity 0.7s ease, clip-path var(--morph) var(--ease-out);
}
.stage__map.is-ready { opacity: 1; }
.stage[data-state="tour"] .stage__map {
  clip-path: inset(var(--frame-inset) var(--frame-right) var(--frame-inset) var(--gutter) round var(--r-large));
}
/* The frame's edge and shadow (a clip cannot cast one). */
.stage__frame {
  position: absolute;
  z-index: 2;
  top: var(--frame-inset);
  bottom: var(--frame-inset);
  left: var(--gutter);
  right: var(--frame-right);
  border-radius: var(--r-large);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-dock);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease 0.35s;
}
.stage[data-state="tour"] .stage__frame { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .stage__map, .stage__frame, .panel, .tour__head, .tour__phone, .credit--map, .chapter__body { transition: none !important; }
}
.plate-hero__fallback {
  position: absolute; left: var(--gutter); top: 24px; z-index: 3;
  display: none; padding: 10px 14px; border-radius: var(--r-small);
  font-size: 14px; color: var(--text-2);
}
.stage.is-failed .plate-hero__fallback { display: block; }

/* Hero layer ------------------------------------------------------------ */
.panel {
  position: absolute;
  z-index: 3;
  left: var(--gutter);
  bottom: clamp(56px, 8vh, 96px);
  width: min(560px, calc(100% - 2 * var(--gutter)));
  padding: 30px 32px 28px;
  border-radius: var(--r-large);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.panel .chip { margin-bottom: 18px; }
.panel .h1 { margin-bottom: 16px; }
.panel__lead { font-size: 17px; line-height: 1.5; color: var(--text-2); max-width: 46ch; margin-bottom: 22px; }
.panel__actions { display: flex; align-items: center; flex-wrap: wrap; gap: 12px 18px; }
.panel__pos {
  display: inline-flex; align-items: center; gap: 10px;
  font-size: 13px; font-weight: 600; color: var(--text-2);
  font-variant-numeric: tabular-nums;
}
.panel__pos span + span::before { content: "·"; margin-right: 10px; color: var(--border); }
/* Explore mode: the panel folds down to the button and the live position. */
.stage.is-exploring .panel { width: auto; padding: 14px 16px; border-radius: var(--r-medium); bottom: clamp(44px, 6vh, 72px); }
.stage.is-exploring .panel .chip,
.stage.is-exploring .panel .h1,
.stage.is-exploring .panel__lead { display: none; }
.stage.is-exploring .panel__actions { gap: 12px 14px; }
/* The tour: the panel steps off. */
.stage[data-state="tour"] .panel { opacity: 0; transform: translateY(24px); pointer-events: none; }

/* The map's credit is a licence requirement. It rides in the map's corner
   as the app's collapsible control: a 26px glass (i) that opens to the
   full line on tap, and on hover where there is a pointer. The full line
   also stands in the footer, never collapsed. Screen corner in the hero,
   frame corner in the tour. */
.credit--map {
  position: absolute; z-index: 3; right: 12px; bottom: 12px; max-width: calc(100% - 24px);
  display: flex; align-items: center; gap: 8px;
  padding: 0; border-radius: var(--r-pill); background: var(--glass);
  -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  box-shadow: 0 0 0 1px var(--border);
  transition: right var(--morph) var(--ease-out), bottom var(--morph) var(--ease-out), background 0.6s ease, color 0.6s ease;
}
.credit__toggle {
  flex: none; width: 26px; height: 26px; border-radius: 50%;
  display: grid; place-items: center;
  font-family: var(--serif); font-style: italic; font-weight: 600; font-size: 15px; line-height: 1;
  color: var(--text); background: transparent;
}
.credit__text { display: none; padding: 0 0 0 12px; white-space: nowrap; }
.credit--map.is-open .credit__text { display: inline; }
@media (hover: hover) { .credit--map:hover .credit__text { display: inline; } }
.stage[data-state="tour"] .credit--map { right: calc(var(--frame-right) + 12px); bottom: calc(var(--frame-inset) + 12px); }

/* The place sheet — the app's detail sheet, as a floating card ------------ */
.sheet {
  position: absolute;
  z-index: 4;
  right: var(--gutter);
  bottom: clamp(56px, 8vh, 96px);
  width: min(400px, calc(100% - 2 * var(--gutter)));
  min-height: min(600px, calc(100% - 120px)); /* the app's sheet is a tall card, not a tooltip */
  max-height: calc(100% - 120px);
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-large);
  box-shadow: var(--shadow-dock);
  transform: translateY(14px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s ease, transform 0.22s ease;
}
.sheet.is-open { opacity: 1; transform: none; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .sheet { transition: none; } }
.sheet__head { display: flex; align-items: center; justify-content: space-between; padding: 14px 14px 0 22px; }
.sheet__eyebrow { font-size: 12px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; color: var(--primary); }
.sheet__close {
  width: 42px; height: 42px; border-radius: 50%; /* AppLayout.floatingControlSize */
  background: var(--elevated); color: var(--text-2); font-size: 22px; line-height: 1;
}
.sheet__close:hover { color: var(--text); }
.sheet__body { flex: 1; display: flex; flex-direction: column; padding: 8px 22px 22px; overflow: auto; transition: opacity 0.16s ease; }
.sheet.is-swapping .sheet__body { opacity: 0; }
.sheet__name {
  font-family: var(--serif); /* AppTextStyles.placeHeadline: Fraunces 600 28 */
  font-weight: 600; font-size: 27px; line-height: 1.15; letter-spacing: -0.3px;
  margin-bottom: 4px; text-wrap: balance;
}
.sheet__name:focus { outline: none; }
.sheet__meta { font-size: 13px; color: var(--text-2); margin-bottom: 12px; }
/* The reel strip: a row of 9:16 cards under the name, as the app's sheet
   carries a place's videos. With none yet, the first card is the app's
   own empty state and the rest shimmer like slots waiting to fill. */
.sheet__reels { margin-bottom: 14px; }
.sheet__reelhead { font-size: 12px; font-weight: 700; letter-spacing: 0.02em; margin-bottom: 8px; }
.sheet__reelhead span { color: var(--text-2); font-weight: 500; letter-spacing: 0; }
.sheet__reel { display: flex; gap: 8px; overflow-x: auto; scroll-snap-type: x mandatory; scrollbar-width: none; }
.sheet__reel::-webkit-scrollbar { display: none; }
.reel-card {
  flex: 0 0 104px; aspect-ratio: 9 / 16;
  border-radius: var(--r-medium);
  scroll-snap-align: start;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 8px; padding: 10px; text-align: center;
}
.reel-card--first { border: 1.5px dashed var(--border); color: var(--text-2); font-size: 12px; line-height: 1.35; font-weight: 600; }
.reel-card__play {
  width: 34px; height: 34px; border-radius: 50%;
  display: grid; place-items: center; padding-left: 2px;
  background: rgba(13, 148, 136, 0.12); color: var(--primary); font-size: 12px;
}
.reel-card--ghost {
  background: linear-gradient(110deg, var(--elevated) 30%, var(--surface) 45%, var(--elevated) 60%);
  background-size: 220% 100%;
  animation: reel-shimmer 1.8s linear infinite;
}
.reel-card--ghost::after { content: "▶"; color: var(--text-2); opacity: 0.35; font-size: 14px; }
@keyframes reel-shimmer { to { background-position: -120% 0; } }
@media (prefers-reduced-motion: reduce) { .reel-card--ghost { animation: none; } }
.sheet__desc { font-size: 14.5px; line-height: 1.5; margin-bottom: 12px; }
.sheet__facts { display: grid; gap: 4px; margin-bottom: 4px; font-size: 13px; }
.sheet__fact { display: flex; gap: 10px; }
.sheet__factlabel { color: var(--text-2); min-width: 62px; }
.sheet__fact a { text-decoration: underline; text-underline-offset: 2px; word-break: break-all; }
.sheet__actions { flex: none; margin: 0 22px; display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0 22px; border-top: 1px solid var(--border); }
.sheet__coords { font-size: 12px; font-weight: 600; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* Tour layer ------------------------------------------------------------ */
/* The stop line, printed on the frame like a margin note. */
.tour__head {
  position: absolute; z-index: 3;
  left: calc(var(--gutter) + 16px); top: calc(var(--frame-inset) + 16px);
  display: inline-flex; align-items: center; flex-wrap: wrap; gap: 6px 12px;
  padding: 9px 16px; border-radius: var(--r-pill);
  font-size: clamp(13px, 0.8vw, 16px); font-weight: 600; color: var(--text); font-variant-numeric: tabular-nums;
  max-width: calc(100% - var(--frame-right) - var(--gutter) - 32px);
  opacity: 0; transform: translateY(-8px);
  transition: opacity 0.4s ease 0.4s, transform 0.4s ease 0.4s, background 0.6s ease, color 0.6s ease, border-color 0.6s ease;
}
.stage[data-state="tour"] .tour__head { opacity: 1; transform: none; }
.tour__head #tourPlateNo { color: var(--primary); }
.tour__head #tourCoords { color: var(--text-2); }
/* The lamp: the last stop is the night sheet. */
.stage.is-night .tour__head { background: var(--night-glass); color: var(--night-text); border-color: rgba(255, 255, 255, 0.14); }
.stage.is-night .tour__head #tourPlateNo { color: var(--night-primary); }
.stage.is-night .tour__head #tourCoords { color: var(--night-text-2); }
.stage.is-night .credit--map { background: var(--night-glass); color: var(--night-text-2); box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.12); }
.stage.is-night .credit__toggle { color: var(--night-text); }
.stage.is-night .credit--map a { color: var(--night-text); text-decoration-color: rgba(255, 255, 255, 0.3); }
.stage.is-night .stage__frame { border-color: rgba(255, 255, 255, 0.12); }

/* The phone: the app's cinematic dark chrome (AppColors.darkCinemaBase)
   around a full-bleed reel that follows the map, feed-style. It waits
   below the screen in the hero and rises into its column for the tour. */
.tour__phone {
  position: absolute; z-index: 3;
  right: var(--gutter); top: 50%;
  width: var(--stage-phone);
  transform: translate3d(0, calc(-50% + 120vh), 0);
  transition: transform 0.9s var(--ease-out) 0.08s;
  will-change: transform;
}
.stage[data-state="tour"] .tour__phone { transform: translate3d(0, -50%, 0); }
.phone {
  width: 100%;
  margin: 0 auto;
  max-width: calc((100svh - var(--bar-h) - 160px) * 9 / 19); /* 160 = breathing room plus the caption below */
  max-height: calc(100svh - var(--bar-h) - 160px);
  aspect-ratio: 9 / 19;
  padding: 9px;
  border-radius: 40px;
  background: var(--night-base);
  box-shadow: var(--shadow-dock), 0 0 0 1px rgba(255, 255, 255, 0.06) inset;
}
.phone__screen {
  position: relative;
  width: 100%; height: 100%;
  border-radius: 32px;
  overflow: hidden;
  background: var(--night-scrim);
}
.phone__feed { position: absolute; inset: 0; overflow: hidden; }
.phone__media { position: absolute; inset: 0; }
.phone__map { position: absolute; inset: 0; opacity: 0; transition: opacity 0.6s ease; }
.phone__map.is-ready { opacity: 1; }
.phone__video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* The feed swipe: the last reel slides up and away while the next one
   slides in from below — the way a reel is flicked past. */
.phone__prev { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 1; }
.phone__prev.is-out { animation: reel-out 0.55s var(--ease-out) forwards; }
.phone__media.is-in { animation: reel-in 0.55s var(--ease-out); }
@keyframes reel-out { from { transform: translateY(0); } to { transform: translateY(-100%); } }
@keyframes reel-in { from { transform: translateY(100%); } to { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) {
  .phone__prev.is-out, .phone__media.is-in { animation: none; }
}
.phone__notch {
  position: absolute; z-index: 3; top: 9px; left: 50%; transform: translateX(-50%);
  width: 76px; height: 22px; border-radius: 12px; background: var(--night-base);
}
.phone__shade {
  position: absolute; z-index: 2; inset: 0;
  background: linear-gradient(180deg, rgba(6, 10, 20, 0.35) 0%, rgba(6, 10, 20, 0) 24%, rgba(6, 10, 20, 0) 55%, rgba(6, 10, 20, 0.86) 100%);
  pointer-events: none;
}
/* Player chrome. The action rail down the right (heart, comment, share,
   sound off), the app's own "Route" action in the bottom corner in the
   brand teal — the one that takes you to the place — and a seek line along
   the bottom that runs the length of the reel: a 12 s loop for the
   fly-over, the clip's own time when one plays. White ink with a soft drop
   shadow, the way every feed does it. */
.phone__rail {
  position: absolute; z-index: 3; right: 10px; bottom: 82px;
  list-style: none; display: flex; flex-direction: column; align-items: center; gap: 15px;
  color: #fff;
}
/* The app's Go, at the foot of the rail: a coral round button with the
   rail's own icon-over-label shape (the same action as the sheet's Go
   above, drawn inside the phone). */
.phone__route {
  position: absolute; z-index: 3; right: 8px; bottom: 20px;
  display: flex; flex-direction: column; align-items: center;
  color: #fff;
}
.phone__route i {
  display: inline-flex; align-items: center; justify-content: center; gap: 1px;
  height: 30px; padding: 0 9px 0 10px; border-radius: var(--r-pill);
  background: var(--go); box-shadow: var(--shadow-floating);
}
.phone__route span { display: block; margin-top: 3px; font-size: 9px; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; text-align: center; }
.phone__route svg { display: block; fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round; }
.phone__route-pin { width: 17px; height: 17px; stroke-width: 2.1; }
.phone__route-go { width: 14px; height: 14px; stroke-width: 2.8; margin-left: -1px; }
.phone__rail svg {
  display: block; width: 24px; height: 24px;
  fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}
.phone__bar { position: absolute; z-index: 3; left: 0; right: 0; bottom: 0; height: 3px; background: rgba(255, 255, 255, 0.22); }
.phone__bar i { display: block; height: 100%; width: 0; background: #fff; }
.phone__bar i.is-running { animation: reel-bar 12s linear infinite; }
@keyframes reel-bar { from { width: 0; } to { width: 100%; } }
@media (prefers-reduced-motion: reduce) {
  .phone__bar i, .phone__bar i.is-running { animation: none; width: 38%; }
}
.phone__foot { position: absolute; z-index: 3; left: 16px; right: 72px; bottom: 20px; color: var(--night-text); }
.phone__filmed { display: inline-block; font-size: 10.5px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--night-primary); margin-bottom: 5px; }
.phone__place { font-family: var(--serif); font-weight: 600; font-size: clamp(19px, 1.3vw, 27px); line-height: 1.15; letter-spacing: -0.2px; text-wrap: balance; } /* placeTitle voice */
.phone__kind { font-size: clamp(11.5px, 0.7vw, 14px); color: var(--night-text-2); margin-top: 3px; }
.tour__phonecap { margin: 12px auto 0; max-width: 32ch; font-size: clamp(12.5px, 0.75vw, 15px); line-height: 1.4; color: var(--text-2); text-align: center; }

/* The stops: one screen each, text centred, scrolling past the sticky map
   in the middle column. */
.chapters {
  position: relative;
  z-index: 2;
  list-style: none;
  margin-left: calc(100% - var(--gutter) - var(--stage-phone) - var(--stage-gap) - var(--stage-text));
  width: var(--stage-text);
  pointer-events: none;
}
.chapter {
  min-height: calc(100vh - var(--bar-h));
  min-height: calc(100svh - var(--bar-h));
  display: flex;
  align-items: center;
  scroll-snap-align: start;
  scroll-snap-stop: always;
  scroll-margin-top: var(--bar-h);
}
.chapter__body {
  position: relative;
  padding-left: 22px;
  max-width: 34ch;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.5s ease 0.3s, transform 0.5s ease 0.3s;
}
.stage[data-state="tour"] .chapter.is-active .chapter__body { opacity: 1; transform: none; }
.chapter__body::before {
  content: ""; position: absolute; left: 0; top: 4px; width: 3px; height: 44px; border-radius: 2px;
  background: var(--sweep);
}
.chapter__no { font-size: 12px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--primary); margin-bottom: 8px; }
.chapter__place { font-weight: 700; font-size: clamp(22px, 1.9vw, 38px); line-height: 1.1; letter-spacing: -0.025em; margin-bottom: 10px; text-wrap: balance; }
.chapter__note { font-size: clamp(15.5px, 0.95vw, 20px); line-height: 1.55; color: var(--text-2); }
.chapter__live { margin-top: 10px; font-size: 15px; font-weight: 600; color: var(--primary); }
/* What you get: two or three plain lines, each with the app's teal dot. */
.chapter__gets { list-style: none; margin-top: 14px; display: grid; gap: 8px; }
.chapter__gets li {
  position: relative; padding-left: 18px;
  font-size: clamp(14.5px, 0.9vw, 18px); line-height: 1.45; color: var(--text);
}
.chapter__gets li::before {
  content: ""; position: absolute; left: 0; top: 0.62em; width: 7px; height: 7px; border-radius: 50%;
  background: var(--primary);
}
/* The footer after the stage is the exit stop of the paging. */
.stage + .foot { scroll-snap-align: start; }

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
/* Two rows on one shared 4/8 grid: the masthead (tagline beside the two
   cards) and the colophon (brand under the tagline, licence under the
   cards). On landscape screens the footer is a full screen tall, so the
   paging's last stop is always reachable; the masthead pins to the top and
   the colophon to the bottom, and the air between them is framed by the two
   rules rather than trailing off. Phones and portrait tablets stack. */
.foot { padding: clamp(48px, 7vh, 112px) 0 clamp(40px, 5vh, 64px); border-top: 1px solid var(--border); background: var(--surface); }
.foot__inner { display: grid; row-gap: 32px; font-size: 14px; color: var(--text-2); }
.tagline { font-family: var(--serif); font-style: italic; font-weight: 500; font-size: clamp(24px, 2.2vw, 34px); color: var(--text); margin-bottom: 8px; } /* brandTagline voice */
.today { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; margin-top: 18px; }
.today > div { padding: 22px 24px; background: var(--base); border: 1px solid var(--border); border-radius: var(--r-medium); }
.today dt { font-size: 12px; font-weight: 700; letter-spacing: 0.09em; text-transform: uppercase; color: var(--primary); margin-bottom: 8px; }
.today dd { font-size: 15px; line-height: 1.55; color: var(--text); max-width: 34em; }
.foot__colophon { display: grid; row-gap: 6px; align-items: start; border-top: 1px solid var(--border); padding-top: 24px; }
.foot .wordmark { margin: 0; color: var(--text); }
.foot__built { max-width: 34em; }
.foot .credit { max-width: 64ch; }
/* Landscape from 700px (where the paging runs) and any screen from 961px:
   the colophon splits into brand | licence, and the footer becomes the
   last full screen. min-height counts the padding (border-box), so the
   stop lands with the footer's top exactly under the bar. */
@media (min-width: 700px) and (orientation: landscape), (min-width: 961px) {
  .foot { display: grid; min-height: calc(100svh - var(--bar-h)); }
  .foot__inner { grid-template-rows: 1fr auto; align-items: start; row-gap: clamp(48px, 6vh, 96px); }
  .foot__mast { align-self: center; } /* the statement floats mid-screen; the colophon holds the floor */
  .foot__colophon { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); column-gap: clamp(40px, 4vw, 72px); }
  .foot__colophon .wordmark { grid-column: 1; grid-row: 1; }
  .foot__built { grid-column: 1; grid-row: 2; }
  .credit--licence { grid-column: 2; grid-row: 1; max-width: none; }
  .credit--copy { grid-column: 2; grid-row: 2; }
}
/* Laptops and up: the masthead takes the same two tracks, so the tagline
   and the wordmark share a left edge, and the cards and the licence do. */
@media (min-width: 1181px) {
  .foot__mast { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); column-gap: clamp(40px, 4vw, 72px); align-items: start; }
  .tagline { max-width: 11ch; line-height: 1.05; letter-spacing: -0.01em; margin: 0.1em 0 0; }
  .today { margin-top: 0; gap: 18px; }
}

/* --------------------------------------------------------------------------
   Screen sizes
   -------------------------------------------------------------------------- */
/* Mid-size landscape screens: the same three columns, proportionally smaller. */
@media (max-width: 1180px) and (min-width: 700px) and (orientation: landscape) {
  .stage { --stage-text: clamp(190px, 24vw, 300px); --stage-phone: clamp(150px, 17vw, 210px); --stage-gap: 20px; }
  .chapter__body { padding-left: 16px; }
  .phone { border-radius: 30px; padding: 7px; }
  .phone__screen { border-radius: 24px; }
  .phone__notch { width: 60px; height: 18px; top: 8px; }
  .phone__foot { left: 12px; right: 62px; bottom: 16px; }
  .phone__rail { right: 8px; bottom: 70px; gap: 11px; }
  .phone__route { right: 7px; bottom: 16px; }
  .phone__route i { height: 26px; padding: 0 7px 0 8px; }
  .phone__rail svg { width: 20px; height: 20px; }
  .phone__route-pin { width: 15px; height: 15px; }
  .phone__route-go { width: 12px; height: 12px; }
}


/* Portrait screens and phones: the map shrinks into a band across the top
   and the stops scroll under it; the phone steps aside. Every LANDSCAPE
   screen keeps the three columns (owner's call, 2026-09-12). */
@media (max-width: 960px) and (orientation: portrait), (max-width: 699px) {
  .stage { --band: 46svh; }
  .stage__sticky { z-index: 2; } /* the band paints over the stops scrolling under it… */
  .chapters { z-index: 1; }      /* …so the stops drop below it (they sit at 2 on landscape) */
  .stage[data-state="tour"] .stage__sticky { background: transparent; } /* below the band the sticky box is glass: the stops show through */
  .stage[data-state="tour"] .stage__map { clip-path: inset(0 0 calc(100% - var(--band)) 0 round 0 0 var(--r-large) var(--r-large)); }
  .stage__frame, .tour__phone { display: none; }
  .tour__head { left: 14px; top: 14px; max-width: calc(100% - 28px); }
  .stage[data-state="tour"] .credit--map { right: 12px; bottom: calc(100% - var(--band) + 12px); }
  .credit--map.is-open .credit__text { white-space: normal; }
  /* The stops flow like a page under the sticky band — no screen-tall
     stops, no blank stretches, no text that waits to fade in. The band
     flies to whichever stop is under the reading line (hero-map.js). */
  .chapters { margin-left: 0; width: auto; padding: 20px var(--gutter) 0; }
  .chapter { min-height: 0; align-items: flex-start; padding: 0 0 40px; scroll-snap-align: none; scroll-snap-stop: normal; }
  .chapter:last-child { padding-bottom: 56px; }
  .chapter__body { padding-left: 16px; max-width: none; opacity: 1; transform: none; }
  .chapter__body::before { opacity: 0.35; transition: opacity 0.3s ease; }
  .chapter.is-active .chapter__body::before { opacity: 1; }
}

@media (max-width: 640px) {
  :root { --bar-h: 56px; }
  .panel { left: 12px; right: 12px; width: auto; bottom: 44px; padding: 20px 20px 18px; border-radius: var(--r-medium); }
  .panel .chip { margin-bottom: 12px; }
  .panel .h1 { font-size: 30px; margin-bottom: 10px; }
  .panel__lead { font-size: 15px; margin-bottom: 16px; }
  .panel__pos { font-size: 12px; }
  .stage.is-exploring .panel { bottom: 44px; }
  .credit--map { font-size: 11px; }
  .sheet { left: 12px; right: 12px; bottom: 44px; width: auto; min-height: 0; max-height: 64%; }
  .reel-card { flex-basis: 84px; }
  .today { grid-template-columns: minmax(0, 1fr); }
  .today > div { padding: 20px; }
}
@media (max-width: 380px) {
  .bar__by { font-size: 13px; }
  .panel .h1 { font-size: 27px; }
}

/* Big screens: the page grows with them instead of floating in the middle. */
@media (min-width: 1600px) {
  :root { --wrap: 1400px; }
  body { font-size: 17px; }
  .tagline { font-size: clamp(34px, 2.8vw, 64px); }
  .today > div { padding: 26px 28px; }
  .today dd { font-size: 17px; }
  .foot__built { font-size: 15px; }
}
@media (min-width: 1700px) {
  .panel { width: 620px; padding: 36px 38px 32px; }
}
@media (min-width: 1900px) {
  :root { --wrap: 1600px; }
  .today > div { padding: 28px 32px; }
  .today dt { font-size: 13px; }
}
@media (min-width: 2400px) {
  :root { --wrap: 1900px; }
  .today dd { font-size: 18px; }
}
