/* ============================================================
   CINEMATIC HERO — scroll-controlled skyline, homepage only
   ------------------------------------------------------------
   The scene is drawn by js/hero-cinematic.js on a <canvas> whose backing
   store is the source artwork's own pixel grid (775 x 683). Every layer —
   dark base, per-building window light, rooftop halos, street lamps, water
   reflections, beam and emblem — is drawn in that one coordinate system, so
   nothing can drift apart however the scene is scaled or cropped here. CSS
   only decides where the scene box sits and how big it is; it always keeps
   the artwork's aspect ratio.

   Layers are derived from images/hero-city.png by
   scripts/derive-hero-skyline.py into images/hero-skyline/.

   images/hero-city.png itself sits under the canvas as the fallback: it is
   the finished composition, shown under reduced motion, when the copy doesn't
   fit a pinned stage, without JS, or if a layer fails to load.

   The pinned sequence (tall section + sticky stage) only exists while JS has
   added .is-cinematic.
   ============================================================ */

.cine-hero {
  --cue: 0;            /* scroll cue opacity (JS)                */
  --settle: 1;         /* bottom fade into the next section (JS) */
  --nav-h: 88px;       /* replaced by the measured navbar height  */
  --scene-max: 62vw;   /* JS: widest scene whose beam source clears the buttons */
  --copy-h: 430px;     /* JS: measured height of the copy block (phones)   */
  --scene-w: min(calc((100vh - var(--nav-h)) * 1.1347), 62vw, var(--scene-max));

  position: relative;
  background: #000;
}
@supports (height: 100svh) {
  .cine-hero { --scene-w: min(calc((100svh - var(--nav-h)) * 1.1347), 62vw, var(--scene-max)); }
}

/* First paint, before js/hero-cinematic.js has run: an inline <head> script
   adds .cine-js to <html> when the sequence will play. Until the canvas has
   drawn its first frame the finished artwork stays hidden, so the page opens
   dark instead of flashing the lit skyline and then switching it off. */
.cine-js .cine-hero:not(.scene-ready):not(.scene-static) .cine-fallback { opacity: 0; }
.cine-js .cine-hero:not(.cine-ready) { --cue: 1; --settle: 0; }

.cine-hero.is-cinematic { height: 300vh; height: 300svh; }

.cine-stage {
  position: relative;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  isolation: isolate;
}
.cine-hero.is-cinematic .cine-stage {
  position: sticky;
  top: 0;
}

/* ── SCENE ─────────────────────────────────────────────────
   Desktop: right- and bottom-aligned like the reference, as tall as the
   space under the navbar but never wider than 62vw, or than --scene-max,
   which the JS measures so the beam's rooftop source (x=92) always lands
   right of the hero buttons. It overhangs the right edge by the artwork's
   empty far-right strip (trees, x 719-775 = 7.2%). Left and top edges are
   feathered into the black stage - narrowly, because the emblem's top is at
   y=6% and the source at x=12%. */
.cine-scene {
  position: absolute;
  z-index: 0;
  right: calc(var(--scene-w) * -0.072);
  bottom: 0;
  width: var(--scene-w);
  aspect-ratio: 775 / 683;
  background: #000;
  -webkit-mask-image:
    linear-gradient(to bottom, transparent 0, #000 3.5%),
    linear-gradient(to right, transparent 0, #000 6%);
  -webkit-mask-composite: source-in;
          mask-image:
    linear-gradient(to bottom, transparent 0, #000 3.5%),
    linear-gradient(to right, transparent 0, #000 6%);
          mask-composite: intersect;
}
.cine-fallback,
.cine-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  max-width: none;
  display: block;
}
.cine-canvas { opacity: 0; }
.cine-hero.scene-ready .cine-canvas { opacity: 1; }
.cine-hero.scene-ready .cine-fallback { visibility: hidden; }

/* ── READABILITY SCRIM + RELEASE FADE ───────────────────── */
.cine-scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(90deg,
    rgba(0,0,0,0.86) 0px,
    rgba(0,0,0,0.6) 480px,
    rgba(0,0,0,0) 760px);
}
.cine-stage::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 18%;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(2,11,24,0), #020B18 92%);
  opacity: calc(0.25 + var(--settle) * 0.75);
}

/* ── CONTENT ───────────────────────────────────────────── */
.cine-content {
  position: relative;
  z-index: 2;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: calc(var(--nav-h) + 24px) clamp(24px, 6vw, 112px) 96px;
  max-width: calc(680px + 2 * clamp(24px, 6vw, 112px));
}
.cine-eyebrow {
  font-family: var(--font-body);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--accent-light);   /* #1565FF fails AA at this size; #5592FF passes */
  margin-bottom: 1.25rem;
  line-height: 1.6;
}
.cine-title {
  font-family: var(--font-display);
  font-size: clamp(2.3rem, 3.2vw, 3.1rem);   /* each line stays on one line down to 1024px */
  font-weight: 800;
  line-height: 1.06;
  letter-spacing: -0.025em;
  color: #fff;
  margin-bottom: 1.4rem;
  text-shadow: 0 2px 24px rgba(0,0,0,0.6);
}
.cine-sub {
  font-size: 1.08rem;
  line-height: 1.7;
  color: rgba(255,255,255,0.78);
  max-width: 30rem;
  margin-bottom: 2.2rem;
  text-shadow: 0 1px 12px rgba(0,0,0,0.7);
}
.cine-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}
.cine-actions .btn-outline {
  background: rgba(0,0,0,0.35);
  border-color: rgba(255,255,255,0.4);
}
.cine-actions .btn:focus-visible {
  outline: 3px solid #fff;
  outline-offset: 3px;
}

.cine-cue {
  position: absolute;
  z-index: 2;
  left: clamp(24px, 6vw, 112px);
  bottom: 32px;
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,0.7);
  opacity: var(--cue);
  pointer-events: none;
}
.cine-hero:not(.is-cinematic) .cine-cue { display: none; }
.cine-cue-line {
  display: block;
  width: 1px;
  height: 32px;
  background: linear-gradient(to bottom, rgba(85,146,255,0), #5592FF);
}

/* The features bar used to sit inside the old hero; it is now the section
   the pinned hero releases into. */
.cine-hero + .hero-features-bar { background: #020B18; }

/* ── PHONES + PORTRAIT TABLETS ─────────────────────────────
   Same query string as `stacked` in js/hero-cinematic.js - keep them identical.
   A centre crop of the scene would lose the beam's source (x=92) or the
   emblem (x=234-384), so phones get their own composition: the copy sits at
   the bottom, and the scene above it is sized so that everything from the
   emblem (image y=20) down to the beam's source (y=446, 62.4% of the
   artwork's height) fits between the navbar and the measured copy block.
   The scene is centred on image x=300, the middle of that action; when it is
   wider than the screen that crops only far-left sky and far-right towers,
   and when it is narrower its edges are feathered into the black stage. */
@media (max-width: 768px), (max-aspect-ratio: 4/5) {
  .cine-hero {
    --scene-w: clamp(38vw, calc((100vh - var(--nav-h) - var(--copy-h) - 12px) * 1.818), 135vw);
  }
  @supports (height: 100svh) {
    .cine-hero { --scene-w: clamp(38vw, calc((100svh - var(--nav-h) - var(--copy-h) - 12px) * 1.818), 135vw); }
  }
  .cine-hero.is-cinematic { height: 220vh; height: 220svh; }
  .cine-scene {
    right: auto;
    bottom: auto;
    left: calc(50vw - var(--scene-w) * 0.3871);                 /* image x=300 at the centre      */
    top: calc(var(--nav-h) - var(--scene-w) * 0.0258);          /* image y=20 under the navbar   */
    -webkit-mask-image:
      linear-gradient(to bottom, #000 72%, transparent 100%),
      linear-gradient(to right, transparent 0, #000 7%, #000 93%, transparent 100%);
    -webkit-mask-composite: source-in;
            mask-image:
      linear-gradient(to bottom, #000 72%, transparent 100%),
      linear-gradient(to right, transparent 0, #000 7%, #000 93%, transparent 100%);
            mask-composite: intersect;
  }
  .cine-scrim {
    background: linear-gradient(to top,
      rgba(0,0,0,0.92) 0%,
      rgba(0,0,0,0.75) 34%,
      rgba(0,0,0,0) 56%);
  }
  .cine-content {
    justify-content: flex-end;
    padding: calc(var(--nav-h) + 16px) 20px 60px;
    max-width: none;
  }
  .cine-eyebrow { font-size: 0.66rem; letter-spacing: 0.16em; margin-bottom: 0.8rem; }
  .cine-title { font-size: clamp(1.95rem, 8.6vw, 3rem); margin-bottom: 0.8rem; }
  .cine-sub { font-size: 0.96rem; line-height: 1.55; margin-bottom: 1.2rem; }
  .cine-actions { gap: 10px; }
  .cine-actions .btn { padding: 12px 20px; font-size: 0.88rem; }
  .cine-cue { left: 20px; bottom: 18px; }
}
@media (max-width: 768px) and (max-height: 700px), (max-aspect-ratio: 4/5) and (max-height: 700px) {
  /* Height-bound as well as width-bound, so the scene keeps its room. */
  .cine-title { font-size: clamp(1.5rem, min(6.4vw, 6.2vh), 2.3rem); }
  .cine-sub { font-size: 0.9rem; margin-bottom: 1rem; }
  .cine-actions .btn { padding: 10px 16px; font-size: 0.84rem; }
  .cine-content { padding-bottom: 42px; }
  .cine-cue { bottom: 12px; }
}

/* Reduced motion: never pinned, never animated. The JS also refuses to add
   .is-cinematic; this is the belt to that brace. */
@media (prefers-reduced-motion: reduce) {
  .cine-hero.is-cinematic { height: auto; }
  .cine-hero.is-cinematic .cine-stage { position: relative; }
}

/* Copy doesn't fit a viewport-high stage (landscape phones, tiny windows):
   the JS leaves it unpinned and adds .is-overflow, and the stage grows to
   fit its content instead of clipping the buttons. */
.cine-hero.is-overflow .cine-stage { height: auto; min-height: 100vh; }
.cine-hero.is-overflow .cine-content { height: auto; min-height: 100vh; }
