/* ── Loader CSS — Phase 8 ────────────────────────────────────────────────── */
/* Progressive-enhancement arming rules, loader overlay layout, scroll-cue bob */
/* All colors via tokens.css — never hardcode #f4f4f4 or #201d1d              */

/* ── DEFAULT state: hero visible, overlay hidden ─────────────────────────── */
/* With no JS or no .loader-armed class, the page renders the Phase 7 hero    */
/* unchanged — this is the no-JS / reduced-motion / session-seen fallback.    */
.loader-overlay {
  display: none;
  position: fixed;
  inset: 0;
  overflow: hidden;
  background: var(--color-bg);
  z-index: 100;
}

/* ── ARMED state: overlay shown, hero hidden ─────────────────────────────── */
/* Added by the synchronous inline gate script only when:                      */
/*   - prefers-reduced-motion is false AND kv_loader_seen is unset (D-03)     */
html.loader-armed .loader-overlay {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* visibility:hidden (NOT display:none) — preserves scroll height (D-04)     */
html.loader-armed .hero {
  visibility: hidden;
}

/* ── FOUC GUARD ──────────────────────────────────────────────────────────── */
/* loader.js is deferred (runs after the GSAP CDN downloads), but .loader-armed */
/* is set during parse — so for a few ms CSS paints the loader at REST (full     */
/* name + ink box) before GSAP applies its first frame. Keep the loader content  */
/* hidden until loader.js adds .loader-ready right after buildTimeline() sets the */
/* start frame (box collapsed, letters below the mask). If GSAP fails to load,    */
/* revealHero() drops .loader-armed and the overlay goes display:none anyway.     */
html.loader-armed .loader { visibility: hidden; }
html.loader-armed.loader-ready .loader { visibility: visible; }

/* ── SCROLL LOCK ──────────────────────────────────────────────────────────── */
/* Rule defined here; loader.js toggles the class in Plan 03 (D-08)           */
html.scroll-locked {
  overflow: hidden;
}

/* ── LOADER INTERNAL LAYOUT ──────────────────────────────────────────────── */
/* overflow:hidden on .loader contains .shape during the 220vmax scale-up     */
/* (Pitfall 7 — without this, the shape escapes the stacking context)         */
.loader {
  position: absolute;
  inset: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
}

.split-line {
  display: flex;
  align-items: center;
  white-space: nowrap;
  font-size: clamp(1.6rem, 6vw, 6.5rem);
  font-weight: var(--display-weight);
  line-height: 1;
  letter-spacing: var(--display-tracking);
  color: var(--color-ink);
}

.split-start {
  display: flex;
  justify-content: flex-end;
  overflow: hidden;
}

.split-end {
  display: flex;
  justify-content: flex-start;
  overflow: hidden;
}

.letter {
  display: block;
}

/* ── GAP + SHAPE ─────────────────────────────────────────────────────────── */
/* .gap is the flex spacer — GSAP animates its width from 0 → 0.82em          */
/* .shape is a child of .gap (NEVER position:fixed left:50% — anti-pattern)  */
/* Sharp corners — NO border-radius (locked design spec)                      */
.gap {
  width: 0;
  height: 0.82em;
  flex: none;
  position: relative;
}

.shape {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 0.82em;
  height: 0.82em;
  background: var(--color-ink);
  z-index: 5;
}

/* ── CSS SCROLL-CUE BOB ──────────────────────────────────────────────────── */
/* Pure @keyframes loop — no GSAP, no ScrollTrigger (MOT-03 / D-09)           */
@keyframes dot-bob {
  0%, 100% { transform: translateY(0);   opacity: 1;   }
  50%       { transform: translateY(5px); opacity: 0.5; }
}

.scroll-cue .dot {
  animation: dot-bob 2s ease-in-out infinite;
}

/* ── REDUCED-MOTION SUPPRESSION ──────────────────────────────────────────── */
/* Stop the CSS bob for users who prefer reduced motion (MOT-03)              */
@media (prefers-reduced-motion: reduce) {
  .scroll-cue .dot {
    animation: none;
  }
}
