/* ════════════════════════════════════════════════════════════════════════
   program-spine.css  ·  Invisible (ported from WEBSITE FABLE 5 / programs.css)
   ────────────────────────────────────────────────────────────────────────
   The day-by-day "week timeline" Program Spine + the "By Friday, you…"
   Outcome Receipt — the FABLE 5 signature program component, transplanted
   onto the program detail pages here. Self-contained: extracted from
   programs.css (no hub router/rhythm/program-card rules) so it sits cleanly
   alongside the existing program-loops.css without overriding it.

   Enhancement only — program-spine.js adds .is-spine / .is-armed. With no JS
   (or reduced motion) the plain numbered timeline + receipt stay fully legible.
   ════════════════════════════════════════════════════════════════════════ */

/* Motion + a11y tokens the spine/receipt rules need (absent from styles.css). */
:root {
  --ease-arrival: cubic-bezier(0.2, 0.8, 0.2, 1);
  --ease-decel:   cubic-bezier(0.22, 1, 0.36, 1);
  --secondary-text: color-mix(in oklab, var(--secondary) 50%, var(--ink));
}

/* ── Day-by-day timeline ("what the week looks like") ─────────────────── */
.program-timeline {
  padding: clamp(80px, 10vw, 132px) clamp(24px, 5vw, 64px);
  background: var(--white);
}
.timeline {
  max-width: 760px;
  margin: 0 auto;
  list-style: none;
}
.timeline-day {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 22px;
  padding: 24px 0;
  border-top: 1px solid var(--line);
  align-items: start;
}
.timeline-day:first-child { border-top: none; }
.timeline-num {
  display: inline-flex;
  gap: 2px;
  padding-top: 2px;
}
.timeline-eyebrow {
  font-family: 'DM Mono', monospace;
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--secondary-text);   /* AA-darkened sage (raw --secondary ~2.7:1 on white) */
  margin-bottom: 5px;
}
.timeline-body h3 {
  font-family: 'Newsreader', serif;
  font-size: clamp(18px, 2vw, 22px);
  font-weight: 500;
  line-height: 1.2;
  color: var(--ink);
  margin-bottom: 6px;
}
.timeline-body p {
  font-family: 'Inter', system-ui, sans-serif;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--body-color);
  max-width: 56ch;
}
.timeline-note {
  max-width: 760px;
  margin: 28px auto 0;
  font-family: 'DM Mono', monospace;
  font-size: 12px;
  line-height: 1.6;
  color: var(--muted);
  text-align: center;
}
@media (max-width: 560px) {
  .timeline-day { grid-template-columns: 1fr; gap: 8px; }
  .timeline-num { grid-row: auto; }
}

/* ════════════════════════════════════════════════════════════════════════
   PROGRAM SPINE  ·  the day-by-day .timeline, threaded onto a vertical rail
   with a single travelling coral progress dot + a sage fill.
   The number column becomes the rail: each dot-digit day-number sits in a
   white circular node, and a sage rule connects their centres (x = 30px).
   The rail is masked-faded at both ends; the moving fill + dot are set in JS.
   ════════════════════════════════════════════════════════════════════════ */
.is-spine .timeline { position: relative; }
.is-spine .timeline-day { grid-template-columns: 56px 1fr; gap: clamp(20px, 2.6vw, 30px); }

/* the rail: a gray thread through the node centres (x = 28px). A RED line grows
   down it as you read through the sections (see .spine-fill below). */
.is-spine .timeline::before {
  content: '';
  position: absolute; left: 28px; top: 0; bottom: 0; width: 2px;
  background: color-mix(in oklab, var(--secondary) 30%, var(--line));
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 5%, #000 92%, transparent 100%);
          mask-image: linear-gradient(to bottom, transparent 0, #000 5%, #000 92%, transparent 100%);
  z-index: 0;
}
/* the progress line — RED, grows top→down (scaleY in JS) as the reader advances
   through the sections. The only moving element; there is no separate dot. */
.is-spine .spine-fill {
  position: absolute; left: 28px; width: 2px; top: 0; height: 0;
  background: var(--primary); z-index: 1; opacity: 0;
  transition: opacity .3s ease;
}
/* number-as-node: the original dot-matrix digits, kept GRAY, inside a ring.
   The ring is gray by default and turns RED once read (.is-reached); the digits
   themselves never change colour. No travelling dot — progress is the red line. */
.is-spine .timeline-num {
  position: relative; z-index: 2;
  width: 56px; height: 56px; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; gap: 2px;
  padding: 0; background: var(--white);
  border: 1.5px solid color-mix(in oklab, var(--secondary) 36%, var(--line));
  color: var(--secondary-text);   /* the gray the dot-matrix digits inherit */
  transition: border-color .5s var(--ease-arrival);
}
/* read: the ring turns red and stays red (an accumulating red trail up the
   spine), set by program-spine.js as the red line passes each node. Only the
   ring changes — the gray digits are left exactly as they were. */
.is-spine .timeline-day.is-reached .timeline-num {
  border-color: var(--primary);
}
.is-spine .timeline-day { border-top-color: color-mix(in oklab, var(--line) 70%, transparent); }

/* reveal each day as it enters (armed by JS so no-JS stays visible) */
@media (prefers-reduced-motion: no-preference) {
  .is-spine.is-armed .timeline-day {
    opacity: 0; transform: translateY(18px);
    transition: opacity .6s var(--ease-arrival), transform .6s var(--ease-arrival);
  }
  .is-spine.is-armed .timeline-day.is-in { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .is-spine .spine-fill { display: none; }
}
/* keep the rail + node layout in the mobile single-column timeline */
@media (max-width: 560px) {
  .is-spine .timeline-day { grid-template-columns: 48px 1fr !important; gap: 16px; align-items: start; }
  .is-spine .timeline-num { width: 48px; height: 48px; }
  .is-spine .timeline-num .dot-digit { transform: scale(.82); }   /* don't kiss the 48px ring */
  .is-spine .timeline::before, .is-spine .spine-fill { left: 24px; }
}
/* Forced-colors (Windows High Contrast): the red ring colour is stripped, so
   give the read node a real border so progress still survives. */
@media (forced-colors: active) {
  .is-spine .timeline-day.is-reached .timeline-num { border-color: Highlight; }
}

/* ── Outcome Receipt — "By Friday, you shipped ___" ───────────────────── */
.outcome-receipt {
  max-width: 600px; margin: clamp(40px, 5vw, 60px) auto 0;
  position: relative;
  background: var(--white);
  border: 1px solid var(--line);
  border-left: 3px solid var(--secondary);
  border-radius: 14px;
  padding: clamp(22px, 3vw, 30px) clamp(24px, 3.4vw, 36px);
  box-shadow: 0 18px 44px -30px rgba(18, 28, 26, .5);
}
.outcome-receipt-eyebrow {
  font-family: 'DM Mono', monospace; font-size: 11px; letter-spacing: .16em;
  text-transform: uppercase; color: var(--secondary-text); margin-bottom: 12px;
  display: inline-flex; align-items: center; gap: 9px;
}
.outcome-receipt-eyebrow::before {
  content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--secondary);
}
.outcome-receipt-line {
  font-family: 'Newsreader', serif; font-weight: 500;
  font-size: clamp(20px, 2.4vw, 27px); line-height: 1.28; color: var(--ink);
  text-wrap: pretty;
}
.outcome-receipt-line em { font-style: italic; color: color-mix(in oklab, var(--ink) 58%, var(--secondary)); }
.outcome-receipt-dot {
  position: relative;
  display: inline-block; vertical-align: middle;
  width: 9px; height: 9px; border-radius: 50%; background: var(--primary);
  margin-left: 4px;
}
.outcome-receipt-dot::after {
  content: ''; position: absolute; inset: 0; border-radius: 50%;
  background: var(--primary); opacity: 0; pointer-events: none;
}
/* Reveal is GATED on .is-armed (added by program-spine.js) so the real payoff
   copy stays fully visible with no JS / on a script failure / reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .outcome-receipt.is-armed {
    opacity: 0; transform: translateY(20px);
    transition: opacity .7s var(--ease-arrival), transform .7s var(--ease-arrival);
  }
  .outcome-receipt.is-armed.is-in { opacity: 1; transform: none; }
  .outcome-receipt.is-armed .outcome-receipt-dot { transform: scale(0); transition: transform .5s var(--ease-decel) .55s; }
  .outcome-receipt.is-armed.is-in .outcome-receipt-dot { transform: scale(1); }
  /* one-shot 'landed' ring — transform + opacity only (no animated box-shadow) */
  .outcome-receipt.is-armed.is-in .outcome-receipt-dot::after { animation: receipt-dot-ring 1.4s var(--ease-decel) 1s 1; }
}
@keyframes receipt-dot-ring {
  0% { transform: scale(1); opacity: .5; }
  100% { transform: scale(2.6); opacity: 0; }
}
