// site/calendar.jsx — interactive ATP 2026 calendar function Calendar() { const [filter, setFilter] = React.useState("all"); const [today] = React.useState(new Date(2026, 4, 20)); // simulate Roma live const filtered = React.useMemo(() => { if (!window.TOURNAMENTS_2026) return []; if (filter === "all") return window.TOURNAMENTS_2026; if (filter === "GS") return window.TOURNAMENTS_2026.filter(t => t.cat === "GS" || t.cat === "FINALS"); return window.TOURNAMENTS_2026.filter(t => t.surface === filter); }, [filter]); const filters = [ { id: "all", label: "All" }, { id: "GS", label: "Grand Slams" }, { id: "clay", label: "Clay" }, { id: "grass", label: "Grass" }, { id: "hard", label: "Hard" }, { id: "indoor", label: "Indoor" }, ]; const trackRef = React.useRef(null); React.useEffect(() => { if (!trackRef.current) return; const liveCard = trackRef.current.querySelector('.cal-card.live'); if (liveCard) { const rect = liveCard.getBoundingClientRect(); const trackRect = trackRef.current.getBoundingClientRect(); trackRef.current.scrollLeft = liveCard.offsetLeft - trackRect.width / 2 + rect.width / 2; } }, [filter]); return (
02 ATP 2026 — Live

Fourteen
tournaments.
One scroll.

The full 2026 ATP main-draw calendar — Grand Slams, Masters 1000s, the Finals. Filter by surface, scroll horizontally, tap any card.

{filters.map(f => ( ))}
{filtered.map(t => { const status = window.tournamentStatus(t, today); return (
{t.cat === "GS" ? "GRAND SLAM" : t.cat === "FINALS" ? "ATP FINALS" : "MASTERS 1000"}
{t.short}
{t.city} · {t.country}
{window.fmtDateRange(t)}
{status === "live" ? "● LIVE" : status === "upcoming" ? "Upcoming" : t.winner ? `🏆 ${t.winner.split(" ").pop()}` : "Past"}
); })}
); } Object.assign(window, { Calendar });