/* Scroll-reveal primitives. JS adds .reveal then .in (see js/motion.js).
   If JS fails to run, nothing is hidden - .reveal alone keeps content visible. */
@media (prefers-reduced-motion: no-preference) {
  .reveal {
    opacity: 0;
    transform: translateY(26px);
    transition: opacity 1s var(--ease), transform 1s var(--ease);
    will-change: opacity, transform;
  }
  .reveal.in { opacity: 1; transform: none; }

  /* Clip-wipe reveal for editorial photography (added to .feat-media by JS).
     The clip lives on the inner <img>, NOT the .feat-media container: the
     container is the element the IntersectionObserver watches, and clipping it
     to zero height would zero its own intersection area, so the observer that
     is meant to reveal it could never fire (deadlock -> permanently blank img).
     Video embeds use the plain fade so an iframe is never left clipped. */
  .media-reveal img { clip-path: inset(0 0 100% 0); will-change: clip-path; }
  .media-reveal.in img { clip-path: inset(0 0 0 0); }

  /* gentle hover zoom on framed editorial photography */
  .feat-media, .hero-media { overflow: hidden; }
  .feat-media img, .hero-media img { transition: transform 1.2s var(--ease), clip-path 1.15s var(--ease); }
  .feat-media:hover img, .hero-media:hover img { transform: scale(1.04); }
}
