/* ============================================================
   MOTION — ink appearing on paper. Things only DRAW, BLOOM,
   STAMP, TURN. Scroll drives animation, never the reverse.
   ============================================================ */

/* (1) Cross-document view transitions — ledger row morphs into lesson folio. */
@view-transition { navigation: auto; }
::view-transition-old(root), ::view-transition-new(root) { animation-duration: 0.22s; }

/* (2) Scroll-driven ink: diagrams draw as you read.
   Fully visible without support — the animation only WITHHOLDS then draws. */
@supports (animation-timeline: view()) {
  .draw-on-read path[pathLength] {
    stroke-dasharray: 1;
    stroke-dashoffset: 1;
    animation: ink-draw 1ms linear both;
    animation-timeline: view();
    animation-range: entry 10% cover 45%;
  }
  @keyframes ink-draw { to { stroke-dashoffset: 0; } }

  /* THE READING LAMP — After Hours only: the in-view section holds full
     contrast; neighbours step down two stepped opacity tokens. */
  :root[data-theme="dark"][data-lamp="on"] .lamp-section {
    animation: lamp-steps 1ms linear both;
    animation-timeline: view();
  }
  @media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"])[data-lamp="on"] .lamp-section {
      animation: lamp-steps 1ms linear both;
      animation-timeline: view();
    }
  }
  @keyframes lamp-steps {
    0%   { opacity: var(--lamp-step-2); }
    18%  { opacity: var(--lamp-step-1); }
    38%, 62% { opacity: 1; }
    82%  { opacity: var(--lamp-step-1); }
    100% { opacity: var(--lamp-step-2); }
  }
  .lamp-section:hover, .lamp-section:focus-within {
    animation: none !important;
    opacity: 1 !important;
  }
}

/* (3) Word-only masked reveals — hero and section thresholds, never body copy. */
.reveal-words > span { display: inline-block; }
@media (prefers-reduced-motion: no-preference) {
  :root:not([data-still-air="on"]) .reveal-words > span {
    opacity: 0;
    transform: translateY(0.35em);
    animation: word-bloom 0.5s cubic-bezier(0.2, 0.6, 0.2, 1) forwards;
    animation-delay: calc(var(--i, 0) * 60ms);
  }
}
@keyframes word-bloom { to { opacity: 1; transform: none; } }

/* BLOOM — simple opacity entrance for plates and wells at threshold. */
@media (prefers-reduced-motion: no-preference) {
  :root:not([data-still-air="on"]) .bloom { animation: bloom 0.45s ease-out both; }
}
@keyframes bloom { from { opacity: 0; } }

/* STAMP — 150ms scale-settle (seals, DONE stamps, filed call slips). */
.stamp { animation: stamp 150ms cubic-bezier(0.2, 1.4, 0.4, 1) both; }
@keyframes stamp {
  from { transform: scale(1.4); opacity: 0; }
  60% { transform: scale(0.96); opacity: 1; }
  to { transform: scale(1); }
}

/* (4) Drop-cap illumination: strokes draw, gold blooms — handled by lesson JS
   adding .illuminate on first scroll; pre-illuminated otherwise. */
@media (prefers-reduced-motion: no-preference) {
  :root:not([data-still-air="on"]) .drop-cap.awaiting-ink::first-letter { color: var(--muted); }
  :root:not([data-still-air="on"]) .drop-cap.illuminate::first-letter {
    animation: gold-bloom 1.2s ease-in-out both;
  }
}
@keyframes gold-bloom {
  from { color: var(--muted); }
  55% { color: var(--ink); }
  to { color: var(--gold); }
}

/* Entrance choreography — ≤900ms, first paint is real content. */
@media (prefers-reduced-motion: no-preference) {
  :root:not([data-still-air="on"]) .entrance > * {
    animation: bloom 0.4s ease-out both;
    animation-delay: calc(var(--i, 0) * 90ms);
  }
}

/* Ink-draw shimmer for loading states — no spinners. */
.ink-loading {
  position: relative;
  min-height: var(--u6);
  overflow: hidden;
}
.ink-loading::after {
  content: '';
  position: absolute; inset: auto 0 0 0;
  height: 1px;
  background: var(--hairline);
  transform-origin: 0 50%;
  animation: rule-draw 1.1s ease-in-out infinite alternate;
}
@keyframes rule-draw { from { transform: scaleX(0.08); } to { transform: scaleX(1); } }

/* The loupe — deep-zoom magnifier cursor, fine pointers only. */
@media (hover: hover) and (pointer: fine) {
  .loupe-surface { cursor: zoom-in; }
  .loupe-surface.zoomed { cursor: zoom-out; }
}

/* ---------- STILL AIR / reduced motion: reduce, don't remove. ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.18s !important;
    animation-delay: 0s !important;
    transition-duration: 0.15s !important;
    scroll-behavior: auto !important;
  }
  .draw-on-read path[pathLength] { stroke-dashoffset: 0 !important; animation: none !important; }
  .lamp-section { animation: none !important; opacity: 1 !important; }
  .drop-cap.awaiting-ink::first-letter { color: var(--gold) !important; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; }
}
:root[data-still-air="on"] *,
:root[data-still-air="on"] *::before,
:root[data-still-air="on"] *::after {
  animation-duration: 0.18s !important;
  animation-delay: 0s !important;
  transition-duration: 0.15s !important;
}
:root[data-still-air="on"] .draw-on-read path[pathLength] { stroke-dashoffset: 0 !important; animation: none !important; }
:root[data-still-air="on"] .lamp-section { animation: none !important; opacity: 1 !important; }
:root[data-still-air="on"] .drop-cap.awaiting-ink::first-letter { color: var(--gold) !important; }
