diff --git a/plugin-designs/research-dashboard/src/components/dashboards/DashboardDataTable.vue b/plugin-designs/research-dashboard/src/components/dashboards/DashboardDataTable.vue
index 096f23e51..04fa0625a 100644
--- a/plugin-designs/research-dashboard/src/components/dashboards/DashboardDataTable.vue
+++ b/plugin-designs/research-dashboard/src/components/dashboards/DashboardDataTable.vue
@@ -491,19 +491,25 @@ useShadowStyles(`
- Filtering or selecting above updates this list
+
{{ exportToast }}
2.2 at z1), so the existing bbox remains sufficient.
// ── ★ THE PIN IS NOW SELF-CONTAINED (card BUILD-MAP-STYLE-MUST-BE-BEAUTIFUL) ──────────
// The white ring used to depend on the GROUND for its visibility, and measured only
// 1.09–1.24 against the light bins — so on pale countries the ring vanished and the dots
@@ -346,12 +347,57 @@ function addLayers() {
//
// HIT-TESTING unchanged: 'rd-bubble-layer' keeps its id and stays the TOP layer; the halo
// is a separate NON-interactive layer beneath it and must not be queried.
- m.addLayer({ id: 'rd-bubble-halo', type: 'circle', source: 'rd-bubbles',
- paint: { 'circle-radius': ['interpolate', ['linear'], ['zoom'], 1, 3.4, 6, 7.4], 'circle-color': '#fff', 'circle-opacity': 1,
- // The outer edge: thin, navy, so the white ring has a hard boundary on ANY ground.
- 'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 1, 0.6, 6, 1], 'circle-stroke-color': '#1a237e', 'circle-stroke-opacity': 0.9 } })
+ // ── ★ ONE CIRCLE WITH A WHITE STROKE — NOT A NAVY/WHITE/NAVY SANDWICH ──────────────────────
+ // (Driver 2026-09-22: "the pins look like eyes, they look kind of creepy")
+ //
+ // THE SANDWICH WAS THE BUG, and the comment above described it accurately without noticing what
+ // it draws. Read outward from the centre at z1 the old construction was:
+ // navy disc r=1.6 → white field r=3.4 → navy stroke 0.6px
+ // dark centre, light middle, dark rim. That is the anatomy of an eye — pupil, sclera, iris
+ // outline — and it is why a bullseye is NAMED after one. Concentric rings sharing a centre are
+ // exactly the pattern the visual system fuses into a single object; sighting equipment exploits
+ // the same involuntary alignment. The inner disc sat at 47% of the halo radius at z1, squarely in
+ // the proportion that reads as a PUPIL rather than as a dot with a border. Worst when zoomed out,
+ // which is where a world map lives.
+ //
+ // THE OUTER NAVY BAND IS THE SPECIFIC CULPRIT: it closes the iris. Without it the same colours
+ // read as an ordinary pin. So the fix removes a band rather than changing a colour.
+ //
+ // MATCHES THE MAPBOX IDIOM, which is ONE layer with a stroke, not two stacked circles. The style
+ // spec draws `circle-stroke-width` OUTSIDE `circle-radius`, so a single layer already produces
+ // disc-plus-ring; the old code hand-rolled that and collected a third colour band for the
+ // trouble. Scaling the stroke with zoom (1.2 → 2) is the documented way to stop the ring
+ // swallowing the fill when circles are small and dense at low zoom. Cartographic practice agrees:
+ // Axis Maps and the ICA Commission both call for casings on symbols that OVERLAP rather than a
+ // global opaque halo, and Esri names halos the single biggest cost in marker drawing performance
+ // — we were paying that on a second full circle layer across every point. Research + sources:
+ // _qa-cycle/01-ideation-research/RESEARCH-pin-design-why-they-read-as-eyes.md
+ //
+ // ★ THE TWO DRIVER RULINGS THIS PRESERVES — do not undo either:
+ // 1. ONE FIXED COLOUR AT FULL OPACITY. Pins were once '#e67e22' at circle-opacity 0.6; the
+ // alpha was the real fault, compositing each pin with whatever bin sat beneath it so it
+ // rendered a different colour per country at 1.18–1.22 contrast. Never reintroduce pin
+ // alpha, never tint per bin.
+ // 2. WHITE RINGS around blue dots so the field does not read as a heat map, and all rings stay
+ // visible when zoomed out. Still here — it is now the stroke instead of a second layer.
+ // Navy #1a237e measures 12.24 / 11.09 / 10.20 / 9.26 / 8.20 / 7.29 across the ramp; unchanged.
+ //
+ // WHAT IS GIVEN UP, stated honestly: the outer navy band gave the white ring a hard boundary on
+ // ANY ground, so over the palest bin the ring now blends into the background. The ring's job is
+ // separating pins from EACH OTHER (it still does that) while the navy disc carries pin-vs-ground
+ // contrast. MEASURE the pale end before calling this settled. If separation genuinely fails
+ // there, the fix is a casing on overlapping symbols only — not a restored global dark rim.
+ //
+ // HIT-TESTING: 'rd-bubble-layer' keeps its id and is now the ONLY bubble layer, so every
+ // click/hover handler bound to that id is unaffected. 'rd-bubble-halo' no longer exists.
m.addLayer({ id: 'rd-bubble-layer', type: 'circle', source: 'rd-bubbles',
- paint: { 'circle-radius': ['interpolate', ['linear'], ['zoom'], 1, 1.6, 6, 5], 'circle-color': '#1a237e', 'circle-opacity': 1 } })
+ paint: {
+ 'circle-radius': ['interpolate', ['linear'], ['zoom'], 1, 2.2, 6, 5.5],
+ 'circle-color': '#1a237e', 'circle-opacity': 1,
+ 'circle-stroke-color': '#ffffff',
+ 'circle-stroke-width': ['interpolate', ['linear'], ['zoom'], 1, 1.2, 6, 2],
+ 'circle-stroke-opacity': 1,
+ } })
// selection pen — a prominent neon ring over the selected PG pin(s), drawn ABOVE the normal bubbles.
m.addSource('rd-bubble-selected', { type: 'geojson', data: selectedGeo() })
m.addLayer({ id: 'rd-bubble-selected', type: 'circle', source: 'rd-bubble-selected',