/* Adamas Digital — growth engine motion.
   The "Clear thinking. Beautiful execution." timeline. The section already
   fades up as one block through [data-reveal]; this animates the parts inside
   it so the five stages arrive in order, which is the one thing the static
   layout cannot say on its own — the track reads as a sequence, so it should
   assemble like one.

   Three movements, timed to overlap:
     the rule between the stages draws itself,
     each stage rises as the rule passes it,
     the node snaps onto the rule a beat later.

   Everything hangs off .revealed, the class site.js adds when the section
   scrolls into view, so there is no new script and no second observer.

   Scoped to .js throughout. Without scripting .revealed is never added, and a
   stage left in its starting state would be a stage nobody can read — the
   same reason hero-type.css gates its typewriter on .js. */

/* ---- The rule between the stages draws itself ------------------------- */
/* .engine-track:before is the horizontal line the nodes sit on. Scaling it
   from the left costs no layout work, unlike animating width. */
.js .growth-engine .engine-track:before {
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1s cubic-bezier(.22, 1, .36, 1) .1s;
}

.js .growth-engine.revealed .engine-track:before {
  transform: scaleX(1);
}

/* ---- Each stage rises as the rule reaches it -------------------------- */
.js .growth-engine .engine-track article {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .6s ease, transform .6s cubic-bezier(.22, 1, .36, 1);
}

.js .growth-engine.revealed .engine-track article {
  opacity: 1;
  transform: none;
}

/* ---- The node snaps onto the rule ------------------------------------- */
/* A slight overshoot on the easing, so the node arrives on the line rather
   than easing into existence. The 8px ring is part of the element's own box,
   so it scales with it and the node appears to punch through the rule. */
.js .growth-engine .engine-node {
  transform: scale(0);
  transition: transform .5s cubic-bezier(.34, 1.56, .64, 1), background-color .45s ease;
}

.js .growth-engine.revealed .engine-node {
  transform: scale(1);
}

/* ---- Stagger ----------------------------------------------------------
   One custom property per stage instead of ten hand-written delays: the node
   inherits --step from the article it sits in, so a stage and its node stay
   locked together and a sixth stage needs one line, not two. The node trails
   its own stage by .12s, which is roughly when the drawing rule passes it. */
.js .growth-engine .engine-track article:nth-child(1) { --step: 0; }
.js .growth-engine .engine-track article:nth-child(2) { --step: 1; }
.js .growth-engine .engine-track article:nth-child(3) { --step: 2; }
.js .growth-engine .engine-track article:nth-child(4) { --step: 3; }
.js .growth-engine .engine-track article:nth-child(5) { --step: 4; }

.js .growth-engine.revealed .engine-track article {
  transition-delay: calc(.16s + var(--step, 0) * .13s);
}

.js .growth-engine.revealed .engine-node {
  transition-delay: calc(.28s + var(--step, 0) * .13s);
}

/* ---- The progress fill -------------------------------------------------
   A second rule laid over the first, blue, growing to wherever the current
   stage sits. site.js measures that distance from the node and puts it in
   --engine-fill, so the bar always ends exactly under a node rather than at
   a guessed fraction of the way along.

   Under the nodes (z-index 0 against their 1) so it runs behind them and
   they punch through it, which is what makes the bar look threaded rather
   than painted on top. */
.js .growth-engine .engine-track {
  --engine-fill: 0px;
}

.js .growth-engine .engine-track:after {
  content: "";
  position: absolute;
  z-index: 0;
  top: 43px;
  left: 8px;
  width: var(--engine-fill);
  height: 1px;
  background: var(--blue);
  transition: width .6s cubic-bezier(.22, 1, .36, 1);
}

/* The bar only exists once the section has arrived; before that the entrance
   is still drawing the rule it sits on. */
.js .growth-engine:not(.revealed) .engine-track:after { opacity: 0; }

/* Snapping back to empty at the end of a pass must not animate, or the bar
   crawls backwards across the whole track instead of restarting. */
.js .growth-engine .engine-track.is-restarting:after { transition: none; }

/* ---- The step being highlighted ---------------------------------------
   Once the entrance has landed, site.js walks .is-active through the stages a
   few seconds apart, so the timeline keeps saying "these happen in order"
   rather than going still. Emphasis only: nothing here hides or moves a
   stage, so whichever one is lit, all five stay equally readable — and if the
   script never runs, the section simply sits in its finished state.

   The node is the thing that carries it. It already reads as the marker on
   the line, so filling it and letting it grow through its ring is the whole
   signal; the heading and body follow in colour to tie the stage together. */
.js .growth-engine .engine-track h3 {
  transition: color .45s ease;
}

.js .growth-engine .engine-track p {
  transition: color .45s ease;
}

/* A stage the fill has passed keeps a solid node: read together they show how
   far the process has run, which is the whole point of a bar rather than a
   single travelling highlight. Only the current one grows. */
.js .growth-engine .engine-track article.is-done .engine-node {
  background: var(--blue);
}

.js .growth-engine .engine-track article.is-active .engine-node {
  background: var(--blue);
  transform: scale(1.3);
}

.js .growth-engine .engine-track article.is-active h3 {
  color: var(--blue);
}

.js .growth-engine .engine-track article.is-active p {
  color: var(--ink);
}

/* ---- Upright on handsets ----------------------------------------------
   mobile.css turns the track into a vertical timeline below 720px: the same
   rule becomes 1px wide and runs top to bottom. Drawing it sideways there
   would scale a hairline across its own width and show nothing, so the axis
   and the origin both change with the layout. */
@media (max-width: 720px) {
  .js .growth-engine .engine-track:before {
    transform: scaleY(0);
    transform-origin: center top;
  }

  .js .growth-engine.revealed .engine-track:before {
    transform: scaleY(1);
  }

  /* The bar turns with it: 1px wide, filling downward from the top of the
     rule. site.js measures on the same axis, so --engine-fill needs no
     separate value. */
  .js .growth-engine .engine-track:after {
    top: 6px;
    left: 6px;
    width: 1px;
    height: var(--engine-fill);
    transition: height .6s cubic-bezier(.22, 1, .36, 1);
  }

  .js .growth-engine .engine-track.is-restarting:after { transition: none; }
}

/* ---- Reduced motion ---------------------------------------------------
   site.css already collapses every transition to .01ms under this query, so
   nothing here would animate regardless. That is not enough on its own: the
   starting states above are what hide a stage, and they are only undone when
   .revealed arrives. Clearing them means the timeline is simply present and
   complete, in step with how site.css treats [data-reveal] itself. */
@media (prefers-reduced-motion: reduce) {
  .js .growth-engine .engine-track:before,
  .js .growth-engine .engine-track article,
  .js .growth-engine .engine-node {
    opacity: 1;
    transform: none;
    transition: none;
  }

  /* site.js does not start the highlight cycle under this setting at all. This
     only covers the case where it was already running and the preference
     changed underneath it: the colour can stay, the movement cannot. */
  .js .growth-engine .engine-track article.is-active .engine-node {
    transform: none;
  }
}
