diff --git a/web/app.js b/web/app.js
index 1dbcd31..4bbd38a 100644
--- a/web/app.js
+++ b/web/app.js
@@ -224,8 +224,12 @@ function renderSignalPopover(rect, signal) {
return `
${label}${Number(value).toFixed(2)}
`;
}).join('');
signalPopover.innerHTML = `${signal.class?.mod_type || 'Signal'}
${fmtMHz(signal.center_hz, 5)} · ${fmtKHz(signal.bw_hz || 0)} · ${(signal.snr_db || 0).toFixed(1)} dB SNR
${rows || '
No classifier scores
'}
`;
- signalPopover.style.left = `${Math.max(8, rect.x + rect.w + 8)}px`;
- signalPopover.style.top = `${Math.max(8, rect.y + 8)}px`;
+ const popW = 220;
+ const left = rect.x + rect.w + 8;
+ const top = rect.y + 8;
+ const maxLeft = Math.max(8, spectrumCanvas.width - popW - 8);
+ signalPopover.style.left = `${Math.max(8, Math.min(maxLeft, left))}px`;
+ signalPopover.style.top = `${Math.max(8, top)}px`;
signalPopover.classList.add('open');
signalPopover.setAttribute('aria-hidden', 'false');
}
@@ -1650,3 +1654,4 @@ setInterval(fetchRecordings, 5000);
setInterval(loadSignals, 1500);
setInterval(loadDecoders, 10000);
+
diff --git a/web/index.html b/web/index.html
index 1f459d2..1b932c2 100644
--- a/web/index.html
+++ b/web/index.html
@@ -83,10 +83,10 @@
Spectrum
- Wheel = zoom · Drag = pan · Dbl-click = reset
+ Wheel = zoom · Drag = pan · Double-click = reset
- CFAR edge (static threshold)
+ Adaptive CFAR threshold
diff --git a/web/style.css b/web/style.css
index bfc2d66..2e74798 100644
--- a/web/style.css
+++ b/web/style.css
@@ -214,7 +214,7 @@ button, input, select { font: inherit; }
canvas { display: block; width: 100%; height: 100%; border-radius: var(--r-sm); background: #030508; }
.signal-popover {
- position: absolute; z-index: 8; pointer-events: none; min-width: 180px;
+ position: absolute; z-index: 8; pointer-events: none; min-width: 180px; max-width: 220px;
padding: 10px 12px; border-radius: 10px; border: 1px solid var(--line-hi);
background: rgba(6, 10, 18, 0.94); box-shadow: 0 18px 50px rgba(0,0,0,0.38);
font-size: 0.72rem; color: var(--text); display: none;