// app.jsx — Montroi root: hash router, cart state, tweaks const { useState: uS, useEffect: uE, useMemo: uM, useCallback: uC } = React; const { Navbar, Footer, CartDrawer, CTA } = window.MONTROI_COMP; const { PageHome } = window.MONTROI_PAGES_HOME; const { PageStory, PageProvenance, PageShop, PageProduct, PageWorkshops, PageGifting, PageBoutiques, PageContact, PageJournal, } = window.MONTROI_PAGES_OTHER; const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "palette": ["#F8F2E8", "#7B4B37", "#6E6A4A", "#B0903F"], "typePair": "Cormorant + Inter", "hero": "editorial", "locale": "EN", "density": "regular" }/*EDITMODE-END*/; const PALETTES = [ // [bg, primary, secondary, accent] — keep order ["#F8F2E8", "#7B4B37", "#6E6A4A", "#B0903F"], // Sand · terracotta · olive · brass (default) ["#EFE7D7", "#5D3A2A", "#3D4A33", "#A78A3C"], // Marrakech — deeper warm ["#F4EFE3", "#2A2620", "#7A6A52", "#9C7A3E"], // Ink & travertine (mono+brass) ["#EAE2D2", "#1F4E55", "#6E6A4A", "#A48B47"], // Oasis teal (focus-led) ]; const TYPE_PAIRS = { "Cormorant + Inter": { display: '"Cormorant Garamond", "Spectral", Georgia, serif', body: '"Inter", system-ui, sans-serif' }, "Spectral + Inter": { display: '"Spectral", "Cormorant Garamond", Georgia, serif', body: '"Inter", system-ui, sans-serif' }, "Cormorant + Manrope": { display: '"Cormorant Garamond", Georgia, serif', body: '"Manrope", system-ui, sans-serif' }, }; // ── Hash router ──────────────────────────────────────────────────── function useRoute() { const [hash, setHash] = uS(() => window.location.hash || "#/"); uE(() => { const onHash = () => setHash(window.location.hash || "#/"); window.addEventListener("hashchange", onHash); return () => window.removeEventListener("hashchange", onHash); }, []); return hash.replace(/^#/, "") || "/"; } function navigate(path) { if (!path.startsWith("/")) path = "/" + path; window.location.hash = path; // Scroll to top on route change (but not when only the anchor changes within the same page) setTimeout(() => window.scrollTo({ top: 0, behavior: "instant" }), 0); } // ── Cart ─────────────────────────────────────────────────────────── function useCart() { const [items, setItems] = uS([]); const add = uC((p) => { setItems((curr) => { const found = curr.find((x) => x.handle === p.handle); if (found) return curr.map((x) => x.handle === p.handle ? { ...x, qty: x.qty + 1 } : x); return [...curr, { ...p, qty: 1 }]; }); }, []); return { items, setItems, add, count: items.reduce((s, i) => s + i.qty, 0) }; } // ── App ──────────────────────────────────────────────────────────── function App() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const route = useRoute(); const cart = useCart(); const [cartOpen, setCartOpen] = uS(false); const [locale, setLocale] = uS(t.locale || "EN"); // ── Apply palette + type to root uE(() => { const r = document.documentElement; const [bg, primary, secondary, accent] = t.palette || PALETTES[0]; r.style.setProperty("--bg", bg); r.style.setProperty("--primary", primary); r.style.setProperty("--secondary", secondary); r.style.setProperty("--accent", accent); const pair = TYPE_PAIRS[t.typePair] || TYPE_PAIRS["Cormorant + Inter"]; r.style.setProperty("--font-display", pair.display); r.style.setProperty("--font-body", pair.body); r.style.setProperty("--density", t.density === "compact" ? ".82" : t.density === "comfy" ? "1.18" : "1"); r.setAttribute("dir", locale === "AR" ? "rtl" : "ltr"); }, [t, locale]); // ── Route parsing ───────────────────────────────────────────────── const parts = route.replace(/^\/+|\/+$/g, "").split("/").filter(Boolean); let Page = null; if (parts.length === 0) Page = ; else if (parts[0] === "story") Page = ; else if (parts[0] === "provenance") Page = ; else if (parts[0] === "shop") Page = ; else if (parts[0] === "product") Page = ; else if (parts[0] === "workshops") Page = ; else if (parts[0] === "gifting") Page = ; else if (parts[0] === "boutiques") Page = ; else if (parts[0] === "contact") Page = ; else if (parts[0] === "journal") Page = ; else if (parts[0] === "one-and-only") Page = ; else if (parts[0] === "legal") Page = ; else Page = ; // Top quiet bar (announcement) const currentRoute = "/" + parts.join("/"); return (
Complimentary worldwide shipping over $200 · Now: Vol. XII — Spring/Summer dispatch · Alserkal flagship · daily 10–8
setCartOpen(true)} locale={locale} setLocale={setLocale}/>
{Page}
setCartOpen(false)} items={cart.items} setItems={cart.setItems} navigate={navigate}/> setTweak("palette", v)}/> setTweak("typePair", v)}/> setTweak("hero", v)}/> setTweak("density", v)}/> setLocale(v)}/> { const demo = window.MONTROI_DATA.PRODUCTS.slice(0, 3); demo.forEach(cart.add); setCartOpen(true); }}/> navigate("/product/mughal-jade-diffuser")}/>
); } function PageStub({ title, body, navigate }) { return (

{title}

{body}

{navigate ? navigate("/")}>Return home : null}
); } ReactDOM.createRoot(document.getElementById("root")).render();