// Shared UI primitives const { useState, useEffect, useRef, useMemo, useCallback } = React; function useMobile(bp = 768) { const [m, setM] = useState(() => window.innerWidth < bp); useEffect(() => { const fn = () => setM(window.innerWidth < bp); window.addEventListener("resize", fn, { passive: true }); return () => window.removeEventListener("resize", fn); }, [bp]); return m; } window.useMobile = useMobile; function Placeholder({ label, src, className = "", style = {}, children }) { if (src) { return (
{label { e.currentTarget.parentElement.className += " ph"; e.currentTarget.remove(); }} style={{ width: "100%", height: "100%", objectFit: "cover", display: "block" }} /> {label && (
{label}
)} {children}
); } return (
{children}
); } function Eyebrow({ children, style = {} }) { return
{children}
; } function IconStar({ filled }) { return ( ); } function IconSearch() { return ( ); } function IconSun() { return ( ); } function IconMoon() { return ( ); } function IconArrow({ rotate = 0 }) { return ( ); } function IconChevron({ rotate = 0 }) { return ( ); } function IconClose() { return ( ); } function IconHeart({ filled }) { return ( ); } function FavoriteButton({ id }) { const [fav, setFav] = useState(() => { try { const list = JSON.parse(localStorage.getItem("cal:favs") || "[]"); return list.includes(id); } catch { return false; } }); const toggle = (e) => { e.preventDefault(); e.stopPropagation(); setFav(v => { const next = !v; try { const list = JSON.parse(localStorage.getItem("cal:favs") || "[]"); const upd = next ? [...new Set([...list, id])] : list.filter(x => x !== id); localStorage.setItem("cal:favs", JSON.stringify(upd)); window.dispatchEvent(new CustomEvent("favsChanged", { detail: upd })); } catch {} window.showToast && window.showToast(next ? "Aggiunto ai preferiti" : "Rimosso dai preferiti"); return next; }); }; return ( ); } function SectionHeader({ kicker, title, link, linkLabel = "Vedi tutti" }) { return (
{kicker}

{title}

{link && ( {linkLabel} )}
); } function showToast(msg) { const t = document.getElementById("toast"); if (!t) return; t.textContent = msg; t.classList.add("on"); clearTimeout(window.__toastTO); window.__toastTO = setTimeout(() => t.classList.remove("on"), 1800); } window.showToast = showToast; Object.assign(window, { Placeholder, Eyebrow, SectionHeader, FavoriteButton, IconStar, IconSearch, IconSun, IconMoon, IconArrow, IconChevron, IconClose, IconHeart });