/* Cascabel — the scroll intro
 *
 * The first thing on the page, and the only thing, until it is finished. A
 * tall section gives the scroll somewhere to go; inside it a sticky panel
 * holds the frame still while the wheel drives the clip. Scrolling down runs
 * the shot forward, scrolling up runs it back — the page does not move on
 * until the shot is over.
 *
 * The runway is expressed in viewport heights, so the same gesture length
 * feels the same on any screen.
 */

/* The site scrolls smoothly for its anchor links, and that interpolation sits
 * between the wheel and the scroll position — which is exactly what a scrubbed
 * shot must not have, or the picture lurches behind the hand. JS adds this
 * class while the intro is on screen and drops it after, so anchors elsewhere
 * keep their easing. */
html.sintro-live { scroll-behavior: auto !important }

.sintro {
  position: relative;
  /* Runway. 460vh meant nearly five screens of wheel for ten seconds of film,
     which read as slow however smooth it was. 280vh puts the whole shot inside
     about two screens of scrolling: still deliberate, no longer a chore. */
  height: 280vh;
  background: #0A0A0A;
  z-index: 1;
}

.sintro-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  overflow: hidden;
  background: #0A0A0A;
}

.sintro-stage { position: absolute; inset: 0 }

.sintro canvas,
.sintro-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
.sintro-poster { z-index: 0 }
.sintro canvas {
  z-index: 1;
  opacity: 0;
  transition: opacity .9s cubic-bezier(.16, 1, .3, 1);
}
.sintro.is-ready canvas { opacity: 1 }

/* Keeps type legible over the picture without flattening the blacks. */
.sintro-scrim {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  background:
    radial-gradient(72% 62% at 50% 54%, transparent 30%, rgba(10,10,10,.55) 100%),
    linear-gradient(180deg, rgba(10,10,10,.7) 0%, transparent 26%, transparent 62%, rgba(10,10,10,.92) 100%);
}

/* ── the beats ────────────────────────────────────────────────────────────
 * Each beat fades in over its own slice of the shot. JS sets --p (0..1) and
 * each beat carries its own in/out window as inline custom properties, so the
 * timing is tunable from the markup rather than buried here.
 */
.sintro-beat {
  position: absolute;
  left: 0; right: 0;
  z-index: 3;
  text-align: center;
  padding: 0 clamp(20px, 5vw, 60px);
  pointer-events: none;
  opacity: 0;
  transform: translateY(16px);
  transition: opacity .45s linear, transform .6s cubic-bezier(.16, 1, .3, 1);
}
.sintro-beat.on { opacity: 1; transform: none }

.sintro-beat.mid { top: 50%; transform: translateY(calc(-50% + 16px)) }
.sintro-beat.mid.on { transform: translateY(-50%) }

.sintro-beat .line {
  font: 800 clamp(1.5rem, 4.4vw, 3.4rem)/1.06 var(--sans, system-ui);
  font-variation-settings: 'wdth' 110;
  letter-spacing: -.035em;
  text-transform: uppercase;
  color: var(--bone, #F5F5F2);
  max-width: 18ch;
  margin: 0 auto;
}
.sintro-beat .line em { font-style: normal; color: var(--venom, #C2261D) }
.sintro-beat .sub {
  margin-top: 14px;
  font: 900 .6rem/1 var(--sans, system-ui);
  font-variation-settings: 'wdth' 125;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: rgba(245, 245, 242, .55);
}

/* the wordmark that lands the intro */
.sintro-mark {
  display: block;
  width: clamp(180px, 26vw, 380px);
  height: clamp(52px, 7.4vw, 108px);
  margin: 0 auto 18px;
  background: var(--logo, none) center/contain no-repeat;
}

/* ── the page opens here ──────────────────────────────────────────────────
 * The hero sits inside the pinned panel and arrives over the last frame, the
 * one where the snake's face fills the lens. The shot lands and the site is
 * already there — there is no second screen to scroll to.
 */
.sintro-hero {
  position: absolute;
  inset: 0;
  z-index: 4;
  opacity: 0;
  pointer-events: none;
  transform: translateY(22px);
  transition: opacity .7s cubic-bezier(.16, 1, .3, 1),
              transform .9s cubic-bezier(.16, 1, .3, 1);
}
.sintro.is-open .sintro-hero {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
/* inside the panel the hero fills it rather than claiming its own screen */
.sintro-hero .hero {
  position: absolute;
  inset: 0;
  min-height: 0;
  height: 100%;
}
/* the beats step aside once the hero is in */
.sintro.is-open .sintro-beat { opacity: 0 }

/* ── the cue, and the progress of the shot ───────────────────────────── */
.sintro-cue {
  position: absolute;
  left: 50%;
  bottom: clamp(22px, 4vh, 48px);
  transform: translateX(-50%);
  z-index: 4;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  font: 900 .56rem/1 var(--sans, system-ui);
  font-variation-settings: 'wdth' 125;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: rgba(245, 245, 242, .6);
  pointer-events: none;
  transition: opacity .5s linear;
}
.sintro-cue i {
  width: 1px; height: 42px;
  background: rgba(245, 245, 242, .18);
  position: relative;
  overflow: hidden;
}
.sintro-cue i::after {
  content: "";
  position: absolute; inset: 0;
  background: var(--venom, #C2261D);
  animation: sintro-drop 2.4s cubic-bezier(.2, .7, .2, 1) infinite;
}
@keyframes sintro-drop {
  0% { transform: translateY(-100%) }
  60%, 100% { transform: translateY(100%) }
}
.sintro.is-running .sintro-cue { opacity: 0 }

/* how much of the shot is left, as a hairline across the foot of the screen */
.sintro-bar {
  position: absolute;
  left: 0; bottom: 0;
  height: 2px;
  width: 100%;
  z-index: 5;
  transform-origin: 0 50%;
  transform: scaleX(var(--p, 0));
  background: linear-gradient(90deg, var(--venom, #C2261D), var(--yellow, #F2C924));
  opacity: .8;
}

@media (max-width: 900px) {
  .sintro { height: 220vh }
  .sintro-beat .line { max-width: 14ch }
}

/* Reduced motion: no runway, no scrubbing — one still frame and the copy. */
@media (prefers-reduced-motion: reduce) {
  .sintro { height: 100vh }
  .sintro canvas { display: none }
  .sintro-cue, .sintro-bar { display: none }
  .sintro-beat { opacity: 1; transform: none }
  .sintro-beat:not(.last) { display: none }
}
