/* ============================================================================
   PROJECT TIMELINE — the counter drives everything.

   The number is fixed and scrolls like an odometer. The circle follows it:
   a crimson arc sweeps the rim and lights each stage marker as it passes.
   The copy loads to whatever stage the number has landed on.

   One value drives all three — scroll progress — so they cannot drift apart.

   Mobile first. The phone gets a horizontal snap rail and no pinning: hijacking
   touch scroll is the worst version of this effect. From 768px the section
   pins and the page scroll scrubs the counter.

   Note on the circle: the design hangs it off the left edge because its dates
   rotate into view. Ours are fixed, so half of them would sit off-screen
   permanently. The circle is centred and whole instead.
   ============================================================================ */

.bm-timeline {
  --tl-bg: var(--raw-navy-900);
  --tl-accent: var(--raw-red-600);
  --tl-glow: rgba(211, 47, 47, 0.20);
  /* Smaller ring and counter on a phone, so the readout, the rail and the
     arrows all land inside the same frame instead of below the fold. */
  --tl-ring: 200px;
  --reel-h: clamp(2rem, 10.5vw, 2.6rem);

  position: relative;
  padding: var(--sp-5) var(--gutter) var(--sp-6);
  overflow: hidden;
  isolation: isolate;
  color: var(--text-inverse);
  background: var(--tl-bg);
}

.bm-timeline__wash {
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background:
    radial-gradient(circle at 50% 40%, var(--tl-glow), transparent 45%),
    linear-gradient(135deg, rgba(255, 255, 255, 0.02), transparent 45%);
}

.bm-timeline__grid {
  width: 100%;
  max-width: var(--measure);
  margin-inline: auto;
  position: relative;
  display: grid;
  gap: var(--sp-4);
}


/* --- Header --------------------------------------------------------------- */

.timeline-header { position: relative; z-index: 20; display: grid; gap: var(--sp-4); }

.timeline-header__eyebrow,
.timeline-readout__eyebrow {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--step--1);
  letter-spacing: 0.17em;
  text-transform: uppercase;
  color: var(--tl-accent);
  transition: color var(--speed-slow) var(--ease);
}

.timeline-header h2 {
  margin: 0;
  /* "From order to final sample." is 27 characters. At roughly 0.52em per
     character it needs about 14em, so capping the size at 6vw keeps it on one
     line from 320px upwards and frees a whole line of height. */
  font-size: min(var(--step-3), 6vw);
  line-height: 1.05;
  letter-spacing: -0.04em;
  text-wrap: nowrap;
  color: var(--text-inverse);
}

.timeline-header p { margin: 0; max-width: 52ch; color: var(--text-inverse-mut); }


/* --- Stage ---------------------------------------------------------------- */

.timeline-stage { display: grid; gap: var(--sp-4); align-items: center; }

/* Capped only while ScrollTrigger actually holds it. */
.bm-timeline.is-pinned { height: 100vh; height: 100svh; }

.timeline-orbit-wrap { display: flex; justify-content: center; }

.timeline-orbit {
  position: relative;
  width: var(--tl-ring);
  height: var(--tl-ring);
  flex: 0 0 auto;
}


/* --- The ring and its arc -------------------------------------------------
   An SVG stroke, because a rotating border shows nothing. The arc grows from
   twelve o'clock as the counter climbs, which is the circle "matching". */

.timeline-ring {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  overflow: visible;
}

.timeline-ring__track {
  fill: none;
  stroke: rgba(255, 255, 255, 0.14);
  stroke-width: 0.8;
}

.timeline-ring__arc {
  fill: none;
  stroke: var(--tl-accent);
  stroke-width: 1.4;
  stroke-linecap: round;
  filter: drop-shadow(0 0 6px var(--tl-glow));
  transition: stroke var(--speed-slow) var(--ease);
}


/* --- Fixed markers: dots on the rim, numbers outside it ------------------- */

.timeline-dots-row,
.timeline-date-row { position: absolute; inset: 0; pointer-events: none; }

.timeline-dot,
.timeline-date {
  position: absolute;
  top: 50%;
  left: 50%;
  transform-origin: center;
  pointer-events: auto;
}

.timeline-dot {
  width: 9px; height: 9px; margin: -4.5px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.28);
  transition: background-color var(--speed-slow) var(--ease),
              box-shadow var(--speed-slow) var(--ease);
}
.timeline-dot.is-passed { background: var(--tl-accent); opacity: 0.55; }
.timeline-dot.is-active {
  background: var(--tl-accent);
  opacity: 1;
  box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.06), 0 0 18px var(--tl-accent);
}

.timeline-date {
  min-width: 34px; min-height: 34px;
  display: grid;
  place-items: center;
  padding: 0;
  background: none;
  border: 0;
  cursor: pointer;
  color: var(--text-inverse-mut);
  font: 700 0.68rem/1 var(--font-mono);
  letter-spacing: 0.05em;
  transition: color var(--speed-slow) var(--ease), transform var(--speed-slow) var(--ease);
}
.timeline-date.is-passed { color: rgba(255, 255, 255, 0.5); }
.timeline-date.is-active { color: var(--tl-accent); transform-origin: center; }


/* --- The odometer --------------------------------------------------------
   Two digit columns behind a fixed-height window. The tens column only rolls
   between 09 and 10, so most of the time one digit is moving and the other is
   perfectly still — which is what makes it read as a counter. */

.timeline-reel {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
}

.timeline-reel__window {
  display: flex;
  height: var(--reel-h);
  overflow: hidden;
  font-family: var(--font-mono);
  font-weight: 800;
  font-size: var(--reel-h);
  line-height: var(--reel-h);
  letter-spacing: -0.04em;
  color: var(--text-inverse);
}

.timeline-reel__col { display: block; will-change: transform; }
.timeline-reel__col span { display: block; height: var(--reel-h); }

.timeline-reel__label {
  position: absolute;
  top: calc(50% + var(--reel-h) * 0.62);
  left: 0;
  right: 0;
  text-align: center;
  font: 600 0.58rem/1 var(--font-mono);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--text-inverse-mut);
}


/* --- Readout -------------------------------------------------------------- */

.timeline-readout {
  display: grid;
  align-content: start;
  gap: var(--sp-3);
  min-width: 0;
}

.timeline-readout__index {
  font: 700 0.64rem/1 var(--font-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-inverse-mut);
}

.timeline-readout h3 {
  margin: 0;
  max-width: 16ch;
  font-size: var(--step-3);
  line-height: 1;
  letter-spacing: -0.045em;
  color: var(--text-inverse);
  transition: color var(--speed-slow) var(--ease);
}

/* All stages share one grid cell, so the block is as tall as the longest and
   nothing below it jumps as the counter moves. */
.timeline-readout__text-list {
  position: relative;
  display: grid;
  max-width: 48ch;
  min-height: clamp(86px, 13vh, 150px);
}

.timeline-out-text {
  grid-area: 1 / 1;
  width: 100%;
  margin: 0;
  font-size: var(--step-1);
  line-height: 1.45;
  color: var(--text-inverse-mut);
  opacity: 0;
  visibility: hidden;
  transform: translateY(12px);
  transition: opacity var(--speed-slow) var(--ease),
              visibility var(--speed-slow) var(--ease),
              transform var(--speed-slow) var(--ease);
}
.timeline-out-text.is-active { opacity: 1; visibility: visible; transform: translateY(0); }

.timeline-meta { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }

.timeline-meta__pill {
  display: inline-flex;
  align-items: center;
  min-height: 30px;
  padding: 0.35rem 0.65rem;
  border: 1px solid var(--border-inverse);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-inverse-mut);
  font: 600 0.6rem/1 var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}


/* --- Phone rail ----------------------------------------------------------
   Native scroll-snap. Dragging it moves the counter, the arc and the copy.
   No pin, no captured scroll, no JavaScript needed to make it scroll. */

.timeline-rail {
  display: flex;
  gap: var(--sp-2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  margin-inline: calc(var(--gutter) * -1);
  padding-inline: var(--gutter);
  scroll-padding-inline: var(--gutter);
}
.timeline-rail::-webkit-scrollbar { display: none; }

.timeline-rail__item {
  flex: 0 0 auto;
  scroll-snap-align: center;
  min-width: 64px;
  min-height: 44px;
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--border-inverse);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-inverse-mut);
  font: 700 0.68rem/1 var(--font-mono);
  letter-spacing: 0.08em;
  transition: background-color var(--speed) var(--ease),
              border-color var(--speed) var(--ease),
              color var(--speed) var(--ease);
}
.timeline-rail__item.is-active {
  background: var(--tl-accent);
  border-color: var(--tl-accent);
  color: var(--on-action);
}


/* --- Controls ------------------------------------------------------------- */

.timeline-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
}

.timeline-controls button {
  appearance: none;
  border: 1px solid var(--border-inverse);
  background: rgba(255, 255, 255, 0.04);
  color: var(--text-inverse);
  border-radius: 999px;
  min-width: 46px;
  min-height: 46px;
  cursor: pointer;
  font: 700 0.8rem/1 var(--font-mono);
  transition: border-color var(--speed) var(--ease),
              background-color var(--speed) var(--ease),
              transform var(--speed) var(--ease);
}
.timeline-controls button:hover,
.timeline-controls button:focus-visible { background: var(--tl-accent); border-color: var(--tl-accent); }
.timeline-controls button:active { transform: scale(0.96); }
.timeline-controls button[disabled] { opacity: 0.35; pointer-events: none; }

.timeline-controls__hint {
  text-align: center;
  color: var(--text-inverse-mut);
  font: 600 0.6rem/1.35 var(--font-mono);
  letter-spacing: 0.06em;
  text-transform: uppercase;
}


/* --- Tablet and up: pin, scrub, two columns ------------------------------- */

@media (min-width: 768px) {
  .bm-timeline {
    --tl-ring: 400px;
    --reel-h: clamp(3.2rem, 7vw, 4.6rem);
    min-height: 100vh;
    min-height: 100dvh;
    display: grid;
    align-content: center;
    padding: var(--sp-7) var(--sp-6);
  }

  .timeline-header {
    grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
    align-items: end;
    column-gap: var(--sp-7);
  }
  .timeline-header__eyebrow { grid-column: 1 / -1; }
  .timeline-header h2 { font-size: var(--step-4); max-width: 18ch; text-wrap: balance; }
  .timeline-header p { padding-bottom: var(--sp-2); }

  .timeline-stage {
    grid-template-columns: auto minmax(0, 1fr);
    gap: var(--sp-7);
  }
  .timeline-readout h3 { font-size: var(--step-4); }

  /* The rail is the phone's input method; the page scroll replaces it here. */
  .timeline-rail { display: none; }
}

@media (min-width: 1200px) {
  .bm-timeline { --tl-ring: 460px; padding: var(--sp-8); }
}


/* --- Reduced motion -------------------------------------------------------
   No pin, no scrub, no rolling digits. The rail stays available at every
   width and every stage is reachable and readable. */

@media (prefers-reduced-motion: reduce) {
  .timeline-rail { display: flex; }
  .timeline-reel__col { transition: none; }
  .timeline-out-text { transition: none; }
  .bm-timeline { min-height: 0; }
}


/* --- Controls on a phone --------------------------------------------------
   The section is not pinned below 768px, so scrolling does not drive it —
   the arrows and the rail do. They were sized as a secondary control and
   need to read as the primary one.
   ---------------------------------------------------------------------- */

.timeline-controls { margin-top: var(--sp-4); }

.timeline-controls button {
  flex: 0 0 auto;
  min-width: 56px;
  min-height: 56px;
  background: rgba(255, 255, 255, 0.08);
  border-color: var(--tl-accent);
  color: var(--text-inverse);
  font-size: 1rem;
}
.timeline-controls button:not([disabled]):active { background: var(--tl-accent); }

.timeline-controls__hint { flex: 1 1 auto; }

/* Base is the phone, so the touch wording shows and the scroll wording does
   not. The 768px rule below swaps them — no max-width query needed. */
.timeline-controls__hint .is-desk { display: none; }

@media (min-width: 768px) {
  .timeline-controls button { min-width: 46px; min-height: 46px; background: rgba(255, 255, 255, 0.04); border-color: var(--border-inverse); }
  .timeline-controls__hint .is-touch { display: none; }
  .timeline-controls__hint .is-desk  { display: inline; }
}
