/* ============================================================
   Riskgaming — site styles
   Built on the Lux Capital design system (css/styles.css).
   Austere black + Cool Gray 8, Pantone Red 485 as a sparing
   accent, Brown type, sharp corners, 1px rules, restrained motion.
   ============================================================ */

/* ---- Theme grounds ------------------------------------------------ */
:root {
  --nav-h: 68px;
  --edge: clamp(1.25rem, 5vw, 5rem);   /* page side margin */
  /* Default the iOS Safari floating URL bar to DARK on every page and at
     first paint — before js/main.js syncBrowserUi() runs (and on static pages
     like /scenarios that have no slides, where it never runs). Without this
     the meta `color-scheme: dark light` lets Safari render the bar light/white
     in the phone's light mode. Per-slide JS still flips this to light where a
     light/paper slide is active. */
  color-scheme: dark;
}

html { -webkit-text-size-adjust: 100%; }
/* The Lux design base sets body background to --color-bg (light/white). Every
   slide and page here is dark-grounded and paints its own ground ON TOP of
   body, so body is normally hidden — EXCEPT in the strip below the mobile deck,
   where main.deck (100lvh) stops short of the iOS floating URL bar and the
   transparent deck lets body show through. A white body = the white gap. Make
   body the dark backstop (the black `html` rule below can't help: body covers
   it). Per-slide grounds still paint over this everywhere they reach. */
body { overflow-x: hidden; background: var(--lux-black); }

/* A slide declares its ground via data-theme; text colors follow. */
[data-theme="dark"]  { --on: var(--lux-white); --on-dim: var(--lux-neutral-400); --ground: var(--lux-black); }
[data-theme="paper"] { --on: var(--lux-black); --on-dim: var(--lux-neutral-600); --ground: var(--lux-paper); }
[data-theme="light"] { --on: var(--lux-black); --on-dim: var(--lux-neutral-600); --ground: var(--lux-white); }

/* ============================================================
   Deck + slide scaffolding (desktop parallax)
   ============================================================ */
.deck {
  /* No CSS scroll-snap: it fights high-resolution / free-spin wheels and
     reverses direction mid-scroll. The wheel/trackpad scrolls freely; when
     scrolling settles, js/main.js smoothly recenters onto the dominant slide.
     scroll-behavior:smooth powers that recenter (and anchor nav), not the
     user's own wheel scroll. */
  scroll-snap-type: none;
  height: 100vh;
  overflow-y: scroll;
  scroll-behavior: smooth;
  overflow-x: hidden;
}

.slide {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--ground);
  color: var(--on);
  padding: calc(var(--nav-h) + 2rem) var(--edge) 3rem;
}

.slide__bg {
  position: absolute;
  inset: -8% 0 -8% 0;   /* overscan so parallax translate never reveals an edge */
  z-index: 0;
  will-change: transform;
}

.slide__content {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  will-change: transform;
}

.section-head { margin-bottom: clamp(1.5rem, 3vw, 2.75rem); }
.section-head .lux-kicker { color: var(--on-dim); margin: 0 0 0.65rem; display: block; }
.lux-rule { border-top-color: var(--on); opacity: 1; }
.lux-rule--onDark { border-top-color: var(--on); }
.section-head--split {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 2rem;
}
.section-head--split > div { flex: 1; }
.section-head__link {
  color: var(--on); font-size: var(--text-sm); letter-spacing: var(--tracking-wide);
  white-space: nowrap; padding-bottom: 0.35rem; border-bottom: 1px solid transparent;
}
.section-head__link:hover { opacity: 1; border-bottom-color: var(--accent); }

/* ============================================================
   Buttons
   ============================================================ */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-sans); font-size: var(--text-sm);
  font-weight: var(--weight-regular); letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: 0.85rem 1.6rem; border-radius: var(--radius-md);
  border: 1px solid transparent; cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
.btn:hover { opacity: 1; }
.btn:active { transform: translateY(1px); }
.btn--primary { background: var(--accent); color: var(--accent-contrast); }
.btn--primary:hover { background: var(--accent-hover); }
.btn--ghost { background: transparent; border-color: currentColor; color: var(--on); }
.btn--ghost:hover { background: var(--on); color: var(--ground); }
.btn--onDark { color: var(--lux-white); }

/* ============================================================
   Floating navigation
   ============================================================ */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: var(--z-sticky);
  height: var(--nav-h);
  display: flex; align-items: center;
  transition: background var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard);
  border-bottom: 1px solid transparent;
}
/* Floating pill effect: a subtle translucent bar that firms up on scroll */
.nav::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--nav-bg, transparent);
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  opacity: var(--nav-bg-opacity, 0);
  transition: opacity var(--duration-base) var(--ease-standard);
}
.nav__inner {
  width: 100%; max-width: 1360px; margin: 0 auto;
  padding: 0 var(--edge);
  display: flex; align-items: center; gap: 2rem;
}
.nav__brand {
  display: flex; align-items: center; text-decoration: none; margin-right: auto;
  /* drives currentColor of the inlined logo wordmark + divider */
  color: var(--nav-fg, var(--lux-white));
  transition: color var(--duration-base) var(--ease-standard);
}
.nav__brand:hover { opacity: 1; }
.nav__logo { display: block; height: 44px; width: auto; }
.nav__links { display: flex; align-items: center; gap: 2rem; }
/* Text links only — the CTA button is excluded so it keeps its .btn metrics */
.nav__links a:not(.nav__cta) {
  color: var(--nav-fg, var(--lux-white)); font-size: var(--text-sm);
  letter-spacing: var(--tracking-wide); text-transform: uppercase;
  padding: 0.4rem 0; border-bottom: 1px solid transparent;
  transition: color var(--duration-base) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.nav__links a:not(.nav__cta):hover { opacity: 1; border-bottom-color: var(--accent); }
.nav__links a:not(.nav__cta).is-active { border-bottom-color: var(--accent); }
/* Red brand CTA in the bar — design-system "sm" button metrics (7px 14px) */
.nav__cta {
  padding: 7px 14px; font-size: var(--text-sm);
  border-radius: var(--radius-md); white-space: nowrap;
}
.nav__toggle { display: none; }

/* Mobile menu (hidden on desktop) */
.mobile-menu { display: none; }

/* ============================================================
   Slide-progress dots (desktop)
   ============================================================ */
.dots {
  position: fixed; right: 1.5rem; top: 50%; transform: translateY(-50%);
  z-index: var(--z-sticky); display: flex; flex-direction: column; gap: 0.9rem;
}
.dots a {
  width: 10px; height: 10px; border-radius: 0; /* sharp: brand */
  border: 1px solid var(--dot-color, rgba(255,255,255,0.6));
  background: transparent; transition: all var(--duration-base) var(--ease-standard);
}
.dots a:hover { opacity: 1; transform: scale(1.25); }
.dots a.is-active { background: var(--accent); border-color: var(--accent); }

/* ============================================================
   SLIDE 1 — HERO
   ============================================================ */
.slide--hero { background: var(--lux-black); align-items: flex-end; }
.hero__img,
.connect__video {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; display: block;
}
.hero__scrim {
  position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.25) 40%, rgba(0,0,0,0.75) 100%);
}
/* Bottom-left hero: content sits against the bottom edge, clear of the scroll cue */
.hero__content { max-width: 1200px; padding-bottom: clamp(1.5rem, 6vh, 4rem); }
.hero__kicker { color: var(--lux-neutral-300); margin-bottom: 1rem; }
.hero__title {
  font-size: clamp(3rem, 10vw, 7rem);
  line-height: 0.95; letter-spacing: var(--tracking-tight);
  color: var(--lux-white); margin: 0 0 1.25rem; max-width: none;
  /* Optically align the large "R" ink with the body text below it: the
     heading glyph carries a ~0.08em left side-bearing that the small lede
     does not. Scales with the fluid font-size. */
  text-indent: -0.075em;
}
.hero__lede {
  font-size: clamp(1.05rem, 1.6vw, 1.375rem); font-weight: var(--weight-light);
  line-height: var(--leading-relaxed); color: var(--lux-neutral-300);
  max-width: 60ch; margin: 0 0 2.25rem;
}
.hero__actions { display: flex; gap: 1rem; flex-wrap: wrap; }

.scroll-cue {
  position: absolute; bottom: 2rem; left: 50%; transform: translateX(-50%);
  z-index: 3; display: flex; flex-direction: column; align-items: center; gap: 0.6rem;
  color: var(--lux-neutral-300);
}
.scroll-cue:hover { opacity: 1; color: var(--lux-white); }
.scroll-cue__label {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
}
.scroll-cue__line {
  width: 1px; height: 42px; background: currentColor; position: relative; overflow: hidden;
}
.scroll-cue__line::after {
  content: ""; position: absolute; top: -100%; left: 0; width: 100%; height: 100%;
  background: var(--accent); animation: scrollcue 2.4s var(--ease-standard) infinite;
}
@keyframes scrollcue { 0% { top: -100%; } 60%,100% { top: 100%; } }

/* ============================================================
   SLIDE 2 — WHAT IS RISKGAMING (full-bleed horizontal carousel)
   ============================================================ */
.slide--about,
.slide--scenarios { padding: 0; display: block; background: var(--lux-black); }
.carousel {
  position: relative; width: 100%; height: 100vh; height: 100svh; overflow: hidden;
}
.carousel__track {
  display: flex; height: 100%; width: 100%;
  transition: transform var(--duration-slow) var(--ease-out);
  will-change: transform;
}
.carousel__track.no-anim { transition: none; }

.acard {
  position: relative; flex: 0 0 100%; width: 100%; height: 100%;
  overflow: hidden; display: flex; align-items: flex-end;
}
.acard__bg {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center; display: block;
  background: var(--lux-neutral-900);   /* fallback tint while the image loads */
}
.acard__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.35) 0%, rgba(0,0,0,0.2) 42%, rgba(0,0,0,0.82) 100%);
}
/* Match the hero's horizontal grid exactly: an --edge gutter with a centered
   1200px content column inside it (max-width = column + both gutters). This
   makes the text left-edge identical to "Riskgaming" on the hero at every width. */
.acard__content {
  position: relative; z-index: 2; width: 100%;
  max-width: calc(1200px + 2 * var(--edge)); margin: 0 auto;
  padding: calc(var(--nav-h) + 2rem) var(--edge) clamp(5rem, 14vh, 9rem);
  color: var(--lux-white);
}
.acard__headline {
  font-size: clamp(1.9rem, 4.6vw, 4.25rem); line-height: 1.04;
  letter-spacing: var(--tracking-tight); color: var(--lux-white);
  max-width: 20ch; margin: 0;
  text-indent: -0.075em;   /* optical: align glyph ink to the grid, matching the hero */
}
.acard__title {
  font-size: clamp(1.9rem, 4vw, 3.25rem); line-height: 1.05;
  letter-spacing: var(--tracking-tight); color: var(--lux-white);
  max-width: 16ch; margin: 0 0 1rem;
  text-indent: -0.04em;   /* optical: balanced across the C/E/A/P title first-letters */
}
.acard__body {
  font-size: var(--text-md); font-weight: var(--weight-light);
  color: var(--lux-neutral-200); max-width: 46ch; margin: 0; line-height: var(--leading-relaxed);
}

/* Scenario carousel (slide 4) — the intro reuses the .acard component; the three
   scenario cards show their illustration at full color and overlay a media-slide
   tile (.mtile) in the bottom-left corner. */
.acard--intro .acard__body { margin-top: 1.25rem; }
.acard--intro .acard__browse { margin-top: 1.9rem; }

/* Position the tile bottom-left within the grid; no giant baseline padding. */
.acard--scenario .acard__content { padding-top: 0; padding-bottom: clamp(3rem, 8vh, 5rem); }

/* The tile is always a white card, so it opts into light-theme text colors
   regardless of the (dark) slide theme. Scoped under .acard--scenario to win over
   the coverage slide's desktop .mtile overrides. It's more compact than the media
   tiles (no publication logo) and is not itself a link — only the CTA is. */
.acard--scenario .mtile {
  /* Dark tile: keep the slide's light-on-dark text; use a lighter tint of the
     accent for the name/CTA so they read against the near-black card. */
  --scn-ink: color-mix(in srgb, var(--scn) 60%, var(--lux-white));
  width: clamp(320px, 32vw, 400px); max-width: 100%;
  background: color-mix(in srgb, var(--scn) 8%, var(--lux-black));
  border-color: rgba(255,255,255,0.14);
  border-top-color: var(--scn);   /* keep the accent tab */
  box-shadow: var(--shadow-md);
}
.acard--scenario .mtile:hover { transform: none; box-shadow: var(--shadow-md); }
.acard--scenario .mtile__scenario {
  padding: 0.85rem 1.15rem;
  background: color-mix(in srgb, var(--scn) 24%, var(--lux-black));
  border-bottom-color: rgba(255,255,255,0.1);
}
.acard--scenario .mtile__scenario:hover { background: color-mix(in srgb, var(--scn) 24%, var(--lux-black)); }
.acard--scenario .mtile__scenario-name::after { content: none; }   /* arrow lives on the CTA */
.acard--scenario .mtile__main { padding: 0.85rem 1.15rem 1.05rem; gap: 0.6rem; }
.acard--scenario .mtile__headline {
  display: block; font-size: var(--text-md); font-weight: var(--weight-regular);
  color: var(--on-dim); margin: 0; padding: 0; -webkit-line-clamp: none; line-height: var(--leading-snug);
}
/* CTA is a real .btn tinted with the scenario accent. The fill is a darkened
   accent so white text stays legible on every scenario color (incl. light blues),
   with a crisp full-accent 1px edge. */
.acard--scenario .mtile__cta {
  align-self: flex-start; margin-top: 0.2rem;
  padding: 0.62rem 1.2rem; text-decoration: none;
  background: color-mix(in srgb, var(--scn) 58%, var(--lux-black));
  color: var(--lux-white); border-color: var(--scn);
}
.acard--scenario .mtile__cta:hover { background: color-mix(in srgb, var(--scn) 74%, var(--lux-black)); }

/* Card ticker (carousel dots): the scenario illustrations have no scrim, so give
   the dots a dark edge and brighter fills so they stay legible on any background —
   dim white for the other cards, solid white for the one you're on. */
.slide--scenarios .carousel__dot {
  height: 4px;
  background: rgba(255,255,255,0.5);
  box-shadow: 0 1px 3px rgba(0,0,0,0.6);
}
.slide--scenarios .carousel__dot:hover { background: rgba(255,255,255,0.8); }
.slide--scenarios .carousel__dot.is-active { background: var(--lux-white); }

/* Controls */
.carousel__ui {
  position: absolute; left: 0; right: 0; bottom: clamp(1.5rem, 4vh, 2.5rem);
  z-index: 5; padding: 0 var(--edge); pointer-events: none;
  /* Promote the controls to their own compositing layer. The card track
     animates `transform`, and without this the overlapping dots sat on a layer
     that only repainted *during* the slide transition, then blanked out (still
     clickable — just not painted) until a hover forced a repaint. translateZ
     keeps them painted at all times. will-change makes the promotion explicit
     (translateZ(0) alone can serialize to a 2D identity and skip promotion). */
  transform: translateZ(0); will-change: transform;
}
.carousel__ui-inner {
  max-width: 1200px; margin: 0 auto;
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
.carousel__dots { display: flex; gap: 0.55rem; pointer-events: auto; }
.carousel__dot {
  width: 30px; height: 3px; padding: 0; border: 0; cursor: pointer;
  background: rgba(255,255,255,0.35);
  transition: background var(--duration-base) var(--ease-standard);
}
.carousel__dot:hover { background: rgba(255,255,255,0.6); }
.carousel__dot.is-active { background: var(--accent); }
.carousel__arrows { display: flex; gap: 0.5rem; pointer-events: auto; }
.carousel__arrow {
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  /* Dark translucent chip + brighter border so the white glyph keeps contrast
     over ANY card photo. A transparent background left the arrows invisible on
     light-toned slides. (Layer promotion for the disappear-on-transition bug
     lives on .carousel__ui, which covers both the arrows and the dots.) */
  background: rgba(0,0,0,0.45); color: var(--lux-white); font-size: 1.3rem; line-height: 1;
  border: 1px solid rgba(255,255,255,0.6); border-radius: var(--radius-md); cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.carousel__arrow:hover { background: var(--lux-white); color: var(--lux-black); border-color: var(--lux-white); }

/* ============================================================
   SLIDE 3 — WHAT THEY ARE SAYING (horizontal-scrolling coverage)
   ------------------------------------------------------------
   Big title on the site grid; uniform tiles flow right in a
   horizontal scroller that bleeds past the right edge.
   --grid-left is the same left inset the hero/carousel use, so the
   title and the first tile line up with every other slide.
   ============================================================ */
/* Dark blue ground so the white coverage tiles pop. Sets --ground too so the
   arrows and other var(--ground) refs match the slide, not the theme's black. */
.slide--coverage { padding: 0; display: block; --ground: #16191E; background: #16191E; }
.coverage__content {
  min-height: 100vh; display: flex; flex-direction: column; justify-content: center;
  gap: clamp(1.5rem, 4vh, 2.75rem);
  padding: calc(var(--nav-h) + 2rem) 0 3rem;
  --grid-left: max(var(--edge), calc((100% - 1200px) / 2));
}
.coverage__head {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 1.5rem;
  padding-left: var(--grid-left); padding-right: var(--edge);
}
.coverage__title {
  font-size: clamp(2rem, 5.2vw, 4rem); line-height: 1.02;
  letter-spacing: var(--tracking-tight); color: var(--on); margin: 0;
  text-indent: -0.05em;   /* optical: align glyph ink to the grid */
}
/* Arrow controls in an absolute bottom bar, matching the scenarios carousel's
   .carousel__ui placement (bottom, right-aligned within the 1200px column). */
.coverage__ui {
  position: absolute; left: 0; right: 0; bottom: clamp(1.5rem, 4vh, 2.5rem);
  z-index: 5; padding: 0 var(--edge); pointer-events: none;
}
.coverage__ui-inner {
  max-width: 1200px; margin: 0 auto; display: flex; justify-content: flex-end;
}
.coverage__arrows { display: flex; gap: 0.5rem; pointer-events: auto; }
.cov__arrow {
  width: 44px; height: 44px; display: flex; align-items: center; justify-content: center;
  background: transparent; color: var(--on); font-size: 1.3rem; line-height: 1;
  border: 1px solid var(--lux-neutral-300); border-radius: var(--radius-md); cursor: pointer;
  transition: background var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-color var(--duration-fast) var(--ease-standard);
}
.cov__arrow:hover { background: var(--on); color: var(--ground); border-color: var(--on); }
.cov__arrow[disabled] { opacity: 0.3; cursor: default; }
.cov__arrow[disabled]:hover { background: transparent; color: var(--on); border-color: var(--lux-neutral-300); }

.coverage__track {
  display: flex; gap: 1.5rem; overflow-x: auto; overflow-y: hidden;
  padding: 0.5rem var(--edge) 1rem var(--grid-left);   /* first tile on the grid, bleed right */
  scroll-snap-type: x proximity; scroll-padding-left: var(--grid-left);
  scrollbar-width: thin;
  /* Fade the tiles out at the right edge so the slide indicators (fixed on the
     right) sit on clean ground and stay clearly visible — also hints "more →". */
  -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 120px), transparent calc(100% - 34px));
          mask-image: linear-gradient(to right, #000 calc(100% - 120px), transparent calc(100% - 34px));
}
.coverage__track.is-dragging { scroll-snap-type: none; cursor: grabbing; }
.coverage__track::-webkit-scrollbar { height: 6px; }
.coverage__track::-webkit-scrollbar-thumb { background: var(--lux-neutral-300); border-radius: 999px; }

/* Each tile carries its scenario's accent via inline --scn.
   --scn-ink = the accent darkened just enough to read as text on white. */
.mtile {
  --scn: var(--accent);
  --scn-ink: color-mix(in srgb, var(--scn) 62%, #16171a);
  flex: 0 0 clamp(300px, 25vw, 360px); scroll-snap-align: start;
  display: flex; flex-direction: column; background: var(--lux-white);
  border: 1px solid var(--lux-neutral-200);
  border-top: 4px solid var(--scn);   /* accent tab */
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-standard);
}
.mtile:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }

/* Scenario row — now at the TOP, gently tinted with the accent */
.mtile__scenario {
  display: flex; flex-direction: column; gap: 0.3rem;
  padding: 1.15rem 1.25rem; color: var(--scn-ink);
  background: color-mix(in srgb, var(--scn) 9%, var(--lux-white));
  border-bottom: 1px solid var(--lux-neutral-200);
  transition: background var(--duration-fast) var(--ease-standard);
}
.mtile__scenario:hover { opacity: 1; background: color-mix(in srgb, var(--scn) 16%, var(--lux-white)); }
.mtile__scenario-kicker {
  font-size: var(--text-sm); text-transform: uppercase; letter-spacing: var(--tracking-caps);
  color: var(--on-dim);
}
.mtile__scenario-name {
  font-size: 1.375rem; line-height: var(--leading-snug); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight); color: var(--scn-ink);
}
.mtile__scenario-name::after { content: " \2192"; }
/* Static variant: a WIP scenario with no page yet — not a link, so drop the
   hover affordance and the trailing arrow. */
.mtile__scenario--static { cursor: default; }
.mtile__scenario--static:hover { background: color-mix(in srgb, var(--scn) 9%, var(--lux-white)); }
.mtile__scenario--static .mtile__scenario-name::after { content: none; }

/* Article body — logo + headline */
.mtile__main { display: flex; flex-direction: column; color: var(--on); padding-bottom: 0.4rem; }
.mtile__main:hover { opacity: 1; }
.mtile__logo { height: 24px; padding: 1rem 1.25rem 0; box-sizing: content-box; }
.mtile__logo img {
  height: 24px; width: auto; max-width: 100%;
  object-fit: contain; object-position: left center; display: block;
  filter: brightness(0);
}
.mtile__headline {
  font-size: 1.25rem; line-height: var(--leading-snug); font-weight: var(--weight-bold);
  margin: 0; padding: 0.3rem 1.25rem 1.25rem;   /* tight to the logo above */
}

/* Desktop: fill the vertical space. Tiles stack top-to-bottom (column-wrap)
   filling the available height into as many rows as fit, then wrap into new
   columns to the right; the track only scrolls horizontally when the columns
   overflow. In a column-direction flex box the main axis is vertical, so the
   tile's flex-basis sets its HEIGHT and width is set explicitly. */
@media (min-width: 861px) {
  .coverage__track {
    flex: 1 1 0; min-height: 0;
    flex-flow: column wrap; align-content: flex-start;
  }
  .mtile {
    flex: 0 0 480px;                       /* tile height (column-wrap main axis) */
    width: clamp(300px, 24vw, 340px);
  }
  /* The scenario row keeps its size; the doubled height goes to a bigger logo
     with more margin and a roomier headline. The body fills the tile so the
     logo sits up top and the headline anchors toward the bottom. */
  .mtile__main { flex: 1 1 auto; justify-content: space-between; padding-bottom: 0; }
  .mtile__logo { height: 40px; padding: 2.25rem 1.25rem 0; }
  .mtile__logo img { height: 40px; }
  .mtile__headline {
    font-size: 1.5rem; padding: 1.75rem 1.25rem 2rem;
    display: -webkit-box; -webkit-line-clamp: 5; -webkit-box-orient: vertical; overflow: hidden;
  }
}

/* ============================================================
   SLIDE 4 — SCENARIOS
   ============================================================ */
.scenarios__grid {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem;
}
.scenario {
  display: flex; flex-direction: column; color: var(--on);
  border: 1px solid var(--lux-neutral-800);
  background: var(--lux-neutral-900);
  transition: border-color var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-out);
}
.scenario:hover { opacity: 1; border-color: var(--lux-white); transform: translateY(-3px); }
.scenario__media { aspect-ratio: 3 / 2; overflow: hidden; background: var(--lux-neutral-800); }
.scenario__media img {
  width: 100%; height: 100%; object-fit: cover; display: block;
  transition: transform var(--duration-slow) var(--ease-out);
}
.scenario:hover .scenario__media img { transform: scale(1.04); }
.scenario__body { padding: 1.1rem 1.15rem 1.4rem; display: flex; flex-direction: column; gap: 0.5rem; }
.scenario__meta {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
  color: var(--on-dim);
}
.scenario__title { font-size: var(--text-lg); margin: 0; line-height: var(--leading-snug); color: var(--lux-white); }
.scenario__sub { font-size: var(--text-sm); color: var(--on-dim); margin: 0; font-weight: var(--weight-light); }

/* ============================================================
   SLIDE 5 — AROUND THE WORLD (interactive map)
   Deep-blue ground with a light-blue "neon" world map. Red pins are
   clickable (photo popup); gray pins are location markers only.
   ============================================================ */
.slide--world { background: #0a1a3a; }
/* Headline scaled to match the other slide titles (cf. .coverage__title). */
.world__title {
  font-size: clamp(2rem, 5.2vw, 4rem); line-height: 1.02;
  letter-spacing: var(--tracking-tight); color: var(--on); margin: 0;
}
.world__intro { font-size: var(--text-md); font-weight: var(--weight-light); color: var(--on-dim); max-width: 52ch; margin: 1rem 0 0; }
/* Map key — matches the pin styling (accent red with a glow, solid white). */
.world__legend {
  display: flex; flex-wrap: wrap; gap: 0.6rem 1.5rem;
  list-style: none; margin: 1rem 0 0; padding: 0;
  font-size: var(--text-sm); color: var(--on-dim);
}
.world__legend-item { display: inline-flex; align-items: center; gap: 0.5rem; }
.world__legend-dot { width: 10px; height: 10px; border-radius: 50%; flex: none; }
.world__legend-dot--lux { background: var(--accent); box-shadow: 0 0 5px rgba(255,28,36,0.75); }
.world__legend-dot--community { background: #fff; }
.world__stage { position: relative; margin-top: clamp(1rem, 3vw, 2rem); }
/* Cap the map by height (viewBox ratio 1010/666 ≈ 1.517) so the whole slide
   fits the viewport instead of bleeding past the screen edges. */
.world__map { width: 100%; max-width: calc(54vh * 1.517); margin: 0 auto; }
.world__map svg { width: 100%; height: auto; display: block; overflow: visible; }

/* Neon land: faint blue fill, bright light-blue edges + a soft glow. */
.slide--world .map-land {
  fill: rgba(88,164,255,0.07);
  stroke: #5bb8ff; stroke-width: 0.5;
  filter: drop-shadow(0 0 1.4px rgba(91,184,255,0.85));
}

.map-pin__dot { transition: r var(--duration-fast) var(--ease-standard); }
.map-pin__ring { fill: none; stroke-width: 1.5; opacity: 0; transform-origin: center; }

/* Suppress the browser's default focus box. Chrome draws it around the pin
   group's bounding box, which the expanding sonar ring inflates into a large
   white/blue square (visible on click). Keyboard focus stays indicated by the
   pulsing ring in the :focus-visible rules below. */
.map-pin:focus { outline: none; }

/* Red = clickable, opens a photo card */
.map-pin--red { cursor: pointer; }
.map-pin--red .map-pin__dot { fill: var(--accent); filter: drop-shadow(0 0 2px rgba(255,28,36,0.85)); }
.map-pin--red .map-pin__ring { stroke: var(--accent); }
.map-pin--red:hover .map-pin__dot,
.map-pin--red:focus-visible .map-pin__dot,
.map-pin--red.is-active .map-pin__dot { r: 7; }
.map-pin--red:hover .map-pin__ring,
.map-pin--red:focus-visible .map-pin__ring,
.map-pin--red.is-active .map-pin__ring { opacity: 1; animation: pin-pulse 1.8s var(--ease-out) infinite; }

/* Gray = location marker only (no ring, no pointer) */
.map-pin--gray .map-pin__dot { fill: #fff; }
.map-pin--gray .map-pin__ring { display: none; }

@keyframes pin-pulse {
  0% { r: 6; opacity: 0.85; } 100% { r: 30; opacity: 0; }
}

/* Floating photo + caption card. Carries the clicked scenario's accent via
   an inline --scn (set in map.js); --scn-ink = that accent darkened to read
   as text on white — same formula as the coverage/scenario media tiles. */
.world__card {
  --scn: var(--accent);
  --scn-ink: color-mix(in srgb, var(--scn) 62%, #16171a);
  position: absolute; top: 0; right: 0; z-index: 5;
  width: min(340px, 80%); margin: 0;
  background: var(--lux-white); color: var(--lux-black);
  border: 1px solid var(--lux-black); border-top: 4px solid var(--scn);
  box-shadow: var(--shadow-lg);
}
.world__card[hidden] { display: none; }
/* Empty/prompt state — the card is always on screen; before a pin is chosen it
   shows this prompt (with a red dot echoing the map pins) instead of a photo. */
.world__card-empty {
  display: flex; align-items: flex-start; gap: 0.7rem;
  padding: 1.4rem 1.4rem 1.6rem;
}
.world__card-empty-dot {
  width: 12px; height: 12px; margin-top: 0.3rem; border-radius: 50%; flex: none;
  background: var(--accent); box-shadow: 0 0 6px rgba(255,28,36,0.75);
}
.world__card-empty-text {
  margin: 0; font-size: var(--text-md); font-weight: var(--weight-light);
  color: var(--lux-neutral-700); line-height: var(--leading-normal);
}
/* Empty hides the populated parts; populated hides the prompt. */
.world__card--empty .world__card-scn,
.world__card--empty .world__card-media,
.world__card--empty .world__card-cap,
.world__card--empty .world__card-close { display: none; }
.world__card:not(.world__card--empty) .world__card-empty { display: none; }
.world__card-media { aspect-ratio: 3 / 2; overflow: hidden; background: var(--lux-neutral-100); }
.world__card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.world__card-cap { padding: 1rem 1.15rem 1.25rem; }
.world__card-place {
  font-size: var(--text-lg); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight); line-height: var(--leading-snug);
  color: var(--lux-black); display: block; margin-bottom: 0.5rem;
}
/* Scenario reference — accent-tinted header band at the TOP of the card,
   mirroring .mtile__scenario. Right padding clears the close button. */
.world__card-scn {
  display: flex; flex-direction: column; gap: 0.2rem;
  margin: 0; padding: 0.7rem 2.75rem 0.7rem 1.15rem; text-decoration: none;
  background: color-mix(in srgb, var(--scn) 10%, var(--lux-white));
  border-bottom: 1px solid var(--lux-neutral-200);
  transition: background var(--duration-fast) var(--ease-standard);
}
.world__card-scn[hidden] { display: none; }
a.world__card-scn:hover { background: color-mix(in srgb, var(--scn) 18%, var(--lux-white)); }
/* Hidden (WIP) scenario: the card shows its name but has no page to link to
   (map.js leaves off the href), so don't let it read as clickable. */
a.world__card-scn:not([href]) { cursor: default; }
a.world__card-scn:not([href]):hover { background: color-mix(in srgb, var(--scn) 10%, var(--lux-white)); }
.world__card-scn-kicker {
  font-size: var(--text-xs); text-transform: uppercase; letter-spacing: var(--tracking-caps);
  color: var(--lux-neutral-600);
}
.world__card-scn-name {
  font-size: 1.05rem; line-height: var(--leading-snug); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight); color: var(--scn-ink);
}
a.world__card-scn[href] .world__card-scn-name::after { content: " \2192"; }
.world__card-text { font-size: var(--text-sm); margin: 0; font-weight: var(--weight-light); line-height: var(--leading-normal); }
.world__card-close {
  position: absolute; top: 0; right: 0; width: 34px; height: 34px;
  background: var(--lux-black); color: var(--lux-white); border: 0; cursor: pointer;
  font-size: 1.1rem; line-height: 1; display: flex; align-items: center; justify-content: center;
}
.world__card-close:hover { background: var(--accent); }

/* ============================================================
   SLIDE 6 — CONNECT (closing outro: short summary + Contact CTA).
   Centered on black; a proper ending after the map, with the red
   primary button as the one clear action.
   ============================================================ */
.slide--connect { background: var(--lux-black); text-align: center; }
/* Centered text over the moved video loop — even, fairly strong darkening so
   the longer paragraph stays legible over the footage's bright spots. */
.connect__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.66) 0%, rgba(0,0,0,0.74) 100%);
}
.connect__content { max-width: 760px; margin: 0 auto; }
.connect__title {
  font-size: clamp(2rem, 5.2vw, 4rem); line-height: 1.02;
  letter-spacing: var(--tracking-tight); color: var(--lux-white); margin: 0;
}
.connect__lede {
  font-size: var(--text-md); font-weight: var(--weight-light);
  color: var(--lux-neutral-200); line-height: var(--leading-relaxed);
  max-width: 54ch; margin: 1.25rem auto 0;
}
/* Explicit bold: default `bolder` against the light (300) lede only resolves to
   400, so "free" wouldn't read as emphasized. Force the real bold cut + white. */
.connect__lede strong { font-weight: var(--weight-bold); color: var(--lux-white); }
.connect__cta { margin-top: clamp(1.75rem, 4vh, 2.5rem); }

/* ============================================================
   RESPONSIVE — mobile (vertical scroll, restacked slides)
   ============================================================ */
@media (max-width: 860px) {
  /* Swipe deck: a fixed-height scroll-snap CONTAINER (not the document root).
     Sized to the LARGE viewport (100lvh = full device height, minus only the
     status bar), NOT dvh. Two reasons:
       1. Fixed height → the deck doesn't resize as iOS animates its toolbar, so
          snap points never shift mid-swipe (this is the jank fix).
       2. Full device height → each slide's background reaches the device's
          bottom edge. dvh stopped short of the iOS 26 floating URL bar, leaving
          the page root (white) showing in the gap below the deck.
     The floating URL pill overlays the bottom; bottom-anchored content (hero) is
     lifted clear of it via `100lvh - 100dvh` (= the browser-UI height) below. */
  html { scroll-snap-type: none; background: var(--lux-black); }
  .deck {
    height: 100vh; height: 100lvh;
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    scroll-snap-type: y mandatory;
  }
  /* Each slide fills the deck exactly. Base .slide is flex + align-items:center,
     so content centers in that height. scroll-snap-align:start lands each swipe
     on a slide top. No scroll-snap-stop:always — it felt sticky/janky on iOS;
     mandatory snap still settles on a slide once you stop. */
  .slide {
    height: 100%;
    min-height: 0;
    padding: calc(var(--nav-h) + 2.5rem) var(--edge) 3.5rem;
    scroll-snap-align: start;
  }
  /* Wordmark + lede sit near the bottom. Because the slide now runs to the device
     edge, lift the content by the browser-UI height (100lvh - 100dvh, which
     collapses to 0 once the toolbar retracts) plus the home-indicator inset, so
     it never hides behind the floating URL pill. */
  .slide--hero { padding-bottom: calc(0.9rem + env(safe-area-inset-bottom, 0px)); }
  .slide--hero { padding-bottom: calc(0.9rem + env(safe-area-inset-bottom, 0px) + (100lvh - 100dvh)); }
  .hero__content { padding-bottom: 0; }
  .slide__bg { position: absolute; inset: 0; }  /* no parallax overscan on mobile */
  /* will-change:transform creates a containing block for position:fixed,
     which would trap the mobile map bottom-sheet. Disable it off-desktop. */
  .slide__content, .slide__bg { will-change: auto; }

  /* Nav: swap links for a hamburger */
  .nav__links { display: none; }
  .nav__toggle {
    display: flex; flex-direction: column; justify-content: center; gap: 5px;
    width: 42px; height: 42px; background: transparent; border: 0; cursor: pointer; margin-left: auto;
  }
  .nav__toggle span {
    display: block; width: 22px; height: 2px; background: var(--nav-fg, var(--lux-white));
    transition: transform var(--duration-base) var(--ease-standard), opacity var(--duration-base) var(--ease-standard);
  }
  .nav.is-menu-open .nav__toggle span:first-child { transform: translateY(3.5px) rotate(45deg); }
  .nav.is-menu-open .nav__toggle span:last-child  { transform: translateY(-3.5px) rotate(-45deg); }

  .dots { display: none; }
  .scroll-cue { display: none; }

  /* Mobile menu overlay */
  .mobile-menu {
    /* Start 1px above nav-h so the panel tucks behind the nav and fills the
       seam left by the nav's 1px bottom border (its ::before bg sits inside the
       border box, so top-aligning to nav-h leaves a 1px background gap). */
    display: block; position: fixed; inset: calc(var(--nav-h) - 1px) 0 0 0; z-index: calc(var(--z-sticky) - 1);
    background: var(--lux-black);
    transform: translateY(-100%); transition: transform var(--duration-base) var(--ease-standard);
  }
  .mobile-menu[hidden] { display: block; }         /* keep in flow for transition */
  .mobile-menu.is-open { transform: translateY(0); }
  .mobile-menu nav { display: flex; flex-direction: column; padding: 2rem var(--edge); gap: 0.5rem; }
  .mobile-menu a {
    color: var(--lux-white); font-size: 1.5rem; font-weight: var(--weight-bold);
    padding: 0.75rem 0; border-bottom: 1px solid var(--lux-neutral-800);
  }
  .mobile-menu a:hover { opacity: 1; color: var(--accent); }
  /* Red brand CTA, rendered as a button rather than a text link */
  .mobile-menu .mobile-menu__cta {
    align-self: flex-start; margin-top: 1.25rem;
    font-size: var(--text-sm); font-weight: var(--weight-regular);
    color: var(--accent-contrast); border-bottom: 0;
    /* design-system "md" button metrics (11px 22px) */
    padding: 11px 22px;
  }
  .mobile-menu .mobile-menu__cta:hover { color: var(--accent-contrast); background: var(--accent-hover); }

  /* Carousel stays a full-height horizontal swiper on mobile */
  .slide--about,
  .slide--scenarios { padding: 0; height: 100%; }
  .slide--about .carousel,
  .slide--scenarios .carousel { height: 100%; }
  .carousel__arrows { display: none; }              /* swipe instead of arrows */
  .acard__content { padding-bottom: clamp(4.5rem, 12vh, 7rem); }
  /* In a portrait crop the centre of this photo is the dead zone; favour its
     right side, which is the strongest part of the frame. */
  .acard__bg--focus-right { object-position: right center; }

  /* Coverage: horizontal swipe of tiles, no arrows. Re-assert padding:0 —
     .coverage__content owns the padding, so without this the base mobile
     .slide padding would stack on top and push the slide past one screen. */
  .slide--coverage { padding: 0; }
  .coverage__content { height: 100%; padding: calc(var(--nav-h) + 2.5rem) 0 3.5rem; }
  .coverage__ui { display: none; }   /* swipe instead of arrows on mobile */
  /* Full-height cards: the track grows to fill the slide, tiles stretch to it.
     A near-full-width tile with a slim right (and left, once scrolled) peek of
     the neighbour makes the horizontal swipe obvious. Mandatory x-snap lands
     one card at a time; drop the desktop right-edge fade. */
  .coverage__track {
    flex: 1; min-height: 0; align-items: stretch;
    gap: 0.85rem; padding: 0.5rem var(--edge) 0.5rem var(--edge);
    scroll-snap-type: x mandatory; scroll-padding-left: var(--edge);
    -webkit-mask-image: none; mask-image: none;
  }
  .mtile { flex-basis: 84vw; }
  /* Accent band stays a top tab; the logo + headline center in the tall body
     so the extra height reads as intentional rather than a void. */
  .coverage__track .mtile__main { flex: 1; justify-content: center; }

  /* Stack everything single-column */
  .scenarios__grid { grid-template-columns: 1fr; gap: 1rem; }
  .scenario { flex-direction: row; }
  .scenario__media { width: 40%; flex: none; aspect-ratio: 1 / 1; }
  .scenario__body { flex: 1; }

  .section-head--split { flex-direction: column; align-items: flex-start; gap: 1rem; }

  /* Map: pins are too small to tap on a phone, so the photo gallery stays
     open below the map and auto-cycles the pins (js/map.js), each lit by its
     sonar ring. Stack map + always-open card, kept compact to fit one screen.
     The intro's "select a location" prompt doesn't apply here, so hide it. */
  .slide--world .world__intro { display: none; }
  .world__stage { display: flex; flex-direction: column; gap: 0.6rem; margin-top: 0.9rem; }
  .world__map { max-width: min(100%, 76vw); }   /* smaller map leaves room for the card */
  .world__card {
    position: static; width: 100%; margin: 0;
    border: 1px solid var(--lux-black); border-top: 4px solid var(--scn);
  }
  .world__card-media { aspect-ratio: 20 / 9; }  /* shorter photo saves height */
  .world__card-cap { padding: 0.7rem 1rem 0.9rem; }
  .world__card-close { display: none; }         /* the gallery never closes on mobile */
}

/* Two-up scenarios on medium screens */
@media (min-width: 861px) and (max-width: 1100px) {
  .scenarios__grid { grid-template-columns: repeat(2, 1fr); }
}

/* ============================================================
   Reduced motion
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
  .deck { scroll-behavior: auto; }
  .slide__bg, .slide__content { transform: none !important; will-change: auto !important; }
  .scroll-cue__line::after, .map-pin.is-active .map-pin__ring { animation: none; }
  * { transition-duration: 0.01ms !important; }
}

/* ============================================================
   SCENARIOS DIRECTORY (/scenarios)
   Deep-blue ground (matches the Around-the-World slide) with light
   filter pills and light scenario tiles. Filtering (js/scenarios-filter.js)
   dims non-matching tiles to gray via .is-dimmed rather than hiding them.
   ============================================================ */
.directory {
  --ground: #0a1a3a;
  background: var(--ground); color: var(--on);
  min-height: 100vh;
  padding: calc(var(--nav-h) + clamp(1.75rem, 5vw, 3.5rem)) var(--edge) clamp(4rem, 10vh, 7rem);
}
.directory__inner { width: 100%; max-width: 1200px; margin: 0 auto; }
.directory__head { margin-bottom: clamp(1.5rem, 4vw, 2.5rem); }
.directory__sub {
  font-size: var(--text-md); font-weight: var(--weight-light);
  color: var(--on-dim); max-width: 52ch; margin: 1rem 0 0;
}

/* ---- Filters ------------------------------------------------------ */
.filters {
  display: flex; flex-direction: column; gap: 1rem;
  padding: clamp(1.1rem, 2.5vw, 1.5rem) 0;
  border-top: 1px solid rgba(255,255,255,0.16);
  border-bottom: 1px solid rgba(255,255,255,0.16);
  margin-bottom: clamp(2rem, 5vw, 3rem);
}
.filters__top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.filters__legend {
  font-size: var(--text-sm); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--on-dim);
}
.filters__group { display: flex; align-items: baseline; gap: 0.75rem 1.25rem; flex-wrap: wrap; }
.filters__label {
  flex: 0 0 auto; min-width: 9.5rem;
  font-size: var(--text-sm); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--on-dim);
}
.filters__pills { display: flex; flex-wrap: wrap; gap: 0.55rem; }

/* Filter control: an angular, hairline-outlined toggle in the Lux idiom — sharp
   ~3px corners (matching .btn / the Lux Button), not a fully-rounded pill, which
   is what reads as a generic component-library default. Blank (transparent) when
   off, filled (light) when on. Press nudges down 1px; focus shows the red ring. */
.pill {
  font-family: var(--font-sans); font-size: var(--text-sm);
  font-weight: var(--weight-regular); letter-spacing: var(--tracking-wide);
  text-transform: uppercase;
  padding: 0.5rem 1.05rem; border-radius: var(--radius-md);
  border: 1px solid rgba(255,255,255,0.45); background: transparent;
  color: var(--lux-white); cursor: pointer; white-space: nowrap;
  transition: background var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}
.pill:hover { background: rgba(255,255,255,0.12); border-color: var(--lux-white); }
.pill:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.pill:active { transform: translateY(1px); }
.pill.is-active {
  background: var(--lux-white); color: #0a1a3a; border-color: var(--lux-white);
}
.pill--reset {
  border-color: transparent; color: var(--on-dim);
  text-decoration: underline; text-underline-offset: 3px;
}
.pill--reset:hover { background: transparent; color: var(--lux-white); }

/* ---- Tile grid --------------------------------------------------- */
.directory__grid {
  list-style: none; margin: 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 2.5vw, 1.75rem);
}
@media (max-width: 980px) { .directory__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .directory__grid { grid-template-columns: 1fr; } }

/* Light card carrying its scenario accent via --scn (same language as the
   homepage .mtile). Dimming just swaps --scn to gray + desaturates the art. */
.scn-tile {
  --scn: var(--accent);
  --scn-ink: color-mix(in srgb, var(--scn) 62%, #16171a);
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--lux-white);
  border: 1px solid var(--lux-neutral-200);
  border-top: 4px solid var(--scn);
  transition: transform var(--duration-base) var(--ease-out),
              box-shadow var(--duration-base) var(--ease-standard),
              border-top-color var(--duration-base) var(--ease-standard);
}
.scn-tile:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.scn-tile__media { position: relative; aspect-ratio: 16 / 10; overflow: hidden; background: var(--lux-neutral-200); }
/* Game-number tag, upper-left of the featured image — the tile echo of the
   scenario hero's "No. N" badge (.scn-hero__no). Solid accent fill with the
   per-scenario readable ink (--scn-on); grays with the tile when filtered out. */
.scn-tile__no {
  position: absolute; top: 0; left: 0; z-index: 1;
  background: var(--scn); color: var(--lux-white);
  font-family: var(--font-display); font-weight: var(--weight-bold);
  font-size: 0.9rem; line-height: 1; letter-spacing: var(--tracking-tight);
  padding: 0.4em 0.6em;
}
.scn-tile__media img {
  width: 100%; height: 100%; object-fit: cover; object-position: center; display: block;
  transition: transform var(--duration-slow) var(--ease-out),
              filter var(--duration-base) var(--ease-standard),
              opacity var(--duration-base) var(--ease-standard);
}
.scn-tile:hover .scn-tile__media img { transform: scale(1.04); }
.scn-tile__body {
  display: flex; flex-direction: column; gap: 0.55rem;
  padding: 1.05rem 1.2rem 1.3rem; flex: 1 1 auto;
}
.scn-tile__kicker {
  font-size: var(--text-xs); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--scn-ink);
  transition: color var(--duration-base) var(--ease-standard);
}
.scn-tile__title {
  font-size: var(--text-xl); line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight); color: #16171a; margin: 0;
}
.scn-tile__desc {
  font-size: var(--text-sm); font-weight: var(--weight-light);
  color: var(--lux-neutral-600); line-height: var(--leading-snug);
  margin: 0; flex: 1 1 auto;
}
/* CTA: real .btn, filled with a darkened accent so white text stays legible on
   every scenario color (matches the homepage scenario-card CTA). */
.scn-tile__cta {
  align-self: flex-start; margin-top: 0.45rem; text-decoration: none;
  padding: 0.62rem 1.2rem;
  background: color-mix(in srgb, var(--scn) 60%, var(--lux-black));
  color: var(--lux-white); border-color: var(--scn);
  transition: background var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard);
}
.scn-tile__cta:hover { background: color-mix(in srgb, var(--scn) 76%, var(--lux-black)); }

/* Dimmed = doesn't match the active filters. Recolor to gray + desaturate.
   !important is required: each tile sets its accent via an inline `--scn`, and
   inline custom properties otherwise beat this rule — so the accent top-tab,
   kicker, and CTA would stay colored. Overriding --scn grays them all at once. */
.scn-tile.is-dimmed { --scn: var(--lux-neutral-500) !important; }
.scn-tile.is-dimmed .scn-tile__media img { filter: grayscale(1); opacity: 0.5; }
.scn-tile.is-dimmed .scn-tile__title { color: var(--lux-neutral-600); }

.directory__empty {
  margin: 2.5rem 0 0; color: var(--on-dim); font-size: var(--text-md);
}

/* Stack filter labels above their pills on narrow screens. */
@media (max-width: 640px) {
  .filters__group { flex-direction: column; align-items: stretch; gap: 0.5rem; }
  .filters__label { min-width: 0; }
}

/* ---- Fixed nav treatment on the directory --------------------------------
   The floating nav (themed by main.js for the homepage slides) has no slide to
   read here, so it renders transparent at top and a translucent BLACK backdrop
   on scroll. Instead we keep it transparent and lay one fixed blue gradient
   behind it: solid page-blue through the nav, then fading to transparent so the
   tiles dissolve into the ground as they scroll up under the bar. */
/* The directory is a single dark-blue ground (no deck/JS to drive it), so set
   its body backstop to match — otherwise the global black body shows as a strip
   below the content on mobile (under the iOS floating URL bar). */
body.page-scenarios { background: #0a1a3a; }
body.page-scenarios .nav::before { opacity: 0; }                        /* kill main.js's backdrop; show the blue below */
body.page-scenarios .nav { border-bottom-color: transparent !important; } /* override main.js's inline scroll hairline */
body.page-scenarios::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0;
  height: calc(var(--nav-h) + 2.75rem);
  background: linear-gradient(180deg,
    #0a1a3a 0,
    #0a1a3a var(--nav-h),          /* solid behind the nav bar */
    rgba(10, 26, 58, 0) 100%);     /* then fade the last band to transparent */
  z-index: calc(var(--z-sticky) - 1);   /* under the nav (100), over the content */
  pointer-events: none;
}

/* When the mobile menu is open, the bar keeps its scroll-dependent (often
   transparent) background, which clashes with the solid black menu below it.
   Force it to a solid black panel with white marks so it reads as one clean
   surface with the menu. !important beats main.js's inline vars and the
   page-scenarios ::before override above. */
.nav.is-menu-open { --nav-fg: var(--lux-white) !important; border-bottom-color: transparent !important; }
.nav.is-menu-open::before { background: var(--lux-black) !important; opacity: 1 !important; }

/* ============================================================
   INDIVIDUAL SCENARIO DECK (/scenarios/<slug>)
   Reuses the homepage deck scaffolding (.deck/.slide/.carousel/.acard) with a
   few scenario-specific pieces: illustration hero, story carousel placeholder,
   why-play photo slide, and movie-style credits. Accent comes from --scn set on
   the deck root.
   ============================================================ */

/* Bottom "safe zone" reserved on every deck slide so the persistent Game Kit
   CTA (fixed, lower-left) never sits over any text. Grows with the iOS safe area. */
.deck { --cta-safe: calc(7rem + env(safe-area-inset-bottom, 0px)); }

/* --- Slide 1: illustration hero (reuses .hero__* typography) --- */
.slide--scn-hero { align-items: flex-end; background: var(--lux-black); padding-bottom: var(--cta-safe); }
.scn-hero__content { padding-bottom: 0; }   /* clearance handled by the slide's --cta-safe */
.scn-hero__img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center; display: block;
  background: var(--lux-neutral-900);
}
.scn-hero__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,0.30) 0%, rgba(0,0,0,0.15) 38%, rgba(0,0,0,0.85) 100%);
}
/* Game-number badge (e.g. "No. 1") — accent-filled chip above the kicker, in
   the spirit of the original riskgaming page's number box. --scn and --scn-on
   (the auto contrast-picked label color: white on dark accents, near-black on
   light ones — see readableInk() in _data/scenarios.js) are set on the deck root. */
.scn-hero__no {
  display: inline-block;
  background: var(--scn); color: var(--scn-on, var(--lux-white));
  font-family: var(--font-display); font-weight: var(--weight-bold);
  font-size: clamp(1rem, 2.6vw, 1.35rem); line-height: 1;
  letter-spacing: var(--tracking-tight);
  padding: 0.4em 0.6em; margin: 0 0 1rem;
}
/* Metadata tags (type · time · players). Borrow the Scenarios filter-pill look
   (.pill) — bordered white chips — so they read clearly over the illustration,
   with a faint translucent fill + blur for legibility on bright art. Static
   presentation, not interactive, so no hover/cursor. */
.scn-hero__tags {
  list-style: none; margin: 0 0 1rem; padding: 0;
  display: flex; flex-wrap: wrap; gap: 0.55rem;
}
.scn-tag {
  font-family: var(--font-sans); font-size: var(--text-sm);
  font-weight: var(--weight-regular); letter-spacing: var(--tracking-wide);
  text-transform: uppercase; white-space: nowrap; color: var(--lux-white);
  padding: 0.5rem 1.05rem; border-radius: var(--radius-md);
  border: 1px solid rgba(255,255,255,0.45);
  background: rgba(255,255,255,0.1);
  backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px);
}
.scn-hero__desc { color: var(--lux-neutral-100); max-width: 40ch; }

/* --- Persistent Game Kit CTA (floats lower-left on every slide) --- */
.deck-cta {
  position: fixed; left: var(--edge);
  bottom: calc(clamp(1.5rem, 4vh, 2.5rem) + env(safe-area-inset-bottom, 0px));
  z-index: calc(var(--z-sticky) - 1);   /* under the nav (100), over slide content */
  box-shadow: var(--shadow-lg);
  text-align: center;   /* center the label when it wraps to two lines */
}
.deck-cta__short { display: none; }

/* --- Slide 2: story (vertical stack) ---
   Each beat is its own full-height slide (see scenario-deck.njk); they stack and
   are reached by normal vertical scroll — settle-snapped like every other slide —
   so there are no arrows or progress dots. The card fills the viewport height and
   pins its text to the bottom (base .acard is display:flex; align-items:flex-end). */
.slide--scn-story { padding: 0; display: block; background: var(--lux-black); }
.slide--scn-story .acard { min-height: 100vh; min-height: 100svh; }
/* Reserve the CTA safe zone below the story text so the fixed Game Kit button
   never covers it. */
.slide--scn-story .acard__content { padding-bottom: var(--cta-safe); }
/* Cards without a supplied illustration get an accent-tinted ground so the
   slide still reads as intentional until real story art is dropped in. */
.acard--story {
  background: linear-gradient(155deg,
    color-mix(in srgb, var(--scn) 55%, var(--lux-black)) 0%,
    var(--lux-black) 88%);
}
.acard--story[data-has-img] { background: var(--lux-neutral-900); }
/* Illustration cards: an even black wash over the whole photo (plus the base
   bottom-weighted gradient) so the white story text stays legible on busy art. */
.acard--story[data-has-img] .acard__scrim {
  background:
    linear-gradient(180deg, rgba(0,0,0,0.30) 0%, rgba(0,0,0,0.18) 40%, rgba(0,0,0,0.82) 100%),
    rgba(0,0,0,0.22);
}
/* "The Story" section title on the first story slide — the story-section echo of
   the "Why Play?" header (.section-head > .world__title). The story cards pin
   their text to the bottom, so this sits absolutely at the TOP, aligned to the
   same centered 1200px grid as the beat text below it. */
.acard__head {
  position: absolute; z-index: 2; left: 0; right: 0;
  top: calc(var(--nav-h) + clamp(1.5rem, 5vh, 3rem));
  width: 100%; max-width: calc(1200px + 2 * var(--edge));
  margin: 0 auto; padding: 0 var(--edge);
}
.acard__headline--story {
  font-size: clamp(1.6rem, 3.4vw, 2.9rem); line-height: var(--leading-snug);
  font-weight: var(--weight-light); max-width: 24ch; text-indent: 0;
}

/* --- Slide 3: why play --- */
.slide--why { background: #0a1a3a; padding-bottom: var(--cta-safe); }
.why__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }
.why__scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(6,14,32,0.55) 0%, rgba(6,14,32,0.80) 100%);
}
.why__lessons {
  list-style: none; margin: clamp(1.5rem, 3vw, 2.25rem) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.5rem, 3vw, 2.5rem);
}
.why__lesson-title {
  font-size: var(--text-lg); line-height: var(--leading-snug);
  letter-spacing: var(--tracking-tight); color: var(--lux-white); margin: 0 0 0.5rem;
}
.why__lesson-title::before {
  content: ""; display: block; width: 2rem; height: 3px;
  background: var(--scn); margin-bottom: 0.9rem;
}
.why__lesson-text {
  font-size: var(--text-md); font-weight: var(--weight-light);
  color: var(--lux-neutral-200); line-height: var(--leading-relaxed); margin: 0;
}

/* --- Slide 4: credits (all black, centered, movie-style) --- */
.slide--credits { background: var(--lux-black); padding-bottom: var(--cta-safe); }
.slide--credits .slide__content { text-align: center; }
.credits { width: 100%; max-width: 620px; margin: 0 auto; }
.credits__title {
  font-size: clamp(1.6rem, 4vw, 2.6rem); line-height: 1.1;
  letter-spacing: var(--tracking-tight); color: var(--lux-white);
  margin: 0 0 clamp(2rem, 5vh, 3.5rem);
}
.credits__list { margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1.3rem; }
.credits__row { display: flex; flex-direction: column; align-items: center; gap: 0.25rem; }
/* dt/dd carry default browser margins (dd has margin-inline-start:40px) which
   pushed the names right of the roles — zero them so both sit dead-center. */
.credits__role, .credits__name { margin: 0; }
.credits__role {
  font-size: var(--text-xs); text-transform: uppercase;
  letter-spacing: var(--tracking-caps); color: var(--lux-neutral-400);
}
.credits__name { font-size: var(--text-lg); color: var(--lux-white); }
.credits__foot {
  margin: clamp(2rem, 5vh, 3.5rem) 0 0; color: var(--lux-neutral-500);
  font-size: var(--text-sm); letter-spacing: var(--tracking-wide);
}

/* The credits slide is a fixed height that can't scroll, so on phones a long
   credit list (e.g. Experimental Automata) ran past the bottom edge and was
   clipped. Tighten the vertical rhythm — title/foot margins and the gaps
   between roles — and ease the name size so the full list fits. The vh-based
   clamps keep compressing further on shorter screens. */
@media (max-width: 860px) {
  /* Reclaim top padding (the block is centered and only needs nav clearance),
     which matters most on short screens where the fixed slide padding eats a
     third of the height. */
  .slide--credits { padding-top: calc(var(--nav-h) + 1rem); }
  .credits__title { margin-bottom: clamp(0.9rem, 2.5vh, 1.75rem); }
  .credits__list  { gap: clamp(0.55rem, 1.5vh, 1.1rem); }
  .credits__name  { font-size: var(--text-md); }
  .credits__foot  { margin-top: clamp(0.9rem, 2.5vh, 1.75rem); }
}

/* ============================================================
   CONTACT (/contact) — one image-free dark slide. Editorial column; each row
   is a bold title + short guidance + email/link, spaced apart (no dividers).
   ============================================================ */
.slide--contact { background: var(--lux-black); }
.contact__content { max-width: 720px; margin: 0 auto; }
.contact__list {
  margin: clamp(2rem, 5vh, 3rem) 0 0; padding: 0;
  display: flex; flex-direction: column; gap: clamp(1.75rem, 4vh, 2.75rem);
}
.contact__row { margin: 0; padding: 0; }
/* Row title — the prominent anchor so each row's purpose is obvious at a glance. */
.contact__label {
  display: block; margin: 0 0 0.4rem;
  font-size: var(--text-xl); font-weight: var(--weight-bold);
  letter-spacing: var(--tracking-tight); color: var(--lux-white);
  line-height: var(--leading-snug);
}
/* Short guidance under the label — dimmer than the value, brighter than the
   label. margin:0 also clears the browser's default 40px dd indent. */
.contact__desc {
  margin: 0 0 0.6rem; max-width: 48ch;
  font-size: var(--text-sm); font-weight: var(--weight-light);
  color: var(--lux-neutral-300); line-height: var(--leading-snug);
}
.contact__value { margin: 0; font-size: var(--text-lg); color: var(--lux-white); }
.contact__value a {
  color: var(--lux-white); text-decoration: none;
  border-bottom: 1px solid rgba(255,255,255,0.35); padding-bottom: 2px;
  transition: border-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}
.contact__value a:hover { border-bottom-color: var(--accent); }

@media (max-width: 860px) {
  .slide--scn-story { padding: 0; height: 100%; }
  /* Each story beat is a snap slide sized to the deck; fill it exactly. */
  .slide--scn-story .acard { min-height: 0; height: 100%; }
  .why__lessons { grid-template-columns: 1fr; gap: 1.5rem; }

  /* Mobile: the Game Kit CTA is a single button CENTERED at the bottom of the
     screen. Every slide reserves --cta-safe at the bottom (story reserves extra
     for the dots that sit just above it), so no page content is ever underneath
     the button. Full "Download Game Kit" label is kept (there's room here). */
  .deck-cta {
    left: 50%; right: auto; transform: translateX(-50%);
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
  }
  .slide--scn-story .acard__content { padding-bottom: calc(var(--cta-safe) + 1.5rem); }
}
