// Fixed, very faint wash of the title stills behind the page. Which still shows follows the section in view; // its opacity eases from 10% (section just entering) to 20% (section centred). function Backdrop() { const D = window.JW_DATA; const stills = [D.hero.src].concat(D.projects.map((p) => p.image)); const [state, setState] = React.useState({ i: 0, t: 0 }); React.useEffect(() => { let raf = 0; const tick = () => { raf = 0; const secs = Array.from(document.querySelectorAll("main > section")); if (!secs.length) return; const mid = window.innerHeight / 2; let best = 0, bestD = Infinity; secs.forEach((s, k) => { const r = s.getBoundingClientRect(); const d = Math.abs(r.top + r.height / 2 - mid); if (r.top < mid && r.bottom > mid) { best = k; bestD = 0; } else if (d < bestD) { best = k; bestD = d; } }); const r = secs[best].getBoundingClientRect(); const t = Math.max(0, 1 - Math.abs(r.top + r.height / 2 - mid) / (r.height / 2 + mid)); setState({ i: best % stills.length, t }); }; const onScroll = () => { if (!raf) raf = requestAnimationFrame(tick); }; tick(); window.addEventListener("scroll", onScroll, { passive: true }); window.addEventListener("resize", onScroll); return () => { window.removeEventListener("scroll", onScroll); window.removeEventListener("resize", onScroll); }; }, []); const op = 0.10 + 0.10 * state.t; return (