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
+136
View File
@@ -1180,3 +1180,139 @@
font-family: var(--font-mono, monospace);
font-size: 9px;
}
/* ---- Enhanced tier: replace blue palette with signals teal ---- */
html[data-ui-tier="enhanced"] .wf-container {
--wf-border: rgba(46, 125, 138, 0.22);
--wf-surface: linear-gradient(180deg, rgba(2, 6, 6, 0.97) 0%, rgba(1, 3, 3, 0.98) 100%);
background: radial-gradient(circle at 14% -18%, rgba(46, 125, 138, 0.08) 0%, rgba(46, 125, 138, 0) 38%),
radial-gradient(circle at 86% -26%, rgba(46, 125, 138, 0.05) 0%, rgba(46, 125, 138, 0) 36%),
#000202;
}
html[data-ui-tier="enhanced"] .wf-headline {
background: rgba(2, 6, 6, 0.86);
}
html[data-ui-tier="enhanced"] .wf-headline-tag {
color: rgba(70, 185, 200, 0.90);
}
html[data-ui-tier="enhanced"] .wf-rx-vfo {
border-color: rgba(46, 125, 138, 0.25);
background: linear-gradient(180deg, rgba(3, 8, 8, 0.92) 0%, rgba(1, 4, 4, 0.95) 100%);
}
html[data-ui-tier="enhanced"] .wf-rx-vfo-status {
color: rgba(65, 175, 192, 0.88);
}
html[data-ui-tier="enhanced"] .wf-rx-vfo-readout {
color: rgba(80, 190, 205, 0.92);
}
html[data-ui-tier="enhanced"] #wfRxFreqReadout {
text-shadow: 0 0 16px rgba(46, 125, 138, 0.25);
}
html[data-ui-tier="enhanced"] .wf-rx-modebank {
border-color: rgba(46, 125, 138, 0.22);
background: rgba(1, 4, 4, 0.86);
}
html[data-ui-tier="enhanced"] .wf-mode-btn {
border-color: rgba(46, 125, 138, 0.24);
background: linear-gradient(180deg, rgba(4, 8, 8, 0.95) 0%, rgba(2, 5, 5, 0.95) 100%);
color: rgba(65, 175, 192, 0.90);
}
html[data-ui-tier="enhanced"] .wf-mode-btn:hover {
border-color: rgba(46, 125, 138, 0.48);
}
html[data-ui-tier="enhanced"] .wf-mode-btn.is-active,
html[data-ui-tier="enhanced"] .wf-mode-btn.active {
border-color: rgba(46, 125, 138, 0.62);
background: linear-gradient(180deg, rgba(6, 16, 18, 0.92) 0%, rgba(4, 12, 14, 0.95) 100%);
color: rgba(100, 210, 222, 0.96);
box-shadow: 0 0 14px rgba(46, 125, 138, 0.22);
}
html[data-ui-tier="enhanced"] .wf-rx-levels,
html[data-ui-tier="enhanced"] .wf-rx-meter-wrap,
html[data-ui-tier="enhanced"] .wf-rx-actions {
border-color: rgba(46, 125, 138, 0.20);
background: rgba(1, 4, 4, 0.85);
}
html[data-ui-tier="enhanced"] .wf-monitor-select {
border-color: rgba(46, 125, 138, 0.25);
background: rgba(1, 3, 3, 0.8);
}
html[data-ui-tier="enhanced"] .wf-rx-smeter-fill {
box-shadow: 0 0 10px rgba(46, 125, 138, 0.22);
}
html[data-ui-tier="enhanced"] .wf-monitor-btn-secondary {
border-color: rgba(46, 125, 138, 0.45);
background: linear-gradient(180deg, rgba(4, 12, 14, 0.95) 0%, rgba(2, 8, 10, 0.95) 100%);
color: rgba(80, 190, 205, 0.90);
}
html[data-ui-tier="enhanced"] .wf-freq-bar {
background: rgba(2, 6, 6, 0.78);
}
html[data-ui-tier="enhanced"] .wf-spectrum-canvas-wrap {
background: radial-gradient(circle at 50% -120%, rgba(46, 125, 138, 0.06) 0%, rgba(46, 125, 138, 0) 65%);
}
html[data-ui-tier="enhanced"] .wf-band-strip {
background: linear-gradient(180deg, rgba(2, 6, 6, 0.96) 0%, rgba(1, 3, 3, 0.98) 100%);
}
html[data-ui-tier="enhanced"] .wf-band-block {
border-color: rgba(46, 125, 138, 0.42);
color: rgba(80, 190, 205, 0.92);
}
html[data-ui-tier="enhanced"] .wf-band-edge {
color: rgba(65, 175, 192, 0.88);
}
html[data-ui-tier="enhanced"] .wf-band-marker::before {
background: rgba(46, 125, 138, 0.58);
box-shadow: 0 0 5px rgba(46, 125, 138, 0.30);
}
html[data-ui-tier="enhanced"] .wf-band-marker-label {
border-color: rgba(46, 125, 138, 0.48);
background: rgba(2, 5, 5, 0.95);
color: rgba(80, 190, 205, 0.90);
}
html[data-ui-tier="enhanced"] .wf-tune-line {
background: rgba(46, 125, 138, 0.72);
}
html[data-ui-tier="enhanced"] .wf-freq-axis {
background: rgba(2, 6, 6, 0.86);
}
html[data-ui-tier="enhanced"] .wf-side .section.wf-side-hero {
background: linear-gradient(180deg, rgba(3, 8, 8, 0.95) 0%, rgba(1, 4, 4, 0.97) 100%);
border-color: rgba(46, 125, 138, 0.30);
box-shadow: 0 8px 24px rgba(0, 8, 10, 0.30), inset 0 0 0 1px rgba(255, 255, 255, 0.03);
}
html[data-ui-tier="enhanced"] .wf-side-chip {
color: rgba(65, 175, 192, 0.88);
border-color: rgba(46, 125, 138, 0.32);
background: rgba(6, 16, 18, 0.30);
}
html[data-ui-tier="enhanced"] .wf-side-stat {
border-color: rgba(46, 125, 138, 0.20);
}