fix: resolve two-window hang and sweep UI/theming updates

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>
This commit is contained in:
James Smith
2026-05-20 22:01:10 +01:00
parent 5100f55586
commit a3f2fa7b88
48 changed files with 1524 additions and 943 deletions
+15 -12
View File
@@ -1031,7 +1031,7 @@ body {
width: 100%;
object-fit: cover;
border-radius: 6px;
border: 1px solid rgba(0, 212, 255, 0.3);
border: 1px solid rgba(var(--accent-cyan-rgb), 0.3);
}
.selected-callsign {
@@ -2227,6 +2227,10 @@ body {
color: var(--text-inverse);
}
html[data-ui-tier="enhanced"] .strip-btn.primary {
background: linear-gradient(135deg, rgba(46, 125, 138, 0.85) 0%, rgba(20, 88, 100, 0.80) 100%);
}
.strip-btn.primary:hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(var(--accent-cyan-rgb), 0.3);
@@ -2462,19 +2466,18 @@ body {
}
/* ============================================
ENHANCED TIER — amber military console
ENHANCED TIER — signals teal console
============================================ */
html[data-ui-tier="enhanced"] {
--bg-dark: #080600;
--bg-panel: #0c0a04;
--bg-card: #0e0b05;
--radar-bg: #0c0a04;
--radar-cyan: #c89628;
--border-glow: rgba(200, 150, 40, 0.25);
--border-color: rgba(200, 150, 40, 0.2);
--grid-line: rgba(200, 150, 40, 0.07);
--accent-cyan: #c89628;
--accent-green: #c89628;
--bg-dark: #000000;
--bg-panel: #020404;
--bg-card: #020404;
--radar-bg: #020404;
--radar-cyan: #2e7d8a;
--border-glow: rgba(46, 125, 138, 0.20);
--border-color: rgba(46, 125, 138, 0.18);
--grid-line: rgba(46, 125, 138, 0.07);
--accent-cyan: #2e7d8a;
}
/* ============================================