diff --git a/apps/hq-web/src/pages/Dashboard.tsx b/apps/hq-web/src/pages/Dashboard.tsx
index e39fbf9..d741859 100644
--- a/apps/hq-web/src/pages/Dashboard.tsx
+++ b/apps/hq-web/src/pages/Dashboard.tsx
@@ -70,13 +70,27 @@ export function Dashboard() {
- {/* SMS low-balance alert (D28) — surfaced here so it's seen without opening the SMS screen. */}
- {smsLow.data !== undefined && smsLow.data.lowCount > 0 && (
+ {/* SMS low-balance alert (D28) — surfaced here so it's seen without opening the SMS
+ screen. Three states, never collapsed into one: while the check is in flight a
+ skeleton stands in; a FAILED check says so with a retry (rendering nothing there
+ would read as "no client is low" — the dangerous direction); and only a loaded,
+ genuinely-empty result gets the positive line. `unknownCount` is spelled out in
+ that line because balances the gateway couldn't return aren't "fine" either. */}
+ {smsLow.error !== undefined ? (
+
+ SMS balances checked — none low + {smsLow.data.unknownCount > 0 ? ` (${smsLow.data.unknownCount} could not be read)` : ''}. +
)} {/* KPIs — the app's existing stat cards (kept minimal; red only when a send failed). */} @@ -146,11 +160,14 @@ export function Dashboard() {