diff --git a/documentation/reference-capability-exemplars.md b/documentation/reference-capability-exemplars.md
index ccd38243f..ebdd960a6 100644
--- a/documentation/reference-capability-exemplars.md
+++ b/documentation/reference-capability-exemplars.md
@@ -13,7 +13,7 @@
> bundle `parameterized` (cap-2) no matter how light it looks, and a `meta.json` `type`
> declares tiers 3/4/5.
-Generated from 24 bundle(s).
+Generated from 25 bundle(s).
### One canonical exemplar per tier (generated — quote these)
@@ -40,6 +40,7 @@ Generated from 24 bundle(s).
| `cities-internet` | `connectivity-list` | `single` |
| `cities-internet` | `connectivity-map` | `single` |
| `cities-internet` | `data-tables` | `single` |
+| `country-map` | `country-map` | `single` |
| `country-posters` | `countries-map` | `single` |
| `country-posters` | `country-poster-wall` | `single` |
| `golden-path-check` | `golden-path-check` | `single` |
diff --git a/documentation/reference-library-index.md b/documentation/reference-library-index.md
index 3bb9397e8..129fa24bf 100644
--- a/documentation/reference-library-index.md
+++ b/documentation/reference-library-index.md
@@ -14,6 +14,8 @@ and a change here can break other maps.
### Components (reusable UI)
+- **BackToTopButton** — BackToTopButton — a ↑ that appears once a long list has been scrolled, and sits NEXT TO the
+ `import … from '@map/components/BackToTopButton.vue'`
- **PeopleGroupDetail** — (no description)
`import … from '@map/components/PeopleGroupDetail.vue'`
- **ResearchMapFilterPanel** — ResearchMapFilterPanel.vue — Multi-field filter UI for the research-map.
@@ -32,10 +34,6 @@ and a change here can break other maps.
`import … from '@map/components/charts/ProgressBar.vue'`
- **ShareCalendar** — ShareCalendar — the same 5,200-cell grid, shaded by a population-weighted share.
`import … from '@map/components/charts/ShareCalendar.vue'`
-- **VisionFunnel** — VisionFunnel — the inverted triangle: all peoples → unreached → frontier, and where a list sits.
- `import … from '@map/components/charts/VisionFunnel.vue'`
-- **DashboardBreadcrumb** — ── KIT LANDING 4c-4: MOVED FROM plugin-designs/research-dashboard/ ───────────────────────────
- `import … from '@map/components/dashboards/DashboardBreadcrumb.vue'`
- **DashboardFacetRail** — DashboardFacetRail (was Sidebar.vue) — RDASH redesign phase 2: the floating @map SemanticTreeLegend is DROPPED
`import … from '@map/components/dashboards/DashboardFacetRail.vue'`
- **DashboardFilterChips** — DashboardFilterChips — the live filterSet rendered as removable AND-stacked chips
@@ -44,6 +42,8 @@ and a change here can break other maps.
`import … from '@map/components/hints/PinHint.vue'`
- **ApproxPinNote** — ApproxPinNote.vue — the ONE wording every map with people-group pins uses (APPROXPIN, 2026-09-26).
`import … from '@map/components/legends/ApproxPinNote.vue'`
+- **LegendCollapseCaret** — LegendCollapseCaret.vue — SHARED (@map/components/legends/LegendCollapseCaret.vue).
+ `import … from '@map/components/legends/LegendCollapseCaret.vue'`
- **LegendDesktop** — This component's chrome, read out of the catalogue. tStatic and not useI18n: these mount inside
`import … from '@map/components/legends/LegendDesktop.vue'`
- **LegendMobile** — (no description)
@@ -54,8 +54,6 @@ and a change here can break other maps.
`import … from '@map/components/legends/LegendRows.vue'`
- **LegendTools** — Does the Fly + Clusters toolbar render for this legend type?
`import … from '@map/components/legends/LegendTools.vue'`
-- **ListSelectorLegend** — ListSelectorLegend.vue — the Driver's VERTICAL LEGEND, used to SELECT a list and filter by it.
- `import … from '@map/components/legends/ListSelectorLegend.vue'`
- **SemanticTreeLegend** — SemanticTreeLegend — reusable hierarchical legend for any one-to-many semantic tree.
`import … from '@map/components/legends/SemanticTreeLegend.vue'`
- **FullscreenButton** — FullscreenButton.vue — Toggles fullscreen for the map host element.
@@ -64,7 +62,7 @@ and a change here can break other maps.
`import … from '@map/components/map-controls/GeocoderComponent.vue'`
- **HamburgerButton** — HamburgerButton.vue — Toggle button for the side menu drawer.
`import … from '@map/components/map-controls/HamburgerButton.vue'`
-- **HelpButton** — HelpButton.vue — Opens the "About this map" help modal.
+- **HelpButton** — HelpButton.vue — the map's "?" control: what this map is and how to use it.
`import … from '@map/components/map-controls/HelpButton.vue'`
- **LocationButton** — LocationButton.vue — Flies the map to the user's current location via the
`import … from '@map/components/map-controls/LocationButton.vue'`
@@ -82,6 +80,8 @@ and a change here can break other maps.
`import … from '@map/components/map-controls/ZoomInButton.vue'`
- **ZoomOutButton** — ZoomOutButton.vue — Decrements the map zoom level by one step.
`import … from '@map/components/map-controls/ZoomOutButton.vue'`
+- **RegionCountryMap** — RegionCountryMap.vue — DX-life's CountryMap, rebuilt on the dx-maps map library.
+ `import … from '@map/components/maps/RegionCountryMap.vue'`
- **PosterDialog** — PosterDialog.vue — modal for previewing + rendering a poster export.
`import … from '@map/components/poster/PosterDialog.vue'`
- **PosterPreview** — PosterPreview.vue — scaled live preview of the poster composition.
@@ -117,6 +117,10 @@ and a change here can break other maps.
### Composables (reusable logic — Vue Composition API)
+- **host-token-url** — host-token-url.js — the tokenUrl rule, with NO framework import, so a gate can run it.
+ `import … from '@map/composables/host-token-url.js'`
+- **joinBase** — joinBase.js — SHARED (@map/composables/joinBase.js). Join a host-supplied base URL to a path.
+ `import … from '@map/composables/joinBase.js'`
- **researchLegendOptions** — researchLegendOptions.js — research-mfe-only options passed to the shared
`import … from '@map/composables/legends/researchLegendOptions.js'`
- **useAffinityBlockLegendData** — useAffinityBlockLegendData — 4-tier affinity-block legend data for SemanticTreeLegend.
@@ -157,6 +161,10 @@ and a change here can break other maps.
`import … from '@map/composables/useFacetAggregation.js'`
- **useGeocoderSearch** — Shared geocoder→map search logic (kind-switch + Mapbox filter builder + the
`import … from '@map/composables/useGeocoderSearch.js'`
+- **useHostTokenUrl** — useHostTokenUrl.js — a composite honours tokenUrl the way ProfileLoader does.
+ `import … from '@map/composables/useHostTokenUrl.js'`
+- **useHostedHelp** — useHostedHelp — a map's "?" that its HOST answers.
+ `import … from '@map/composables/useHostedHelp.js'`
- **useMapAttribution** — useMapAttribution.js — the data-credit line every map MUST carry.
`import … from '@map/composables/useMapAttribution.js'`
- **useMapClustering** — useMapClustering.js — Map Clustering Composable
@@ -173,8 +181,6 @@ and a change here can break other maps.
`import … from '@map/composables/useMapLayers.js'`
- **useMapProvider** — useMapProvider.js — resolve the active map engine ("provider").
`import … from '@map/composables/useMapProvider.js'`
-- **useMapSelection** — useMapSelection.js - Map Selection Composable
- `import … from '@map/composables/useMapSelection.js'`
- **useMapTheme** — useMapTheme.js — shared light/dark theme for every map profile.
`import … from '@map/composables/useMapTheme.js'`
- **useOptionalT** — ★ NO .-SHAPED EXAMPLES IN THIS FILE'S COMMENTS. check:i18n-keys-exist reads any such
@@ -236,6 +242,8 @@ and a change here can break other maps.
`import … from '@map/utils/languageLabel.js'`
- **loadPinnedUmd** — loadPinnedUmd — load a PINNED, integrity-checked UMD library and capture it WITHOUT touching the host
`import … from '@map/utils/loadPinnedUmd.js'`
+- **peopleGroupPoints** — peopleGroupPoints.js — SHARED (@map/utils/peopleGroupPoints.js).
+ `import … from '@map/utils/peopleGroupPoints.js'`
- **viewportScrim** — viewportScrim.js — make a position:fixed full-screen SCRIM actually cover the VIEWPORT,
`import … from '@map/utils/viewportScrim.js'`
diff --git a/plugin-designs/research-map-plus-grid/scripts/check-no-free-identifiers.mjs b/plugin-designs/research-map-plus-grid/scripts/check-no-free-identifiers.mjs
index 8b6189dd8..91272e3de 100644
--- a/plugin-designs/research-map-plus-grid/scripts/check-no-free-identifiers.mjs
+++ b/plugin-designs/research-map-plus-grid/scripts/check-no-free-identifiers.mjs
@@ -60,6 +60,7 @@ const GLOBALS = [
'Event', 'CustomEvent', 'EventTarget', 'MessageChannel', 'BroadcastChannel',
'IntersectionObserver', 'DOMException', 'createImageBitmap', 'ResizeObserver', 'MutationObserver', 'PerformanceObserver', 'performance',
'HTMLElement', 'HTMLCanvasElement', 'HTMLImageElement', 'Element', 'Node', 'NodeList', 'DOMParser',
+ 'Path2D', 'OffscreenCanvas', 'ImageData', // canvas built-ins (the Wall draws its icons with Path2D)
'Image', 'Audio', 'Intl', 'getComputedStyle', 'matchMedia', 'alert', 'confirm', 'prompt',
'localStorage', 'sessionStorage', 'devicePixelRatio', 'innerWidth', 'innerHeight',
'process', 'Buffer', '__dirname', '__filename', 'require', 'module', 'exports',