/* ============================================================
   LOOMSTATE — cinematic motion layer
   Scroll-scrubbed heading line reveals, media entrance rises,
   and a hero title-build sequence. Purely additive — layered
   on top of the existing reveal (.rv) + parallax systems.
   ============================================================ */

/* ---------- cinematic heading line reveal ---------- */
/* [data-cine] headings are split into line-masks by motion.js.
   Each line sits in an overflow-clipped frame and rises in. */
[data-cine]{--cine-d:0ms}
.cine-line{display:block;overflow:hidden;padding-bottom:.04em;margin-bottom:-.04em}
.cine-line__i{display:block;transform:translateY(112%) rotate(2deg);opacity:0;
  transition:transform 1.05s cubic-bezier(.16,1,.3,1),opacity 1.05s cubic-bezier(.16,1,.3,1)}
[data-cine].cine-in .cine-line__i{transform:none;opacity:1}
/* stagger lines within a heading */
.cine-line:nth-child(1) .cine-line__i{transition-delay:calc(var(--cine-d) + 0ms)}
.cine-line:nth-child(2) .cine-line__i{transition-delay:calc(var(--cine-d) + 90ms)}
.cine-line:nth-child(3) .cine-line__i{transition-delay:calc(var(--cine-d) + 180ms)}
.cine-line:nth-child(4) .cine-line__i{transition-delay:calc(var(--cine-d) + 270ms)}
.cine-line:nth-child(5) .cine-line__i{transition-delay:calc(var(--cine-d) + 360ms)}

/* ---------- media entrance rise (scroll-scrubbed) ---------- */
/* motion.js writes --rise (0..1) as the frame travels into view.
   0 = just entering from below, 1 = settled. */
[data-rise]{
  --rise:0;
  transform:translate3d(0,calc((1 - var(--rise)) * 46px),0) scale(calc(0.965 + 0.035 * var(--rise)));
  opacity:calc(0.15 + 0.85 * var(--rise));
  will-change:transform,opacity}

/* a faint focus-blur that resolves as the frame settles — reads as a rack focus */
[data-rise].rise-focus{filter:blur(calc((1 - var(--rise)) * 7px))}

/* ---------- scroll-linked section tint sweep ---------- */
/* a thin accent line that draws across a lab head as it enters */
.lab__head,.journey__head,.catalogue__head,.xp__head{position:relative}
[data-underline]::after{content:"";position:absolute;left:0;bottom:-10px;height:1px;width:100%;
  background:linear-gradient(90deg,var(--accent),transparent);transform:scaleX(0);transform-origin:left;
  transition:transform 1.1s cubic-bezier(.16,1,.3,1);opacity:.6}
[data-underline].cine-in::after,[data-underline].uline-in::after{transform:scaleX(1)}

/* ============================================================
   HERO — title-build boot sequence
   Body carries .cine-booting until motion.js releases it.
   ============================================================ */
body.cine-booting{overflow:hidden}

/* letterbox bars slide shut then relax — like a film gate opening */
.hero__bars::before,.hero__bars::after{transition:height .9s cubic-bezier(.16,1,.3,1)}
body.cine-booting .hero__bars::before,
body.cine-booting .hero__bars::after{height:50vh}

/* HUD chrome + foot fade/slide in after the gate */
.hero__cam,.hero__camfoot{transition:opacity .8s ease .5s,transform .8s cubic-bezier(.16,1,.3,1) .5s}
body.cine-booting .hero__cam{opacity:0;transform:translateY(-10px)}
body.cine-booting .hero__camfoot{opacity:0;transform:translateY(10px)}

/* eyebrow + sub rise after the wordmark */
.hero__eyebrow{transition:opacity .9s ease,transform .9s cubic-bezier(.16,1,.3,1)}
.hero__row{transition:opacity 1s ease .15s,transform 1s cubic-bezier(.16,1,.3,1) .15s}
body.cine-booting .hero__eyebrow{opacity:0;transform:translateY(16px)}
body.cine-booting .hero__row{opacity:0;transform:translateY(24px)}

/* the film itself pushes in from a slight over-scale — a lens settling */
.hero__film{transition:transform 1.4s cubic-bezier(.16,1,.3,1),filter 1.4s ease}
body.cine-booting .hero__film{transform:scale(1.14);filter:blur(6px) brightness(.7)}

/* a one-shot horizontal scan wipe across the frame at boot */
.hero__wipe{position:absolute;inset:0;z-index:6;pointer-events:none;opacity:0}
body.cine-booting .hero__wipe{opacity:1;
  background:linear-gradient(90deg,transparent 0%,transparent 42%,color-mix(in oklab,var(--accent) 70%,#fff) 50%,transparent 58%,transparent 100%);
  background-size:260% 100%;background-position:180% 0;
  animation:heroWipe 1.5s cubic-bezier(.16,1,.3,1) .2s forwards}
@keyframes heroWipe{to{background-position:-120% 0;opacity:0}}

/* ---------- reduced motion: everything resolves to its end state ---------- */
@media(prefers-reduced-motion:reduce){
  .cine-line__i{transform:none;opacity:1;transition:none}
  [data-rise]{transform:none;opacity:1;filter:none}
  [data-underline]::after{transform:scaleX(1);transition:none}
  .hero__wipe{display:none}
  body.cine-booting{overflow:auto}
  body.cine-booting .hero__film,
  body.cine-booting .hero__cam,
  body.cine-booting .hero__camfoot,
  body.cine-booting .hero__eyebrow,
  body.cine-booting .hero__row,
  body.cine-booting .hero__bars::before,
  body.cine-booting .hero__bars::after{transform:none;opacity:1;filter:none}
}

/* ---------- global kill-switch when cinematic build is toggled off ---------- */
body.cine-off .cine-line__i{transform:none !important;opacity:1 !important}
body.cine-off [data-rise]{transform:none !important;opacity:1 !important;filter:none !important}
body.cine-off [data-underline]::after{transform:scaleX(1) !important}
