/* ==========================================================================
   Features — How it works (shared)
   ==========================================================================
   An axis of time, not a list of steps. The real question is "how long until I
   get something?", so the structure answers with moments rather than numbers.

   The axis is built as an instrument, not a rule: a dim base track carries the
   whole span, three lit segments sit on top of it — one per interval — and each
   beat is a station where the segment changes hands. The segments walk violet →
   blue → mint, the family's own semantics for raw signal → produced value, and
   the last one dissolves because the sequence does not stop at the third beat.

   Every station drops a short thread onto its copy, so a paragraph is visibly
   attached to its moment instead of floating under a line. The timestamps read
   as ticks on that scale: mono, in the interval's colour, opened by a small
   rule.

   Nothing loops. The axis draws itself once, left to right, and each station
   lands as the drawing front reaches it — one arrival, not three effects.
   Revealed is the default so the section reads complete without JavaScript.
   ========================================================================== */

.feat-how__head {
  margin-bottom: clamp(3.4rem, 6.5vw, 5.4rem);
}

/* The shared lede is justified by default (PageStyles.css); this section's head
   is centred, and a justified line inside a centred head reads as misaligned. */
.feat-how__head .feat-lede {
  text-align: center;
}

.fhw-axis {
  --fhw-draw: 1500ms;
  --fhw-gap: clamp(1.5rem, 3.5vw, 3.2rem);
  /* Where the axis sits: the timestamps own the band above this line. */
  --fhw-mark-y: 2.6rem;
  /* Left edge of each column as a fraction of the axis — three equal columns
     with equal gutters put station n at n × 0.35 of the full width. */
  --fhw-step: 0.35;
  --fhw-collapse: scaleX(0);

  position: relative;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--fhw-gap);
  padding: 0;
  margin: 0;
  list-style: none;
}

/* The base track: the span exists before anything is lit on it. */
.fhw-axis::before {
  content: '';
  position: absolute;
  top: var(--fhw-mark-y);
  right: 0;
  left: 0;
  height: 1px;
  background: rgba(176, 173, 224, 0.16);
  mask-image: linear-gradient(90deg, #000 68%, transparent);
  -webkit-mask-image: linear-gradient(90deg, #000 68%, transparent);
}

/* A wide, very dim wash under the axis, so the track reads as lit rather than
   drawn. One shallow gradient — never a glow around every element. */
.fhw-axis::after {
  content: '';
  position: absolute;
  top: calc(var(--fhw-mark-y) - 3.5rem);
  right: -4%;
  left: -4%;
  z-index: -1;
  height: 7rem;
  pointer-events: none;
  background: radial-gradient(
    58% 50% at 42% 50%,
    rgba(var(--feat-violet-rgb), 0.14),
    rgba(90, 116, 255, 0.05) 55%,
    transparent 78%
  );
}

/* --- A beat --------------------------------------------------------------- */

.fhw-beat {
  --fhw-cue: calc(var(--beat) * var(--fhw-step) * var(--fhw-draw));
  --beat-accent: var(--feat-violet);
  --beat-accent-rgb: 124, 60, 255;

  position: relative;
  min-width: 0;
  padding-top: calc(var(--fhw-mark-y) + 2.6rem);
}

.fhw-beat:nth-child(2) {
  --beat-accent: var(--feat-blue);
  --beat-accent-rgb: 90, 116, 255;
}

.fhw-beat:nth-child(3) {
  --beat-accent: var(--feat-mint);
  --beat-accent-rgb: 25, 206, 136;
}

/* The lit segment for this interval. It runs across its own column and the
   gutter that follows, so consecutive intervals meet exactly at a station. */
.fhw-beat::before {
  content: '';
  position: absolute;
  top: var(--fhw-mark-y);
  right: calc(-1 * var(--fhw-gap));
  left: 0;
  height: 1.5px;
  border-radius: 1px;
  background: linear-gradient(90deg, var(--beat-accent), rgba(var(--beat-accent-rgb), 0.55));
  transform-origin: left center;
  transition: transform var(--fhw-draw) cubic-bezier(0.22, 1, 0.36, 1);
}

/* The last interval has nowhere to hand over to, so it dissolves. */
.fhw-beat:last-child::before {
  right: 0;
  mask-image: linear-gradient(90deg, #000 34%, transparent);
  -webkit-mask-image: linear-gradient(90deg, #000 34%, transparent);
}

/* The tick that ties a paragraph to its moment — a measurement mark, drawn
   crisp and short rather than as a fading wisp. */
.fhw-beat::after {
  content: '';
  position: absolute;
  top: var(--fhw-mark-y);
  left: 0;
  width: 1px;
  height: 1.25rem;
  background: rgba(var(--beat-accent-rgb), 0.55);
  transition: opacity 520ms ease-out calc(var(--fhw-cue) + 220ms);
}

/* The timestamp reads as a tick on the scale, not as a label above a line. */
.fhw-beat__when {
  position: absolute;
  top: 0;
  left: 0;
  display: flex;
  gap: 0.6rem;
  align-items: center;
  height: var(--fhw-mark-y);
  margin: 0;
  color: var(--beat-accent);
  font-family: var(--feat-mono);
  font-size: 0.71rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  line-height: 1.3;
  text-transform: uppercase;
}

.fhw-beat__when::before {
  width: 0.85rem;
  height: 1px;
  background: currentColor;
  content: '';
  opacity: 0.55;
}

/* A station: a lit core inside a ring, punched out of the page background so
   the segment appears to pass behind it. */
.fhw-beat__mark {
  position: absolute;
  top: var(--fhw-mark-y);
  left: 0;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--beat-accent);
  box-shadow:
    0 0 0 4px var(--feat-bg),
    0 0 0 5px rgba(var(--beat-accent-rgb), 0.4),
    0 0 16px rgba(var(--beat-accent-rgb), 0.75);
  transform: translate(-50%, -50%);
  transition:
    opacity 380ms ease-out var(--fhw-cue),
    scale 560ms cubic-bezier(0.22, 1.5, 0.36, 1) var(--fhw-cue);
}

/* Value lands on the last station, so it carries a little more light. */
.fhw-beat:last-child .fhw-beat__mark {
  width: 9px;
  height: 9px;
  box-shadow:
    0 0 0 4px var(--feat-bg),
    0 0 0 6px rgba(var(--beat-accent-rgb), 0.45),
    0 0 22px rgba(var(--beat-accent-rgb), 0.85),
    0 0 46px rgba(var(--beat-accent-rgb), 0.35);
}

.fhw-beat__title {
  margin: 0;
  color: var(--feat-text);
  font-size: clamp(1.28rem, 2.05vw, 1.62rem);
  font-weight: 760;
  letter-spacing: -0.034em;
  line-height: 1.16;
  text-wrap: balance;
}

/* A beat title is a short phrase and reads badly broken in two, but a column of
   the axis is only a third of the container: at the shared display size the
   longer ones wrapped mid-phrase. One size down is enough for a ~30-character
   title to hold its line here, and anything longer still wraps on its own —
   which is the point. Forcing `nowrap` instead would make the longest titles
   overflow into the neighbouring column rather than fold. */
@media (min-width: 1024px) {
  .fhw-beat__title {
    font-size: clamp(1.2rem, 1.85vw, 1.5rem);
  }
}

.fhw-beat__body {
  max-width: 32ch;
  margin: 0.75rem 0 0;
  color: var(--feat-muted);
  font-size: 1rem;
  line-height: 1.68;
  text-wrap: pretty;
}

/* --- The single arrival --------------------------------------------------- */

.fhw-beat__when,
.fhw-beat__title,
.fhw-beat__body {
  transition:
    opacity 620ms ease-out calc(var(--fhw-cue) + 160ms),
    translate 720ms cubic-bezier(0.22, 1, 0.36, 1) calc(var(--fhw-cue) + 160ms);
}

.fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat::before {
  transform: var(--fhw-collapse);
  transition-delay: calc(var(--fhw-cue) - 60ms);
}

.fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat::after {
  opacity: 0;
  transition-delay: 0s;
}

.fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__when,
.fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__title,
.fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__body {
  opacity: 0;
  translate: 0 0.75rem;
  transition-delay: 0s;
}

.fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__mark {
  opacity: 0;
  scale: 0.3;
  transition-delay: 0s;
}

/* --- Responsive ----------------------------------------------------------- */

/* Stacked, the axis turns and runs down the left margin: same stations, same
   cadence, one column of reading. */
@media (max-width: 860px) {
  .fhw-axis {
    --fhw-collapse: scaleY(0);

    /* The rail hugs the container's left edge — a phone has no width to spare
       for a margin the axis does not need. */
    --fhw-rail-x: 0.5rem;
    /* Every line of a beat starts past the tick, so the copy has one straight
       left edge instead of a timestamp indented against a flush headline. */
    --fhw-copy-inset: 1.85rem;

    grid-template-columns: minmax(0, 1fr);
    gap: clamp(2.4rem, 6vw, 3.2rem);
    padding-left: var(--fhw-rail-x);
  }

  /* Absolute children resolve against the padding box, so the base track has to
     be pushed in by the same amount as the columns or it draws a second rail. */
  .fhw-axis::before {
    top: 0.6rem;
    right: auto;
    bottom: 0;
    left: var(--fhw-rail-x);
    width: 1px;
    height: auto;
    mask-image: linear-gradient(180deg, #000 84%, transparent);
    -webkit-mask-image: linear-gradient(180deg, #000 84%, transparent);
  }

  .fhw-axis::after {
    display: none;
  }

  .fhw-beat {
    padding-top: 0;
  }

  .fhw-beat::before {
    top: 0.6rem;
    right: auto;
    bottom: calc(-1 * clamp(2.4rem, 6vw, 3.2rem));
    left: 0;
    width: 1.5px;
    height: auto;
    background: linear-gradient(180deg, var(--beat-accent), rgba(var(--beat-accent-rgb), 0.55));
    transform-origin: top center;
  }

  .fhw-beat:last-child::before {
    bottom: 0;
    mask-image: linear-gradient(180deg, #000 34%, transparent);
    -webkit-mask-image: linear-gradient(180deg, #000 34%, transparent);
  }

  /* The tick turns with the axis: a horizontal tie into the copy. */
  .fhw-beat::after {
    top: 0.6rem;
    left: 0;
    width: 1.1rem;
    height: 1px;
    background: rgba(var(--beat-accent-rgb), 0.55);
  }

  .fhw-beat__when {
    position: static;
    height: auto;
    margin-bottom: 0.7rem;
    padding-left: var(--fhw-copy-inset);
  }

  .fhw-beat__when::before {
    display: none;
  }

  .fhw-beat__mark {
    top: 0.6rem;
    left: 0;
  }

  .fhw-beat__title,
  .fhw-beat__body {
    padding-left: var(--fhw-copy-inset);
  }

  .fhw-beat__body {
    max-width: 52ch;
  }
}

@media (prefers-reduced-motion: reduce) {
  .fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat::before {
    transform: none;
  }

  .fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat::after,
  .fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__when,
  .fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__title,
  .fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__body,
  .fhw-axis.scroll-observer-prepared:not(.is-visible) .fhw-beat__mark {
    opacity: 1;
    scale: 1;
    translate: 0 0;
  }

  .fhw-beat::before,
  .fhw-beat::after,
  .fhw-beat__when,
  .fhw-beat__title,
  .fhw-beat__body,
  .fhw-beat__mark {
    transition: none;
  }
}
