// Furnishfy — main app: router, tweaks const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ "direction": "sapphire", "gold": window.FURN?.PRIMARY_COLOR || "#fd6221", "secondary": window.FURN?.SECONDARY_COLOR || "#2c2c2c", "radius": 4, "displayFont": "Cormorant Garamond" }/*EDITMODE-END*/; // ---------- Search overlay ---------- function SearchOverlay({ open, onClose, go }) { const [q, setQ] = useState(""); const { PRODUCTS } = window.FURN; const inputRef = useRef(null); useEffect(() => { if (open) { setQ(""); setTimeout(() => inputRef.current?.focus(), 80); } }, [open]); const res = q.trim() ? PRODUCTS.filter((p) => (p.en + p.material.en).toLowerCase().includes(q.toLowerCase())).slice(0, 5) : []; return (
setQ(e.target.value)} placeholder="Search the collection..." style={{ flex: 1, background: "none", border: "none", outline: "none", color: "var(--ink)", fontFamily: "var(--font-display)", fontSize: "clamp(24px,4vw,38px)" }} />
{res.map((p) => { const hasImg = p.thumbnail && !p.thumbnail.includes('no-product'); return (
{ onClose(); go("product", p.id); }} style={{ display: "flex", alignItems: "center", gap: 18, padding: "16px 4px", borderBottom: "1px solid var(--line)", cursor: "pointer" }} className="searchres"> {hasImg ? ( {p.en} ) : ( )}
{p.en}
{p.material.en}
{money(p.price)}
); })} {q.trim() && res.length === 0 &&

No results found.

}
); } // ---------- Story page ---------- function Story({ go }) { useReveal(); return (
The Atelier

We build as if time stands still.

Since 1988, we have gathered the finest makers around a single bench — choosing timber by hand and refusing anything disposable.

{[["Hand-selected", "We travel to the mills ourselves and reject 9 of every 10 boards."], ["Slow-finished", "Each surface is oiled and rubbed over twelve patient days."], ["Built to repair", "Joinery is designed to be opened, mended, and passed on."]].map((b, i) => (
{b[0]}

{b[1]}

))}
); } function var_radius3() { return getComputedStyle(document.documentElement).getPropertyValue("--radius") || "4px"; } const { BrowserRouter, Routes, Route, useNavigate, useParams, useSearchParams, useLocation } = window.ReactRouterDOM; function ShopWrapper({ go, lang }) { const [searchParams] = useSearchParams(); const cat = searchParams.get("cat") || null; return ; } function ProductWrapper({ go, lang }) { const { productId } = useParams(); return ; } // ---------- AppContent ---------- function AppContent() { const [t, setTweak] = useTweaks(TWEAK_DEFAULTS); const [searchOpen, setSearchOpen] = useState(false); const [lang, setLang] = useState("en"); const navigate = useNavigate(); const location = useLocation(); // apply tweaks → root useEffect(() => { const r = document.documentElement; r.setAttribute("data-theme", t.direction); r.style.setProperty("--gold", t.gold); r.style.setProperty("--secondary", t.secondary || "#2c2c2c"); r.style.setProperty("--radius", t.radius + "px"); r.style.setProperty("--font-display", `"${t.displayFont}", Georgia, serif`); }, [t]); const go = useCallback((p, id = null, cat = null) => { if (p !== "product") window.scrollTo({ top: 0, behavior: "instant" }); if (p === "home") { navigate("/"); } else if (p === "shop") { navigate(cat ? `/shop?cat=${cat}` : "/shop"); } else if (p === "rooms") { navigate(cat ? `/rooms?cat=${cat}` : "/rooms"); } else if (p === "product") { navigate(`/product/${id}`); } else { navigate(`/${p}`); } }, [navigate]); // Active page determination for header active state highlighting let activePage = "home"; const path = location.pathname; if (path.startsWith("/shop")) activePage = "shop"; else if (path.startsWith("/rooms")) activePage = "rooms"; else if (path.startsWith("/product")) activePage = "product"; else if (path.startsWith("/story")) activePage = "story"; else if (path.startsWith("/contact")) activePage = "contact"; return ( <>
setSearchOpen(true)} lang={lang} /> } /> } /> } /> } /> } /> } />