diff --git a/frontend/src/components/MapView.tsx b/frontend/src/components/MapView.tsx
index 0e21bc9..134d265 100644
--- a/frontend/src/components/MapView.tsx
+++ b/frontend/src/components/MapView.tsx
@@ -911,7 +911,15 @@ export function MapView({
{infoLabel}
{!showPackets && (
- <>
+ // Grouped and labelled like the "Since" filter below it. The colour
+ // dots are aria-hidden, so without this the legend is unlabelled to
+ // assistive tech — and its bucket names collide with the identically
+ // named filter chips for anything selecting by text.
+
{' '}
older
- >
+
)}
{showPackets && (
<>
diff --git a/tests/e2e/specs/node-map.spec.ts b/tests/e2e/specs/node-map.spec.ts
index d6d850c..c0d7a6d 100644
--- a/tests/e2e/specs/node-map.spec.ts
+++ b/tests/e2e/specs/node-map.spec.ts
@@ -7,8 +7,10 @@ test.describe('Node Map page', () => {
// Verify heading (also appears in sidebar, so scope to main)
await expect(page.getByRole('main').getByText('Node Map')).toBeVisible({ timeout: 10_000 });
- // Verify legend elements
- await expect(page.getByText('<1h')).toBeVisible();
- await expect(page.getByText('<1d')).toBeVisible();
+ // Verify legend elements. Scoped to the legend group: the "Since" filter
+ // chips carry the same bucket names, so an unscoped text match is ambiguous.
+ const legend = page.getByRole('group', { name: 'Marker recency legend' });
+ await expect(legend.getByText('<1h')).toBeVisible();
+ await expect(legend.getByText('<1d')).toBeVisible();
});
});