(function(){ var rm = matchMedia('(prefers-reduced-motion: reduce)').matches; var bar = document.getElementById('bar'); var s20 = document.querySelector('#s20 img'); var ring = document.getElementById('ring'); var glows = [].slice.call(document.querySelectorAll('.s22-glow')); var s24 = document.querySelector('#s24 img'); function prog(el){ var r = el.getBoundingClientRect(), vh = innerHeight; return Math.max(0, Math.min(1, (vh - r.top) / (vh + r.height))); } function onScroll(){ var d = document.documentElement; bar.style.width = (100 * d.scrollTop / (d.scrollHeight - innerHeight)) + '%'; if (rm) return; var p20 = prog(s20); /* dock-and-stow: assembles inward */ s20.style.transform = 'scale(' + (1.07 - 0.07 * Math.min(1, p20 * 1.6)) + ') translateY(' + (26 - 26 * Math.min(1, p20 * 1.6)) + 'px)'; var p21 = prog(ring); /* ring-walk: the cycle turns */ ring.style.transform = 'rotate(' + (p21 * 300) + 'deg)'; glows.forEach(function(g, i){ /* checkpoint procession: three beats */ var p = prog(g.parentElement); var band = 0.18 + i * 0.22; g.style.opacity = Math.max(0, Math.min(0.85, (p - band) * 6)); }); var p24 = prog(s24); /* two-plane parallax */ s24.style.transform = 'translateY(' + ((p24 - 0.5) * -26) + 'px) scale(1.03)'; } addEventListener('scroll', onScroll, {passive: true}); addEventListener('resize', onScroll); onScroll(); if (!rm){ /* the jam breathes; nothing else does */ var pulse = document.getElementById('pulse'), t0 = null; requestAnimationFrame(function breathe(t){ if (t0 === null) t0 = t; pulse.style.opacity = 0.18 + 0.2 * (0.5 + 0.5 * Math.sin((t - t0) / 520)); requestAnimationFrame(breathe); }); } })();