+ {/* Header */}
+
+
+ token
+
+
+ Monthly free-token budget
+
+
+ {fmt(remaining)} remaining Β· {pct}% of {fmt(steadyRecurringTokens)}
+
+
+
+ {/* Stacked bar β pool-deduped; segments sum to steadyRecurringTokens */}
+ {barSegments.length > 0 && (
+
+
+ {barSegments.map((seg) => {
+ const width =
+ totalBarTokens > 0
+ ? ((seg.tokens / totalBarTokens) * 100).toFixed(2)
+ : "0";
+ return (
+
+ );
+ })}
+
+
+ )}
+
+ {/* First-month callout */}
+
+ Up to{" "}
+
+ {fmt(firstMonthRealisticTokens)}
+ {" "}
+ in your first month with signup credits
+
+
+ {/* ToS-restricted callout */}
+ {avoidModels.length > 0 && (
+
+
+ warning
+
+
+ {avoidModels.length} model
+ {avoidModels.length !== 1 ? "s" : ""} flagged as ToS-restricted
+
+
+ )}
+
+ {/* Per-model legend grid β filtered to non-zero entries; colors match bar */}
+
+
+ {legendModels.map((m) => {
+ const swatchColor = legendColorMap.get(m.modelId) ?? BAR_HUES[0];
+ return (
+
+
+
+ {m.displayName}
+
+
+ {m.monthlyTokens >= 1e6 ? fmt(m.monthlyTokens) : m.monthlyTokens.toLocaleString()}
+
+ {m.tos === "avoid" && (
+
+ warning
+
+ )}
+
+ );
+ })}
+
+
+
+ );
+}
+
+// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+// Fetch wrapper (client component)
+// ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
+
+export default function FreeBudgetCard() {
+ const [data, setData] = useState