/* ProLine — authorized enhancement layer (MOTION-STORYBOARD 2.1, 2.2, 4, 7.1)
   Additive only: Gate 3 renders unchanged if this file is removed.
   All state travels through custom properties, so every rule below ports into
   a WordPress block stylesheet without a build step or a JS config object. */

/* ============================ 2.1 · LIVING LOGIC FIELD ============================ */
/* Three shallow SVG planes. The SVG elements retain the existing pointer and
   scroll transforms; one inner group per plane supplies automatic drift. */
.hero__planes {
  position: absolute; inset-block: 0; left: 0; width: var(--seam);
  perspective: 1200px;
  perspective-origin: 38% 45%;
  opacity: .70;
  /* the field recedes behind the headline and lede rather than sitting under
     them at full strength — background supports, never competes */
  -webkit-mask-image: radial-gradient(136% 104% at 24% 69%, transparent 0 19%, rgb(0 0 0 / 42%) 42%, #000 76%);
          mask-image: radial-gradient(136% 104% at 24% 69%, transparent 0 19%, rgb(0 0 0 / 42%) 42%, #000 76%);
}
.hero__planes .plane-shell,
.hero__planes .plane {
  position: absolute; inset: 0; width: 100%; height: 100%;
}
.hero__planes .plane {
  /* --mx/--my are pointer position in -1..1, written by motion.js; --p is the
     hero progress already driving the cinematic. Depth scales both. */
  transform:
    translate3d(calc(var(--mx, 0) * var(--depth) * 14.3px), calc(var(--my, 0) * var(--depth) * 11.7px), 0)
    rotateY(calc(var(--mx, 0) * var(--depth) * 1.04deg))
    rotateX(calc(var(--my, 0) * var(--depth) * -1.04deg))
    scale(calc(1 + var(--depth) * .05 * (var(--g-frag, 0) - var(--g-settle, 0) * .7)));
  transition: transform 380ms var(--e-out);
}
.plane-1 { --depth: .34; }
.plane-2 { --depth: .66; }
.plane-3 { --depth: 1; }
.cinema .drift .hero__planes .plane { will-change: transform; }
.cinema .drift .plane-shell--near {
  animation: logic-plane-roll 38s ease-in-out -11s infinite alternate;
  transform-origin: 72% 44%;
  will-change: transform;
}
@keyframes logic-plane-roll {
  0% { transform: translate3d(5%, -1%, 0) rotateX(1.2deg) rotateY(-3.6deg) rotateZ(-.35deg) scale(.91); }
  50% { transform: translate3d(8%, .8%, 0) rotateX(-1.4deg) rotateY(.8deg) rotateZ(.25deg) scale(.95); }
  100% { transform: translate3d(4%, -.2%, 0) rotateX(.9deg) rotateY(3.4deg) rotateZ(.4deg) scale(.92); }
}

.logic-links { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.logic-links--far { stroke: var(--blue-500); opacity: .10; }
.logic-links--mid { stroke: #168AB9; opacity: .18; }
.logic-links--near { stroke: var(--cyan-400); opacity: .26; }
.logic-links .logic-detail { display: none; }
.plane-1 .frag { fill: #3477a8; }
.plane-2 .frag { fill: #49b7ee; }
.plane-3 .frag { fill: #27d7f5; }
.hero__planes .frag { opacity: .58; }
.cinema .hero__planes .frag { transform: none; }
.cinema .hero__planes .frag-link { stroke-dasharray: none; stroke-dashoffset: 0; }
.logic-route__glow {
  fill: none;
  stroke: #22D5F5;
  stroke-width: 5;
  stroke-linecap: round;
  opacity: calc(.035 + var(--g-cross, 0) * .12);
}
.logic-route { opacity: calc(.26 + var(--g-cross, 0) * .54); }
.logic-orbit {
  fill: none;
  stroke: #2baede;
  stroke-width: .7;
  stroke-dasharray: 2 8;
  opacity: .12;
}
.logic-flow {
  --flow-dash: 80px;
  --flow-gap: 700px;
  --flow-end: -700px;
  fill: none;
  stroke-dasharray: var(--flow-dash) var(--flow-gap);
  stroke-dashoffset: 0;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0;
}
.logic-flow--two { --flow-dash: 92px; --flow-gap: 850px; --flow-end: -850px; }
.logic-flow--three { --flow-dash: 54px; --flow-gap: 390px; --flow-end: -390px; }
.logic-flow__glow { stroke: var(--cyan-400); stroke-width: 2.2; opacity: .24; }
.logic-flow__core { stroke: #efffff; stroke-width: .8; opacity: .90; }
.cinema .drift .logic-flow { animation: logic-flow-run 9s linear infinite; }
.cinema .drift .logic-flow--one { animation-delay: 0s; }
.cinema .drift .logic-flow--two { animation-delay: -3s; }
.cinema .drift .logic-flow--three { animation-delay: -6s; }
@keyframes logic-flow-run {
  0% { stroke-dashoffset: 0; opacity: 0; }
  5% { opacity: 1; }
  82% { stroke-dashoffset: var(--flow-end); opacity: 1; }
  90%, 100% { stroke-dashoffset: var(--flow-end); opacity: 0; }
}
.logic-foci > :not(.logic-spark) { fill: #22D5F5; opacity: .25; }
.logic-foci .logic-spark {
  fill: #eafcff;
  stroke: #22D5F5;
  stroke-width: .8;
  opacity: .42;
  transform-box: fill-box;
  transform-origin: center;
}
.cinema .drift .logic-foci .logic-spark { animation: logic-node-pass 12s ease-in-out infinite; }
.cinema .drift .logic-foci .logic-spark:nth-child(4) { animation-delay: -4s; }
.cinema .drift .logic-foci .logic-spark:nth-child(6) { animation-delay: -8s; }
@keyframes logic-node-pass {
  0%, 14%, 100% { opacity: .42; transform: scale(.92); }
  7% { opacity: 1; transform: scale(1.16); }
}

/* Business logic is tied to the existing scroll gates, so it changes with the
   narrative rather than behaving like a timed code carousel. */
.logic-code {
  --code-o: .44;
  fill: var(--cyan-400);
  font-family: var(--font-mono);
  font-size: 13px;
  letter-spacing: .025em;
  opacity: var(--code-o);
  transform: none;
  transform-box: fill-box;
  transform-origin: center;
}
/* Code is part of the first composition. It reveals once with the initial
   hero entrance, then remains stable and never waits for scroll progress. */
@media (min-width: 901px) {
  .js.intro .logic-code {
    animation: logic-code-in 720ms var(--e-out) backwards;
    animation-play-state: paused;
  }
  .js.intro .logic-code--analytics { animation-delay: 500ms; }
  .js.intro .logic-code--predictive { animation-delay: 580ms; }
  .js.intro .logic-code--agentic { animation-delay: 660ms; }
  .js.intro.intro-go .logic-code { animation-play-state: running; }
}
@keyframes logic-code-in {
  from { opacity: 0; transform: translate3d(0, 8px, 0); }
  to { opacity: var(--code-o); transform: none; }
}

/* One transform-driven pulse. It is visible for less than half of each cycle,
   then disappears before returning to the path origin. */
.logic-pulse {
  offset-path: path("M330 410 L420 355 L510 385 L600 315 L690 350 L750 300");
  offset-anchor: center;
  offset-rotate: 0deg;
  opacity: 0;
}
.logic-pulse .logic-pulse__halo { opacity: .22; }
.logic-pulse > :last-child { stroke: #fff; stroke-width: .75; }
.cinema .drift .logic-pulse { animation: logic-pulse-run 9s linear -6s infinite; }
@keyframes logic-pulse-run {
  0% { offset-distance: 0%; opacity: 0; }
  5% { opacity: .94; }
  82% { offset-distance: 100%; opacity: .94; }
  90%, 100% { offset-distance: 100%; opacity: 0; }
}

/* Laptop/tablet landscape keeps the same world with lighter geometry. */
@media (min-width: 901px) and (max-width: 1439px) {
  .hero__planes .logic-detail { display: none; }
  .logic-code { font-size: 12px; }
}

/* ============================ 2.2 · HERO TEXT CHOREOGRAPHY ============================ */
/* Authored line structure. Below the cinematic breakpoint the spans go back to
   inline and the browser wraps naturally, so the copy stays one editable
   string in WordPress and degrades to a single block if .ln is ever absent. */
.promise .ln { display: inline; }
@media (min-width: 901px) { .promise .ln { display: block; } }

@media (min-width: 901px) {
  /* Headline: mask reveal plus a 14px upward travel, 60ms per line,
     complete at 120 + 400 = 520ms. */
  .js.intro .promise .ln {
    animation: line-in 400ms var(--e-out) backwards;
    animation-delay: calc(var(--i, 0) * 60ms);
  }
  .promise .ln:nth-child(1) { --i: 0; }
  .promise .ln:nth-child(2) { --i: 1; }
  .promise .ln:nth-child(3) { --i: 2; }

  /* Eyebrow: the rule draws, then the label resolves — 300ms total. */
  .js.intro .eyebrow { animation: label-in 180ms var(--e-out) 120ms backwards; }
  .js.intro .eyebrow::before { animation: rule-draw 200ms var(--e-signal) backwards; transform-origin: left; }

  /* Lede and metadata resolve after the headline, inside 320ms. */
  .js.intro .hero__lede { animation: soft-up 320ms var(--e-out) 470ms backwards; }
  .js.intro .hero__meta { animation: soft-up 320ms var(--e-out) 540ms backwards; }

  /* The light world follows one beat later. */
  .js.intro .hero__statement { animation: soft-up 340ms var(--e-out) 260ms backwards; }
  .js.intro .hero__sub { animation: soft-up 320ms var(--e-out) 380ms backwards; }
  /* CTAs appear together and never move: opacity only. */
  .js.intro .hero__actions { animation: fade-only 300ms var(--e-out) 430ms backwards; }
  .js.intro .hero__stack { animation: fade-only 340ms var(--e-out) 520ms backwards; }
}

/* The gate must come after every `animation` shorthand above: the shorthand
   resets animation-play-state, so declaring the pause earlier would let the
   sequence run at parse time and finish before the loader hands over. */
.js.intro :is(.promise .ln, .eyebrow, .hero__lede, .hero__meta, .hero__actions,
               .hero__statement, .hero__sub, .hero__stack),
.js.intro .eyebrow::before { animation-play-state: paused; }
.js.intro.intro-go :is(.promise .ln, .eyebrow, .hero__lede, .hero__meta,
                        .hero__actions, .hero__statement, .hero__sub, .hero__stack),
.js.intro.intro-go .eyebrow::before { animation-play-state: running; }

@keyframes line-in {
  from { clip-path: inset(0 0 100% 0); translate: 0 14px; }
  to   { clip-path: inset(-.16em 0 -.24em 0); translate: 0 0; }
}
@keyframes rule-draw { from { scale: 0 1; } to { scale: 1 1; } }
@keyframes label-in { from { opacity: 0; translate: 0 4px; } to { opacity: 1; translate: 0 0; } }
@keyframes soft-up { from { opacity: 0; translate: 0 10px; } to { opacity: 1; translate: 0 0; } }
@keyframes fade-only { from { opacity: 0; } to { opacity: 1; } }

/* One controlled light sweep across the cyan phrase. Runs once, ends on solid
   brand cyan, and the colour is inherited if the animation never runs. */
@media (min-width: 901px) {
  .js.intro.intro-go .promise em {
    background-image: linear-gradient(100deg,
      var(--cyan-400) 0 42%, #eafcff 50%, var(--cyan-400) 58% 100%);
    background-size: 320% 100%;
    background-position: 100% 0;
    -webkit-background-clip: text;
            background-clip: text;
    -webkit-text-fill-color: transparent;
    animation: sweep 900ms var(--e-out) 480ms 1 forwards;
  }
}
@keyframes sweep {
  from { background-position: 100% 0; }
  to   { background-position: 0 0; }
}

/* ============================ 4 · SECTION TITLE TRANSITIONS ============================ */
/* Retuned into the authorized band: eyebrow leads by 70ms, the heading takes a
   380ms mask/up reveal, the paragraph follows and completes inside 300ms.
   The reveal observer unobserves on first entry, so scrolling back never
   re-animates anything. */
.js .stagger.is-in > * { transition: none; }
.js .stagger > *:nth-child(1) { opacity: 1; translate: none; }
.js .stagger.is-in > *:nth-child(1) { animation: label-in 200ms var(--e-out) backwards; }
.js .stagger.is-in > *:nth-child(2) { animation: title-in 380ms var(--e-out) 70ms backwards; }
.js .stagger.is-in > *:nth-child(3) { animation: soft-up 300ms var(--e-out) 300ms backwards; }
.js .stagger > *:nth-child(n + 2) { opacity: 0; }
.js .stagger.is-in > *:nth-child(n + 2) { opacity: 1; }

@keyframes title-in {
  from { clip-path: inset(0 0 100% 0); translate: 0 16px; }
  to   { clip-path: inset(-.16em 0 -.24em 0); translate: 0 0; }
}

/* ============================ 7.1 · FALLBACKS ============================ */
/* Mobile and tablet portrait: simplified, no pinning, and above all no content
   delay — the copy is present at first paint and only the eyebrow rule draws. */
@media (max-width: 900px) {
  .js.intro :is(.promise .ln, .hero__lede, .hero__meta, .hero__actions,
                 .hero__statement, .hero__sub, .hero__stack) { animation: none; opacity: 1; }
  .hero__planes { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .js.intro :is(.promise .ln, .eyebrow, .hero__lede, .hero__meta, .hero__actions,
                 .hero__statement, .hero__sub, .hero__stack),
  .js.intro .eyebrow::before,
  .js .stagger.is-in > * { animation: none; opacity: 1; translate: none; clip-path: none; scale: 1; }
  .js.intro.intro-go .promise em { background-image: none; -webkit-text-fill-color: currentColor; animation: none; }
  .hero__planes .plane { transform: none; transition: none; }
  .cinema .drift .hero__planes .plane-shell,
  .cinema .drift .logic-pulse,
  .cinema .drift .logic-flow,
  .cinema .drift .logic-foci .logic-spark { animation: none; }
  .logic-pulse, .logic-flow { opacity: 0; }
  .logic-foci .logic-spark { opacity: .72; transform: none; }
  .js.intro .logic-code { animation: none; opacity: var(--code-o); transform: none; }
}
