/**
 * Entry animation — canvas-reveal override.  (MIKO-owned, theme-side.)
 *
 * entry v1 flash stripped 2026-07-12, utilities retained for entry v2
 * ([[Entry Animation — Motion Spec v2 2026-07-12]]).
 *
 * The v1 flash-sweep layer (`.vz-entry-flash`, its gradient band, keyframes, and the
 * `hero-cosmos-lumamask.png` mask) is deleted — superseded by a v2 point-cloud reveal being
 * specced now. What remains is the canvas-reveal OVERRIDE: it neutralizes the gfx stock
 * is-ready fade during `.vz-entry-active`; on field-mount the canvas is held visible by the
 * [data-vz-entry="first"] rule below. `is-settled` is a loader-stamped state hook — no CSS
 * rule here consumes it.
 *
 * The orchestrator (10-entry-flash.js) sets `.vz-entry-active` on `.vz-hero` (the stage's
 * ANCESTOR — required by the descendant selectors below) BEFORE the field loader mounts, so the
 * is-ready→blob fade is neutralized before any first frame.
 *
 * Fabão seam: NONE. This file lives in assets/entry/ (no gfx glob claims it). The canvas-reveal
 * override lives here, not in 10-hero-field.css, so the gfx fade path is untouched on every
 * no-entry route.
 */

/* ─────────────────────────────────────────────────────────────────────────────
   CANVAS-REVEAL OVERRIDE
   While the entry runs, the entry owns the canvas reveal. `.vz-entry-active` is set on
   `.vz-hero` (the stage's ancestor) by the orchestrator BEFORE the field loader mounts —
   the descendant selectors below require it there, not on the stage itself.
   ───────────────────────────────────────────────────────────────────────────── */

/* DARK BOOT (2026-07-12, MIKO — "strip the loading image, get straight into the animation").
   On the FIELD-MOUNT path the orchestrator stamps `data-vz-field="mount"` on the stage at parse
   (mobile ≤781px / no-WebGL2 do NOT get it — the poster stays their destination). Hide the cosmos
   `.poster` while the entry runs, so the stage's first paint is the field's clear colour (#090909,
   the stage's own background) instead of the poster. This closes the ~1.9s window between first
   paint and canvas-mount (load → requestIdleCallback → three.js import → bake → shader compile),
   which used to show the cosmos poster before the coalesce landed. `.vz-entry-active` is set at
   parse and released only after settle, so the poster is hidden across the whole boot; by the time
   it is released the canvas is opaque over the (still-dark) stage. The `.poster` element stays in
   the DOM and is untouched on every non-field / fallback route — GEO/LCP fallback contract intact.
   `visibility:hidden` (not display:none) keeps the box for any layout/measurement; the dark stage
   shows through regardless. */
.vz-entry-active .vz-gfx-stage[data-vz-field="mount"] .poster {
  visibility: hidden;
}

/* CANVAS-REVEAL — the IN-FIELD COALESCE is the opening (2026-07-12, MIKO — Option A), on EVERY
   visit (session gate removed; `data-vz-entry` is always "first"). The canvas is VISIBLE from first
   paint so the coalesce is seen AS IT HAPPENS — the runtime paints an opaque-dark frame 1 (clear
   #090909) with the points scattered+dim and the nebula gated to near-zero, then ignites over ~3s
   (uIntroProgress), so there is no bright warm-up blob to hide. We only neutralize the stock 2.5s
   is-ready fade (opacity:1 immediately, no transition) so it can't run a SECOND, conflicting opacity
   animation over the coalesce. Releasing `.vz-entry-active` hands control back to the stock
   is-ready rule at the SAME value (opacity:1) — no visual step. (`is-settled` is a loader-stamped
   state hook; no CSS rule here consumes it.) */
.vz-entry-active .vz-gfx-stage[data-vz-entry="first"].is-ready canvas {
  opacity: 1;
  transition: none;
}

/* GROUND relocated 2026-07-12 (L-01) → assets/css/10-site-ground.css. The site-wide
   `body::before` background is site chrome, not entry animation, so it no longer lives
   in this entry stylesheet. Behaviour is unchanged; see that file. */

/* ─────────────────────────────────────────────────────────────────────────────
   ENTRY BEAT — physarum → logo morph, PROGRESSIVE UNCOVER   (v2, [[Entry Animation
   — Motion Spec v2 2026-07-12]], MIKO tweaks 2026-07-12). The overlay is JS-injected
   by 10-entry-flash.js; these styles describe it. NO TEXT (the network RESOLVES INTO
   the logo shape). NEVER opaque OVER THE H1: the hero-floor H1 must remain the LCP.

   UNCOVER MODEL (MIKO 2026-07-12): the viewport starts near-DARK (the cosmos is
   COVERED) and the growing physarum ERODES the dark cover along its filaments, so the
   image is revealed bit by bit — "light tracing through". The dark cover now lives on
   a CANVAS (`.vz-entry-cover`, JS-painted + eroded with destination-out), NOT on this
   scrim — so the cover can be punched-through cumulatively AND kept clear over the H1.
   This container background is therefore only a faint vignette that never darkens the
   lower-left H1 zone. See the JS header for the two-canvas architecture + the H1 gap.
   ───────────────────────────────────────────────────────────────────────────── */
.vz-entry-bloom {
  position: fixed;
  inset: 0;
  z-index: 200;
  pointer-events: none;
  /* Only a faint edge vignette — the DARK COVER is the canvas layer below, which is
     masked to spare the H1. This container never paints a flat cover over the copy. */
  background: radial-gradient(120% 120% at 50% 42%, transparent 58%, rgba(7, 3, 18, .34));
  overflow: hidden;
  opacity: 1;
  transition: background .8s ease;
}
/* Two stacked canvases. `.vz-entry-cover` is the DARK COVER (below); `.vz-entry-fil` is
   the filament + particle layer (above). Both fill the overlay. */
.vz-entry-bloom canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
/* The dark cover reads at full strength — its own pixels carry the darkness AND the eroded
   reveal-holes (where the network spread, the cover is punched transparent, so the cosmos shows).
   Layer opacity stays 1 through BOTH phases: the reveal is done by erosion in the pixels, not by
   dimming the layer, and the Phase-B interior VOID mask lives on this same canvas — dimming the
   layer would wash the black interior grey (that bug: the mask pixels were dark but a .35 layer
   opacity let 65% of the bright cosmos through). It fades to 0 only with the overlay on dismiss. */
.vz-entry-bloom .vz-entry-cover {
  opacity: 1;
  transition: opacity .6s ease;
}
/* Phase A filaments sit at .8 over the (dark or eroded) cover so the traced light reads. */
.vz-entry-bloom .vz-entry-fil {
  opacity: .8;
  transition: opacity .6s ease;
}
/* Phase B: the migrating/landing particles carry the moment — full opacity so the
   convergence pops as the field dissolves in underneath. */
.vz-entry-bloom.is-morphing .vz-entry-fil {
  opacity: 1;
}
/* NOTE: the cover is NOT dimmed in Phase B (no `.is-morphing .vz-entry-cover` opacity rule).
   By Phase B the reveal is mostly complete via erosion, so the un-eroded remainder is just a
   thin vignette, and the interior VOID mask on this layer must stay fully dark. Both fade out
   together with the overlay (.is-out) at dismiss — the field's own void continues the interior. */
/* fade-out beat: JS adds .is-out on dismiss, then display:none + tears down after .6s.
   Everything (remaining cover incl. the logo interior mask) fades with the overlay. */
.vz-entry-bloom.is-out {
  opacity: 0;
  transition: opacity .6s ease;
}
/* Belt-and-braces: if reduced-motion is on, the JS never injects this overlay, but
   should any bloom node exist, it never animates or shows. */
@media (prefers-reduced-motion: reduce) {
  .vz-entry-bloom { display: none !important; }
}
