// app.jsx — entry point for Version Française Pour Elle // Hash-route between Home / Services / Contact (other routes show a stub). // Hosts Tweaks panel for live theming. const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": ["#F6F1EA","#FBF8F3","#E7D8CC","#C2A24A","#1C1A18"], "displayFont": "Cormorant Garamond", "heroLayout": "centered", "rowDensity": "airy", "goldIntensity": "balanced", "showFAB": true }/*EDITMODE-END*/; const PALETTES = { ivory: ["#F6F1EA","#FBF8F3","#E7D8CC","#C2A24A","#1C1A18"], blush: ["#F4ECE6","#FCF6F2","#E8C9BD","#C8956C","#2A201D"], noir: ["#EFEAE3","#F8F4ED","#D5C2AE","#A8884A","#16140F"], quiet: ["#F0EFEB","#FAF9F5","#D8D2C7","#A89A7F","#1F1E1B"], }; function App() { const [route, setRoute] = React.useState(() => { const fallback = window.__BYTESGLUE_SHOWCASE_ROUTE || "home"; const h = window.location.hash.replace(/^#\/?/, "") || fallback; return h || "home"; }); const [lang, setLang] = React.useState(() => { return localStorage.getItem("vfpe-lang") || "en"; }); const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); // Persist route in URL hash so refresh keeps page. React.useEffect(() => { const onHash = () => { const h = window.location.hash.replace(/^#\/?/, "") || (window.__BYTESGLUE_SHOWCASE_ROUTE || "home"); setRoute(h || "home"); }; window.addEventListener("hashchange", onHash); return () => window.removeEventListener("hashchange", onHash); }, []); React.useEffect(() => { window.location.hash = "/" + route; window.scrollTo({ top: 0, behavior: "instant" }); }, [route]); React.useEffect(() => { localStorage.setItem("vfpe-lang", lang); document.documentElement.lang = lang; }, [lang]); // Make setRoute reachable from leaf components without prop-drilling. React.useEffect(() => { window.__VFPE_setRoute = setRoute; }, []); // Apply tweaks → CSS vars on :root React.useEffect(() => { const root = document.documentElement; const [ivory, cream, blush, gold, noir] = t.palette; root.style.setProperty("--ivory", ivory); root.style.setProperty("--cream", cream); root.style.setProperty("--blush-nude", blush); root.style.setProperty("--champagne-gold", gold); root.style.setProperty("--noir", noir); // Gold intensity rewrites hairline opacity. const goldOpacity = { subtle: 0.32, balanced: 0.55, present: 0.85 }[t.goldIntensity] || 0.55; const goldFaint = { subtle: 0.10, balanced: 0.18, present: 0.30 }[t.goldIntensity] || 0.18; root.style.setProperty("--gold-hairline", hexToRgba(gold, goldOpacity)); root.style.setProperty("--gold-faint", hexToRgba(gold, goldFaint)); root.style.setProperty("--display", `"${t.displayFont}", "Playfair Display", serif`); document.body.style.paddingBottom = ""; // reset on each render so mobile bar logic is sole owner }, [t]); return ( <>