Fix app becoming unresponsive when two browser windows are open: the
root cause was HTTP/1.1 connection pool exhaustion (6-connection limit
per origin). VoiceAlerts was opening 3 SSE streams per window by
default, so two windows produced 8 connections and permanently starved
all regular HTTP requests.
- voice-alerts.js: default all streams to false (opt-in) to stay within
the browser connection limit; existing user preferences in localStorage
are preserved
- routes/alerts.py: replace direct AlertManager.stream_events() with
sse_stream_fanout so both windows receive every alert instead of
competing for the same queue
- routes/bluetooth_v2.py: same fanout fix via subscribe_fanout_queue,
preserving named SSE events (device_update, scan_started, etc.)
Also includes accumulated UI/theming changes: accent-cyan CSS variable
sweep across mode CSS/JS files, standalone dashboard pages, template
updates, satellite TLE data refresh, and tile provider default rename.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
All files used hardcoded rgba(74, 163/158, 255, X) values in actual CSS
rules that CSS variable overrides couldn't touch. Solution: add
--accent-cyan-rgb triplet to variables.css root/light/enhanced blocks,
then replace every rgba(74,1xx,255,) occurrence across all CSS files
with rgba(var(--accent-cyan-rgb),). Enhanced tier sets the triplet to
200, 150, 40 (amber), so tscm.css panel bg, index.css card borders,
and all other tinted surfaces go amber automatically.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove backdrop-filter: blur(5px) from .card and .panel — on ARM/Linux
Chromium this is software-rendered, causing severe CPU overhead at 42+
instances. The opaque surface gradient makes blur imperceptible anyway.
- Remove inset vignette box-shadow from .panel added in 51c1014
- Rewrite panel-pulse keyframes to animate opacity only (was box-shadow,
which triggers CPU repaint every frame; opacity is compositor-only)
- Gate body::before and .visuals-container::after scanline pseudo-elements
under [data-animations="off"] — the toggle was blind to both
- Gate panel-indicator pulse under [data-animations="off"] for consistency
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ensureModeScript() used document.body.appendChild() to load lazy mode
scripts, but the preload for ?mode= query params runs in <head> before
<body> exists, causing all deep-linked modes to silently fail.
Also fix cross-mode handoffs (BT→BT Locate, WiFi→WiFi Locate,
Spy Stations→Waterfall) that assumed target module was already loaded.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add theme-aware severity/neon CSS variables and replace hardcoded hex
colors (#fff, #000, #00ff88, #ffcc00, etc.) with var() references
across 26 files so text remains readable in both dark and light themes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>