Indexer offline: frontend has no user-visible signal when :3100 is unreachable, silently spams 100+ failed requests
## Summary
When the YO indexer (`:3100`) becomes unreachable mid-session, the frontend silently spams hundreds of `net::ERR_CONNECTION_REFUSED` requests with **no user-visible indication** that indexer-derived data is stale or offline. The "Indexer v1.8.0 · latest indexed block N · live" status banner that normally appears at the bottom of every route is simply gone — there is no "Indexer offline" badge, no "Reconnecting..." copy, and no stale-data warning.
## Repro
1. Stack `282eb62` up (SKIP+KUMBAYA+NO_COOLDOWN), Vite on 5173, sale live, MetaMask on Chain 31337
2. Confirm `/timecurve` is healthy: timer ticking, indexer status banner visible at bottom showing "Indexer v1.8.0 · latest indexed block N · live"
3. Drop the SSH tunnel forwarding for `3100 → 3100` (kill the indexer port forward only, leave 8545 + 5173 alone)
4. Wait ~5 seconds for the next indexer poll cycle
5. Open DevTools console
## Observed
- **Console:** 155+ errors in ~10 seconds, all `net::ERR_CONNECTION_REFUSED` on URLs like:
- `http://127.0.0.1:3100/v1/timecurve/chain-timer`
- `http://127.0.0.1:3100/v1/timecurve/buys?limit=3&offset=0`
- Repeating aggressively, no apparent backoff
- **Page UI:** No visible change. The indexer status banner that normally reads "Indexer v1.8.0 · latest indexed block N · live" is just absent — no "offline" replacement, no error state, no stale badge.
- **Recent Buys panel:** Shows "Waiting for the first buy of this round" — identical to the empty state when there genuinely are zero buys. Indistinguishable from "indexer offline + couldn't fetch buy list".
- **RPC-derived reads still work:** Timer ticks, current price reads, live band reads, wallet balance, charmWeight reads, BUY CHARM button stays clickable. Anything that goes through the chain RPC at 8545 is fine.
## Why this matters
Indexer-derived data is mainly:
- Recent Buys feed (Live ticker)
- Indexer mirror panel for fee distributions (Canonical fee sinks "Recent fee distributions" rows)
- Latest indexed block status banner
- Battle Feed on Arena page (likely)
- Podium / leaderboard data on Arena page (likely)
A user with degraded indexer connectivity:
- Sees "Waiting for the first buy" and may assume they're early when there are actually 100+ buys (just can't fetch them)
- Sees no Recent fee distributions and may assume the protocol isn't routing fees yet
- Has no signal to refresh, switch RPC, restart wallet, etc. — just silent emptiness
At TGE this becomes a real risk:
- A user mistakenly thinks no one's buying yet and waits — meanwhile the band is moving against them
- Or assumes the protocol broke and FUDs in TG / discord
Plus the 155+ console errors in seconds is itself concerning — aggressive polling without circuit-breaker / exponential backoff hammers the indexer once it comes back up too.
## Suggested resolution options
**Option A — explicit "Indexer offline" banner.** When indexer fetches fail N times in a row (e.g., 3 consecutive), replace the "Indexer v1.8.0 · live" status text with "Indexer offline · retrying" in red/orange. Surface in the same footer location it currently uses.
**Option B — stale-data badges on indexer-derived panels.** "Recent Buys" panel shows a "Last updated Xs ago · cannot reach indexer" subtitle when fetches start failing. Same for Battle Feed, Recent fee distributions.
**Option C — exponential backoff + circuit breaker.** After N consecutive failures, throttle from "every block" to "every 30s, then 60s, then 120s" with auto-recovery on first success. Reduces console spam + indexer DDoS-on-recovery.
**Option D — distinguish empty state from offline state in copy.** "Waiting for the first buy of this round" should only show when indexer is live AND has zero rows. When indexer is offline or fetches are failing, show "Cannot reach indexer · cached data may be stale" instead.
A + C + D together is the strongest fix. Single-issue scope, but fix probably touches the indexer client / hooks layer.
## Severity
**MEDIUM.** Not a launch-blocker (RPC-derived buys still work), but is a real user-trust gap that becomes more painful at TGE. Console pollution + unclear empty states + no offline signal stack together.
## Reference
Caught during F-14 walkthrough on `/timecurve` Simple. Reproducible deterministically by killing port 3100 routing.
cc @PlasticDigits
issue