// Little Bloom Photo Studio — App shell + routing + tweaks const { useState: useStateApp, useEffect: useEffectApp } = React; // Tweak defaults — host can rewrite the JSON between markers const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "accent": "#b29b7b", "bg": "#fbf7ec", "bgAlt": "#efe8d8", "ink": "#3a2e25", "headingFont": "Cormorant Garamond", "scriptFont": "Pinyon Script", "bodyFont": "Jost" }/*EDITMODE-END*/; function App() { const [page, setPage] = useStateApp('home'); const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); // Apply tweaks to CSS variables useEffectApp(() => { const r = document.documentElement.style; r.setProperty('--lb-tan', t.accent); r.setProperty('--lb-bg', t.bg); r.setProperty('--lb-cream-3', t.bg); r.setProperty('--lb-cream', t.bgAlt); r.setProperty('--lb-brown-dark', t.ink); r.setProperty('--lb-display', `"${t.headingFont}", Georgia, serif`); r.setProperty('--lb-script', `"${t.scriptFont}", cursive`); r.setProperty('--lb-body', `"${t.bodyFont}", system-ui, sans-serif`); }, [t]); // Inject fonts dynamically when tweaked useEffectApp(() => { const id = 'lb-tweaked-fonts'; let link = document.getElementById(id); if (!link) { link = document.createElement('link'); link.id = id; link.rel = 'stylesheet'; document.head.appendChild(link); } const families = [ `${t.headingFont}:ital,wght@0,300;0,400;0,500;1,300;1,400`, `${t.scriptFont}`, `${t.bodyFont}:wght@300;400;500;600`, ].map(f => `family=${encodeURIComponent(f).replace(/%2C/g, ',').replace(/%40/g, '@').replace(/%3B/g, ';').replace(/%3A/g, ':')}`).join('&'); link.href = `https://fonts.googleapis.com/css2?${families}&display=swap`; }, [t.headingFont, t.scriptFont, t.bodyFont]); // Scroll to top on route change useEffectApp(() => { window.scrollTo({ top: 0, behavior: 'instant' }); }, [page]); // Determine nav color (dark over hero images of certain pages) return (
); } /* ========== Tweaks panel ========== */ function LittleBloomTweaks({ t, setTweak }) { return ( setTweak('accent', v)} options={['#b29b7b', '#4b503e', '#a8896a', '#7a8163', '#c2a989']} /> setTweak('bg', v)} options={['#fbf7ec', '#f5f0e3', '#efe8d8', '#f7f2e6', '#fffaf0']} /> setTweak('bgAlt', v)} options={['#efe8d8', '#e8e0cc', '#f0ead8', '#e6dcc6']} /> setTweak('ink', v)} options={['#3a2e25', '#2a241e', '#4b503e', '#2f3328', '#5c4a3c']} /> setTweak('headingFont', v)} options={['Cormorant Garamond', 'Cormorant', 'Italiana', 'Tenor Sans', 'Bodoni Moda', 'DM Serif Display', 'Marcellus']} /> setTweak('scriptFont', v)} options={['Pinyon Script', 'Allura', 'Dancing Script', 'Sacramento', 'Petit Formal Script', 'Parisienne']} /> setTweak('bodyFont', v)} options={['Jost', 'Manrope', 'DM Sans', 'Outfit', 'Nunito Sans', 'Work Sans']} /> ); } ReactDOM.createRoot(document.getElementById('root')).render();