diff --git a/src/web/www/overview.html b/src/web/www/overview.html
index 59153dc..4bc377c 100644
--- a/src/web/www/overview.html
+++ b/src/web/www/overview.html
@@ -423,7 +423,12 @@
.ov-perf-name {
font-size: 12px;
font-weight: 700;
- letter-spacing: 0.4px;
+ /* UPPERCASE to match the chain's stage labels (INPUT/PROCESS/OUTPUT), which
+ are text-transform:uppercase. Owner consistency ruling 2026-08-17: every
+ card header in the signal chain reads uppercase, so this one does too.
+ Letter-spacing bumped to sit with the stage labels' 1.4px feel. */
+ letter-spacing: 1.2px;
+ text-transform: uppercase;
color: var(--info-text);
margin-bottom: 8px;
padding-bottom: 6px;
@@ -439,6 +444,15 @@
}
.ov-perf-row .ov-perf-k { color: var(--text-muted); }
.ov-perf-row .ov-perf-v { color: var(--text-primary); }
+/* Threshold colouring for the RF Performance values, matching the dashboard's
+ scheme (owner, 2026-08-17). Same tokens the dashboard uses (value-ok/warn/err/
+ off resolve to these), so a below-threshold reading turns the same colour here
+ as on the dashboard. Status is computed by the dashboard's OWN getSnrStatus/
+ getImdStatus (one source of truth), not re-thresholded here. */
+.ov-perf-row .ov-perf-v.ov-v-ok { color: var(--accent-green); }
+.ov-perf-row .ov-perf-v.ov-v-warn { color: var(--status-warn); }
+.ov-perf-row .ov-perf-v.ov-v-err { color: var(--status-err); }
+.ov-perf-row .ov-perf-v.ov-v-off { color: var(--text-muted); }
.ov-perf-foot {
margin-top: auto;
padding-top: 10px;
@@ -768,13 +782,24 @@ function fbArrow() {
box's full width and can wrap without clipping. Values pass through exactly
as parse() produced them, so 'N/A-FSSI' shows verbatim under FSSI Refresh. */
function perfBox(snr, limd, uimd) {
+ /* Colour each value by the dashboard's OWN threshold functions (getSnrStatus:
+ >=27 ok / >=20 warn / else err; getImdStatus: >=47 ok / else err; 'N/A*' ->
+ off/grey). One source of truth shared with the dashboard, so the box and the
+ dashboard never disagree. The status maps to ov-v-* (same colours as the
+ dashboard's value-* tokens). SNR can go amber; the IMDs jump straight to red,
+ exactly as the dashboard treats them. */
+ var H = window.DashboardHelpers;
+ var vc = function(cls){ return 'ov-perf-v' + (cls ? ' ov-v-' + cls : ''); };
+ var snrC = vc(H.getSnrStatus(snr));
+ var limdC = vc(H.getImdStatus(limd));
+ var uimdC = vc(H.getImdStatus(uimd));
return '' +
'
' +
'
RF Performance
' +
'
Sampled transmit signal
' +
- '
SNR' + snr + ' dB
' +
- '
LIMD' + limd + ' dBc
' +
- '
UIMD' + uimd + ' dBc
' +
+ '
SNR' + snr + ' dB
' +
+ '
LIMD' + limd + ' dBc
' +
+ '
UIMD' + uimd + ' dBc
' +
' ' +
'
';
}
@@ -861,9 +886,13 @@ window.Trends = (function () {
/* Chart set per sub-mode. Order = display order. Duplicated from the 1.0
verbatim per the owner's law (exciter 5 charts / translator 7). smod has
only these two modes, so only these two are defined. */
+ /* Chart set per sub-mode. Order = display order. LIMD before UIMD (lower
+ intermodulation product first, then upper) — owner-ruled 2026-08-17. The
+ 1.0 has these reversed (uimd, limd); that is logged as a cross-product fix,
+ NOT copied here. smod has only these two modes. */
var CHARTS_FOR_MODE = {
- exciter: ['input_bitrate', 'snr', 'fwd_pct', 'uimd', 'limd'],
- translator: ['input_bitrate', 'rsnr', 'rssi', 'snr', 'fwd_pct', 'uimd', 'limd']
+ exciter: ['input_bitrate', 'snr', 'fwd_pct', 'limd', 'uimd'],
+ translator: ['input_bitrate', 'rsnr', 'rssi', 'snr', 'fwd_pct', 'limd', 'uimd']
};
var SPARK_W = 200, SPARK_H = 40, SPARK_PAD_Y = 2;
diff --git a/src/web/www/sys_spectrum.html b/src/web/www/sys_spectrum.html
index 35f134f..0e0eab9 100755
--- a/src/web/www/sys_spectrum.html
+++ b/src/web/www/sys_spectrum.html
@@ -210,9 +210,28 @@
negative). Verified: raw -22.7 -> -33.7 vs IMD 32.3/32.5; raw ~-63.4 -> -74.4
vs IMD 73.6/73.9. */
var IMD_PILOT_OFFSET = 11; // dB; documented pilot offset (1.0 status_info_new.html)
- setReadout('rd_shoulder', d.shoulder - IMD_PILOT_OFFSET, 1);
- setReadout('rd_limd', d.limd + IMD_PILOT_OFFSET, 1);
- setReadout('rd_uimd', d.uimd + IMD_PILOT_OFFSET, 1);
+ /* Threshold colouring for the three shoulder-suppression readouts, to match
+ the dashboard's scheme (owner, 2026-08-17). The dashboard colours SNR/LIMD/
+ UIMD via getSnrStatus/getImdStatus; SNR here is already coloured below
+ (line ~303). LIMD and UIMD use the dashboard's IMD rule directly: >= 47 dBc
+ green, else red (they already carry the +11 offset so they match the
+ dashboard values). Shoulder has NO pre-existing threshold anywhere; owner
+ ruled it uses the SAME 47 dBc line as the IMDs on its ABSOLUTE value (it is
+ the same kind of dBc shoulder-suppression measure, only signed negative). All
+ OTHER spectrum readouts (FSSI, Pilot, Peak, RBW, ...) stay plain — no invented
+ thresholds. A '--'/NaN reading clears the colour (stays default), never red. */
+ function imdColour(v){ // dBc magnitude vs the 47 dBc pass line
+ return (v === null) ? '' : (Math.abs(v) >= 47 ? 'var(--accent-green)' : 'var(--status-err)');
+ }
+ var shoulderVal = setReadout('rd_shoulder', d.shoulder - IMD_PILOT_OFFSET, 1);
+ var limdVal = setReadout('rd_limd', d.limd + IMD_PILOT_OFFSET, 1);
+ var uimdVal = setReadout('rd_uimd', d.uimd + IMD_PILOT_OFFSET, 1);
+ var shoulderEl = document.getElementById('rd_shoulder');
+ var limdEl = document.getElementById('rd_limd');
+ var uimdEl = document.getElementById('rd_uimd');
+ if (shoulderEl) shoulderEl.style.color = imdColour(shoulderVal);
+ if (limdEl) limdEl.style.color = imdColour(limdVal);
+ if (uimdEl) uimdEl.style.color = imdColour(uimdVal);
setReadout('rd_pilot', d.pilot, 4);
setReadout('rd_peak', d.peak, 1);
setReadout('rd_rbw', d.rbw_khz, 2);