/* ==========================================================
   3comp — the immersive layer
   Boot, node field, veil, corner frame, depth reveal, cursor tilt.
   Everything here is driven from the single rAF loop in main.js
   through the CSS vars declared in tokens.css.
   ========================================================== */

/* ---------- boot ---------- */
#boot{
  position:fixed;inset:0;z-index:200;background:var(--ink);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;
  transition:opacity .7s ease,visibility .7s;
}
#boot.done{opacity:0;visibility:hidden;}
#boot .mark{font-family:var(--f-display);font-size:clamp(38px,7vw,74px);letter-spacing:-.045em;}
#boot .mark i{font-style:normal;color:var(--ultra-lift);}
#boot .bar{width:min(280px,60vw);height:1px;background:var(--rule);position:relative;overflow:hidden;}
#boot .bar span{position:absolute;inset:0 100% 0 0;background:var(--ultra-lift);transition:right .25s ease;}
#boot .pct{font-family:var(--f-mono);font-size:11.5px;letter-spacing:.2em;color:var(--dimmer);}

/* ---------- field + atmosphere ---------- */
#field{position:fixed;inset:0;z-index:0;pointer-events:none;}

.veil{
  position:fixed;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(120% 80% at 50% 0%,transparent 40%,rgba(8,15,22,.72) 100%),
    radial-gradient(80% 60% at calc(50% - var(--cam-x) * 7%) calc(50% - var(--cam-y) * 7%),
      rgba(var(--amb-r),var(--amb-g),var(--amb-b),calc(.07 + var(--vel) * .09)),transparent 70%);
}

/* faint scanlines that only surface while you are moving */
.scan{
  position:fixed;inset:0;z-index:1;pointer-events:none;
  opacity:calc(var(--vel) * .35);
  background:repeating-linear-gradient(180deg,rgba(238,241,244,.06) 0 1px,transparent 1px 3px);
}

#prog{position:fixed;top:0;left:0;height:2px;width:0;background:var(--amb-lift);z-index:110;box-shadow:0 0 14px var(--amb-lift);}

/* ---------- blackout bands ----------
   Content darkens into the page ground at the top and bottom edges of the
   viewport; the middle is untouched. Fixed to the screen, so the bands stay
   put while content scrolls through them. This replaced the old per-element
   scroll-driven fade entirely — it is static, so it cannot desync.

   Layering: above the content (#smooth, z2), below the header (z100), the
   HUD (105), the progress bar (110) and the boot screen (200).

   rgba(8,15,22,0) rather than `transparent`: the latter is rgba(0,0,0,0) and
   interpolating to it washes the ramp grey. --ink is #080F16 = rgb(8,15,22).
   pointer-events:none, or the overlay swallows every click on the page.

   The bottom inset is what keeps the footer out of the blackout. The footer
   lives inside #smooth — a stacking context at z-index:2 — so it can never be
   raised above this overlay; instead the overlay's own box stops at the
   footer's top edge, scroll.js writing --fade-stop as the footer comes into
   view. The gradient is unchanged; its bottom band simply lands there instead.
   Side effect: the stops are percentages of this box, so the top band shrinks
   by the same ~8px while the footer is on screen. */
body::after{
  content:"";
  position:fixed;top:0;left:0;right:0;bottom:var(--fade-stop,0px);
  z-index:90;pointer-events:none;
  background:linear-gradient(to bottom,
    var(--ink) 0%,
    rgba(8,15,22,0) var(--fade-top),
    rgba(8,15,22,0) calc(100% - var(--fade-bottom)),
    var(--ink) 100%);
}

/* ---------- smooth scroll shell ---------- */
#smooth{position:relative;z-index:2;width:100%;}
#smooth.fixed{position:fixed;top:0;left:0;will-change:transform;}

/* ---------- depth reveal ---------- */
/* No `.has-motion .z{opacity:0}` here, deliberately. That rule only ever
   worked because reveal.js overwrote the opacity every frame; nothing
   writes opacity any more, so reinstating it would leave every block
   permanently invisible. Blocks are always fully opaque — the blackout is
   the fixed band below, and reveal.js only moves them. */
.z{will-change:transform;}
/* Pinned on purpose. Driving perspective-origin from the cursor shifts the
   vanishing point for the whole section, so every .z block still carrying any
   Z slides sideways as the pointer moves — the section drifts as one piece.
   The cards get their own pointer response from .tilt; sections stay put. */
.persp{
  perspective:1500px;
  perspective-origin:50% 45%;
}

/* ---------- hero chips ---------- */
/* The chips only read as depth if the hero establishes a camera.
   1800px keeps the far chips legible while still letting the near
   ones sweep past; reveal.js fades them out well before z reaches
   this value, so they never cross the lens plane. */
.hero{perspective:1800px;}
.chips{position:absolute;inset:0;z-index:2;pointer-events:none;transform-style:preserve-3d;}
/* Sizes are authored, not rendered: perspective shrinks each chip by
   1800/(1800+|data-z|), so the deepest ones land ~35% smaller than this.
   At 16px the deepest chip (z=-950) renders at about 10.5px. */
.chip{
  position:absolute;font-family:var(--f-mono);font-size:16px;letter-spacing:.09em;
  padding:11px 19px;border:1px solid rgba(110,138,255,.42);border-radius:2px;
  background:rgba(44,75,238,.10);color:rgba(238,241,244,.88);white-space:nowrap;
  backdrop-filter:blur(3px);will-change:transform,opacity;opacity:0;
}
.chip.core{
  border-color:var(--ultra-lift);background:rgba(44,75,238,.24);
  font-family:var(--f-display);font-size:19px;font-weight:600;letter-spacing:-.01em;
  box-shadow:0 0 40px -8px var(--ultra-glow);
}

.scroll-cue{
  position:absolute;bottom:34px;left:var(--gut);z-index:3;
  font-family:var(--f-mono);font-size:10.5px;letter-spacing:.2em;color:var(--dimmer);
  display:flex;align-items:center;gap:12px;
}
.scroll-cue .ln{width:44px;height:1px;background:var(--rule);position:relative;overflow:hidden;}
.scroll-cue .ln::after{content:"";position:absolute;inset:0;background:var(--amb-lift);animation:sweep 2.2s ease-in-out infinite;}
@keyframes sweep{0%{transform:translateX(-100%);}60%,100%{transform:translateX(100%);}}

/* ---------- cursor tilt ---------- */
.tilt{perspective:1000px;}
.tilt-in{
  position:relative;overflow:hidden;
  transform:translateZ(var(--tz,0px)) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
  transform-style:preserve-3d;
}
/* .lit takes the same cursor light without the rotation — see tilt.js. It
   carries the light on itself, so it needs its own containing box. */
.lit{position:relative;}
.tilt-in::after,
.lit::after{
  content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:radial-gradient(340px circle at var(--mx,50%) var(--my,50%),
    rgba(var(--amb-lr),var(--amb-lg),var(--amb-lb),.15),transparent 62%);
  opacity:0;transition:opacity .35s;
}
.tilt:hover .tilt-in::after,
.lit:hover::after{opacity:1;}

/* ---------- corner frame ---------- */
.hud{position:fixed;inset:0;z-index:105;pointer-events:none;display:none;}
.has-hud .hud{display:block;}

.hud-frame i{
  position:absolute;width:16px;height:16px;
  border:1px solid rgba(238,241,244,calc(.10 + var(--vel) * .22));
}
.hud-frame i:nth-child(1){top:82px;left:calc(var(--gut) - 12px);border-right:0;border-bottom:0;}
.hud-frame i:nth-child(2){top:82px;right:calc(var(--gut) - 12px);border-left:0;border-bottom:0;}
.hud-frame i:nth-child(3){bottom:26px;left:calc(var(--gut) - 12px);border-right:0;border-top:0;}
.hud-frame i:nth-child(4){bottom:26px;right:calc(var(--gut) - 12px);border-left:0;border-top:0;}

/* ---------- reduced motion: strip the whole engine ---------- */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto;}
  /* The engine never starts here, so nothing writes --fade-stop and the
     bottom band would sit on the footer for good. Drop the band instead. */
  :root{--fade-bottom:0%;}
  *,*::before,*::after{animation:none!important;transition:none!important;}
  #field,.scan,.hud,.chips,#boot{display:none!important;}
  .z{opacity:1!important;transform:none!important;}
  .tilt-in{transform:none!important;}
}

/* ---------- touch: no chips, no tilt chrome ---------- */
/* The chips are aimed at the margins beside the headline. Below ~1280px
   those margins are gone and they would land on the text, so they go. */
@media (max-width:1280px){
  .chips{display:none;}
}
@media (hover:none){
  .tilt-in::after,.lit::after{display:none;}
}
