/* ---------------------------------------------------------------------------
   The hero flythrough section.

   A tall section with a sticky stage inside it, which is what turns ordinary page
   scrolling into a camera move without hijacking anything: the page scrolls exactly
   as it always did, and the stage simply stays put while the section passes it. The
   height is the timeline -- 420vh of scroll for one take.

   The fallback screenshot is in the markup and visible from the start. Everything
   here only decides what to hide once the canvas is ready, so a browser with no
   WebGL, no JavaScript, or `prefers-reduced-motion` gets the picture instead of a
   hole. That is the same rule the rest of the page's motion follows: the state
   without the script is the finished page, not a broken one.
   --------------------------------------------------------------------------- */

.hero3d {
  /* The timeline. Long enough to be a journey, short enough that nobody scrolls
     through it wondering whether the page has frozen. */
  height: 420vh;
  position: relative;
  margin: 18px 0 0;
}
.hero3d-stage {
  position: sticky;
  top: 60px;                     /* clear of the sticky nav */
  height: calc(100vh - 60px);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Night corridor: the canvas paints its own clear colour over this; the gradient
     is what shows for the moment before the module mounts, so the hand-off between
     screenshot-fallback and scene is not a white flash. */
  background:
    radial-gradient(120% 90% at 50% 0%, #16233d 0%, #0a0f1a 58%, #060a12 100%);
}
@media (max-width: 720px) {
  /* Shorter on a phone: 420vh of thumb-scrolling is a chore, and the canvas is
     small enough that the flythrough reads in less travel. */
  .hero3d { height: 300vh; }
}

.hero3d-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity .6s ease;
}
.hero3d[data-hero3d="on"] .hero3d-canvas,
.hero3d[data-hero3d="running"] .hero3d-canvas,
.hero3d[data-hero3d="ending"] .hero3d-canvas { opacity: 1; }

/* The screenshot the flythrough replaces. Shown until the canvas is actually
   drawing, and kept for anyone the canvas never arrives for. */
.hero3d-fallback {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 clamp(16px, 5vw, 72px);
  transition: opacity .6s ease;
}
.hero3d-fallback img {
  max-width: 100%;
  max-height: 76%;
  border: 1px solid var(--line);
  border-radius: 16px;
  box-shadow: 0 14px 44px rgba(20,30,55,.12);
}
.hero3d[data-hero3d="on"] .hero3d-fallback,
.hero3d[data-hero3d="running"] .hero3d-fallback,
.hero3d[data-hero3d="ending"] .hero3d-fallback { opacity: 0; }
/* Once the canvas is up, the picture must not answer clicks through it. */
.hero3d[data-hero3d="on"] .hero3d-fallback img,
.hero3d[data-hero3d="running"] .hero3d-fallback img,
.hero3d[data-hero3d="ending"] .hero3d-fallback img { pointer-events: none; }

/* ---------------------------------------------------------------- captions */
.hero3d-copy {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1040px;
  margin: 0 auto;
  padding: 0 24px;
  pointer-events: none;
  align-self: flex-end;
  padding-bottom: clamp(28px, 7vh, 72px);
}
.hero3d-caps { position: relative; min-height: 96px; }
.hero3d-cap {
  position: absolute;
  left: 0;
  bottom: 0;
  margin: 0;
  max-width: 460px;
  font-size: clamp(15px, 1.7vw, 18px);
  line-height: 1.55;
  color: #c8d8f2;
  background: rgba(10, 16, 28, .78);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(46, 147, 255, .35);
  border-radius: 12px;
  padding: 12px 16px;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity .45s ease, transform .45s ease;
}
.hero3d-cap.on { opacity: 1; transform: none; }
.hero3d-cap span {
  display: block;
  font-weight: 640;
  color: #ecf4ff;
  letter-spacing: -.2px;
  margin-bottom: 3px;
}
.hero3d-under {
  margin: 14px 0 0;
  font-size: 13px;
  color: #7d94bd;
  opacity: 0;
  transition: opacity .45s ease;
}
.hero3d-under.on { opacity: 1; }

.hero3d-hint {
  position: absolute;
  right: clamp(16px, 4vw, 40px);
  bottom: 24px;
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #6d84ad;
  z-index: 2;
  transition: opacity .4s ease;
}
.hero3d[data-hero3d="ending"] .hero3d-hint { opacity: 0; }
/* Nothing to scroll through when the flythrough is off; a hint to scroll would be
   telling the visitor to do something that does nothing. */
.hero3d[data-hero3d="off"] .hero3d-hint { display: none; }
.hero3d[data-hero3d="off"] { height: auto; }
.hero3d[data-hero3d="off"] .hero3d-stage {
  position: static;
  height: auto;
  padding: 26px 0 8px;
}
.hero3d[data-hero3d="off"] .hero3d-fallback { position: static; padding: 0; }
.hero3d[data-hero3d="off"] .hero3d-fallback img { max-height: none; }
.hero3d[data-hero3d="off"] .hero3d-copy { display: none; }
.hero3d[data-hero3d="armed"] .hero3d-fallback img { max-height: 60%; }

@media (prefers-reduced-motion: reduce) {
  .hero3d { height: auto; }
  .hero3d-stage { position: static; height: auto; padding: 26px 0 8px; }
  .hero3d-fallback { position: static; padding: 0; }
  .hero3d-fallback img { max-height: none; }
  .hero3d-copy, .hero3d-hint { display: none; }
}
