/* ============================================================================
   Scroll-reveal classes — IntersectionObserver toggles .is-visible.
   ============================================================================ */

@layer components {
  /* Reveal is purely additive: the FROM state lives on the .is-pending
     class (added by JS only if it can guarantee the observer will fire).
     If JS never runs, content stays visible — no opacity:0 trap. */
  [data-reveal] {
    transition:
      opacity var(--bw-duration-slow) var(--bw-ease-out-soft),
      transform var(--bw-duration-slow) var(--bw-ease-out-soft);
    transition-delay: var(--reveal-delay, 0ms);
  }
  /* Transform-only reveal — opacity stays at 1 throughout, so content is
     always readable even if the observer never fires (e.g. full-page
     screenshots, search engine crawlers without JS). */
  [data-reveal].is-pending {
    transform: translateY(28px);
  }
  [data-reveal].is-pending.is-visible {
    transform: none;
  }

  [data-reveal="left"].is-pending  { transform: translateX(-32px); }
  [data-reveal="right"].is-pending { transform: translateX(32px); }
  [data-reveal="zoom"].is-pending  { transform: scale(0.94); }

  @media (prefers-reduced-motion: reduce) {
    [data-reveal].is-pending { opacity: 1; transform: none; transition: none; }
  }
}
