/*
 * mobile.css — vertical HUD card stack for the mobile homepage.
 *
 * Loaded by index.html on every page (small payload). Class names
 * are scoped under `.mobile-journey` so the rules only "activate"
 * when MobileJourney renders. Mirrors public/cinema.css conventions
 * (plain CSS, no Tailwind dependency, semantic class naming).
 *
 * The mobile-vs-desktop branch happens in code (useIsMobile in
 * CinemaHomePreview.tsx) — not via CSS media queries. This means
 * mobile.css doesn't need to compete with cinema.css; they coexist
 * but only one set of class names is ever applied at a time.
 */

/* ============================================================
 * Brand color constants (mirrors cinema.css for portability —
 * mobile.css should be independently inspectable).
 * ============================================================ */
:root {
  --mobile-plasma-blue: #48caff;
  --mobile-plasma-blue-dim: rgba(72, 202, 255, 0.6);
  --mobile-plasma-blue-fill: rgba(72, 202, 255, 0.12);
  --mobile-bg-base: #050507;        /* neutral dark substrate */
  --mobile-bg-tint: #07080e;        /* slight plasma tint over neutral */
  --mobile-text-primary: #E5E7EB;
  --mobile-text-muted: #A8CFEC;
  --mobile-accent-gold: #CCA866;
  --mobile-accent-cyan: #22D3EE;
}

/* ============================================================
 * Journey container — full-page scroll-snap host.
 * ============================================================ */
.mobile-journey {
  /* Natural flow inside main — body scrolls through all 6 cards and
     the footer appends at the end naturally. */
  width: 100%;
  background: var(--mobile-bg-base);
  background-image:
    radial-gradient(
      ellipse at top,
      var(--mobile-bg-tint) 0%,
      var(--mobile-bg-base) 60%
    );
  scroll-behavior: smooth;
}

/* Scroll-snap moved to the BODY (the actual scroll container now that
   journey is in natural flow). Scoped via :has() so it ONLY activates
   when the mobile journey is rendered — no leak to other pages. Cards
   keep their scroll-snap-align: center to act as snap targets. */
body:has(.mobile-journey) {
  scroll-snap-type: y proximity;
}

/* ============================================================
 * Card base — every station card uses this. Full viewport height,
 * scroll-snap stop, centered content column with breathing room.
 * ============================================================ */
.mobile-card {
  min-height: 100vh;
  width: 100%;
  scroll-snap-align: center;
  scroll-snap-stop: normal;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 64px 6vw 48px;          /* 64px top accounts for fixed header */
  box-sizing: border-box;
  position: relative;
  /* isolation: isolate creates a stacking context so .mobile-card-bg's
     z-index: -1 stays inside the card and doesn't sink below the
     page background. Combined with position: relative, this makes the
     card a self-contained layer host. */
  isolation: isolate;
  /* Entrance animation — opacity + slide-up, triggered by adding
     .is-visible class via IntersectionObserver. */
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 400ms ease-out, transform 400ms ease-out;
}

/* Bg image layer — extracted from .mobile-card itself so it can bleed
   to 100vw on tablet while the card content stays capped at 640px.
   Sits at z-index: -1 BEHIND content (and behind hero's scrim ::before
   at z:0), contained by the card's isolation: isolate stacking ctx. */
.mobile-card-bg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  z-index: -1;
  pointer-events: none;
}

.mobile-card.is-visible {
  opacity: 1;
  transform: translateY(0);
}

/* Reduced motion — preserve readability, drop motion entirely. */
@media (prefers-reduced-motion: reduce) {
  .mobile-card,
  .mobile-card.is-visible {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ============================================================
 * Placeholder rule used during early scaffolding tasks. Removed
 * once real station/hero components render their own content.
 * ============================================================ */
.mobile-journey-placeholder {
  color: var(--mobile-text-primary);
  font-family: 'Roboto', sans-serif;
  text-align: center;
}

/* ============================================================
 * Station card — HUD frame block (top) + bullets + CTAs (below).
 * ============================================================ */
.mobile-station-card {
  /* Override default mobile-card centering: top-aligned column
     so frame sits high and bullets/CTAs flow naturally below. */
  justify-content: flex-start;
  gap: 24px;
}

/* HUD frame block — near-square PNG with content positioned in
   its safe area via the journey config's inset percentages. */
.mobile-station-frame {
  position: relative;
  width: 92vw;
  max-width: 540px;
  flex-shrink: 0;
}

.mobile-station-frame-png {
  display: block;
  width: 100%;
  height: auto;       /* PNG's natural aspect dictates the frame's height,
                         giving absolute children a real positioning box */
  pointer-events: none;
  user-select: none;
}

.mobile-station-frame-content {
  position: absolute;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  text-align: left;
  color: var(--mobile-text-primary);
  padding: 0;
}

/* Slate — rune above slate-word, tight stack, brand-cosmology gold
   for the slate word when the station's accent is gold; otherwise
   inherits the accent color. */
.mobile-station-slate {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-bottom: 12px;
}

.mobile-station-rune {
  font-family: 'Noto Sans Old Hungarian', 'Roboto Condensed', sans-serif;
  font-size: 14px;
  letter-spacing: 0.15em;
  color: var(--mobile-plasma-blue);
  text-shadow: 0 0 6px var(--mobile-plasma-blue-dim);
}

.mobile-station-slate-word {
  font-family: 'Orbitron', sans-serif;
  font-weight: 600;
  font-size: 13px;
  letter-spacing: 0.35em;
  text-transform: uppercase;
  color: var(--mobile-accent-gold);
  opacity: 0.92;
}

.mobile-station-kicker {
  font-family: 'Roboto Condensed', sans-serif;
  font-size: 11px;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--mobile-text-muted);
  margin: 0 0 10px;
}

.mobile-station-headline {
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: 22px;
  line-height: 1.15;
  margin: 0;
  color: var(--mobile-text-primary);
}

.mobile-station-headline .mobile-headline-accent {
  color: var(--mobile-plasma-blue);
}

/* Per-accent override for the headline accent word — matches the
   station's accentColor field from config/journey.ts. */
.mobile-accent-gold .mobile-headline-accent { color: var(--mobile-accent-gold); }
.mobile-accent-blue .mobile-headline-accent { color: var(--mobile-plasma-blue); }
.mobile-accent-cyan .mobile-headline-accent { color: var(--mobile-accent-cyan); }

/* Per-accent override for the slate-word: only Production (gold)
   keeps the gold; other stations override to their accent. */
.mobile-accent-blue .mobile-station-slate-word { color: var(--mobile-plasma-blue); }
.mobile-accent-cyan .mobile-station-slate-word { color: var(--mobile-accent-cyan); }

/* Bullets — diamond markers, full-width comfortable readout. */
.mobile-station-bullets {
  list-style: none;
  padding: 0;
  margin: 0;
  width: 100%;
  max-width: 540px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  color: var(--mobile-text-primary);
  font-family: 'Roboto', sans-serif;
  font-size: 16px;
  line-height: 1.45;
}

.mobile-station-bullets li {
  display: flex;
  gap: 12px;
  align-items: flex-start;
}

.mobile-bullet-marker {
  color: var(--mobile-plasma-blue);
  flex-shrink: 0;
  font-size: 12px;
  line-height: 1.5;
}

.mobile-accent-gold .mobile-bullet-marker { color: var(--mobile-accent-gold); }
.mobile-accent-cyan .mobile-bullet-marker { color: var(--mobile-accent-cyan); }

/* CTAs — unified plasma blue across all stations. Primary = solid
   fill; secondary = outlined. Full-width stacked. 44px+ tap target. */
.mobile-station-ctas {
  width: 100%;
  max-width: 540px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.mobile-cta {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 48px;
  padding: 12px 20px;
  font-family: 'Orbitron', sans-serif;
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  text-decoration: none;
  border-radius: 2px;
  transition: background 200ms ease, color 200ms ease;
}

.mobile-cta-primary {
  background: var(--mobile-plasma-blue);
  color: #050507;
  border: 1px solid var(--mobile-plasma-blue);
}

.mobile-cta-primary:active {
  background: var(--mobile-plasma-blue-dim);
}

.mobile-cta-secondary {
  background: transparent;
  color: var(--mobile-plasma-blue);
  border: 1px solid var(--mobile-plasma-blue);
}

.mobile-cta-secondary:active {
  background: var(--mobile-plasma-blue-fill);
}

/* ============================================================
 * Hero card — "operator's HUD ingress."
 *
 * Cinematic-HUD composition that maps the desktop hero's slate
 * vocabulary onto portrait phone viewports. CSS-rendered corners,
 * tick, rules, and bullet markers (no images beyond the bg). Boot-
 * sequence ingress staggers elements in over ~2s on first paint.
 *
 * Element vocabulary:
 *   .mobile-hero-corner-{tl,tr,bl,br}  gold L-bracket corner cuts
 *   .mobile-hero-meta-{top,bottom}     HUD metadata rows
 *   .mobile-hero-slate                 tick + rune + wordmark
 *   .mobile-hero-rule                  gradient line + diamond pip
 *   .mobile-hero-headline              staggered line reveal
 *   .mobile-hero-list                  rotated-square bullets
 * ============================================================ */
.mobile-hero-card {
  /* Override .mobile-card centering: top-aligned, asymmetric column.
     Override the .mobile-card opacity/translateY entrance too — hero
     handles its own staggered boot sequence per element.
     Bg image now lives on .mobile-card-bg child element (extracted so
     it can bleed to 100vw on tablet); .mobile-hero-card no longer
     paints its own bg directly. */
  justify-content: flex-start;
  align-items: stretch;
  padding: 72px 28px 100px 54px;  /* extra top pad nudges the blok off the nav line */
  gap: 0;
  overflow: hidden;
  opacity: 1;
  transform: none;
  transition: none;
}

/* Lighter scrim — let the sigil bg COMPOSE through the lower half.
   Top stays darker so headline wins legibility; mid + bottom lighter
   so the sigil and circuitry walls breathe as part of the image. */
.mobile-hero-card::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(5, 5, 7, 0.70) 0%,
    rgba(5, 5, 7, 0.45) 35%,
    rgba(5, 5, 7, 0.15) 65%,
    rgba(5, 5, 7, 0.45) 100%
  );
  pointer-events: none;
  z-index: 0;
}

/* Lift all hero content above the scrim. (Original rule restored —
   the earlier :not(.mobile-card-bg) version had specificity 0,2,0
   which silently beat .mobile-hero-corner (0,1,0) and forced the
   HUD frame brackets into position: relative, making them flex items
   and breaking the entire card layout. Instead of excluding bg here,
   bg is given its own higher-specificity override below.) */
.mobile-hero-card > * {
  position: relative;
  z-index: 1;
}

/* Bg layer override — more specific (0,2,0) than the > * lift (0,1,0)
   so the bg stays at position: absolute / z-index: -1 (below scrim,
   below content). The base .mobile-card-bg rule at the top of this
   file sets position+z-index defensively too, but that's specificity
   0,1,0 which the > * lift would otherwise override. */
.mobile-hero-card > .mobile-card-bg {
  position: absolute;
  z-index: -1;
}

/* ─── HUD frame (operator's custom art, TL + BR brackets) ───
   The frame is defined by two corner brackets diagonally opposite:
   - TL: tech_bracket_half.png — top-left, arms extending right + down
   - BR: tech_bracket_half_flipped.png (180°) — bottom-right, arms
         extending left + up
   Together they imply a full rectangular HUD frame. Both sit BENEATH
   content (z-index: 0). TL pulled up so top arm anchors at the nav
   line; BR positioned so the DW//001//MANIFEST label can attach to
   the inside of its top arm. */
.mobile-hero-corner {
  position: absolute;
  pointer-events: none;
  z-index: 0;                   /* below content (z:1), above scrim (auto) */
}
/* HERO (locked v1): TL + BR bracket pair (tech_bracket_half + flipped).
   These rules apply to MobileHero ONLY because they are NOT overridden
   below for .mobile-scene-station. */
.mobile-hero-corner-tl {
  top: 64px;
  bottom: 50%;
  left: 0;
  width: 180px;
  background-image: url('/icons/tech_bracket_half.png');
  background-size: contain;
  background-position: left top;
  background-repeat: no-repeat;
}
.mobile-hero-corner-tr {
  display: block;
  top: auto;
  bottom: 413px;                /* locked value from commit 9659761 */
  right: 0;
  left: auto;
  width: 180px;
  height: 378px;
  background-image: url('/icons/tech_bracket_half_flipped.png');
  background-size: contain;
  background-position: right bottom;
  background-repeat: no-repeat;
}
.mobile-hero-corner-bl,
.mobile-hero-corner-br {
  display: none;
}

/* STATION SCENE override: full LCD-screen HUD frame
   (hudframe_narrow.png) replaces the bracket pair. Hero is untouched
   because these rules are scoped to .mobile-scene-station.

   Frame is positioned at top:56 (below header) at full card width,
   with height auto-derived from the asset's native aspect ratio
   (1080:1780). No distortion — sides + corners stay pixel-correct.
   Below the frame the bg's production-scene content (camera/chair/
   light beam) shows naturally as the lower composition. */
.mobile-scene-station .mobile-hero-corner-tl {
  top: 76px;
  left: 0;
  right: 0;
  bottom: auto;
  width: auto;
  height: auto;
  aspect-ratio: 1080 / 1780;       /* matches hudframe_narrow.png native */
  background-image: url('/icons/hudframe_narrow.png');
  background-size: 100% 100%;
  background-position: center;
  background-repeat: no-repeat;
}
.mobile-scene-station .mobile-hero-corner-tr {
  display: none;               /* full frame replaces the BR bracket */
}

/* Station card padding override — symmetric since there's no left
   bracket asymmetry to clear like there was on hero. */
.mobile-scene-station {
  padding: 100px 32px 100px 32px;
  /* CSS variable holding the frame's bottom edge in viewport coords —
     used to position the DW// text at the inside-bottom-left of the
     HUD frame. Frame is top:76 + (100vw * 1780/1080). */
  --mobile-frame-bottom: calc(76px + 100vw * 1780 / 1080);
}

/* Station CTAs — ANCHORED absolute to the HUD frame's bottom area so
   they sit at the SAME visual position across every scene regardless
   of content above. Sits ~16px above the DW// text. */
.mobile-scene-station .mobile-scene-ctas {
  position: absolute;
  /* Anchored by BOTTOM (not top) so the bottom-most CTA always sits
     at the same y position regardless of 1 or 2 CTAs. With JSX
     ordering the section-nav button LAST, every scene's bottom CTA
     is the arrow-button consistently. */
  bottom: calc(100vh - var(--mobile-frame-bottom) + 96px);
  top: auto;
  left: 12px;
  right: 52px;
  transform: translateX(-15px);
  align-items: center;
  z-index: 1;
}
.mobile-scene-station .mobile-cta {
  max-width: 300px;
  min-height: 54px;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: 0.18em;
}
/* ALL station CTAs use the outlined-on-dark style (no solid fill).
   Operator: "all the buttons should look the same as the production
   button". Both primary and secondary share the outlined treatment. */
.mobile-scene-station .mobile-cta-primary,
.mobile-scene-station .mobile-cta-secondary {
  background: transparent;
  color: var(--mobile-plasma-blue);
  border: 1px solid var(--mobile-plasma-blue);
}
.mobile-scene-station .mobile-cta-primary:active,
.mobile-scene-station .mobile-cta-secondary:active {
  background: var(--mobile-plasma-blue-fill);
}

/* Horizontal divider under the headline — REAL breathing room between
   Fabrication and the divider, and between the divider and bullets.
   Bumped to 24px both sides (was 12 before any edits — now visibly
   spaced). */
.mobile-scene-station .mobile-hero-rule-small {
  margin: 24px 0 24px;
}

/* Station headline — let the segments flow inline so the accent word
   sits on the same line as adjacent words and wraps naturally based
   on viewport width. The AFTER segment (last span) is nowrap so its
   words always stay together — e.g. "into action" doesn't break
   apart, gets wrapped to its own line as a unit if it can't fit
   with what comes before. Hero keeps the locked 3-line stack. */
.mobile-scene-station .mobile-hero-headline {
  display: block;
}
.mobile-scene-station .mobile-hero-headline-line {
  display: inline;
}
.mobile-scene-station .mobile-hero-headline-line:last-child {
  white-space: nowrap;
}

/* DW// text — repositioned for stations to inside-bottom-left of the
   HUD frame (was attached to the hero's BR bracket area). */
.mobile-scene-station .mobile-hero-meta-top {
  /* Lands the DW// text along the inside bottom edge of the HUD frame,
     just above the hatching decoration. */
  top: calc(var(--mobile-frame-bottom) - 60px);
  bottom: auto;
  left: 64px;
  right: auto;
  flex-direction: row;          /* dot on the LEFT (matches BL corner anchor) */
}

/* ─── Top HUD metadata bar ───────────────────────────────────── */
.mobile-hero-meta-top {
  /* Attached to the BR bracket — sits just ABOVE the bracket's TOP
     arm, matching the gap that the TL bracket has between its top arm
     and the rune lines. Dot on the right end so it visually meets the
     bracket's right vertical bar. Right offset cleared so the bracket's
     diagonal chamfer doesn't cut into the text when it rises. */
  position: absolute;
  top: calc(50% + 16px);        /* locked value from commit 9659761 */
  bottom: auto;
  left: auto;
  right: 56px;
  display: flex;
  flex-direction: row-reverse;  /* dot ends up at the right (corner) edge */
  align-items: center;
  gap: 10px;
  z-index: 2;
  font-family: 'Roboto Condensed', 'Roboto', sans-serif;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--mobile-plasma-blue);
  opacity: 0.85;
}
.mobile-hero-meta-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--mobile-accent-cyan);
  box-shadow: 0 0 8px var(--mobile-accent-cyan),
              0 0 14px rgba(34, 211, 238, 0.55);
  animation: mobileHeroDotPulse 2.2s ease-in-out infinite;
}
.mobile-hero-meta-text {
  display: inline-block;
  white-space: nowrap;
}
@keyframes mobileHeroDotPulse {
  0%, 100% { opacity: 0.45; transform: scale(0.92); }
  50%      { opacity: 1;    transform: scale(1.08); }
}

/* ─── Slate (vertical plasma tick + rune + gold wordmark) ───── */
.mobile-hero-slate {
  display: flex;
  align-items: stretch;
  gap: 16px;
  margin-top: 36px;             /* sits just under the bracket's top arm */
  margin-bottom: 0;
}
.mobile-hero-slate-tick {
  width: 2px;
  background: linear-gradient(
    180deg,
    transparent 0%,
    var(--mobile-plasma-blue) 18%,
    var(--mobile-plasma-blue) 82%,
    transparent 100%
  );
  box-shadow: 0 0 8px var(--mobile-plasma-blue),
              0 0 16px var(--mobile-plasma-blue-dim);
  flex-shrink: 0;
}
.mobile-hero-slate-stack {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0;                       /* zero gap — rune sits flush above wordmark */
  padding: 2px 0;
  /* Lift rune + wordmark up while keeping the tick anchored in
     place (translate doesn't affect siblings' layout). */
  transform: translateY(-14px);
}
.mobile-hero-slate-rune {
  font-family: 'Noto Sans Old Hungarian', 'Roboto Condensed', sans-serif;
  font-weight: 400;
  font-size: 16px;              /* up from 13 — runes read with more presence */
  line-height: 1;               /* tight line-height closes gap to wordmark */
  letter-spacing: 0.32em;
  color: var(--mobile-plasma-blue);
  text-shadow: 0 0 6px var(--mobile-plasma-blue-dim);
  white-space: nowrap;
}
.mobile-hero-slate-word {
  font-family: 'Orbitron', sans-serif;
  font-weight: 300;
  font-size: 20px;
  line-height: 1;               /* tight — closes vertical gap to rune above */
  letter-spacing: 0.52em;
  text-transform: uppercase;
  color: var(--mobile-accent-gold);
  text-shadow: 0 0 10px rgba(204, 168, 102, 0.35);
  /* Pull right margin a tiny bit because letter-spacing pushes the
     last letter's bearing visually past the bounding box edge. */
  margin-right: -0.52em;
}

/* ─── Divider — gradient line with gold diamond pip ─────────── */
.mobile-hero-rule {
  position: relative;
  height: 1px;
  width: 100%;
  margin: 6px 0 14px;           /* tucks divider just under the vertical tick;
                                    everything below cascades up with it */
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(72, 202, 255, 0.25) 6%,
    var(--mobile-plasma-blue) 50%,
    rgba(72, 202, 255, 0.25) 94%,
    transparent 100%
  );
}
.mobile-hero-rule span {
  position: absolute;
  /* Card padding is asymmetric (left:54, right:28). 50% of the divider
     puts the diamond 13px right of viewport center. The bg sigil's
     vertical light beam is at viewport center — subtract that 13px
     offset so the diamond aligns with the beam. */
  left: calc(50% - 14px);
  top: 50%;
  width: 7px;
  height: 7px;
  transform: translate(-50%, -50%) rotate(45deg);
  background: var(--mobile-plasma-blue);
  box-shadow: 0 0 10px var(--mobile-plasma-blue),
              0 0 22px var(--mobile-plasma-blue-dim);
}
.mobile-hero-rule-small {
  margin: 12px 0;
  /* opacity removed — match upper divider's visibility */
}
/* Diamond pip on the small rule matches the upper one's size + glow now. */

/* ─── Headline — DOMINANT. Three discrete lines, staggered reveal.
   Scale way up — hero deserves the visual weight. ─────────── */
.mobile-hero-headline {
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: clamp(40px, 12.5vw, 58px);
  line-height: 0.94;
  letter-spacing: -0.015em;
  margin: 0;
  color: var(--mobile-text-primary);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.mobile-hero-headline-line {
  display: block;
}
.mobile-hero-headline-accent {
  font-style: italic;
  font-weight: 700;
  /* Match desktop hero exactly: cinema.css line 340 uses #48caff
     (plasma blue brand constant), NOT #22D3EE (cyan station accent).
     The hero specifically overrides cyan → plasma blue. */
  color: var(--mobile-plasma-blue);
  text-shadow:
    0 0 8px rgba(72, 202, 255, 0.55),
    0 0 22px rgba(72, 202, 255, 0.32),
    0 0 48px rgba(72, 202, 255, 0.18);
}

/* ─── Subline — single line, pipe-separated sentences ──────── */
.mobile-hero-subline {
  margin: 0;
  font-family: 'Roboto Condensed', sans-serif;
  font-style: italic;
  font-weight: 400;
  font-size: 14px;              /* slightly smaller so the line fits */
  letter-spacing: 0.04em;
  color: var(--mobile-text-muted);
  line-height: 1.4;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;      /* graceful fail if a viewport is too narrow */
}
.mobile-hero-subline-sep {
  color: var(--mobile-plasma-blue);
  opacity: 0.55;
  margin: 0 8px;
}

/* ─── Bullets — rotated-square markers in plasma blue ──────── */
.mobile-hero-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;              /* tightened — reclaims 14px of vertical space */
  display: flex;
  flex-direction: column;
  gap: 10px;
  font-family: 'Roboto', sans-serif;
  font-size: 17px;              /* up from 14 — more presence */
  line-height: 1.45;
  color: var(--mobile-text-primary);
}
.mobile-hero-list li {
  position: relative;
  padding-left: 26px;
}
.mobile-hero-list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: 0.55em;
  width: 8px;
  height: 8px;
  background: var(--mobile-plasma-blue);
  transform: rotate(45deg);
  box-shadow: 0 0 8px var(--mobile-plasma-blue-dim);
}

/* ─── Bottom HUD coord ─────────────────────────────────────── */
.mobile-hero-meta-bottom {
  position: absolute;
  bottom: 56px;                 /* sits above the BL/BR corners */
  left: 0;
  right: 0;
  text-align: center;
  z-index: 2;
  font-family: 'Roboto Condensed', 'Roboto', sans-serif;
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--mobile-plasma-blue);
  opacity: 0.6;
}

/* ─── Scroll cue ───────────────────────────────────────────── */
.mobile-hero-scroll-cue {
  position: absolute;
  bottom: 28px;
  /* Aligned to the same off-center axis as the divider diamonds + the
     bg sigil's vertical light beam. */
  left: calc(50% - 14px);
  transform: translateX(-50%);
  z-index: 2;
  font-size: 22px;              /* larger — reads clearly at viewport scale */
  line-height: 1;
  color: var(--mobile-plasma-blue);
  text-shadow: 0 0 8px var(--mobile-plasma-blue-dim);
  opacity: 0.7;
  animation: mobileHeroScrollPulse 2.4s ease-in-out infinite;
}
@keyframes mobileHeroScrollPulse {
  0%, 100% { opacity: 0.5;  transform: translate(-50%, 0); }
  50%      { opacity: 0.95; transform: translate(-50%, 4px); }
}

/* ============================================================
 * BOOT-SEQUENCE INGRESS — staggered reveal of every element when
 * .is-visible lands on the hero card. Each element has a hidden
 * initial state and a transition-delay that lands sequentially.
 * Total runtime ~2.0s.
 * ============================================================ */
.mobile-hero-card .mobile-hero-corner,
.mobile-hero-card .mobile-hero-meta-top,
.mobile-hero-card .mobile-hero-meta-bottom,
.mobile-hero-card .mobile-hero-slate-tick,
.mobile-hero-card .mobile-hero-slate-rune,
.mobile-hero-card .mobile-hero-slate-word,
.mobile-hero-card .mobile-hero-rule,
.mobile-hero-card .mobile-hero-headline-line,
.mobile-hero-card .mobile-hero-subline,
.mobile-hero-card .mobile-hero-list li,
.mobile-hero-card .mobile-hero-scroll-cue {
  opacity: 0;
  transform: translateY(6px);
  transition:
    opacity 700ms cubic-bezier(0.2, 0.6, 0.2, 1),
    transform 700ms cubic-bezier(0.2, 0.6, 0.2, 1);
}

.mobile-hero-card .mobile-hero-slate-tick {
  /* Tick draws in by height, not translate. */
  transform: scaleY(0);
  transform-origin: top center;
  transition:
    opacity 700ms cubic-bezier(0.2, 0.6, 0.2, 1),
    transform 900ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

.mobile-hero-card .mobile-hero-rule {
  /* Rule draws in by width. */
  transform: scaleX(0);
  transform-origin: left center;
  transition:
    opacity 700ms cubic-bezier(0.2, 0.6, 0.2, 1),
    transform 850ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

/* Ingress timeline — staggered delays on .is-visible. */
.mobile-hero-card.is-visible .mobile-hero-corner-tl  { opacity: 1; transform: none; transition-delay:  120ms; }
.mobile-hero-card.is-visible .mobile-hero-corner-tr  { opacity: 1; transform: none; transition-delay:  180ms; }
.mobile-hero-card.is-visible .mobile-hero-corner-bl  { opacity: 1; transform: none; transition-delay:  240ms; }
.mobile-hero-card.is-visible .mobile-hero-corner-br  { opacity: 1; transform: none; transition-delay:  300ms; }
.mobile-hero-card.is-visible .mobile-hero-meta-top   { opacity: 0.78; transform: none; transition-delay: 380ms; }
.mobile-hero-card.is-visible .mobile-hero-slate-tick { opacity: 1; transform: scaleY(1); transition-delay: 460ms; }
.mobile-hero-card.is-visible .mobile-hero-slate-rune { opacity: 1; transform: none; transition-delay: 600ms; }
.mobile-hero-card.is-visible .mobile-hero-slate-word { opacity: 1; transform: none; transition-delay: 720ms; }
.mobile-hero-card.is-visible .mobile-hero-rule:not(.mobile-hero-rule-small) {
  opacity: 1; transform: scaleX(1); transition-delay: 880ms;
}
.mobile-hero-card.is-visible .mobile-hero-headline-line:nth-child(1) { opacity: 1; transform: none; transition-delay: 1020ms; }
.mobile-hero-card.is-visible .mobile-hero-headline-line:nth-child(2) { opacity: 1; transform: none; transition-delay: 1140ms; }
.mobile-hero-card.is-visible .mobile-hero-headline-line:nth-child(3) { opacity: 1; transform: none; transition-delay: 1260ms; }
.mobile-hero-card.is-visible .mobile-hero-rule.mobile-hero-rule-small {
  opacity: 1; transform: scaleX(1); transition-delay: 1380ms;
}
.mobile-hero-card.is-visible .mobile-hero-subline    { opacity: 1; transform: none; transition-delay: 1480ms; }
.mobile-hero-card.is-visible .mobile-hero-list li:nth-child(1) { opacity: 1; transform: none; transition-delay: 1620ms; }
.mobile-hero-card.is-visible .mobile-hero-list li:nth-child(2) { opacity: 1; transform: none; transition-delay: 1720ms; }
.mobile-hero-card.is-visible .mobile-hero-list li:nth-child(3) { opacity: 1; transform: none; transition-delay: 1820ms; }
.mobile-hero-card.is-visible .mobile-hero-meta-bottom { opacity: 0.6; transform: none; transition-delay: 1960ms; }
.mobile-hero-card.is-visible .mobile-hero-scroll-cue  { opacity: 0.7; transform: translateX(-50%); transition-delay: 2080ms; }

/* Reduced motion — nuke the boot sequence, everything visible immediately. */
@media (prefers-reduced-motion: reduce) {
  .mobile-hero-card .mobile-hero-corner,
  .mobile-hero-card .mobile-hero-meta-top,
  .mobile-hero-card .mobile-hero-meta-bottom,
  .mobile-hero-card .mobile-hero-slate-tick,
  .mobile-hero-card .mobile-hero-slate-rune,
  .mobile-hero-card .mobile-hero-slate-word,
  .mobile-hero-card .mobile-hero-rule,
  .mobile-hero-card .mobile-hero-headline-line,
  .mobile-hero-card .mobile-hero-subline,
  .mobile-hero-card .mobile-hero-list li,
  .mobile-hero-card .mobile-hero-scroll-cue {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
  .mobile-hero-card .mobile-hero-meta-top { opacity: 0.78 !important; }
  .mobile-hero-card .mobile-hero-meta-bottom { opacity: 0.6 !important; }
  .mobile-hero-card .mobile-hero-rule-small { opacity: 1 !important; }
  .mobile-hero-card .mobile-hero-scroll-cue {
    opacity: 0.8 !important;
    animation: none !important;
  }
  .mobile-hero-card .mobile-hero-meta-dot {
    animation: none !important;
  }
}

/* ============================================================
 * STATION SCENE — modifies the hero card pattern for stations 2-6.
 * Same HUD frame composition; differences:
 *  - Per-station accent color drives slate word, headline accent,
 *    and bullet markers (hero locks plasma blue regardless).
 *  - Adds CTA block (hero has no CTAs).
 *  - Optional kicker line for AI station.
 * ============================================================ */

/* Slate word: ALWAYS gold across every scene + station (operator-locked
   slate vocabulary — rune always plasma blue, slate-word always gold).
   No per-accent override = base .mobile-hero-slate-word gold rule applies
   to all stations. */

/* Headline accent on station — per-accent color driven by parent.
   Hero's .mobile-hero-headline-accent (plasma blue) is a separate
   class so this doesn't affect it. */
.mobile-headline-accent {
  font-style: italic;
  font-weight: 700;
  color: var(--mobile-plasma-blue);
  text-shadow:
    0 0 8px rgba(72, 202, 255, 0.55),
    0 0 22px rgba(72, 202, 255, 0.32),
    0 0 48px rgba(72, 202, 255, 0.18);
}
.mobile-scene-station.mobile-accent-gold .mobile-headline-accent {
  color: var(--mobile-accent-gold);
  text-shadow:
    0 0 8px rgba(204, 168, 102, 0.55),
    0 0 22px rgba(204, 168, 102, 0.32),
    0 0 48px rgba(204, 168, 102, 0.18);
}
.mobile-scene-station.mobile-accent-cyan .mobile-headline-accent {
  color: var(--mobile-accent-cyan);
  text-shadow:
    0 0 8px rgba(34, 211, 238, 0.55),
    0 0 22px rgba(34, 211, 238, 0.32),
    0 0 48px rgba(34, 211, 238, 0.18);
}

/* Bullet markers — same per-accent cascade */
.mobile-scene-station.mobile-accent-gold .mobile-hero-list li::before {
  background: var(--mobile-accent-gold);
  box-shadow: 0 0 8px rgba(204, 168, 102, 0.45);
}
.mobile-scene-station.mobile-accent-cyan .mobile-hero-list li::before {
  background: var(--mobile-accent-cyan);
  box-shadow: 0 0 8px rgba(34, 211, 238, 0.45);
}

/* Kicker line (between slate and headline) — used by AI station */
.mobile-scene-kicker {
  margin: 8px 0 0;
  font-family: 'Roboto Condensed', sans-serif;
  font-weight: 500;
  font-size: 12px;
  letter-spacing: 0.32em;
  text-transform: uppercase;
  color: var(--mobile-text-muted);
}

/* CTA pair block — sits below bullets/subline on stations */
.mobile-scene-ctas {
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 22px 0 0;
}

/* ============================================================
 * TABLET PROFILE — iPad / Surface / any touch device at >= 768px.
 *
 * Activation strategy: CSS @media query, NOT JS class. Reason: the
 * mobile journey only renders at all when useIsMobile() returns true,
 * which is touch-OR-narrow-window. So if .mobile-journey is in the
 * DOM AND viewport >= 768px, it MUST be a tablet — phones are <768,
 * desktops are non-touch (no journey rendered). The @media approach
 * sidesteps any JS state-sync edge cases (hook race condition, cache
 * mismatch, Safari iOS quirks) — pure CSS, fires on viewport match.
 *
 * Strategy inside the @media block:
 *  • Cap journey at 640px max-width, centered, so the HUD frame
 *    (sized via card-width * 1780/1080) stays within iPad portrait
 *    vertical space instead of overshooting it.
 *  • Compress frame aspect 1080/1780 -> 1080/1400 (operator-approved
 *    distortion) so the LCD doesn't bleed into the next scene.
 *  • Bump type sizes ~25-35% across the board for arm's-length
 *    reading on a 10-13" iPad screen.
 *  • Phone profile (< 768) and desktop profile (non-touch) are
 *    untouched — every rule below sits inside the @media.
 * ============================================================ */
@media (min-width: 768px) {
  .mobile-journey {
    max-width: 640px;
    margin-left: auto;
    margin-right: auto;
  }

  /* Bg image bleeds to 100vw on tablet — operator's call: 'stretch out
     the mobile bg to fill the screen, those black gutters suck'. The
     bg div is repositioned to sit centered at viewport scale (not card
     scale), with translateX(-50%) anchoring it to the viewport center.
     Card content (HUD frame, slate, headline, bullets) remains capped
     at the 640px journey width — only the bg image escapes the column.

     .mobile-hero-card has overflow:hidden as a defensive clip; release
     it on tablet so the bg layer can escape the card's 640px width.
     Other absolutely-positioned elements (HUD frame, slate, brackets,
     CTAs) sit inside the card boundary and don't need the clip. */
  .mobile-card-bg {
    left: 50%;
    width: 100vw;
    transform: translateX(-50%);
  }
  .mobile-hero-card {
    overflow: visible;
  }
  /* Scrim ::before bleeds with the bg. Without this, the scrim stays
     clipped to the 640px column while the bg extends 100vw — creating
     a visible "darker rectangle" inside the column (brighter raw bg
     in the gutters) that reads as a shadow trailing above/below the
     HUD frame. Bleeding the scrim out matches the bg layer, giving a
     uniform top-vignette → mid-clear → bottom-vignette tone across
     the full viewport width. */
  .mobile-hero-card::before {
    left: 50%;
    right: auto;
    width: 100vw;
    transform: translateX(-50%);
  }

  /* ── HERO scene on tablet — operator: 'bring the upper left bracket
        and entire text block down like 20 and then we need to bring
        that lower right bracket up to the right place and then fit
        in the dw// text under the 3rd bullet point but above the
        right brackets horizontal arm'.

        Root cause of the iPad-form-factor drift: base
        .mobile-hero-corner-tr has fixed pixel positioning
        (bottom: 413px + height: 378px). On iPad mini 1024-tall the
        bracket lands at y=233 (top portion); on iPad Pro 1366-tall it
        lands at y=575 (middle). TL bracket uses 'bottom: 50%' so it
        scales with viewport height. They drift at different rates
        across iPad form factors → operator sees the BR bracket moving
        relative to the text block as he switches between iPad sizes.

        Fix: mirror TL's anchor logic on BR so both scale together as
        a linked entity. TL: top: 84, bottom: 50% (with the 20px push).
        BR: top: 50%, bottom: 84 (the mirror). Both now anchored to
        the same viewport-relative halves — they scale identically. */

  /* Push text content down 20 + right 30 (operator dial): padding-top
     72 -> 112, padding-left 54 -> 84. Right and bottom inherit from base.
     :not(.mobile-scene-station) scopes to hero ONLY — stations have
     their own padding override (padding-left 52, padding-top 76). */
  .mobile-hero-card:not(.mobile-scene-station) {
    padding-top: 112px;
    padding-left: 84px;
  }

  /* TL bracket follows text down 20: top 64 -> 84. */
  .mobile-hero-corner-tl {
    top: 84px;
  }

  /* BR bracket: mirror TL anchors. Removes the hardcoded bottom:413
     + height:378 pair that drifted across iPad sizes. Now scales
     proportionally. Operator: 'now we just need to bring that entire
     dw text and bracket up... bring it up fifty'. Shift both edges of
     the bracket up by 50: top: 50% -> calc(50% - 50px), bottom: 84
     -> 134. Bracket maintains the same height (50vh - 84) and stays
     mirror-paired with TL. */
  /* HERO scene on tablet — operator's Plan B: single combined-bracket
     PNG (tech_bracket_full.png, 1080x1732) replaces the separate TL+BR
     brackets. The frame perimeter is now locked by image construction:
     both brackets baked into one asset, sized via aspect-ratio + card
     width. No more cross-bracket drift across iPad form factors.

     Approach mirrors how stations use hudframe_narrow.png — single
     element, full card width (left: 0, right: 0), aspect-ratio computes
     height proportionally. */

  /* HERO ONLY — hijack .mobile-hero-corner-tl to render the full
     combined frame (tech_bracket_full.png at 1080x1146).
     :not(.mobile-scene-station) scopes to hero — stations keep their
     hudframe_narrow.png HUD frame untouched.
     At 640 wide, frame height = 640 * 1146/1080 ≈ 679. Frame bottom
     = 76 + 679 = 755. */
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-tl {
    top: 76px;
    left: 0;
    right: 0;
    bottom: auto;
    width: auto;
    height: auto;
    aspect-ratio: 1080 / 1146;
    background-image: url('/icons/tech_bracket_full.png');
    background-size: 100% 100%;
    background-position: center;
  }

  /* HERO ONLY — hide the separate corner brackets (combined into the
     image). Stations already hide these via their own rules. */
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-tr,
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-bl,
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-br {
    display: none;
  }

  /* HERO ONLY — DW// identifier final dial: top 685, right 100. */
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-meta-top {
    top: 685px;
    right: 100px;
    bottom: auto;
  }

  /* Station text block — operator's note: text on stations sits flush
     against the HUD frame's left chrome on every station scene. Bump
     padding-left from 32 -> 52 to inset the text into the frame's
     visible interior (~27px past the chrome's left edge). Padding-right
     stays at 32 — keeps the asymmetric bias 'using the room on the
     right' the operator called out. */
  .mobile-journey .mobile-scene-station {
    padding-left: 52px;
  }

  /* DW // NNN // SLATEWORD identifier — operator tweaks:
       1. 'slipped down, bring it up just a tiny bit' (15px higher)
       2. 'the little blinky thing is touching the frame' — the dot
          prefix was kissing the frame's left chrome. Shift left from
          64 -> 84 so the dot has the same 20px right-inset as the
          text content shift above. */
  .mobile-journey .mobile-scene-station .mobile-hero-meta-top {
    top: calc(var(--mobile-frame-bottom) - 75px);
    left: 84px;
  }

  /* COMPRESS the LCD/HUD frame — operator's call. Native PNG aspect
     (1080/1780) makes a frame ~1054px tall at 640px wide that bleeds
     into the next scene during scroll. Override to 1080/1400 shaves
     ~22% off frame height. The PNG chrome stretches vertically
     (operator greenlit: 'compressing it might not look that bad'). */
  .mobile-journey .mobile-scene-station .mobile-hero-corner-tl {
    aspect-ratio: 1080 / 1400;
  }
  .mobile-journey .mobile-scene-station {
    --mobile-frame-bottom: calc(76px + 640px * 1400 / 1080);
  }

  /* ── Type scale bump for arm's-length reading. ─────────────────── */
  .mobile-journey .mobile-hero-slate-rune {
    font-size: 22px;
  }
  .mobile-journey .mobile-hero-slate-word {
    font-size: 30px;
  }
  .mobile-journey .mobile-hero-meta-top {
    font-size: 16px;
  }
  .mobile-journey .mobile-hero-meta-bottom {
    font-size: 15px;
  }
  /* Headline — bump cap from 58 -> 80. */
  .mobile-journey .mobile-hero-headline {
    font-size: clamp(52px, 11vw, 80px);
  }
  .mobile-journey .mobile-hero-subline {
    font-size: 19px;
  }
  .mobile-journey .mobile-scene-kicker {
    font-size: 15px;
  }
  /* Bullets — THE primary scannable readout, 17 -> 25. */
  .mobile-journey .mobile-hero-list {
    font-size: 25px;
  }
  /* CTAs — bump from 17 -> 22, min-height 54 -> 60. */
  .mobile-journey .mobile-scene-station .mobile-cta {
    font-size: 22px;
    min-height: 60px;
  }
  .mobile-journey .mobile-hero-scroll-cue {
    font-size: 32px;
  }
}

/* ============================================================
 * SMALL PHONE PROFILE — < 430px wide.
 *
 * Activated by @media (max-width: 429px). Covers iPhone SE 375,
 * iPhone 12/13/14/15 standard 390-393, iPhone XR/11 414, iPhone
 * 12/13/14 Plus 428. Does NOT match iPhone 14/15/16 Pro Max at
 * 430+ — that operator-locked baseline stays byte-identical.
 *
 * Operator directive: 'go lazy-boi, tune for SE, have every phone
 * up to 14 Pro Max get this same look so I don't lose my mind on
 * this'. So values inside this block are FIXED PIXELS tuned for
 * iPhone SE (375x667). They apply uniformly 375-429 — no clamp
 * scaling within the range. Across the 55px width spread the
 * consistency reads better than per-phone fluid sizing anyway.
 * ============================================================ */
@media (max-width: 429px) {
  /* ── Station CTAs: absolute at frame bottom. Offset 66 (down 30
        from prev 96) — CTAs sit closer to frame bottom edge. */
  .mobile-scene-station .mobile-scene-ctas {
    position: absolute;
    bottom: calc(100vh - var(--mobile-frame-bottom) + 66px);
    top: auto;
    left: 0;
    right: 0;
    transform: none;
    width: auto;
    max-width: 240px;
    margin: 0 auto;
    gap: 8px;
    padding: 0;
    align-items: center;
  }

  /* Individual CTA buttons — smaller on SE to fit within the frame
     vertical budget. Was 17px / 54 min-height (tablet+). */
  .mobile-scene-station .mobile-cta {
    font-size: 14px;
    min-height: 40px;
    letter-spacing: 0.14em;
  }

  /* ── Station padding (SE-tuned). Padding-top 100 — text block
        up 30 more (operator dial). */
  .mobile-scene-station {
    padding-left: 22px;
    padding-right: 22px;
    padding-top: 90px;
  }

  /* ── Hero card padding (SE-tuned). Padding-top 92 puts content
        inside the combined frame which starts at top: 76. Padding-left
        50 clears the frame's left chrome on the bg-image. */
  .mobile-hero-card:not(.mobile-scene-station) {
    padding: 92px 22px 80px 50px;
  }

  /* ── Headline 42px fixed (HERO). At SE 375 with 58px L+R padding,
        content area = 317px. 42px Orbitron Bold Italic fits
        'imagination' (11 chars ≈ 240px) cleanly. ──────────── */
  .mobile-hero-headline {
    font-size: 42px;
  }

  /* Stations get smaller type than hero on SE — operator wants the
     PRODUCTION/FORGE/AI/etc. slate + headline reduced so the block
     stack fits within the compressed LCD frame. Hero stays at 42px.
     margin-left: 15 shifts headline (and bullets below) right of the
     slate/dividers — operator-requested asymmetric inset. */
  .mobile-scene-station .mobile-hero-headline {
    font-size: 32px;
    margin-left: 10px;
  }
  .mobile-scene-station .mobile-hero-list {
    margin-left: 15px;
  }
  .mobile-scene-station .mobile-hero-slate-word {
    font-size: 14px;
  }
  .mobile-scene-station .mobile-hero-slate-rune {
    font-size: 12px;
  }
  .mobile-scene-station .mobile-scene-kicker {
    font-size: 10px;
  }

  /* ── Bullets 15px fixed. ─────────────────────────────────── */
  .mobile-hero-list {
    font-size: 15px;
  }

  /* ── Hero subline 12px fixed — pipe-separated 'Props on set
        | Agents on screen | Artifacts in hand' was clipping
        at the right edge on SE. 12px fits across 317px content
        width without truncation. ──────────────────────────── */
  .mobile-hero-subline {
    font-size: 12px;
  }

  /* ── Hero BR bracket + DW// identifier: paired visual that both
        need to move down on small phones (operator: 'for SE the
        bracket on right and dw need to come down'). On the locked
        baseline (14 Pro Max), bracket at bottom: 413 + DW// at
        top: 50% + 16 puts them in the lower-middle area where the
        viewport has dedicated space. On shorter phones the same
        proportional position landed mid-screen, overlapping the
        bullet flow.
        Fix: anchor both via bottom: with fixed px (SE-tuned), so
        across the 375-429 range they sit ~90px from card bottom
        (bracket) and ~200px from bottom (DW//) — a 'near-corner'
        composition that consistently clears the bullet zone. */
  /* HERO ONLY — combined-bracket frame (tech_bracket_full.png) replaces
     the separate TL+BR brackets on small phones too. Same approach
     used on tablet hero. Operator: 'do we just change the mobile to
     the full bracket hud thing i made so we can be done with this
     maaaaadddnneessss???' — yes.
     :not(.mobile-scene-station) scopes to hero card only. */
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-tl {
    top: 76px;
    left: 0;
    right: 0;
    bottom: auto;
    width: auto;
    height: auto;
    aspect-ratio: 1080 / 1146;
    background-image: url('/icons/tech_bracket_full.png');
    background-size: 100% 100%;
    background-position: center;
  }

  /* HERO ONLY — hide separate TR/BL/BR brackets, all baked into the
     combined image above. */
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-tr,
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-bl,
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-corner-br {
    display: none;
  }
  /* HERO ONLY DW// — centered horizontally above LAT/LON. Stations
     keep their base 'inside frame at lower-left' position. */
  .mobile-hero-card:not(.mobile-scene-station) .mobile-hero-meta-top {
    top: auto;
    bottom: 40px;
    left: 0;
    right: 0;
    justify-content: center;
  }

  /* LAT/LON pushed down. Scroll cue also moves down so the stack
     order stays DW// → LAT/LON → scroll cue from top to bottom. */
  .mobile-hero-card .mobile-hero-meta-bottom {
    bottom: 22px;
  }
  .mobile-hero-card .mobile-hero-scroll-cue {
    bottom: 4px;
  }

  /* Station DW// — base offset is -60 above frame bottom. Operator
     dial: down 10 (offset -50). DW// moves toward frame bottom edge. */
  .mobile-scene-station .mobile-hero-meta-top {
    top: calc(var(--mobile-frame-bottom) - 50px);
  }

  /* ── Station HUD frame: aspect compression so frame fits
        within SE's 667-tall viewport. Native 1780/1080 ratio
        produces a 618px frame at 375 wide; +76 top = 694 bottom,
        27px past SE's viewport. Override to 1500/1080 gives a
        521px frame at 375 wide; +76 top = 597 bottom, 70px
        clearance for LAT/LON + scroll cue. PNG chrome stretches
        vertically by ~15% — same kind of compression operator
        approved for the tablet profile. ───────────────────── */
  .mobile-scene-station .mobile-hero-corner-tl {
    aspect-ratio: 1080 / 1500;
  }
  .mobile-scene-station {
    --mobile-frame-bottom: calc(76px + 100vw * 1500 / 1080);
  }
}
