/* ============================================================
   TIDY BEAR — MOTION LAYER  (Phase 1)
   ------------------------------------------------------------
   Reveal-on-scroll + a little hover/press polish. Pure
   transform/opacity, GPU-friendly. Loaded AFTER style.css.

   Content is visible by DEFAULT. The hidden state only applies
   when site.js adds body.js-reveal — so no-JS users, reduced-
   motion users, and crawlers always see the full page. Motion
   tokens (--ease*, --dur-*, --reveal-*, --stagger) live in
   foundation.css :root. No new colors are introduced here.
   ============================================================ */

/* ---------- reveal-on-scroll ---------- */
@keyframes tb-rise {
  from { opacity: 0; transform: translateY(var(--reveal-y)); }
  to   { opacity: 1; transform: none; }
}

/* Armed only once JS confirms motion is OK (body.js-reveal). Hidden until the
   element's group scrolls into view and JS adds .is-visible. */
body.js-reveal .reveal:not(.is-visible) { opacity: 0; }

body.js-reveal .reveal.is-visible {
  /* `backwards` (not forwards) so the final transform is NOT locked — card
     hover-lift still works after the reveal finishes. */
  animation: tb-rise var(--dur-entrance) var(--ease) backwards;
  animation-delay: calc(var(--i, 0) * var(--stagger));
}

/* ---------- tactile button press (<100ms feedback) ---------- */
.btn:active { transform: translateY(0) scale(.97); }

/* ---------- reduced-motion: belt and suspenders ----------
   site.js already skips body.js-reveal under reduced-motion, and foundation.css
   zeroes durations globally. This is a third safety net. */
@media (prefers-reduced-motion: reduce) {
  body.js-reveal .reveal { opacity: 1 !important; }
  body.js-reveal .reveal.is-visible { animation: none !important; }
}
