/* global React, ReactDOM, Icons, Landing, Gallery, Builder, CoverScreen, SAMPLE_RESUME, getProfile, makeCoverDoc, COVER_TEMPLATES, LegalPage, ContactPage, useTweaks, TweaksPanel, TweakSection, TweakColor, TweakRadio, TweakToggle, TweakSelect, Pro, useProState, UpgradeGate */ // ============================================================ // App — routing, nav, tweaks // ============================================================ const { useState, useEffect } = React; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "appAccent": ["#e6e600", "#7deb00"], "editorLayout": "split", "displayFont": "Poppins", "skillScale": "template", "roundedChrome": true }/*EDITMODE-END*/; const ACCENTS = [ ["#e6e600", "#7deb00"], // yellow → lime (default) ["#3dd7c6", "#5b8cff"], // teal → blue ["#ff8a4c", "#ffd24c"], // amber ["#ff5c8a", "#b06bff"], // rose → violet ["#8be24c", "#3dd7c6"], // lime → teal ]; const deepCopy = (o) => JSON.parse(JSON.stringify(o)); function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const { isPro } = useProState(); const [screen, setScreen] = useState("landing"); const [galMode, setGalMode] = useState("resumes"); // gallery: resumes | covers const [profileId, setProfileId] = useState("design"); const [menuOpen, setMenuOpen] = useState(false); const [templateId, setTemplateId] = useState("spectrum"); const [accent, setAccent] = useState({ custom: false }); const [resume, setResume] = useState(() => { try { const s = localStorage.getItem("rb_resume"); if (s) return JSON.parse(s); } catch (e) {} return SAMPLE_RESUME; }); // cover-letter state const [coverTemplateId, setCoverTemplateId] = useState("cl-spectrum"); const [coverAccent, setCoverAccent] = useState({ custom: false }); const [coverDoc, setCoverDoc] = useState(() => { try { const s = localStorage.getItem("rb_cover"); if (s) return JSON.parse(s); } catch (e) {} return makeCoverDoc("design"); }); // persist useEffect(() => { try { localStorage.setItem("rb_resume", JSON.stringify(resume)); } catch (e) {} }, [resume]); useEffect(() => { try { localStorage.setItem("rb_cover", JSON.stringify(coverDoc)); } catch (e) {} }, [coverDoc]); // apply app accent + font tweaks to :root useEffect(() => { const r = document.documentElement; const [a, b] = t.appAccent || ACCENTS[0]; r.style.setProperty("--acc", a); r.style.setProperty("--acc-2", b); r.style.setProperty("--font-display", `"${t.displayFont}", system-ui, sans-serif`); }, [t.appAccent, t.displayFont]); const go = (s) => { setScreen(s); setMenuOpen(false); window.scrollTo(0, 0); }; // allow any component (e.g. the upgrade modal) to navigate to a screen useEffect(() => { const h = (e) => { const s = e.detail && e.detail.screen; if (s) { setScreen(s); setMenuOpen(false); window.scrollTo(0, 0); } }; window.addEventListener("rb-goto", h); return () => window.removeEventListener("rb-goto", h); }, []); const goTemplates = () => { setProfileId("all"); setGalMode("resumes"); go("gallery"); }; const goCovers = () => { setGalMode("covers"); go("gallery"); }; // pick a résumé design → load that profile's data + layout into the builder, // and prime a matching cover letter for the dedicated Cover letters page const pickResume = (pid, tid) => { const p = getProfile(pid); setProfileId(pid); setTemplateId(tid); setResume(deepCopy(p.data)); setAccent({ custom: false }); setCoverDoc(makeCoverDoc(pid)); setCoverTemplateId("cl-" + tid); // pair the cover that matches this résumé design setCoverAccent({ custom: false }); go("builder"); }; // pick a cover-letter design → draft for that profile + open the editor const pickCover = (pid, ctid) => { setProfileId(pid); setCoverTemplateId(ctid); setCoverDoc(makeCoverDoc(pid)); setCoverAccent({ custom: false }); go("cover"); }; const inGallery = screen === "gallery"; return (