/*
 * developments/css/dev-loader.css — D77 Cycle 2 first-paint editorial loader.
 *
 * One static editorial card centered over the empty map area at t=0.
 * Fades out when map.on('idle') first fires. All tokens from _tokens.css.
 * Chrome (header, today, rail) is held at opacity 0.6 during load via the
 * .dev-shell[data-loading="true"] selector below so the whole composition
 * resolves together instead of the chrome arriving 4 seconds before the
 * map (per D77-FIRST-PAINT.md §2.3).
 */

.dev-loader {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: grid;
  place-items: center;
  background: var(--surface-3);
  /* Sits over the still-mounting canvas. Mapbox canvas sits at z-index
     auto within #dev-map, so this is above it. */
  pointer-events: none;
}

.dev-loader__card {
  width: min(480px, calc(100vw - var(--space-6)));
  padding: var(--space-5) var(--space-5) var(--space-4);
  background: var(--surface-1);
  border: 1px solid var(--line);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  display: grid;
  gap: var(--space-3);
}

.dev-loader__eyebrow {
  font: var(--weight-medium) var(--text-sm)/1.2 var(--font-display);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* VL.LOAD — was --ink-3 (#6b7280 ≈ 4.4:1 on paper, the documented
     brand-lie). Gold is reserved for the rule/bar only; the eyebrow is
     asserted-visible label text so it sits on --ink-2 (#374151 ≈ 10:1)
     per the WCAG contrast-gate lesson. */
  color: var(--ink-2);
}

.dev-loader__headline {
  font: var(--weight-medium) var(--text-md)/1.3 var(--font-mono);
  color: var(--ink-1);
  font-variant-numeric: tabular-nums;
  /* Numbers fade in once data resolves. */
  transition: opacity var(--duration-base) var(--ease-out);
}
.dev-loader[data-state="reading"] .dev-loader__headline { opacity: 0.55; }
.dev-loader[data-state="ready"]   .dev-loader__headline { opacity: 1; }
.dev-loader__sep { color: var(--ink-4); margin: 0 var(--space-1); }

.dev-loader__status {
  font: var(--weight-regular) var(--text-base)/1.4 var(--font-body);
  color: var(--ink-2);
}

.dev-loader__progress {
  position: relative;
  height: 4px;
  background: var(--gold-faint);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
/* VL.LOAD — Goldlight sweep. Was a 28%-wide translateX shuttle; now a
   full-width gold travelling-highlight via background-position (the ONE
   shared shimmer vocabulary — identical tempo + idiom to the panel
   skeleton's dev-skel-sweep). Compositor-cheap (background-position only,
   no translate/layout). 1300ms is the one shared tempo, hardcoded inline
   exactly as the old keyframe hardcoded 1100ms (no parallel :root token). */
.dev-loader__progress-bar {
  position: absolute;
  inset: 0;
  width: 100%;
  background: linear-gradient(90deg, transparent 0%, var(--gold) 50%, transparent 100%);
  background-size: 200% 100%;
  border-radius: inherit;
  animation: dev-loader-sweep 1300ms var(--ease-in-out) infinite;
}
@keyframes dev-loader-sweep {
  from { background-position: 200% 0; }
  to   { background-position: -200% 0; }
}

/* VL.LOAD — determinate gold underline under the count line. Grows in
   discrete steps as REAL data sources resolve (DevLoader.setProgress sets
   --loader-progress = ticks/3). Honest: never advances ahead of resolution.
   transform:scaleX is compositor-only — no reflow. */
.dev-loader__underline {
  height: 2px;
  background: var(--gold);
  border-radius: var(--radius-sm);
  transform: scaleX(var(--loader-progress, 0));
  transform-origin: left;
  transition: transform var(--duration-slow) var(--ease-out);
}

.dev-loader__checklist {
  list-style: none;
  margin: var(--space-1) 0 0;
  padding: 0;
  display: grid;
  gap: var(--space-1);
}
.dev-loader__checklist li {
  font: var(--weight-regular) var(--text-sm)/1.4 var(--font-body);
  color: var(--ink-3);
  display: flex;
  align-items: center;
  gap: var(--space-2);
}
.dev-loader__dot {
  width: 6px;
  height: 6px;
  border-radius: var(--radius-pill);
  background: var(--ink-4);
  transition: background var(--duration-base) var(--ease-out);
  flex-shrink: 0;
}
.dev-loader__checklist li[data-resolved="true"] .dev-loader__dot {
  background: var(--gold);
}

/* ── Exit ──────────────────────────────────────────────────────────── */
.dev-loader.is-exiting {
  opacity: 0;
  transform: translateY(-4px);
  transition:
    opacity   var(--duration-slow) var(--ease-out),
    transform var(--duration-slow) var(--ease-out);
}

/* After exit completes, JS sets data-state="done" → display:none, removed
   from layer stack so it never blocks future repaint or accessibility tree. */
.dev-loader[data-state="done"] { display: none; }

/* ── Chrome held back during load ──────────────────────────────────── */
/* Header, detail container, rail were rendering at +30ms; held to 0.6
   until idle so the whole composition resolves together. */
.dev-shell[data-loading="true"] #dev-header,
.dev-shell[data-loading="true"] #dev-detail,
.dev-shell[data-loading="true"] #dev-rail {
  opacity: 0.6;
  transition: opacity var(--duration-slow) var(--ease-out);
}
.dev-shell[data-loading="false"] #dev-header,
.dev-shell[data-loading="false"] #dev-detail,
.dev-shell[data-loading="false"] #dev-rail {
  opacity: 1;
  transition: opacity var(--duration-slow) var(--ease-out);
}

/* ── Reduced motion ────────────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .dev-loader__progress-bar {
    animation: none;
    width: 100%;
    background: var(--gold);
    opacity: 0.4;
  }
  /* VL.LOAD — underline still communicates "complete" without animating:
     jump to full width, no transition. The count-up is skipped in JS
     (loader.js RM() writes the final number instantly). */
  .dev-loader__underline { transform: scaleX(1); transition: none; }
  .dev-loader.is-exiting {
    transition: opacity var(--duration-fast) var(--ease-out);
    transform: none;
  }
  .dev-loader__dot { transition: none; }
  .dev-shell[data-loading="true"] #dev-header,
  .dev-shell[data-loading="true"] #dev-detail,
  .dev-shell[data-loading="true"] #dev-rail { opacity: 1; }
}

/* ── Error state ───────────────────────────────────────────────────── */
.dev-loader[data-state="error"] .dev-loader__progress { display: none; }
.dev-loader[data-state="error"] .dev-loader__status   { color: var(--status-error); }
.dev-loader__error-action {
  margin-top: var(--space-2);
  font: var(--weight-medium) var(--text-sm)/1.2 var(--font-body);
  color: var(--gold-dark);
  background: transparent;
  border: 1px solid var(--gold);
  border-radius: var(--radius-sm);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  pointer-events: auto;
}
.dev-loader__error-action:hover,
.dev-loader__error-action:focus-visible {
  background: var(--gold-faint);
}

/* ── MOB2 (owner 2026-06-11): phone boot screen ────────────────────────
   Two problems on phones, one fix each:
   1. OCCLUSION — the loader was z:5 inside #dev-map while the open #dev-nav
      (z:5, later in DOM, opaque paper) painted over it: the "giant colour
      block blocking the loading panel". position:fixed + z-index:9000 makes
      the phone loader a true full-screen overlay above ALL chrome (bar is 9,
      sheets 6/8; .dev-skiplink stays on top at 10001). Desktop is untouched.
   2. POLISH — a dark charcoal-and-gold "goldlight" treatment (brand tokens),
      and the exit scales the card up 6% while it fades over 600ms, timed so
      the INTRO_CAMERA→CAMERA swoop (map.js, fires on the same first idle)
      is revealed mid-dive: the loader dissolves INTO the camera motion.
      (loader.js's exit fallback timer is 700ms to outlast this fade.) */
@media (max-width: 540px) {
  .dev-loader {
    position: fixed;
    inset: 0;
    z-index: 9000;
    background:
      radial-gradient(120% 90% at 50% 0%, rgba(212, 168, 75, 0.10), transparent 60%),
      linear-gradient(180deg, #191919 0%, #111111 100%);
  }
  .dev-loader__card {
    background: rgba(31, 31, 31, 0.72);
    border-color: rgba(212, 168, 75, 0.28);
    backdrop-filter: blur(14px) saturate(140%);
    -webkit-backdrop-filter: blur(14px) saturate(140%);
    box-shadow: 0 18px 48px rgba(0, 0, 0, 0.5);
  }
  .dev-loader__eyebrow  { color: var(--gold-400, #e5c57a); }
  .dev-loader__headline { color: #f5f5f4; }
  .dev-loader__sep      { color: rgba(245, 245, 244, 0.35); }
  .dev-loader__status   { color: rgba(245, 245, 244, 0.78); }
  .dev-loader__checklist li { color: rgba(245, 245, 244, 0.55); }
  .dev-loader__dot      { background: rgba(255, 255, 255, 0.22); }
  .dev-loader__progress { background: rgba(212, 168, 75, 0.16); }
}
@media (max-width: 540px) and (prefers-reduced-motion: no-preference) {
  .dev-loader.is-exiting {
    opacity: 0;
    transform: scale(1.06);
    transition:
      opacity   600ms var(--ease-in-out),
      transform 600ms var(--ease-in-out);
  }
}
