/* ============================================================================
   scroll-choreography.css — cinematic motion layer for signature moments

   Layered on top of components.css (reveal / reveal-up) and utilities.css
   (stagger). Loaded last so its rules win over the baseline reveal styles
   where they overlap. Selectors are scoped to elements that opt in via
   data-observe — zero rendering cost on pages that don't use them.

   Hooks (paired with observer.js):
     [data-observe~='draw-path']      — SVG path stroke-dashoffset 1 → 0
     [data-observe~='signature-reveal'] — clip-path unmask of [data-line] children
     [data-observe~='scroll-progress'] — element exposes --scroll-progress 0..1
                                          for consumers to read in calc()

   All effects collapse to the final state under prefers-reduced-motion.
   ============================================================================ */

@layer components {
  /* -- Draw-path: SVG line-draw on enter ----------------------------------
     observer.js sets stroke-dasharray + stroke-dashoffset inline on each
     descendant <path data-draw>. When .observed lands on the host, the
     transition kicks in and unspools the path to its drawn state. */
  [data-observe~='draw-path'] path[data-draw] {
    transition:
      stroke-dashoffset var(--duration-cinema) var(--ease-signature),
      opacity var(--duration-slow) var(--ease-decelerate);
    /* Per-path stagger via inline style="--draw-index: N" lets a parent
       orchestrate multiple paths in sequence without bespoke JS. The
       existing utilities.css stagger rule is for direct children only —
       this delay rule reaches into nested <path> elements. */
    transition-delay: calc(var(--draw-index, 0) * var(--stagger-slow));
  }
  [data-observe~='draw-path'].observed path[data-draw] {
    stroke-dashoffset: 0 !important;
  }

  /* -- Signature reveal: clip-path unmask of typographic lines ------------
     The reveal-up baseline does translateY + opacity. signature-reveal
     instead unmasks each line from left to right, holding the bottom
     edge so the type "rises" out of nothing. observer.js sets
     --stagger-index on each [data-line] child before adding .observed. */
  [data-observe~='signature-reveal'] [data-line] {
    /* clip-path + transform require a non-pure-inline display; promote so
       the unmask works reliably across browsers and the translateY takes. */
    display: inline-block;
    clip-path: inset(0 100% 0 0);
    transform: translateY(0.25em);
    opacity: 0;
    transition:
      clip-path var(--duration-signature) var(--ease-signature),
      transform var(--duration-signature) var(--ease-signature),
      opacity var(--duration-slow) var(--ease-decelerate);
    transition-delay: calc(var(--stagger-index, 0) * var(--stagger-mid));
    /* GPU promotion — the clip-path + transform pair animates per-frame */
    will-change: clip-path, transform;
  }
  [data-observe~='signature-reveal'].observed [data-line] {
    clip-path: inset(0 0 0 0);
    transform: translateY(0);
    opacity: 1;
  }

  /* -- Scroll-progress: element exposes 0..1 as CSS var -------------------
     No default visual effect — the hook just keeps --scroll-progress
     updated. Consumers read it in their own rules, e.g.
       .step-tile { background: color-mix(in oklch,
                       var(--surface-container),
                       var(--org) calc(var(--phase-progress, 0) * 100%)); }
     where --phase-progress is derived per-tile from --scroll-progress
     via calc() with offset thresholds.

     Nothing to declare here; the rule exists so the contract is
     documented alongside the hook it pairs with. */
  /* (intentional no-op rule below — preserves the contract in the cascade) */
  [data-observe~='scroll-progress'] {
    --scroll-progress: var(--scroll-progress, 0);
  }
}

/* ----------------------------------------------------------------------------
   Reduced-motion: every cinematic effect collapses to final state instantly.
   The baseline reveal/reveal-up already does this in components.css; we
   repeat the discipline here for the cinematic-only hooks.
   ---------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  [data-observe~='draw-path'] path[data-draw],
  [data-observe~='draw-path'].observed path[data-draw] {
    transition: none !important;
    stroke-dashoffset: 0 !important;
    stroke-dasharray: none !important;
  }
  [data-observe~='signature-reveal'] [data-line],
  [data-observe~='signature-reveal'].observed [data-line] {
    transition: none !important;
    clip-path: inset(0 0 0 0) !important;
    transform: none !important;
    opacity: 1 !important;
    will-change: auto;
  }
}
