/* SceneReveal (Frontier Motion, direction 1c): major landing sections enter
   like film scenes instead of scrolling past. Companion to scene-reveal.js,
   which only supplies the IntersectionObserver fallback where CSS
   scroll-driven animations are unsupported. Tag sections with data-scene. */

@keyframes sceneEnter{
  from{opacity:0;transform:scale(.955);filter:blur(5px)}
  to{opacity:1;transform:none;filter:blur(0)}
}

/* fallback default: hidden until scene-reveal.js adds .scene-in */
[data-scene]{opacity:0}
[data-scene].scene-in{animation:sceneEnter .7s var(--ease-scene,cubic-bezier(.4,0,.2,1)) both}

/* scroll-driven where supported (the JS fallback stands down) */
@supports (animation-timeline: view()){
  [data-scene]{
    opacity:1;
    /* NOTE: the explicit `auto` duration is REQUIRED. Without it the shorthand
       resolves the duration to 0s and the scroll-driven animation sticks at
       its from-frame (opacity:0), hiding every section below the hero. */
    animation:sceneEnter auto linear both;
    animation-timeline:view();
    animation-range:entry 0% entry 60%;
  }
}

/* self-healing: scene-reveal.js verifies the scroll timeline actually ticks
   (some embedded engines report support but never advance it) and flips to
   the IO fallback by stamping .scene-fallback on <html> */
:root.scene-fallback [data-scene]{animation:none;opacity:0}
:root.scene-fallback [data-scene].scene-in{animation:sceneEnter .7s var(--ease-scene,cubic-bezier(.4,0,.2,1)) both}

/* mobile: plain 500ms fades; blur and scale are the expensive part */
@media (max-width:760px){
  @keyframes sceneEnter{from{opacity:0}to{opacity:1}}
  [data-scene].scene-in,:root.scene-fallback [data-scene].scene-in{animation-duration:.5s}
}

@media (prefers-reduced-motion: reduce){
  [data-scene],[data-scene].scene-in,
  :root.scene-fallback [data-scene],:root.scene-fallback [data-scene].scene-in{opacity:1;animation:none}
}
