);
}
// Responsive grid of public content sites. Card stats follow the active metric
// and the grid sorts by that metric's "this month" count. In the By-site
// breakdown the cards double as the chart legend (colored swatch + Show/Hide
// toggle that filters the matching band); colors key on each site's place in
// the unsorted `sites` list so they stay aligned with the chart — its chart
// colour (siteChartColors: its accent's hue family in the validated palette,
// else seriesColor at its index), the one homepageChartData gives its series.
export function SiteGrid({
sites,
metric,
breakdown,
hidden,
onToggle,
}: {
sites: HomepageSummarySite[];
metric: Metric;
breakdown: Breakdown;
hidden: ReadonlySet;
onToggle: (siteId: string) => void;
}) {
if (sites.length === 0) return null;
const bySite = breakdown === "site";
const chart = siteChartColors(sites);
const colorOf = new Map(sites.map((s, i) => [s.siteId, chart[i]]));
const ordered = [...sites].sort(
(a, b) =>
b[metric].thisMonth - a[metric].thisMonth ||
b[metric].total - a[metric].total ||
a.siteTitle.localeCompare(b.siteTitle),
);
const maxThisMonth = Math.max(0, ...sites.map((s) => s[metric].thisMonth));
const leaderId =
maxThisMonth > 0
? ordered.find((s) => s[metric].thisMonth === maxThisMonth)?.siteId
: undefined;
return (