/* ==========================================================================
   Motion — shared by every public page (loaded from base.html).

   Rules this file lives by:
   • The finished state is the default. Anything that moves is an
     enhancement layered on top, so a browser that cannot do it (Firefox
     before scroll-driven animations, an older iPhone) shows the same page,
     simply still.
   • Only transform, opacity and clip-path are ever animated.
   • Nothing is hidden by CSS alone: static/js/motion.js marks the elements
     that start below the fold (.rv) and reveals them as they arrive. If the
     script never runs, nothing was hidden.
   • Everything is inside prefers-reduced-motion: no-preference.
   ========================================================================== */

/* ---------- Reveal on scroll (marked by motion.js) ---------- */
@media (prefers-reduced-motion: no-preference) {
  .rv {
    opacity: 0; transform: translate3d(0, 1.75rem, 0);
    transition: opacity .8s var(--ease-out, ease-out) var(--rv-d, 0ms), transform .9s var(--ease-out, ease-out) var(--rv-d, 0ms);
  }
  .rv.rv-fade { transform: none; }
  .rv.rv-scale { transform: scale(.94); }
  .rv.is-in { opacity: 1; transform: none; }
}

/* A photograph that fills its frame and may drift inside it (see below). The
   frame is the positioned, clipping box; the picture is laid over it. */
.sd-parallax { position: relative; overflow: hidden; }
.sd-parallax > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--focus, 50% 66%); }

/* ---------- Scroll-scrubbed effects (Chromium, Safari 26+) ---------- */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    /* A photograph that drifts inside its frame as the frame crosses the
       screen. The image is taller than the frame; the frame clips it. */
    .sd-parallax > img {
      inset: auto; inset-inline: 0; top: -9%; height: 118%;
      animation: sd-drift linear both; animation-timeline: view(); animation-range: cover;
    }
    /* A frame that opens from a smaller window to its full size. */
    .sd-mask { animation: sd-open linear both; animation-timeline: view(); animation-range: entry 0% entry 90%; }
    /* A rule that draws itself from the start edge. */
    .sd-draw-x { transform-origin: right center; animation: sd-draw-x linear both; animation-timeline: view(); animation-range: entry 10% cover 45%; }
    .sd-draw-y { transform-origin: center top; animation: sd-draw-y linear both; animation-timeline: view(); animation-range: entry 10% cover 60%; }
    /* The thin progress bar on top of the page. */
    .page-progress { animation: sd-progress linear both; animation-timeline: scroll(root); }
  }
  @keyframes sd-drift { from { transform: translate3d(0, -7%, 0); } to { transform: translate3d(0, 7%, 0); } }
  @keyframes sd-open { from { clip-path: inset(9% 5% round 1.5rem); } to { clip-path: inset(0 round 1.5rem); } }
  @keyframes sd-draw-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }
  @keyframes sd-draw-y { from { transform: scaleY(0); } to { transform: scaleY(1); } }
  @keyframes sd-progress { from { transform: scaleX(0); } to { transform: scaleX(1); } }
}

/* The page progress bar: invisible unless the browser can drive it. */
.page-progress { position: fixed; inset-inline: 0; top: 0; height: 3px; z-index: 1101; background: var(--accent); transform: scaleX(0); transform-origin: right; pointer-events: none; display: none; }
@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) { .page-progress { display: block; } }
}

/* ---------- Page-to-page transitions (cross-document View Transitions) ----------
   Chromium and Safari 18.2+ cross-fade between pages; a card photo can
   morph into the matching hero on the next page (named in motion.js). */
@media (prefers-reduced-motion: no-preference) {
  @view-transition { navigation: auto; }
  ::view-transition-old(root) { animation-duration: .22s; }
  ::view-transition-new(root) { animation-duration: .32s; }
  ::view-transition-group(card-photo) { animation-duration: .5s; animation-timing-function: var(--ease-out, ease-out); }
}

/* ---------- A single reduced-motion switch for anything missed above ---------- */
@media (prefers-reduced-motion: reduce) {
  .rv { opacity: 1 !important; transform: none !important; transition: none !important; }
}
