/* Shared cinematic-scroll primitives for the NovaBot demo pages */
[data-reveal] { opacity: 0; transform: translateY(28px); transition: opacity .9s cubic-bezier(.2,.7,.2,1), transform .9s cubic-bezier(.2,.7,.2,1); transition-delay: calc(var(--i, 0) * 70ms); }
[data-reveal="left"] { transform: translateX(-40px); } [data-reveal="right"] { transform: translateX(40px); } [data-reveal="scale"] { transform: scale(.92); }
[data-reveal].in { opacity: 1; transform: none; }
[data-speed] { will-change: transform; }
.progress { position: fixed; top: 0; left: 0; height: 2px; width: 0; z-index: 50; background: currentColor; }
.scene { position: relative; height: 300vh; }
.scene .pin { position: sticky; top: 0; height: 100vh; overflow: hidden; display: grid; place-items: center; }
.marquee { overflow: hidden; white-space: nowrap; }
.marquee > div { display: inline-block; animation: marquee var(--dur, 28s) linear infinite; }
@keyframes marquee { to { transform: translateX(-50%); } }
.grain::after { content: ""; position: fixed; inset: -50%; z-index: 40; pointer-events: none; opacity: .07; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='300' height='300'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>");
  animation: grain 1.2s steps(6) infinite; }
@keyframes grain { 0%,100% { transform: translate(0,0) } 20% { transform: translate(-4%,3%) } 40% { transform: translate(3%,-5%) } 60% { transform: translate(-2%,6%) } 80% { transform: translate(5%,-2%) } }
@media (prefers-reduced-motion: reduce) { [data-reveal] { opacity: 1; transform: none; transition: none; } .marquee > div, .grain::after { animation: none; } }
