Scroll is the scrubber
This footage is not playing. Your scroll position is its playhead, and every pixel you travel advances a single frame.
Your scroll position is the playhead. Keep scrolling: a real video seeks frame-by-frame while a track of chapters pans sideways across it.
ScrollScroll down slowly and the ink blooms one frame at a time; flick the wheel and the film races while the type smears with your speed, then settles crisp. The rail at the bottom is a live playhead. Scroll back up and it rewinds, exactly.
This footage is not playing. Your scroll position is its playhead, and every pixel you travel advances a single frame.
No sprite sheet, no image sequence. One <video>, its currentTime driven straight from ScrollTrigger progress and re-encoded all-intra so every seek lands instantly.
While the film scrubs, this chapter track pans horizontally across it. Two motions, one gesture, locked to the same scrubbed timeline.
Throw the wheel and the type skews and blurs with your scroll velocity, then relaxes back to crisp the moment you stop. Fast in, controlled out.
Let go. The playhead holds exactly where you left it. That is the whole trick, and it is just a video and a tween.
One ScrollTrigger owns the pin and a scrubbed timeline. The timeline runs the horizontal pan and a slow push-in on the film; its onUpdate maps scroll progress onto the video's currentTime, throttled by the seeked event so seeks never pile up. On touch, the film loops muted as a backdrop and the chapters stack; reduced motion holds the poster with the chapters read as a static list.