// Main app const { useState, useEffect, useRef } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accentHue": 195, "density": "comfortable", "showTypewriter": true, "noise": true }/*EDITMODE-END*/; function HueSwatches({ value, onChange }) { const hues = [ { v: 195, label: "cyan" }, { v: 168, label: "teal" }, { v: 145, label: "green" }, { v: 32, label: "amber" }, { v: 12, label: "ember" }, { v: 320, label: "magenta" }, { v: 285, label: "violet" }, { v: 220, label: "blue" }, ]; return (
{hues.map((h) => { const active = value === h.v; return ( ); })}
); } function App() { const t = window.useTweaks ? window.useTweaks(TWEAK_DEFAULTS) : { values: TWEAK_DEFAULTS, setTweak: () => {} }; const tweaks = t.values; const setTweak = t.setTweak; const [bootState, setBootState] = useState("booting"); // booting → settling → ready const [openProjectId, setOpenProjectId] = useState(null); const { PROJECTS, SKILLS, CERTIFICATIONS, TIMELINE } = window.PORTFOLIO_DATA; const { GridBackground, Nav, Hero, ProjectModal, WorkSection, AboutSection, StackSection, ContactSection, TechMarquee } = window.PortfolioParts; // CSS var sync for accent hue useEffect(() => { document.documentElement.style.setProperty("--accent-hue", tweaks.accentHue); }, [tweaks.accentHue]); // Scroll reveal useEffect(() => { const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add("reveal--in"); io.unobserve(e.target); } }); }, { threshold: 0.12, rootMargin: "0px 0px -60px 0px" }); document.querySelectorAll(".reveal").forEach((el) => io.observe(el)); return () => io.disconnect(); }, []); // body class for boot-aware hero entrance useEffect(() => { document.body.dataset.boot = bootState; return () => { delete document.body.dataset.boot; }; }, [bootState]); const openProject = PROJECTS.find((p) => p.id === openProjectId); const onNavigate = (id) => { if (window.scrollToId) window.scrollToId(id); }; return ( {bootState !== "ready" && window.LoadingScreen && ( setBootState("settling")} onDone={() => setBootState("ready")} /> )}