/* ProLine — Gate 3 section motion.
   Restrained by construction: every effect below is opacity or transform,
   triggered once by the reveal observer that already existed in Gate 1, and
   removed wholesale under reduced motion. Section transitions stay inside the
   350–700ms band; micro-interactions inside 140–220ms. */

/* ============================ RENDER COST ============================ */
/* Below the hero, sections are skipped until they are near the viewport. This
   is the single largest saving on the initial style-and-layout pass, and it is
   pure CSS. `auto` in contain-intrinsic-size makes the browser remember each
   section's real height once measured, so the scrollbar does not jump.
   Estimates below are re-measured at 1440x900 after the height-aware
   spacing change; `auto` corrects them per viewport at runtime. */
#why         { content-visibility: auto; contain-intrinsic-size: auto 828px; }
#proof       { content-visibility: auto; contain-intrinsic-size: auto 964px; }
#capabilities{ content-visibility: auto; contain-intrinsic-size: auto 992px; }
#technology  { content-visibility: auto; contain-intrinsic-size: auto 669px; }
#method      { content-visibility: auto; contain-intrinsic-size: auto 663px; }
#consult     { content-visibility: auto; contain-intrinsic-size: auto 511px; }

/* Printing and full-page capture need every section laid out at once. */
@media print { #why, #proof, #capabilities, #technology, #method, #consult { content-visibility: visible; } }
.render-all :is(#why, #proof, #capabilities, #technology, #method, #consult) { content-visibility: visible; }

/* ============================ SHARED ============================ */
/* Order comes from the DOM, not from JS: no timers, no per-element attributes. */
:is(.stagger, .why__benefits, .tech__flow, .method__path) > *:nth-child(1) { --i: 0; }
:is(.stagger, .why__benefits, .tech__flow, .method__path) > *:nth-child(2) { --i: 1; }
:is(.stagger, .why__benefits, .tech__flow, .method__path) > *:nth-child(3) { --i: 2; }
:is(.stagger, .why__benefits, .tech__flow, .method__path) > *:nth-child(4) { --i: 3; }
:is(.stagger, .why__benefits, .tech__flow, .method__path) > *:nth-child(5) { --i: 4; }

/* A staggered block moves its children, so the container itself stays put. */
.js .reveal.stagger { opacity: 1; translate: none; }
.js .stagger > * { opacity: 0; translate: 0 12px; }
.js .stagger.is-in > * {
  opacity: 1; translate: 0 0;
  transition: opacity 520ms var(--e-out) calc(var(--i, 0) * 90ms),
              translate 520ms var(--e-out) calc(var(--i, 0) * 90ms);
}

/* ============================ HEADER ============================ */
/* Usable instantly; refines once the page has actually moved. */
/* Refinement is background, shadow and a transform only. Changing the bar's
   height would move its children and score as layout shift even though the
   header is fixed; transforms are exempt. Measured CLS stays at 0. */
.header__bar {
  transition: background-color 220ms var(--e-out), box-shadow 220ms var(--e-out),
              translate 220ms var(--e-out);
}
body.scrolled .header__bar {
  translate: 0 -3px;
  background: rgb(6 11 20 / 94%);
  box-shadow: inset 0 0 0 1px var(--line-dark), 0 10px 34px rgb(3 7 18 / 44%);
}
.header__sentinel { position: absolute; top: 0; height: 40px; width: 1px; pointer-events: none; }

/* ============================ WHY — line reveal ============================ */
/* The rule above each benefit draws in, then the copy follows. No card parade. */
.js .why__benefits li { position: relative; border-top-color: transparent; }
.js .why__benefits li::before {
  content: ""; position: absolute; inset-inline: 0; top: -1px; height: 1px;
  background: var(--line-light); transform-origin: left;
  scale: 0 1;
}
.js .why__benefits.is-in li::before {
  scale: 1 1;
  transition: scale 560ms var(--e-out) calc(var(--i) * 110ms);
}

/* ============================ PROOF — one honest state change ============================ */
/* On retune the trace redraws itself. Nothing simulates live data. */
.instrument .trace { stroke-dasharray: 1; stroke-dashoffset: 0; }
.js .instrument.retune [data-state].is-active .trace {
  animation: draw 620ms var(--e-signal);
}
.js .instrument.retune [data-state].is-active .band,
.js .instrument.retune [data-state].is-active .node {
  animation: fade-up 480ms var(--e-out);
}
@keyframes draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes fade-up { from { opacity: 0; } to { opacity: 1; } }

/* ============================ CAPABILITIES — shared signal path ============================ */
/* The bus carries one cyan segment that travels to the active station, so the
   four families visibly stay on one system. */
.cap__bus { --active: 0; --stations: 4; }
.cap__line { overflow: hidden; }
.cap__line::after {
  content: ""; position: absolute; inset-block: 0; left: 0;
  width: calc(100% / var(--stations));
  background: linear-gradient(90deg, transparent, var(--blue-500), var(--cyan-400), transparent);
  translate: calc(var(--active) * 100%) 0;
  transition: translate 420ms var(--e-signal);
}
.station .t, .station .n { transition: color 200ms var(--e-out); }

/* ============================ TECHNOLOGY — reveal by function ============================ */
.js .tech__flow.is-in .tech__group {
  animation: rise 520ms var(--e-out) backwards;
  animation-delay: calc(var(--i) * 90ms);
}
@keyframes rise { from { opacity: 0; translate: 0 14px; } to { opacity: 1; translate: 0 0; } }

/* ============================ METHODOLOGY — the path activates ============================ */
/* Reading never depends on this: the steps are readable before it runs. */
.js .method__path::before { scale: 0 1; transform-origin: left; }
.js .method__path.is-in::before { scale: 1 1; transition: scale 700ms var(--e-signal); }
.js .method__path .step::before { scale: 0; }
.js .method__path.is-in .step::before {
  scale: 1;
  transition: scale 380ms var(--e-out) calc(240ms + var(--i) * 120ms);
}

/* ============================ CTA — light response, no pulse ============================ */
.consult { background-size: 100% 100%, 108% 108%; background-position: 0 0, 50% 50%; }
body.drift-cta .consult { animation: cta-drift 16s var(--e-out) infinite alternate; }
@keyframes cta-drift {
  from { background-position: 0 0, 47% 50%; }
  to   { background-position: 0 0, 53% 50%; }
}

/* ============================ REDUCED MOTION ============================ */
@media (prefers-reduced-motion: reduce) {
  .js .stagger > *, .js .stagger.is-in > * { opacity: 1; translate: none; transition: none; }
  .js .why__benefits li { border-top-color: var(--line-light); }
  .js .why__benefits li::before, .js .why__benefits.is-in li::before { scale: 1 1; transition: none; }
  .js .instrument.retune [data-state].is-active :is(.trace, .band, .node) { animation: none; }
  .js .tech__flow.is-in .tech__group { animation: none; }
  .cap__line::after { transition: none; }
  .js .method__path::before, .js .method__path.is-in::before,
  .js .method__path .step::before, .js .method__path.is-in .step::before { scale: 1; transition: none; }
  body.drift-cta .consult { animation: none; }
}

/* Portrait: the methodology path runs vertically, so its reveal must too. */
@media (max-width: 900px) {
  .js .method__path::before { transform-origin: top; scale: 1 0; }
  .js .method__path.is-in::before { scale: 1 1; }
}
