// app.jsx — root: wires sections together + reveal-on-scroll + tweaks
const { useEffect: useEffectApp, useState: useStateApp } = React;
const PALETTES = {
purple: { primary: "#A78BFA", primarySoft: "rgba(167,139,250,0.18)" },
cyan: { primary: "#22D3EE", primarySoft: "rgba(34,211,238,0.18)" },
orange: { primary: "#FF6B35", primarySoft: "rgba(255,107,53,0.20)" },
lime: { primary: "#BEF264", primarySoft: "rgba(190,242,100,0.22)" },
pink: { primary: "#F472B6", primarySoft: "rgba(244,114,182,0.20)" }
};
function useReveal() {
useEffectApp(() => {
const els = document.querySelectorAll(".reveal:not(.in)");
const io = new IntersectionObserver((ents) => {
ents.forEach(e => {
if (e.isIntersecting) {
e.target.classList.add("in");
io.unobserve(e.target);
}
});
}, { threshold: 0.12, rootMargin: "0px 0px -40px 0px" });
els.forEach(el => io.observe(el));
return () => io.disconnect();
});
}
function App() {
const [t, setTweak] = useTweaks(window.TWEAK_DEFAULTS);
useReveal();
useEffectApp(() => {
const root = document.documentElement;
const p = PALETTES[t.palette] || PALETTES.purple;
root.style.setProperty("--primary", p.primary);
root.style.setProperty("--primary-soft", p.primarySoft);
}, [t.palette]);
useEffectApp(() => {
const noise = document.querySelector(".bg-noise");
if (noise) noise.style.display = t.showNoise ? "" : "none";
}, [t.showNoise]);
return (
<>
{
const k = Object.keys(PALETTES).find(p => PALETTES[p].primary === hex) || "purple";
setTweak("palette", k);
}} />
setTweak("showNoise", v)} />
>
);
}
ReactDOM.createRoot(document.getElementById("app")).render();