# UI-09 — Monochrome dark map tiles **Depends on** nothing · **Size** S · **Status** Not started ## Goal Replace the tan/cream default OpenStreetMap raster style with a monochrome dark map, so the map actually looks like it belongs in a dark-mode HUD instead of a light basemap punched through a dark overlay. ## Context `RideMap`, the Plan/Route Planning canvas, and every Stitch mockup all assume a dark or near-monochrome map underneath the HUD. Today's `TileLayer` (`ride_map.dart`) points at `tile.openstreetmap.org`, OSM's standard light/tan default style — the actual on-device result is nothing like the mockups, regardless of how dark the chrome on top of it is. This affects every screen that shows a map (Map HUD, Plan, Route Planning, and UI-01's dimmed background on every other tab), so it's worth settling once, early, rather than each screen ticket discovering the same mismatch independently. ## Design Two real options, not one obvious answer: **Option A — switch tile provider to CARTO's "Dark Matter" basemap.** `https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png` (subdomains a-d, retina `{r}` variant available, max native zoom 20). Purpose-built dark, desaturated/monochrome cartography — closest to the mockups with the least engineering. Free for reasonable usage same as OSM's own tiles, but it's a **different third party with its own usage policy and attribution requirement** ("© OpenStreetMap contributors © CARTO", not just OSM's own attribution) — a real dependency to add, not a style tweak. **Option B — keep OSM tiles, apply a color filter client-side.** Wrap `TileLayer` in a `ColorFiltered` widget using a `ColorFilter.matrix` that desaturates and inverts/darkens the tan basemap into a monochrome dark look. No new third party, no new attribution, and V3-11's offline tile cache keeps working against the exact tiles it already knows about — but the result is a filtered light map, not tiles actually designed for dark presentation, and will read as slightly "off" next to CARTO's purpose-built version (road/building contrast tuned for light backgrounds doesn't always invert cleanly). **Recommendation: Option A.** The mockups' whole aesthetic depends on the map itself being dark, not just tinted dark, and CARTO's dark tiles are a well-established, free, no-API-key option already widely used in the Flutter/Leaflet ecosystem for exactly this. The added attribution line and a second host to trust are a small, one-time cost. **V3-11 interaction:** the offline tile cache (`FileTileCache`/`CachedTileProvider`) is already keyed by `TileKey(z, x, y)` with no provider-specific data baked in — but that means a cache built against OSM tiles and a cache built against CARTO tiles are **indistinguishable to the cache** despite being visually different. Switching providers without a plan here would silently serve stale, wrong-looking cached OSM tiles once CARTO's URL is live. This needs a cache-busting or provider-tagging fix as part of this ticket, not a separate one — see Implementation. ## Implementation 1. Add a `provider`-qualified cache key (or a cache-version bump that invalidates existing V3-11 cache contents wholesale) so switching tile sources can't silently mix cached tiles from two visually different sources. 2. Update `RideMap`'s `TileLayer` (and the Route Planner's separate `TileLayer` instance — see `route_planner_screen.dart`) to CARTO's dark tile URL template, correct `subdomains`, and `maxNativeZoom: 20`. 3. Update the attribution requirement — check whether `flutter_map`'s `RichAttributionWidget`/`AttributionWidget` is in use anywhere already, or add one; OSM-only attribution is no longer sufficient once CARTO tiles are in the mix. 4. Update `tileUserAgent`/any OSM-specific comments in `ride_map.dart` that assumed OSM's tile servers specifically (the "respect OSM's usage policy" reasoning still applies in spirit to CARTO's own policy, but the specific server being addressed changes). 5. Re-verify V3-11's tile math/download flow still works end-to-end against the new URL template (tile enumeration and caching are provider-agnostic already; only the fetch URL construction needs updating). ## Acceptance criteria - [ ] The map renders in a dark, desaturated/monochrome style matching the Stitch mockups, not OSM's default tan basemap - [ ] Correct attribution for both OpenStreetMap and CARTO is shown wherever the map is shown - [ ] Switching tile providers does not silently serve stale, visually-mismatched cached tiles from before the switch (V3-11's cache is invalidated or provider-tagged) - [ ] Both `RideMap` and the Route Planner's independent `TileLayer` are updated consistently — one dark style everywhere, not just on the screens that happened to get touched first ## Tests - Existing `ride_map`/route-planner widget tests updated for the new tile URL and still passing - Unit: cache-key/versioning change is exercised the same way V3-11's eviction tests are — a cache built under the old scheme does not get served for the new provider ## Risks - **A second third-party tile host is a real dependency, not a free color swap** — its own usage policy, its own risk of being blocked if misused, and its own attribution obligation. Treat it with the same care V3-11 already applies to OSM (rate-limit respecting, no bulk prefetch, real user agent). - If CARTO's free tier ever proves insufficient or is discontinued, Option B (a color filter over OSM tiles) is the fallback with no new third-party dependency — worth keeping in mind as a documented Plan B, not re-deriving from scratch later. ## Out of scope A fully custom/self-hosted vector tile style — much larger scope, and not needed to hit "looks like the mockups" today.