/* ============================================================================
   Bratischka birthday scroll-flight — bespoke, no UI chrome.
   Vertical (9:16) source footage: on wide viewports it plays inside a centered
   phone-shaped panel with a blurred cinematic backdrop; on narrow/mobile
   viewports the panel goes full-bleed. Same panel carries every scene so the
   frame itself never changes — only its content does — which is what sells
   the "continuous flight" illusion across four unrelated clips.
   ========================================================================== */

:root{
  --bg: #0b0705;
  --ink: #f3e9da;
  --accent: #d99a4e;
}

*{ box-sizing: border-box; }
html, body{
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  overflow-x: hidden;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, sans-serif;
}

/* the scroll track just exists to give the page height; nothing renders in it */
.track{ position: relative; width: 100%; pointer-events: none; }

/* subtle scroll-progress hairline — indicator only, not a control */
.progress{
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  height: 2px; background: rgba(255,255,255,0.08); pointer-events: none;
}
.progress__fill{
  height: 100%; width: 100%; transform-origin: 0 50%; transform: scaleX(0);
  background: var(--accent); opacity: 0.55;
}

/* fixed viewport-filling stage: blurred backdrop + framed panel, both fixed */
.stage{ position: fixed; inset: 0; z-index: 1; overflow: hidden; }

.backdrop{ position: absolute; inset: -4%; z-index: 1; }
.backdrop__layer{
  position: absolute; inset: 0; opacity: 0; will-change: opacity;
}
.backdrop__layer img, .backdrop__layer video{
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 38%;
  filter: blur(38px) saturate(1.15) brightness(0.55);
  transform: scale(1.18);
}

.panel{
  position: absolute; left: 50%; top: 50%; z-index: 2;
  width: min(100vw, 56.25vh);
  height: min(100vh, 177.78vw);
  aspect-ratio: 9 / 16;
  transform: translate(-50%, -50%);
  overflow: hidden;
  border-radius: 14px;
  box-shadow: 0 40px 120px rgba(0,0,0,0.65);
  background: #000;
}

.scene{ position: absolute; inset: 0; opacity: 0; overflow: hidden; will-change: opacity, transform; }
.scene--minimal{ background: var(--bg); }
.scene__media{
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 38%;
  will-change: transform;
  filter: saturate(1.1) contrast(1.06) sepia(0.05);
}
/* poster overlay for video scenes, painted on top of the <video> (later in
   DOM order) until 'has-clip' says a real frame has painted — see the iOS
   note at the top of scroll.js. Same look as scene__media so there's no
   visible swap when it's hidden. */
.scene__still{
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: center 38%;
  will-change: transform;
  filter: saturate(1.1) contrast(1.06) sepia(0.05);
}
.scene.has-clip .scene__still{ opacity: 0; }

/* unified warm color-grade + vignette; one instance per scene, painted between
   that scene's media (unpositioned z-index) and its text (z-index 10) */
.grade{
  position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 15%, rgba(255,200,140,0.10), transparent 55%),
    radial-gradient(140% 100% at 50% 100%, rgba(0,0,0,0.55), transparent 60%),
    linear-gradient(180deg, rgba(20,10,5,0.35) 0%, rgba(0,0,0,0) 22%, rgba(0,0,0,0) 70%, rgba(10,5,2,0.55) 100%);
  mix-blend-mode: multiply;
}
.grade::after{
  content:""; position:absolute; inset:0;
  box-shadow: inset 0 0 18vh 4vh rgba(0,0,0,0.55);
}

/* text layer, lives inside the framed panel so it reads as part of the scene */
.copy{
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 8%;
  perspective: 600px;
}
.copy__inner{ transform-style: preserve-3d; }

.beat{
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.beat__word{
  opacity: 0;
  font-weight: 800;
  font-size: clamp(2.6rem, 13vw, 4.2rem);
  letter-spacing: 0.02em;
  text-shadow: 0 6px 30px rgba(0,0,0,0.55), 0 1px 0 rgba(255,255,255,0.08);
  will-change: opacity, transform;
}

.build{
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.build__word{
  display: inline-flex;
  font-weight: 900;
  font-size: clamp(1.9rem, 9.6vw, 3.4rem);
  letter-spacing: 0.06em;
  text-shadow: 0 8px 34px rgba(0,0,0,0.6);
}
.build__letter{ opacity: 0; transform: translateY(0.25em) scale(0.85); will-change: opacity, transform; }

/* lower-third caption — sits below the subject, not centered on the frame */
.caption{
  position: absolute; inset: 0; z-index: 10;
  display: flex; align-items: flex-end; justify-content: center;
  text-align: center; padding: 0 8% 14%;
  pointer-events: none;
}
.caption__text{
  opacity: 0;
  font-size: clamp(1.05rem, 4.6vw, 1.6rem);
  font-weight: 700;
  text-shadow: 0 4px 20px rgba(0,0,0,0.65);
  will-change: opacity, transform;
}

.finale{ position: absolute; inset: 0; z-index: 10; pointer-events: none; }
.finale__text{
  /* each line is its own full-bleed centered layer, stacked directly on top
     of the others — only one (or two, mid-crossfade) visibly opaque at once */
  position: absolute; inset: 0; margin: 0;
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 12%;
  opacity: 0;
  font-size: clamp(1.3rem, 5.6vw, 2.1rem);
  line-height: 1.4;
  font-weight: 600;
  text-shadow: 0 6px 26px rgba(0,0,0,0.6);
  will-change: opacity, transform;
}

/* signature close: pure vector path (no font shipped), stroke drawn in via
   stroke-dashoffset then filled — see scroll.js SIGNATURE / sequence handling */
.finale__signature svg{
  width: min(78vw, 560px);
  height: auto;
  overflow: visible;
  filter: drop-shadow(0 6px 22px rgba(0,0,0,0.55));
}
.finale__signature path{
  fill: var(--ink);
  fill-opacity: 0;
  stroke: var(--ink);
  stroke-width: 3;
  /* butt, not round: a round cap turns the near-zero-length dash sliver on
     not-yet-drawn letters (dashoffset never lands exactly on dasharray) into
     a small visible dot floating ahead of the pen — confirmed by testing. */
  stroke-linecap: butt;
  stroke-linejoin: round;
}

@media (prefers-reduced-motion: reduce){
  /* no stroke-draw animation — just show the finished signature */
  .finale__signature path{ stroke-dashoffset: 0 !important; fill-opacity: 1 !important; }
}

@media (max-width: 700px){
  .panel{
    width: 100vw; height: 100vh; aspect-ratio: auto;
    border-radius: 0; box-shadow: none;
  }
  .backdrop{ display: none; }
}

@media (prefers-reduced-motion: reduce){
  .scene__media, .scene__still{ transform: none !important; }
}
