/* ============================================================================
   REVEAL SYSTEM — from MOTION-DIRECTION.md (the Amber build).

   Values marked MEASURED came off the reference in a real browser; don't
   retune them without a reason. The load sequence from §9 is deliberately
   ABSENT here: on this site a page is entered by a tile inflating to fill
   the screen, so the transition already does the job a loader would. Reveals
   initialise immediately instead of being gated behind an overlay.
   ========================================================================== */

:root{
  /* MEASURED — the two curves the whole system runs on. --ease-snap is the
     workhorse: fast out of the gate, long glide to rest. The second control
     point at 0,1 is what produces the tail; ease-out visibly flattens it. */
  --ease-snap: cubic-bezier(.4, 0, 0, 1);
  --ease-soft: ease;
  --t-base: 0.4s;
}

/* -- base fade -------------------------------------------------------- */
[data-reveal="fade"]{ opacity:0; transition: opacity var(--t-base) var(--ease-snap); }
[data-reveal="fade"].is-in{ opacity:1; }

/* -- slow soft fade for imagery. MEASURED: 0.75s ease + 0.4s delay.
      The built-in delay lets a photo settle AFTER the text over it lands. */
[data-reveal="opacity"]{ opacity:0; transition: opacity .75s var(--ease-soft) .4s; }
[data-reveal="opacity"].is-in{ opacity:1; }

/* -- lift + fade ------------------------------------------------------ */
[data-reveal="up"]{
  opacity:0; transform: translateY(18px);
  transition: opacity .6s var(--ease-snap), transform .6s var(--ease-snap);
}
[data-reveal="up"].is-in{ opacity:1; transform:none; }

[data-reveal="scale"]{
  opacity:0; transform: scale(.94);
  transition: opacity .9s var(--ease-snap), transform .9s var(--ease-snap);
}
[data-reveal="scale"].is-in{ opacity:1; transform:none; }

/* -- SIDE ENTRIES -----------------------------------------------------
   Things arrive from the edge they're nearest, so a section assembles from
   the outside in rather than everything rising off the floor together.
   Distances are in vw so the travel reads at any width — a 40px slide on a
   1600px screen is invisible. */
[data-reveal="left"]{
  opacity:0; transform: translateX(-14vw);
  transition: opacity .8s var(--ease-snap), transform .9s var(--ease-snap);
}
[data-reveal="right"]{
  opacity:0; transform: translateX(14vw);
  transition: opacity .8s var(--ease-snap), transform .9s var(--ease-snap);
}
[data-reveal="left"].is-in, [data-reveal="right"].is-in{ opacity:1; transform:none; }

/* A harder shove for big blocks — further, and it overshoots slightly. */
[data-reveal="slam-left"]{
  opacity:0; transform: translateX(-30vw) rotate(-2deg);
  transition: opacity .7s var(--ease-snap), transform 1s cubic-bezier(.2,1.06,.3,1);
}
[data-reveal="slam-right"]{
  opacity:0; transform: translateX(30vw) rotate(2deg);
  transition: opacity .7s var(--ease-snap), transform 1s cubic-bezier(.2,1.06,.3,1);
}
[data-reveal="slam-left"].is-in, [data-reveal="slam-right"].is-in{ opacity:1; transform:none; }

/* A rule that draws itself across. */
[data-reveal="rule"]{
  transform: scaleX(0); transform-origin: left center;
  transition: transform .9s var(--ease-snap);
}
[data-reveal="rule"].is-in{ transform: scaleX(1); }

/* Counts up from below, for the index numerals. */
[data-reveal="index"]{
  opacity:0; transform: translateY(.6em);
  transition: opacity .5s var(--ease-snap), transform .6s var(--ease-snap);
}
[data-reveal="index"].is-in{ opacity:1; transform:none; }

/* -- THE SIGNATURE EFFECT --------------------------------------------
   Headline words do NOT slide up out of a mask. Each word animates
   blur + scale + opacity — a camera pulling into focus. MEASURED from a
   frame caught mid-animation: blur(10px), scale(1.05), opacity 0. */
[data-reveal="word"]{ opacity:1; }
[data-reveal="word"] .word{
  display:inline-block; opacity:0;
  filter: blur(10px); transform: scale(1.05);
  transition: opacity .9s var(--ease-snap), filter .9s var(--ease-snap), transform .9s var(--ease-snap);
  will-change: opacity, filter, transform;
}
[data-reveal="word"].is-in .word{ opacity:1; filter:blur(0); transform:none; }

/* -- left-to-right polygon wipe. MEASURED geometry. ------------------- */
[data-reveal="clip"]{
  clip-path: polygon(0 0, 0 0, 0 100%, 0% 100%);
  transition: clip-path .75s var(--ease-soft);
}
[data-reveal="clip"].is-in{ clip-path: polygon(0 0, 100% 0, 100% 100%, 0% 100%); }

/* -- button-only circular iris. MEASURED: origin 25% 100% — bottom LEFT,
      not centre — overshooting to 130% to clear the far corner. Expanding
      from a corner is what makes it read as painted on rather than popped. */
[data-reveal="circle"]{
  clip-path: circle(0% at 25% 100%);
  transition: clip-path .85s var(--ease-soft) .4s;
}
[data-reveal="circle"].is-in{ clip-path: circle(130% at 25% 100%); }

/* -- whole-section angled wipe. APPLY TO A BACKGROUND LAYER, NEVER THE
      SECTION ITSELF — a clip-path on a section hides its own children from
      the observer and the entire section deadlocks. See §10.1. */
.wipe{ position:absolute; inset:0; z-index:0; background: var(--accent-block); }
[data-reveal="section"]{
  clip-path: polygon(0 -100%, 0 0, 0 100%, 0% 200%);
  transition: clip-path .95s var(--ease-soft);
}
[data-reveal="section"].is-in{ clip-path: polygon(0 -100%, 100% -50%, 100% 150%, 0 200%); }

/* -- concentric rings, for background decoration. MEASURED: 0.175s per ring,
      which is deliberately slower than the 0.1s content ladder — the rings are
      the stage settling, not content arriving, and at 0.1s they read as part
      of the copy. The first ring starts at scale 0 rather than 0.5 so the set
      opens from a point instead of popping. */
.rings-host{ overflow:hidden; }        /* on any section containing .rings */
.rings{
  position:absolute; left:50%; top:50%;
  transform: translate(-50%,-50%);
  width: min(1100px, 115%); height:auto;
  pointer-events:none; z-index:0;
}
.rings circle{
  scale:.5; opacity:0; transform-origin:center center;
  transition: scale .95s var(--ease-snap), opacity .95s var(--ease-snap);
}
.rings circle:nth-child(1){ scale:0; transition-delay:0s; }
.rings circle:nth-child(2){ transition-delay:.175s; }
.rings circle:nth-child(3){ transition-delay:.35s; }
.rings circle:nth-child(4){ transition-delay:.525s; }
.rings circle:nth-child(5){ transition-delay:.7s; }
.rings.is-in circle{ scale:1; opacity:1; }

/* -- stagger ladder. MEASURED: flat 0.1s per step. Not a curve, not
      random jitter — plain arithmetic. */
[data-delay="1"]{ transition-delay:.1s; }
[data-delay="2"]{ transition-delay:.2s; }
[data-delay="3"]{ transition-delay:.3s; }
[data-delay="4"]{ transition-delay:.4s; }
[data-delay="5"]{ transition-delay:.5s; }
[data-delay="6"]{ transition-delay:.6s; }
/* circle/opacity carry a built-in 0.4s; their ladder adds on top */
[data-reveal="circle"][data-delay="1"]{ transition-delay:.5s; }
[data-reveal="circle"][data-delay="2"]{ transition-delay:.6s; }

@media (prefers-reduced-motion: reduce){
  *{ animation:none !important; transition:none !important; }
  [data-reveal]{ opacity:1 !important; transform:none !important; clip-path:none !important; filter:none !important; }
  [data-reveal="word"] .word{ opacity:1 !important; filter:none !important; transform:none !important; }
  .rings circle{ scale:1 !important; opacity:1 !important; }
}
