## Summary
Adds asymmetric overlap percentages to the existing observer compare
page so it can be used as a **reference observer comparison** tool
(Uncle Lit's request, #671).
## What changed
`public/compare.js` (frontend only — no backend changes)
- New `computeOverlapStats(cmp)` helper that turns a
`comparePacketSets()` result into two-way coverage:
- `aSeesOfB` — % of B's packets that A also saw
- `bSeesOfA` — % of A's packets that B also saw
- plus shared / onlyA / onlyB / totalA / totalB
- Two callout cards on the compare summary view:
- `<A> saw N of <B>'s X packets` (Y%)
- `<B> saw N of <A>'s X packets` (Y%)
- Existing "Only A / Only B / Both" tabs already identify unique
packets; that's the second half of the issue and is left intact.
## Operator workflow
Pick a known-good observer (LOS to key nodes) as the reference. Pair it
with a candidate. If the candidate's overlap with the reference is high
→ healthy. If low → investigate antenna, obstruction, or RF deafness.
## Out of scope (future work)
Issue lists several follow-on milestones — full Analytics sub-tab with
reference-vs-many table, SNR delta, geographic proximity filter,
server-side `/api/analytics/observer-comparison` endpoint. Those are
larger and tracked by the issue's M1-M4 milestones; this PR closes the
core ask (asymmetric overlap on the existing compare page) and leaves
the rest for follow-ups.
## Tests
`test-compare-overlap.js` — 6 unit tests via vm sandbox:
- exposes `computeOverlapStats` on `window`
- basic asymmetric scenario (8/10 vs 8/12)
- zero packets — no division by zero
- one observer empty — both percentages 0
- perfect overlap — 100% both ways
- disjoint observers — 0% both ways
TDD: red commit landed first with stub returning zeros (assertions
failed), green commit added the math.
Closes#671
---------
Co-authored-by: bot <bot@corescope.local>