/* ============================================================================
   Intro cinematic
   ----------------------------------------------------------------------------
   Timings here are driven from JS using cues measured out of WebsiteIntro.mp3
   (see build-notes/INTRO-CUES.md). Nothing in this file assumes a duration -
   scenes are shown/hidden by a class, so if the audio is ever re-recorded the
   cue table changes and the CSS does not.
   ============================================================================ */

#intro {
  position: fixed; inset: 0; z-index: 9000;
  background: var(--void);
  display: grid; place-items: center;
  overflow: hidden;
  transition: opacity 1.1s var(--ease-in-out);
}
#intro[hidden] { display: none; }
#intro.is-leaving { opacity: 0; pointer-events: none; }

#intro-canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
}

/* Vignette.
   Was 0.86 black from 38% out, which was tuned for the old flat-black cave. Over
   the real engine's daylight world it crushed the sky to near-black and made a
   midday shot read as night. It is a lens effect now, not a backdrop. */
.intro__vignette {
  position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(115% 80% at 50% 120%, rgba(108,194,74,0.10), transparent 60%),
    radial-gradient(100% 100% at 50% 50%, transparent 58%, rgba(0,0,0,0.40) 100%);
}

/* ---------------------------------------------------------------- gate */
.intro-gate {
  position: relative; z-index: 3;
  text-align: center;
  animation: gate-in 1s var(--ease) both;
}
.intro-gate__mark {
  font-family: var(--font-pixel);
  font-size: clamp(1.6rem, 5vw, 3rem);
  letter-spacing: 0.16em;
  margin-bottom: var(--gap-md);
  color: var(--text);
  text-shadow: 0 0 40px rgba(108,194,74,0.5);
}
.intro-gate__hint {
  color: var(--text-dim); font-size: 0.86rem;
  margin-top: var(--gap-md); letter-spacing: 0.04em;
}
@keyframes gate-in { from { opacity: 0; transform: translateY(18px); } }

/* ------------------------------------------------------------- captions */
/* Kinetic typography. Each beat replaces the whole block, and every letter is
   its own element so it can carry an individual delay - a word that resolves
   letter by letter reads as an edit, while a word that fades as one block reads
   as a slide deck. Animations are declarative (not transitions) so a freshly
   inserted element plays them immediately on insert. */
/* Captions sit in the lower third so the shot stays visible behind them - a
   title centred over the subject is covering the exact thing it is naming. The
   three big beats (the open, the "more than a server" line, the title card) are
   the exception: there the type IS the shot, so it takes the centre. */
.intro-stage {
  position: absolute; inset: 0; z-index: 2;
  display: grid;
  align-items: end; justify-items: center;
  padding: 0 4vw 11vh;
  text-align: center;
  pointer-events: none;
}
.intro-stage:has(.cap--big) { align-items: center; padding-bottom: 4vh; }

.intro-caption { display: grid; place-items: center; width: min(1100px, 92vw); }

.cap { display: grid; place-items: center; }

.cap__kicker {
  font-family: var(--font-pixel);
  font-size: clamp(0.6rem, 1.4vw, 0.8rem);
  letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--grass);
  margin-bottom: var(--gap-md);
  animation: cap-kicker 0.7s var(--ease) both;
}
@keyframes cap-kicker {
  from { opacity: 0; transform: translateY(10px); letter-spacing: 0.55em; }
}

.cap__title {
  font-size: clamp(1.9rem, 6.4vw, 5rem);
  font-weight: 900; letter-spacing: -0.03em;
  line-height: 0.98; margin: 0;
  text-shadow: 0 6px 40px rgba(0, 0, 0, 0.55);
}
.cap__title span {
  display: inline-block;
  white-space: pre;                       /* keeps the spaces between words */
  animation: cap-letter 0.38s var(--ease) both;
}
@keyframes cap-letter {
  from { opacity: 0; transform: translateY(0.44em) scale(0.92); filter: blur(7px); }
  to   { opacity: 1; transform: none; filter: blur(0); }
}

.cap__sub {
  margin-top: var(--gap-md);
  font-size: clamp(0.95rem, 2vw, 1.2rem);
  color: var(--text-soft); max-width: 46ch;
  animation: cap-sub 0.8s 0.24s var(--ease) both;
}
@keyframes cap-sub { from { opacity: 0; transform: translateY(12px); } }

/* The big moments: the opening, the "more than a server" line, and the title. */
.cap--big .cap__title {
  font-size: clamp(2.8rem, 11vw, 8rem);
  background: linear-gradient(180deg, #fff 0%, var(--grass) 62%, var(--grass-deep) 100%);
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 10px 40px rgba(108, 194, 74, 0.35));
}


/* ---------------------------------------------------------------- controls */
.intro__controls {
  position: absolute; z-index: 4;
  right: clamp(16px, 3vw, 34px);
  bottom: clamp(16px, 3vw, 34px);
  display: flex; align-items: center; gap: var(--gap-sm);
}
.intro__skip {
  font-family: var(--font-pixel); font-size: 0.66rem;
  letter-spacing: 0.18em; color: var(--text-dim);
  padding: 10px 16px; border: 2px solid var(--iron);
  background: rgba(10,13,18,0.7); backdrop-filter: blur(6px);
  transition: color 0.2s, border-color 0.2s;
}
.intro__skip:hover { color: var(--text); border-color: var(--grass); }

.intro__vol { display: flex; align-items: center; gap: 8px; }
.intro__vol input[type='range'] {
  width: 86px; accent-color: var(--grass); cursor: pointer;
}
.intro__mute {
  width: 38px; height: 38px; display: grid; place-items: center;
  border: 2px solid var(--iron); background: rgba(10,13,18,0.7);
  font-size: 0.9rem;
}
.intro__mute:hover { border-color: var(--grass); }

/* Progress hairline, so a viewer can see how long is left. */
.intro__progress {
  position: absolute; left: 0; bottom: 0; height: 3px; z-index: 4;
  width: 0%; background: linear-gradient(90deg, var(--grass-deep), var(--grass-lit));
  box-shadow: 0 0 14px var(--grass);
  transition: width 0.2s linear;
}

@media (max-width: 620px) {
  .intro__controls { left: 16px; right: 16px; justify-content: space-between; }
  .intro__vol input[type='range'] { width: 64px; }
}

/* ------------------------------------------------------------- subtitles */
/* The spoken script, line by line. Sits below the kinetic title and pinned near
   the bottom of the frame, the way a subtitle actually belongs - the title layer
   is motion graphics, this is what is being said. */
.intro-subtitle {
  position: absolute;
  left: 50%; bottom: 8vh;
  transform: translateX(-50%) translateY(8px);
  width: min(70ch, 88vw);
  margin: 0;
  text-align: center;
  font-size: clamp(0.95rem, 1.9vw, 1.35rem);
  line-height: 1.45;
  color: #fff;
  text-shadow: 0 2px 14px rgba(0, 0, 0, 0.9), 0 0 3px rgba(0, 0, 0, 0.8);
  opacity: 0;
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
  pointer-events: none;
  z-index: 4;
}
.intro-subtitle.is-on { opacity: 1; transform: translateX(-50%) translateY(0); }

/* Keep the big centred titles clear of the subtitle line. */
.intro-stage:has(.cap--big) { padding-bottom: 12vh; }

@media (max-width: 640px) {
  .intro-subtitle { bottom: 12vh; font-size: 1rem; }
}
