/* ===== assets/css/components/hero-transition.css ===== */
/* =============================================================================
   hero-transition.css — Varedat.io · Hero → light-content scroll transition (v18: OVERLAY + CRESCENTS)
   WP mapping: assets/css/components/hero-transition.css + template-parts/sections/hero-transition.php

   Reference (United Carriers + client screenshots 1405-06-04): the blue is an OVERLAY that rises from the
   bottom OVER the hero and the globe (they stay visible under it, dimmed). Its upper boundary is NOT a
   line, a wave or one centred orb: the colour rises much higher toward the LEFT and RIGHT edges and stays
   lower in the middle: two soft crescents enter from the sides while the black hero reads as a huge dome
   pushing down between them. Measured on the reference, that boundary is the lower arc of ONE enormous
   circle (radius ≈ 0.66 × viewport width, centre far above the viewport) — the crescents are what is left
   of the viewport outside that circle. Near the bottom the blue softens into periwinkle and white.

   Structure: .hero-stage wraps the hero + a scroll spacer; BOTH the overlay (.hero-transition__visual, the
   stage's FIRST child, z above the hero, pointer-events: none) and the hero are sticky for the stage's
   duration, so the blue physically passes OVER the still-present globe (the hero scrolling away would
   pull the globe out through the top before it could be submerged). Inside the overlay one tall layer
   carries the colour body (linear, translucent blue → opaque white); its mask cuts the dome (transparent
   inside the circle, long soft rim, opaque outside). Scroll progress (--tp) translates the layer upward.
   Mask + gradient are static, only the transform changes → one composited layer. No autonomous timing.
   ============================================================================= */

.hero-stage {                        /* the custom properties live on the stage so BOTH the overlay and the spacer see them */
  /* v35: z-index so the next section can be pulled up UNDERNEATH this one — see figures.css.
     A sticky child releases one viewport before its container ends, so --tp reaches 1 with a
     full screen of the stage still to scroll: that screen is all white and has nothing in it,
     and it is the gap the client keeps hitting between the blue and the figures. */
  z-index: 2;
  --tp: 0;
  /* colour body sampled from the reference screenshots (deep navy → royal → strong blue → soft → periwinkle → white):
     rich and slightly indigo — no cyan, no purple, no grey */
  --tr-navy: #150a45;         /* v18.1: re-sampled from the client's screenshot 1405-06-04 13:55 (deeper, more opaque body) */
  --tr-royal: #1f1490;
  --tr-blue: #2733b5;
  --tr-soft: #3b58d5;
  --tr-sky: #6e98ed;
  --tr-pale: #acd0f9;
  --tr-near-white: #dff0fe;
  --tr-white: #ffffff;
  /* v36: 200vh -> 130vh. The stage's total is --tr-height + 100dvh (see .hero-transition),
     so this is 230vh against the old 300vh — the run from the hero to the figures is a third
     shorter, and none of what is left is frozen. */
  /* v40: 100vh -> 70vh. The white the client is scrolling through is the pinned pair leaving:
     a 100dvh overlay that has been stuck cannot get off the screen in less than a screen of
     scrolling, so that part is structural and cannot be shortened — what CAN be shortened is
     everything before it and the section's own top padding, and both now are. Total stage is
     --tr-height + 100dvh = 170vh, against 300vh in v37. */
  /* v1.1.1 — measured against the supplied desktop recording. 60vh let the
     complete dome → blue → pale → white move finish in less than one wheel
     gesture. 130vh gives the colour field room to travel without reintroducing
     the empty white band (that band is controlled separately below). */
  --tr-height: 130vh;
  /* v38: --layer-h lives on the stage now so the white floor below the layer can read it. */
  --layer-h: 170vh;
  position: relative;
  isolation: isolate;
}

.hero-transition {                   /* scroll room after the hero */
  position: relative;
  /* v43b: it absorbs the 100dvh the two pinned children no longer occupy, so the stage's
     height is set by --tr-height alone. */
  block-size: calc(var(--tr-height) + var(--figures-uncover));
  /* v43b: TRANSPARENT. This box is scroll room, and it is the only thing in .hero-stage that is
     not clipped by the wipe — so an opaque background here sat over the figures section in
     exactly the band the wipe had just opened, and the curtain lifted onto more white. The
     pinned pair cover the window for the whole transition, so this never shows.
     Reduced motion paints it, because there the overlay is a static bridge rather than a cover. */
  background: transparent;
}

/* the sticky overlay: sits over the hero from the start, covers the viewport, follows the stage */
.hero-transition__visual {
  position: sticky;
  inset-block-start: 0;
  block-size: 100vh;
  block-size: 100dvh;
  /* v43b: on the bottom again — a zero-height margin box, so this stays stuck to the END of
     the stage and the wipe has something pinned to clip. See the note in the markup. */
  margin-block-end: -100vh;
  margin-block-end: -100dvh;
  overflow: hidden;
  z-index: 5;                        /* above the hero (sibling), below the site header */
  pointer-events: none;              /* the globe stays draggable underneath while the overlay is transparent */
}

/* the colour layer: taller than the viewport; starts entirely below it and rises with --tp.
   Blue is translucent (the hero shows through, dimmed); the bottom is opaque white. */
.hero-transition__layer {
  /* dome geometry (the enormous circle), in layer coordinates:
     --dome-r     radius · --dome-cy  centre y (negative = above the layer top; 50% horizontally)
     --dome-soft  length of the soft rim where the blue fades into the black (never a line) */
  /* Measured from the supplied 2868×1330 captures: the lower arc is near
     y=300 at the sides and y=700 at centre. That solves to a very large circle
     (r≈.96W, cy≈-.72W), which creates the shallow luminous bowl in the reference. */
  --dome-r: 96vw;
  --dome-cy: -72vw;
  --dome-soft: 20vh;
  position: absolute;
  inset-inline: 0;
  inset-block-start: 100vh;
  inset-block-start: 100dvh;
  block-size: var(--layer-h);
  background: linear-gradient(
    to bottom,
    rgba(21, 10, 69, 0.78) 0%,
    rgba(21, 10, 69, 0.88) 6%,
    rgba(31, 20, 144, 0.94) 15%,
    rgba(39, 51, 181, 0.97) 27%,
    rgba(59, 88, 213, 0.99) 40%,
    var(--tr-sky) 52%,
    var(--tr-pale) 63%,
    var(--tr-near-white) 73%,
    var(--tr-white) 82%,
    var(--tr-white) 100%
  );
  /* the dome: transparent inside the circle (the hero shows), eased soft rim, opaque outside (the crescents + floor) */
  -webkit-mask-image: radial-gradient(circle var(--dome-r) at 50% var(--dome-cy),
    rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) calc(100% - var(--dome-soft)), rgba(0, 0, 0, 0.35) calc(100% - var(--dome-soft) * 0.5), rgba(0, 0, 0, 0.78) calc(100% - var(--dome-soft) * 0.18), #000 100%);
          mask-image: radial-gradient(circle var(--dome-r) at 50% var(--dome-cy),
    rgba(0, 0, 0, 0) 0, rgba(0, 0, 0, 0) calc(100% - var(--dome-soft)), rgba(0, 0, 0, 0.35) calc(100% - var(--dome-soft) * 0.5), rgba(0, 0, 0, 0.78) calc(100% - var(--dome-soft) * 0.18), #000 100%);
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;     mask-size: 100% 100%;
  transform: translate3d(0, calc(var(--tp) * -1 * (100vh + var(--layer-h) * 0.88)), 0);   /* at 1: the white band covers the viewport */
  will-change: transform;
}

/* v29 — THE TRANSITION MUST END WHITE.
   The layer starts at inset-block-start:100vh and travels (100vh + 0.88 x --layer-h)
   upward, so at --tp:1 its lower edge sits at 100vh + H - T = ~20vh. Below that line
   nothing in the overlay paints, the pinned hero (z-index 1) shows through, and the
   page ends the transition on a tall BLACK band carrying the hero H1 and lead again —
   read by the client as "a black section repeating the hero copy before the truck".
   There is no duplicate markup to delete: it is the hero itself, still stuck.
   The black band starts appearing at --tp ~0.68 (the point where T exceeds H) and
   grows to ~80vh, so the white wash is timed to open there and to be complete by 0.84,
   which is the same threshold applyTransition() already uses to pause the renderer.
   Alpha is clamped by CSS, and --tp defaults to 0, so with JS off this stays
   transparent and nothing regresses. */
.hero-transition__visual {
  background: rgb(255 255 255 / calc((var(--tp) - 0.66) * 5.5));
}

/* v38 — THE WHITE FLOOR, and this is the black band the client kept reporting.
   The colour layer is 170vh tall, starts one viewport below the fold and travels
   (100vh + 0.88 x 170vh) = 249.6vh upward. Its own bottom edge therefore crosses into the
   viewport at --tp 170/249.6 = 0.681 — and below that edge the overlay painted NOTHING, so
   what showed under the blue was the pinned hero: black, with the globe's dots still in it.
   The white wash on .hero-transition__visual only reaches full opacity at 0.842, so between
   those two numbers the hero came through it as a grey band across the bottom of the screen.
   That is the "black section" — it was never a section.
   This is the layer's floor: a white block that starts where the layer ends and carries the
   same transform, so it travels with it and there is never an uncovered strip beneath it. It
   is a pseudo-element of the OVERLAY, not of the layer — the layer is masked to the dome and
   anything parented to it would be masked away too. */
.hero-transition__visual::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-start: calc(100vh + var(--layer-h) - 1px);
  inset-block-start: calc(100dvh + var(--layer-h) - 1px);
  block-size: 300vh;
  background: var(--tr-white);
  transform: translate3d(0, calc(var(--tp) * -1 * (100vh + var(--layer-h) * 0.88)), 0);
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  /* the layer is static there, so the floor must be too */
  .hero-transition__visual::after { transform: none; inset-block-start: var(--layer-h); }
}

/* the hero is pinned for the stage's duration (see the header comment); z below the overlay */
/* v45: A CROSS-FADE, not a wipe (client). --tq is 0 for the whole pinned run and only moves
   while the pair are leaving, so this is inert until the transition is over; then the two of
   them dissolve across the first half of that screen and the section behind them is simply
   there. Both elements already have their own layer, so this is a composited opacity change
   and nothing re-paints.
   The pair are still PINNED while it happens — that is what v43b was for, and it matters just
   as much here: a curtain that has started scrolling away fades from a place the reader is no
   longer looking at. */
/* v47 — THE SECTION IS PART OF THE SAME MOVE.
   The cross-fade was only ever half of it: the curtain dissolved and the section was just
   sitting there behind it, already in place, which is why it read as flat. It comes UP into
   place now on the same 0-to-1, a beat behind the curtain — so what the reader sees is one
   gesture, not one thing disappearing and another thing revealed.
   --tq defaults to 1, so with no JavaScript at all this resolves to "fully arrived" and the
   section is simply visible. It cannot fail hidden. */
.figures__inner { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .figures__inner { opacity: 1; transform: none; }
}

/* v45b: THE TWO OF THEM CANNOT FADE AT THE SAME RATE. The overlay is opaque white and the
   hero is behind it, so fading both together turns the overlay translucent while the hero is
   still partly there — and what crosses the section is a grey ghost of the hero. The hero goes
   first, under cover, and the overlay only starts once it is gone. */
/* v48: both faster. The hero is gone by --tq 0.05 and the curtain by 0.34, so the whole
   hand-off is over inside the first third of that screen instead of two thirds of it. */
.hero-stage > .hero { opacity: calc(1 - var(--tq, 0) * 25); }
.hero-transition__visual { opacity: calc((0.22 - var(--tq, 0)) * 5); }
@media (prefers-reduced-motion: reduce) {
  .hero-transition__visual, .hero-stage > .hero { opacity: 1 !important; }
  .figures { margin-block-start: 0; }
}

.hero-stage > .hero {
  position: sticky;
  inset-block-start: 0;
  z-index: 1;
  /* v43b: the hero gets the same zero-height margin box as the overlay above it, so the pair
     stay pinned together for the whole stage and release together at its end — which is where
     the wipe finishes. (This is v36's trick, brought back for a different reason: there it was
     closing a gap between release points, here it is holding the curtain still.) */
  margin-block-end: -100vh;
  margin-block-end: -100dvh;
  /* v37's dissolve is GONE (v38). They were covering
     for the overlay's release being a viewport later than everything else, and the client is
     right that the dissolve reads wrong: the section is meant to be part of the page you scroll
     to, not something that appears over it. With the releases aligned the pinned pair simply
     scroll away and the figures rise into the same screen behind them. */
}

/* ---------- Next section placeholder (transition approval only) ---------- */
.next-placeholder {
  position: relative;
  z-index: 2;
  background: #ffffff;
  color: var(--color-ink);
  min-block-size: 70vh;
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--space-9) var(--gutter);
}
.next-placeholder__inner { display: grid; gap: var(--space-3); justify-items: center; }
.next-placeholder__title {
  font-family: var(--font-mono); font-size: var(--text-label); letter-spacing: 0.2em; text-transform: uppercase; color: var(--color-ink-2);
}

/* ---------- Tablet / phone: shorter scroll, wider dome so the curve stays readable ---------- */
/* tablets (portrait): the circle keeps its size relative to the width, so its centre moves down */
@media (max-width: 63.99em) {
  .hero-stage { --tr-height: 115vh; }
  .hero-transition__layer { --dome-r: 70vw; --dome-cy: -35vw; --dome-soft: 18vh; }
}
/* phones: tuned independently — a slightly tighter circle so the side crescents still rise clearly above the centre */
@media (max-width: 47.99em) {
  .hero-stage { --tr-height: 100vh; }
  .hero-stage { --layer-h: 150vh; }
  .hero-transition__layer { --dome-r: 78vw; --dome-cy: 9vw; --dome-soft: 14vh; }
}

/* ---------- Reduced motion: no pinning; a static overlay state at mid-progress ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero-stage { --tr-height: 120vh; }
  /* nothing is pinned here, so the two margin-box tricks above have to come off or they take
     a viewport of real height out of the page */
  .hero-stage > .hero { position: relative; margin-block-end: 0; }  /* no pinning */
  .hero-transition { block-size: var(--tr-height); background: var(--tr-white); }
  .hero-transition { background: var(--hero-bg, #050505); }        /* the bridge sits on black */
  /* the overlay becomes a static bridge section right after the hero: dome + crescents → blue → white */
  .hero-transition__visual { position: absolute; inset-block-start: 100vh; inset-block-start: 100dvh; inset-inline: 0; block-size: var(--tr-height); margin-block-end: 0; }
  .hero-transition__layer { --layer-h: var(--tr-height); inset-block-start: 0; transform: none; will-change: auto; }
}

/* Mobile has no interstitial effect: Hero ends and figures enter normal flow. */
@media (max-width: 63.99em) {
  .hero-stage { --tr-height: 0; --layer-h: 0; }
  .hero-stage > .hero {
    position: relative;
    margin-block-end: 0;
    opacity: 1 !important;
  }
  .hero-transition,
  .hero-transition__visual { display: none; }
}
