/* ==========================================================================
   TeamTrek V4 — The assemble section's state line
   --------------------------------------------------------------------------
   Loaded only by index-v4.html, paired with js/assemble-v4.js.

   What this replaces, in order:

     1. One <p class="assemble__caption"> whose textContent the shared
        js/scroll.js swapped at two thresholds. A hard cut, no transition, no
        sign that there were three states — the section's argument went past
        unread.
     2. A first attempt that showed all three sentences at once with a fill
        rule under each. It carried the information but read as a block of
        small grey text under a display heading, and rules under centred
        lines look like broken underlines rather than progress.

   This is one sentence at a time under a three-segment rail. The rail says
   where you are; the sentence says what is happening; the label in front of
   it names the state. Nothing is measured in JS, and the slot cannot reflow:
   the three sentences share a single grid cell, so it is always as tall as
   the tallest one.

   index.html (v1) and index-v3.html load the same css/ directory but not this
   file, and both still carry .assemble__caption, which nothing here touches.
   ========================================================================== */

.asmsteps {
  margin-top: 1.5rem;
  display: flex; flex-direction: column; align-items: center; gap: 1.125rem;
}

/* ---- The rail ----------------------------------------------------------
   Three segments, not a continuous bar: the section has three states, and a
   single bar would say it has none. Each segment is its own track with its
   own fill, so a passed state stays solid while the current one grows.
   ------------------------------------------------------------------------ */
.asmsteps__rail { display: flex; gap: .5rem; }
.asmsteps__seg {
  position: relative;
  width: 3.25rem; height: 3px;
  border-radius: var(--r-pill);
  background: var(--neutral-200);
  overflow: hidden;
}
.asmsteps__seg::after {
  content: ''; position: absolute; inset: 0;
  border-radius: inherit;
  background: var(--primary-600);
  /* --p is written by the driver each frame. No transition on the scaleX:
     the value already follows the scroll, and easing it only adds lag behind
     the finger. */
  transform: scaleX(var(--p, 0)); transform-origin: left center;
}
/* The current segment is the one to look at, so it is the only one at full
   contrast; the ones behind it settle back without disappearing. */
.asmsteps__seg.is-done::after { background: var(--primary-300); }
.asmsteps__seg.is-on { box-shadow: 0 0 0 3px var(--primary-50); }

/* ---- The sentence ------------------------------------------------------ */
.asmsteps__slot {
  display: grid;                 /* one cell, three children */
  max-width: 40rem;
  text-align: center;
}
.asmsteps__line {
  grid-area: 1 / 1;
  font-size: var(--text-body-lg); line-height: 1.5;
  color: var(--neutral-600);
  /* Hidden states keep their space but must not be read aloud or hovered. */
  opacity: 0; visibility: hidden;
  transform: translate3d(0, 8px, 0); filter: blur(4px);
  transition: opacity var(--dur-ui) var(--ease-ui),
              transform var(--dur-ui) var(--ease-brand),
              filter var(--dur-ui) var(--ease-ui),
              visibility var(--dur-ui) linear;
}
.asmsteps__line.is-on {
  opacity: 1; visibility: visible;
  transform: none; filter: none;
}

/* The state's name, in front of its sentence. A label rather than a heading:
   it is the same phrase the rail's position stands for, so it carries the
   brand colour and the sentence stays quiet behind it. */
.asmsteps__line b {
  display: inline-block; margin-right: .4375rem;
  font-weight: var(--weight-bold); color: var(--primary-700);
  letter-spacing: -.01em;
}

/* Word entrance on the line that takes over. --i is set per word by the
   driver, so the stagger holds however many words a sentence has. */
.asmsteps__w { display: inline-block; }
.asmsteps__line.is-on .asmsteps__w {
  animation: asmWord .5s var(--ease-brand) both;
  animation-delay: calc(var(--i, 0) * .028s);
}
@keyframes asmWord {
  from { opacity: 0; transform: translate3d(0, 5px, 0); }
  to   { opacity: 1; transform: none; }
}

/* ---- The headline pays off -------------------------------------------- */
.assemble__punch { transition: color var(--dur-figure) var(--ease-brand); }
.assemble.is-landed .assemble__punch { color: var(--primary-600); }

/* ---- Narrow ------------------------------------------------------------
   Below 768px the stage is a plain stacked grid (css/responsive.css) and
   there is no scroll progress to report, so the rail has nothing to say and
   the settled sentence is the whole story.
   ------------------------------------------------------------------------ */
@media (max-width: 767px) {
  .asmsteps { margin-top: 1rem; gap: .875rem; }
  .asmsteps__rail { display: none; }
  .asmsteps__line { font-size: 1rem; }
}

/* ---- Reduced motion ---------------------------------------------------
   The state, the colour and the rail stay — they are the information. The
   blur, the lift and the word entrance are what go.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .asmsteps__line {
    transform: none; filter: none;
    transition: opacity var(--dur-ui) linear, visibility var(--dur-ui) linear;
  }
  .asmsteps__line.is-on .asmsteps__w { animation: none; }
  .assemble__punch { transition: none; }
}
