When a bulk metadata fetch hits a provider rate limit, the backend
aborts the batch and broadcasts {status: "rate_limited"} over the
fetch-progress WebSocket. The frontend switch in fetchCivitaiMetadata
never handled that status, so the completion promise never settled and
the loading overlay stayed up forever -- users had to cancel and
re-trigger, and the aborted batch silently never resumed.
- Add case 'rate_limited' to the fetch-progress switch: settle the
promise so the overlay closes, and show an aborted status line.
- Show a warning toast with updated/failed/skipped counts and a hint to
re-run Fetch from Civitai later.
- Reuse the failure-details modal with a rate-limited notice banner
listing the models skipped due to rate limiting.
Backend behavior (abort after 3 consecutive rate limits, no automatic
resume) is the deliberate #1085 design and is unchanged.
The elevated surface tokens (--bg-elevated / --surface-elevated) are
translucent, so sticky modal footers and table headers double-composited
over the modal surface and showed a visible lighter seam in light themes.
Add derived opaque tokens (--bg-elevated-solid / --surface-elevated-solid,
aliased as --lora-surface-solid) and use them for .modal-content, the
download/import modal sticky action footers, and the refresh result
table's sticky header, so the modal surface and its sticky layers always
share one opaque color across every theme and preset.
Bulk metadata refresh picked candidates purely from cache state, so the
entries the scoped scan deliberately keeps for unreachable drives were
fetched anyway — burning CivitAI rate limit on sidecar/preview writes
that cannot land.
- Filter the fetch queue by root reachability (live check via
describe_model_roots), covering both startup-offline and mid-session
drive-off; probing failures degrade to no filtering
- Report offline_skipped / offline_roots in the WS terminal payloads,
the HTTP result and the completion message
- Show a "Drive Offline" stat card in the fetch summary modal when
any model was skipped this way