/* ---- approach -----------------------------------------------------------
   Four commitments as an asymmetric grid with one photographic cell, not as
   a divided list and not as three equal cards. The image cell is what stops
   the block reading as a text grid. */

.appr__in {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: clamp(20px, 2.6vw, 40px) clamp(20px, 3vw, 56px);
  align-items: start;
}

.appr__head { grid-column: 1 / span 5; }
.appr__title { font-size: var(--fs-h2); max-width: 12ch; }
.appr__lede { margin-top: 1.2rem; }

/* The photograph anchors the left column under the heading and runs long,
   so the right-hand items sit against an image rather than against space. */
.appr__figure {
  grid-column: 1 / span 5;
  margin-top: clamp(20px, 3vw, 44px);
}
.appr__figure .ph { aspect-ratio: 5 / 4; }

.appr__items {
  --rail: clamp(24px, 2.4vw, 36px);
  grid-column: 7 / span 6;
  display: grid;
  gap: clamp(24px, 3vw, 44px);
  position: relative;
  padding-left: var(--rail);
}

/* --- the journey line ----------------------------------------------------
   An SVG rail running down the left of the four steps, drawing itself forward
   with scroll. The path and its nodes are generated in js/journey.js from the
   measured position of each step number, so the nodes land on the steps at
   any viewport rather than at guessed percentages.

   Absolutely positioned, so it is out of grid flow and never becomes a fifth
   grid item. */
.journey {
  position: absolute;
  left: 0;
  top: 0;
  width: var(--rail);
  overflow: visible;
  pointer-events: none;
}

.journey__track {
  fill: none;
  stroke: var(--line-soft);
  stroke-width: 1.5;
  stroke-linecap: round;
}

/* The drawn line. No dasharray here on purpose: journey.js sets it, so if the
   script never runs the route simply renders complete rather than invisible. */
.journey__line {
  fill: none;
  stroke: url(#fh-journey);
  stroke-width: 2.4;
  stroke-linecap: round;
}

.journey__node {
  fill: var(--void);
  stroke: var(--line);
  stroke-width: 1.5;
  transition: fill var(--dur-1) var(--ease), stroke var(--dur-1) var(--ease);
}
.journey__node.is-lit {
  fill: var(--pop);
  stroke: var(--pop);
}

/* The burning tip, sitting at the head of the drawn line. */
.journey__tip {
  fill: #FFB347;
  opacity: 0;
  transition: opacity var(--dur-1) var(--ease);
}
.journey.is-running .journey__tip { opacity: 1; }

/* The step numeral brightens as the line reaches it, so the rail and the
   copy tell the same story. */
.item__n { transition: color var(--dur-1) var(--ease); }
.js .appr__items.has-journey .item__n { color: var(--bone-dim); }
.js .appr__items.has-journey .item.is-reached .item__n { color: var(--pop); }

@media (prefers-reduced-motion: reduce) {
  .journey__tip { display: none; }
}

.item {
  display: grid;
  grid-template-columns: 3rem minmax(0, 1fr);
  gap: clamp(12px, 1.6vw, 24px);
  align-items: start;
}
.item__n {
  font-family: var(--mono);
  font-size: var(--fs-micro);
  letter-spacing: var(--track-micro);
  color: var(--pop);
  padding-top: 0.45em;
}
.item__h {
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: 0.35em;
}
.item__b {
  font-size: var(--fs-sm);
  color: var(--bone-soft);
  max-width: 38ch;
}

@media (max-width: 980px) {
  .appr__head,
  .appr__figure,
  .appr__items { grid-column: 1 / -1; }
  .appr__figure .ph { aspect-ratio: 16 / 10; }
}
@media (max-width: 560px) {
  .item { grid-template-columns: 2.25rem minmax(0, 1fr); }
}
