Files
exploded-cluster/pilot/mirror.js
T
jwright 08e80d9f9f site: directory landing + The Mirror (chapter 02)
The face of learn.bztmon.com is now a chapter index: 01 The Exploded Cluster
(moved to /cluster) and 02 The Mirror (/mirror), with a forming-chapter ghost
slot. The Mirror ships rev 3 of the dossier - six curated plates fingerprinted
under /assets/, its scroll engine as an external fingerprinted script (CSP
script-src self holds), diagrams as inline SVG, replay panes from real
receipts. Assembler grows a shared document shell + per-page preflight gates;
build.sh inline-script check now covers every page.
2026-08-24 21:28:09 +10:00

40 lines
1.8 KiB
JavaScript

(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);
});
}
})();