v3: P2 prompt pack (scenes 00, II-V) + pilot bench - regime detect, HUD, hand scrub
This commit is contained in:
+59
-23
@@ -96,6 +96,12 @@ body{margin:0;background:var(--void);color:var(--ink);font-family:var(--sans);
|
||||
.masthead{padding:10vh 22px 6vh}
|
||||
}
|
||||
|
||||
/* ---- pilot bench (HUD + hand scrub) - strip before P3 wiring ---- */
|
||||
.bench{width:min(720px,100%);margin:18px auto 0;text-align:center}
|
||||
.bench input{width:100%;accent-color:var(--cyan)}
|
||||
.bench .hud{font-family:var(--mono);font-size:.68rem;letter-spacing:.06em;
|
||||
color:var(--dim);margin:.5rem 0 0}
|
||||
|
||||
/* ---- no JS: the flat hero and the full legend are the page ---- */
|
||||
body:not(.fx) .slab{display:none}
|
||||
body:not(.fx) .legend li{position:static;transform:none;opacity:1}
|
||||
@@ -157,37 +163,67 @@ body:not(.fx) .legend{height:auto;min-height:0;display:flex;flex-direction:colum
|
||||
setLit(t);
|
||||
};
|
||||
|
||||
const mm = gsap.matchMedia();
|
||||
// ---- pilot bench: HUD + hand scrub - strip before P3 wiring ----
|
||||
const bench = document.createElement("div");
|
||||
bench.className = "bench";
|
||||
bench.innerHTML =
|
||||
'<input type="range" min="0" max="1000" value="0" aria-label="scrub the teardown">' +
|
||||
'<p class="hud">boot</p>';
|
||||
document.querySelector(".pin").appendChild(bench);
|
||||
const hud = bench.querySelector(".hud");
|
||||
const slider = bench.querySelector("input");
|
||||
let mode = "boot";
|
||||
const show = v => {
|
||||
hud.textContent = mode + " \u00b7 " + innerWidth + "x" + innerHeight +
|
||||
" \u00b7 scroll " + Math.round(scrollY) + " of " +
|
||||
Math.max(0, document.documentElement.scrollHeight - innerHeight) +
|
||||
" \u00b7 t=" + v.toFixed(2);
|
||||
slider.value = String(Math.round(v * 1000));
|
||||
};
|
||||
const drive = v => { apply(v); show(v); };
|
||||
slider.addEventListener("input", () => drive(+slider.value / 1000));
|
||||
|
||||
mm.add("(min-width: 861px) and (prefers-reduced-motion: no-preference)", () => {
|
||||
const st = ScrollTrigger.create({
|
||||
// The artifact viewer can size the iframe to the content and scroll the PARENT page:
|
||||
// then this window never scrolls and a pinned scrub can never fire. Pick the engine
|
||||
// by what the environment can actually do, not by viewport width alone.
|
||||
const initPin = () => {
|
||||
mode = "pin+scrub";
|
||||
ScrollTrigger.create({
|
||||
trigger: "#course-1",
|
||||
start: "top top",
|
||||
end: "+=2200",
|
||||
pin: ".pin",
|
||||
scrub: 0.6,
|
||||
onUpdate: self => apply(self.progress),
|
||||
onUpdate: self => drive(self.progress),
|
||||
onRefreshInit: () => apply(0)
|
||||
});
|
||||
apply(0);
|
||||
return () => { st.kill(); apply(1); };
|
||||
});
|
||||
ScrollTrigger.refresh();
|
||||
drive(0);
|
||||
};
|
||||
|
||||
// Small screens and reduced-motion: no pin, no scrub. The scene assembles once on
|
||||
// entry so the teardown still *reads*, then stays put.
|
||||
mm.add("(max-width: 860px), (prefers-reduced-motion: reduce)", () => {
|
||||
if (RM) { apply(1); return () => {}; }
|
||||
apply(0);
|
||||
const st = ScrollTrigger.create({
|
||||
trigger: "#course-1",
|
||||
start: "top 70%",
|
||||
once: true,
|
||||
onEnter: () => gsap.to({ v: 0 }, {
|
||||
v: 1, duration: 1.5, ease: "power3.out",
|
||||
onUpdate: function () { apply(this.targets()[0].v); }
|
||||
})
|
||||
});
|
||||
return () => { st.kill(); apply(1); };
|
||||
});
|
||||
const initAssemble = () => {
|
||||
mode = "assemble";
|
||||
document.querySelector(".pin").style.minHeight = "0"; // svh is degenerate when the frame is content-sized
|
||||
drive(0);
|
||||
const io = new IntersectionObserver(es => {
|
||||
if (!es.some(e => e.isIntersecting)) return;
|
||||
io.disconnect();
|
||||
gsap.to({ v: 0 }, {
|
||||
v: 1, duration: 1.6, ease: "power3.out",
|
||||
onUpdate: function () { drive(this.targets()[0].v); }
|
||||
});
|
||||
}, { threshold: 0.15 });
|
||||
io.observe(scene);
|
||||
};
|
||||
|
||||
const boot = () => {
|
||||
if (RM) { mode = "reduced-motion"; drive(1); return; }
|
||||
const scrollable = document.documentElement.scrollHeight - innerHeight > 120;
|
||||
if (scrollable && matchMedia("(min-width: 861px)").matches) initPin();
|
||||
else initAssemble();
|
||||
};
|
||||
const flat = scene.querySelector(".flat");
|
||||
(flat.decode ? flat.decode().catch(() => {}) : Promise.resolve())
|
||||
.then(() => requestAnimationFrame(() => requestAnimationFrame(boot)));
|
||||
})();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user