/* ============================================================
   2BE CLOTHING WORLD — PHASE 3 MOTION LAYER
   Reveals, route fade, editorial Ken Burns.

   EVERY rule here is scoped to `html.motion`. That class is set by a
   one-line synchronous head script ONLY when JS is on AND
   prefers-reduced-motion is not "reduce" — so with reduced motion (or no
   JS) none of these selectors match and nothing below can animate. The
   @media block at the bottom is a second, independent belt-and-braces
   kill switch (site.css §BASE carries a global one too).
   ============================================================ */

/* ---------- SCROLL REVEAL (guide §02 easing, 8px grid → 24px rise) ----------
   motion.js tags below-the-fold targets with data-reveal and sets
   --reveal-delay for the 120ms stagger. Elements already inside the first
   viewport are never tagged: no hidden LCP content, no entry flash. */
html.motion [data-reveal]{
  opacity:0;
  transform:translateY(24px);
  transition:opacity var(--t-slow) var(--ease), transform var(--t-slow) var(--ease);
  transition-delay:var(--reveal-delay,0ms);
  will-change:opacity,transform;
}
html.motion [data-reveal].is-revealed{
  opacity:1;
  transform:none;
  will-change:auto;
}

/* ---------- ROUTE TRANSITION (150ms both directions) ----------
   Enter: body fades up on load. Leave: motion.js holds the navigation for
   one 150ms fade, then follows the href. */
html.motion body{ animation:page-in 150ms var(--ease) both; }
@keyframes page-in{ from{ opacity:0; } to{ opacity:1; } }
html.motion body.is-leaving{
  opacity:0;
  transition:opacity 150ms var(--ease);
  animation:none;
}

/* ---------- KEN BURNS — EDITORIAL HEROES ONLY ----------
   Applied via the data-kenburns attribute, which is hand-placed on the four
   editorial hero images and NOWHERE else. Product imagery (.card__media,
   [data-gallery], .tile) must never carry it — a product photo that drifts
   misrepresents the garment. tests/e2e3.mjs asserts both halves of that. */
html.motion [data-kenburns]{
  animation:kenburns 8s var(--ease) both;
  transform-origin:50% 45%;
}
@keyframes kenburns{
  from{ transform:scale(1); }
  to{ transform:scale(1.06); }
}

/* ---------- LOW-STOCK BADGE (Phase 5) ----------
   "Vibrating" per the brief, scoped through the same html.motion gate as
   everything above — see shop.css .lowstock for layout. A user with
   reduced motion gets a plain, still badge with the same count, not a
   dot with no context (the kill switch below removes the animation only,
   never the element or its text). */
html.motion [data-lowstock]{
  animation:lowstock-shake 2.4s ease-in-out infinite;
}
@keyframes lowstock-shake{
  0%, 88%, 100%{ transform:rotate(0); }
  90%{ transform:rotate(-8deg); }
  92%{ transform:rotate(8deg); }
  94%{ transform:rotate(-6deg); }
  96%{ transform:rotate(6deg); }
  98%{ transform:rotate(0); }
}

/* ---------- STYLE ASSISTANT PANEL (Phase 9) ----------
   Same 150ms class as the route fade, gated the same way. The panel slides
   in from the right edge it is docked to; under reduced motion it simply
   appears, which is the correct behaviour — the panel is content, the
   slide is decoration. */
html.motion .asst__panel{
  animation:asst-in 150ms var(--ease) both;
}
@keyframes asst-in{
  from{ transform:translateX(16px); opacity:0; }
  to{ transform:translateX(0); opacity:1; }
}
html.motion .asst__launch{
  transition:border-color var(--t-fast) var(--ease), transform var(--t-fast) var(--ease);
}
html.motion .asst__launch:hover{ transform:translateY(-2px); }

/* ---------- RAIL CONTROLS ----------
   The edge fade and the arrow/thumb states ease only under the gate. The
   SMOOTH SCROLL itself is gated in rails.js (scrollBehavior()), because
   scroll-behavior is a script decision here, not a stylesheet one. */
html.motion .railx::before,
html.motion .railx::after{
  transition:opacity var(--t-fast) var(--ease);
}
html.motion .railx__arrow{
  transition:border-color var(--t-fast) var(--ease), opacity var(--t-fast) var(--ease);
}
html.motion .railx__thumb{
  transition:height var(--t-fast) var(--ease);
}

/* ---------- KILL SWITCH ---------- */
@media (prefers-reduced-motion:reduce){
  html.motion .railx::before,
  html.motion .railx::after,
  html.motion .railx__arrow,
  html.motion .railx__thumb{ transition:none!important; }
  html.motion .asst__panel{ animation:none!important; transform:none!important; opacity:1!important; }
  html.motion .asst__launch,
  html.motion .asst__launch:hover{ transition:none!important; transform:none!important; }
  html.motion [data-reveal]{
    opacity:1!important; transform:none!important; transition:none!important;
  }
  html.motion body,
  html.motion body.is-leaving{ opacity:1!important; animation:none!important; transition:none!important; }
  html.motion [data-kenburns]{ animation:none!important; transform:none!important; }
  html.motion [data-lowstock]{ animation:none!important; transform:none!important; }
  html.motion .reel__frame > img,
  html.motion .post__frame > img{ transition:none!important; transform:none!important; }
}

/* ---------- EDITORIAL MEDIA HOVER (Phase 8) ----------
   The reels/community posters get the same restrained 1.0 -> 1.04 lift the
   product cards use (guide §05). Scoped through html.motion like everything
   else here, and killed below under prefers-reduced-motion — the image
   still shows, it simply stops moving. */
html.motion .reel__frame > img,
html.motion .post__frame > img{
  transition:transform 400ms var(--ease);
}
html.motion .reel__btn:hover .reel__frame > img,
html.motion .reel__btn:focus-visible .reel__frame > img,
html.motion .post__frame:hover > img,
html.motion .post__frame:focus-visible > img{ transform:scale(1.04); }
