/* Glass v2 motion system. Contract: round3/DIRECTION.md section B.
   Everything is scoped under html.m-on (set by motion.js only when
   prefers-reduced-motion is no-preference). No JS or reduced motion = all
   content visible, static, pinned scenes stacked with height:auto.
   Only opacity / translate / scale / clip-path are animated. The hero device
   additionally interpolates width and radius from --p (contract: section B).

   ATTRIBUTES
     data-reveal="up|fade|scale|left|right"  + data-reveal-delay="ms"
     data-stagger="stepMs"  (parent; children reveal up, max 12 steps)
     data-scrub="zoom|zoom-out|parallax|fade" + data-range="entry 0% cover 60%"
     data-pin data-pin-steps="N"   container; add <div class="m-pin-stage"> inside
     data-hero-zoom [data-hero-distance="vh", default 120]
     data-count="1234" [data-count-ms/-prefix/-suffix]
     data-vt="shared:<name>"

   PIN: container gets --p (0..1) and data-step (0..N-1). Children carrying
   [data-step="k"] get .is-step when k is current and .is-seen when k <= current.
   Put overlapping step captions in <div class="m-steps"> (grid stack).

   HERO ZOOM (home builder). Markup:
     <div data-hero-zoom data-hero-distance="120">   full-bleed, outside .g-mwrap
       <div class="m-device"> <iframe|img ...> </div>
       <p class="m-cap h-cap">...</p>                 optional, fades in when settled
   Preferred: wrap device + caption in <div class="m-hero-stage"> (the sticky box; caption
   is scrubbed by --p, so it is visible together with the settled device).
     </div>
   The wrapper gets --p (0..1) and .is-settled at p=1. Defaults below style
   .m-device (sticky, width 100% -> min(1180px,92vw), radius 0 -> --g-r-device,
   shadow opacity = --p). Its first child fills it and inherits the radius.
   Consume --p yourself for anything else, e.g.
     [data-hero-zoom] .h-cap { opacity: clamp(0, calc(var(--p) * 4 - 3), 1); }
   Set --m-hero-top on the wrapper if a sticky nav needs clearing. */

@layer glass.page {

  /* ---------- reveal ---------- */
  :where(html.m-on) :where(.mc-glass) {
    --m-tx: 0px; --m-ty: var(--g-reveal-y); --m-s: 1;
  }
  :where(html.m-on) :where(.mc-glass) [data-reveal="fade"] { --m-ty: 0px; }
  :where(html.m-on) :where(.mc-glass) [data-reveal="scale"] { --m-ty: 0px; --m-s: .96; }
  :where(html.m-on) :where(.mc-glass) [data-reveal="left"] { --m-tx: calc(var(--g-reveal-y) * -1); --m-ty: 0px; }
  :where(html.m-on) :where(.mc-glass) [data-reveal="right"] { --m-tx: var(--g-reveal-y); --m-ty: 0px; }

  :where(html.m-on) :where(.mc-glass) [data-reveal]:not(.is-in),
  :where(html.m-on) :where(.mc-glass) [data-stagger]:not(.is-in) > * {
    opacity: 0; translate: var(--m-tx) var(--m-ty); scale: var(--m-s);
  }
  :where(html.m-on) :where(.mc-glass) [data-reveal].is-in,
  :where(html.m-on) :where(.mc-glass) [data-stagger].is-in > * {
    animation: m-reveal var(--g-d-reveal) var(--g-spring-smooth) backwards;
    animation-delay: var(--m-delay, 0ms);
  }
  :where(html.m-on) :where(.mc-glass) [data-stagger].is-in > * {
    animation-delay: calc(var(--m-i, 0) * var(--m-step, 70ms));
  }
  @keyframes m-reveal {
    from { opacity: 0; translate: var(--m-tx, 0px) var(--m-ty, 28px); scale: var(--m-s, 1); }
  }

  /* ---------- scrub ---------- */
  :where(html.m-on) :where(.mc-glass) [data-scrub].m-vis { will-change: transform; }
  @supports (animation-timeline: view()) {
    :where(html.m-on) :where(.mc-glass) [data-scrub] {
      animation: m-zoom linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 60%;
    }
    :where(html.m-on) :where(.mc-glass) [data-scrub="zoom-out"] { animation-name: m-zoom-out; }
    :where(html.m-on) :where(.mc-glass) [data-scrub="parallax"] { animation-name: m-parallax; }
    :where(html.m-on) :where(.mc-glass) [data-scrub="fade"] { animation-name: m-fade; animation-range: entry 0% cover 40%; }
    @keyframes m-zoom { from { scale: 1; } to { scale: 1.08; } }
    @keyframes m-zoom-out { from { scale: 1.06; } to { scale: 1; } }
    @keyframes m-parallax { from { translate: 0 0; } to { translate: 0 -6%; } }
    @keyframes m-fade { from { opacity: 0; } to { opacity: 1; } }
  }
  /* Fallback: motion.js writes --p (0..1) on each scrubbed element in view. */
  @supports not (animation-timeline: view()) {
    :where(html.m-on) :where(.mc-glass) [data-scrub="zoom"] { scale: calc(1 + .08 * var(--p, 0)); }
    :where(html.m-on) :where(.mc-glass) [data-scrub="zoom-out"] { scale: calc(1.06 - .06 * var(--p, 0)); }
    :where(html.m-on) :where(.mc-glass) [data-scrub="parallax"] { translate: 0 calc(-6% * var(--p, 0)); }
    :where(html.m-on) :where(.mc-glass) [data-scrub="fade"] { opacity: var(--p, 0); }
  }

  /* ---------- pin ---------- */
  :where(html.m-on) :where(.mc-glass) [data-pin] {
    height: calc((var(--m-steps, 1) + 1) * 100vh);
    height: calc((var(--m-steps, 1) + 1) * 100svh);
  }
  :where(html.m-on) :where(.mc-glass) [data-pin] > .m-pin-stage {
    position: sticky; top: 0; height: 100vh; height: 100svh; overflow: clip;
  }
  :where(html.m-on) :where(.mc-glass) [data-pin] [data-step]:not(.is-step) {
    opacity: 0; translate: 0 12px; pointer-events: none;
  }
  :where(html.m-on) :where(.mc-glass) [data-pin] [data-step] {
    transition: opacity var(--g-d-base) linear, translate var(--g-d-base) var(--g-spring);
  }
  :where(html.m-on) :where(.mc-glass) [data-pin] .m-steps { display: grid; }
  :where(html.m-on) :where(.mc-glass) [data-pin] .m-steps > [data-step] { grid-area: 1 / 1; }

  /* ---------- hero zoom ---------- */
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] {
    --p: 0;
    height: calc(100vh + var(--m-hero-d, 120vh));
    height: calc(100svh + var(--m-hero-d, 120vh));
  }
  /* Stage = sticky box holding device + caption, so both are on screen when settled.
     Direct-child .m-device (no stage) keeps the older behaviour. */
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] > .m-hero-stage {
    position: sticky; top: var(--m-hero-top, 0px);
    height: calc(100vh - var(--m-hero-top, 0px)); height: calc(100svh - var(--m-hero-top, 0px));
    display: grid; align-content: start; justify-items: center;
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] :is(.m-device) {
    width: calc(100% + (min(1180px, 92vw) - 100%) * var(--p, 0));
    margin-inline: auto;
    aspect-ratio: 16 / 10;
    border-radius: calc(var(--g-r-device) * var(--p, 0));
    isolation: isolate;
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] > .m-device {
    position: sticky; top: var(--m-hero-top, 0px);
    max-height: calc(100svh - var(--m-hero-top, 0px));
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] > .m-hero-stage > .m-device {
    max-height: calc(100svh - var(--m-hero-top, 0px) - 64px);
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] .m-device::before {
    content: ""; position: absolute; inset: 0; z-index: -1; border-radius: inherit;
    box-shadow: var(--g-pop-shadow); opacity: var(--p, 0); pointer-events: none;
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] .m-device > :first-child {
    display: block; width: 100%; height: 100%; border: 0; border-radius: inherit; overflow: hidden; object-fit: cover;
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] > .m-cap {
    position: sticky; bottom: 24px; text-align: center;
    opacity: 0; translate: 0 10px;
    transition: opacity var(--g-d-base) linear, translate var(--g-d-base) var(--g-spring);
  }
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom].is-settled > .m-cap { opacity: 1; translate: 0 0; }
  /* In the stage the caption is scrubbed by --p (visible from p .75, full at 1). */
  :where(html.m-on) :where(.mc-glass) [data-hero-zoom] .m-hero-stage > .m-cap {
    margin-top: 16px; opacity: clamp(0, calc(var(--p, 0) * 4 - 3), 1); translate: none; transition: none;
  }

  /* ---------- count ---------- */
  :where(.mc-glass) [data-count] { font-variant-numeric: tabular-nums; }

  @media print {
    :where(html.m-on) :where(.mc-glass) [data-reveal],
    :where(html.m-on) :where(.mc-glass) [data-stagger] > *,
    :where(html.m-on) :where(.mc-glass) [data-pin] [data-step],
    :where(html.m-on) :where(.mc-glass) [data-hero-zoom] .m-cap { opacity: 1 !important; translate: none !important; scale: none !important; animation: none !important; }
    :where(html.m-on) :where(.mc-glass) [data-pin],
    :where(html.m-on) :where(.mc-glass) [data-hero-zoom] { height: auto; }
    :where(html.m-on) :where(.mc-glass) [data-pin] > .m-pin-stage { position: static; height: auto; }
    :where(html.m-on) :where(.mc-glass) [data-hero-zoom] > .m-hero-stage { position: static; height: auto; }
  }
}

/* ---------- view transitions (cross-document) ---------- */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 220ms; }
}
