diff --git a/app/main.py b/app/main.py
index 0e489c5..adb335d 100644
--- a/app/main.py
+++ b/app/main.py
@@ -391,6 +391,8 @@ PAGE_HTML = """
@@ -447,17 +449,27 @@ async function load() {
const remaining = d.remaining ?? Math.max(0, balance - spend);
const pct = balance > 0 ? Math.min(100, (spend / balance) * 100) : 0;
+ // Two buckets: monthly allowance (resets) + purchased credits (never expire).
+ const allowance = d.allowance ?? 15;
+ const credits = d.credits ?? 0;
+ const spentThisCycle = Math.min(spend, allowance);
+ const allowanceLeft = Math.max(0, allowance - spentThisCycle);
+
$('spend').textContent = fmtMoney(spend);
$('of').textContent = 'of ' + fmtMoney(balance) + ' used';
$('remaining').textContent = fmtMoney(remaining);
+ $('allowance').textContent = fmtMoney(allowanceLeft);
+ $('credits').textContent = fmtMoney(credits);
$('fill').style.width = pct + '%';
$('fill').className = 'fill' + (pct > 80 ? ' warn' : '');
- // Renewal date (when the next round of credits lands)
+ // Reset date (when the monthly allowance renews)
if (d.reset_at) {
const d2 = new Date(d.reset_at);
const opts = { year: 'numeric', month: 'long', day: 'numeric' };
- $('meta').textContent = 'Shared across chat and API · Credits renew ' + d2.toLocaleDateString(undefined, opts) + '.';
+ let meta = 'Shared across chat and API · Allowance renews ' + d2.toLocaleDateString(undefined, opts);
+ if (credits > 0) meta += ' · Credits carry over and never expire';
+ $('meta').textContent = meta + '.';
}
const tokens = d.total_tokens ?? 0;