/* style-scroll.css — P5 scroll-journey UI layer for the homepage.
 *
 * Owns ONLY the dot-rail progress spine + styled section labels and the
 * scroll-cue dismiss. Kept in a separate file (linked from index.html after
 * reveal.css) so it never collides with P3's style.css. References the shared
 * motion tokens from tokens.css (var(--ease-out-expo) / var(--dur-*)) — never
 * redefines them. Honors prefers-reduced-motion (no transitions) and adds no
 * urgency/scarcity; the dot-rail fill maps to the TRUE section index only.
 */

/* ── Dot-rail constellation spine ──────────────────────────────────────────
 * A stylised star-map line behind the rail, in place of the old straight 2px
 * spine. The inline <svg class="dot-nav-spine"> (in index.html, first child of
 * #dot-nav, position:absolute so it never joins the flex flow) draws a jagged
 * path weaving behind the planet dots, faint "twig" offshoots ending in star
 * nodes, and a faint full-height track. A gold, glowing copy of the same path
 * is revealed top→down by a clip-rect scaled with --rail-progress (0..1, set by
 * intro.js from the TRUE active section index); a bright "you-are-here" bead
 * rides the reveal front. No fabricated progress — honest section index only.
 * Cap the rail height on short viewports so the dots + spine never overflow.
 * AI-NOTE: the SVG uses preserveAspectRatio="none" + a fixed 0 0 48 1000
 * viewBox, so .rail-head's translateY(progress*1000px) and the clip-rect
 * scaleY map to the same vertical reveal front — keep the 1000 user-height and
 * the viewBox in sync or the bead detaches from the fill edge. */
.dot-nav {
  --rail-progress: 0;
  max-height: 90svh;
}

.dot-nav-spine {
  position: absolute;
  left: 50%;
  top: 6px;
  height: calc(100% - 12px);
  width: 48px;
  transform: translateX(-50%);
  pointer-events: none;
  z-index: -1;
  overflow: visible;            /* let the glow spill past the viewBox */
}

/* Gold glow wrapping the illuminated path + nodes. */
.dot-nav-spine .rail-bright {
  filter:
    drop-shadow(0 0 1.6px rgba(255, 214, 110, 0.9))
    drop-shadow(0 0 5px rgba(255, 150, 45, 0.42))
    drop-shadow(0 0 10px rgba(255, 120, 20, 0.22));
}

/* The reveal grows top→down with the journey (clip-rect scaled by progress). */
.dot-nav-spine .rail-reveal-rect {
  transform: scaleY(var(--rail-progress, 0));
  transform-origin: 0 0;
  transition: transform var(--dur-slow, 0.5s) var(--ease-out-expo, ease-out);
}

/* The "you-are-here" bead glides along the reveal front. */
.dot-nav-spine .rail-head {
  transform: translateY(calc(var(--rail-progress, 0) * 1000px));
  transition: transform var(--dur-slow, 0.5s) var(--ease-out-expo, ease-out);
  filter:
    drop-shadow(0 0 3px #ffe9a8)
    drop-shadow(0 0 7px rgba(255, 170, 60, 0.7));
}

/* ── Styled dot label (replaces the slow native title tooltip) ──────────────
 * A pill that slides in to the LEFT of the rail (the rail hugs the right edge)
 * on hover / keyboard focus. Pure transform + opacity (compositor-only). The
 * label text comes from data-rail-label; the button's aria-label still wins the
 * accessible-name computation, so the generated text isn't double-announced. */
/* Positioning context for the per-dot label. style.css only set position:relative
 * via .dot[title], which no longer matches now that the native titles are gone,
 * so the ::after would otherwise anchor to .dot-nav instead of the dot. */
.dot[data-rail-label] {
  position: relative;
}

.dot[data-rail-label]::after {
  content: attr(data-rail-label);
  position: absolute;
  right: calc(100% + 6px);
  top: 50%;
  transform: translateY(-50%) translateX(8px);
  white-space: nowrap;
  padding: 0.28rem 0.6rem;
  border-radius: 999px;
  font-family: var(--font-body, inherit);
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  color: #fff;
  background: rgba(12, 10, 28, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  z-index: 1;
  transition:
    opacity var(--dur-fast, 0.18s) var(--ease-out-expo, ease-out),
    transform var(--dur-fast, 0.18s) var(--ease-out-expo, ease-out);
}

.dot[data-rail-label]:hover::after,
.dot[data-rail-label]:focus-visible::after {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}

/* RTL: rail is on the left edge → label slides in on the right side. */
[dir="rtl"] .dot[data-rail-label]::after {
  right: auto;
  left: calc(100% + 6px);
  transform: translateY(-50%) translateX(-8px);
}
[dir="rtl"] .dot[data-rail-label]:hover::after,
[dir="rtl"] .dot[data-rail-label]:focus-visible::after {
  transform: translateY(-50%) translateX(0);
}

/* The rail is display:none under 600px (style.css) — labels would crowd the
 * thin edge strip on phones, and the spine adds little there. Hide both. */
@media (max-width: 600px) {
  .dot-nav-spine { display: none; }
  .dot[data-rail-label]::after { display: none; }
}

/* ── Scroll-cue dismiss (scroll-rhythm F6) ─────────────────────────────────
 * intro.js adds .cue-dismissed on first scroll/keydown/pointerdown so the
 * infinitely-bobbing cue fades out + stops bobbing — it must END, no nag. */
.cosmos-scroll-cue {
  transition: opacity var(--dur-slow, 0.6s) var(--ease-out-expo, ease-out);
}
.cosmos-scroll-cue.cue-dismissed {
  opacity: 0;
}
.cosmos-scroll-cue.cue-dismissed .cosmos-scroll-cue-chevron {
  animation: none;
}

/* ── Reduced motion: keep the payoff legible, kill the motion ───────────────
 * Spine fill still maps to the true index (instant, no tween); labels appear
 * instantly on focus/hover; the scroll-cue snaps away with no fade or bob. */
@media (prefers-reduced-motion: reduce) {
  .dot-nav-spine .rail-reveal-rect,
  .dot-nav-spine .rail-head { transition: none; }
  .dot[data-rail-label]::after { transition: none; }
  .cosmos-scroll-cue { transition: none; }
}
