The scan terminal hooks were each carrying their own fetch, SSE parsing, error normalization, previous-data handling, and market request behavior. This adds a small scanTerminalClient plus RemoteData helpers so terminal data, city detail, market scans, and AI city streams share one request boundary without introducing React Query.
Constraint: Do not add dependencies or change backend API contracts.
Rejected: Introduce React Query immediately | too broad for this release and would force larger UI state rewrites.
Rejected: Move localStorage caches in the same pass | safer to first isolate network and stream IO before cache policy migration.
Confidence: high
Scope-risk: moderate
Reversibility: clean
Tested: npm run build
Not-tested: Live SSE cancellation against production latency.