Commit graph

104 commits

Author SHA1 Message Date
a07b33db6d feat: switch to global planet PMTiles for worldwide vector coverage
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-02 03:24:12 +00:00
66f91fd379 fix: Properly restore layers when switching view modes
Three bugs fixed:
1. Map mode now restores all hidden layers - using separate tracking
   arrays for fills, lines, and symbols that persist across mode switches
2. Satellite mode now hides ALL vector layers (fills, lines, symbols)
   for true satellite-only view
3. Hybrid mode keeps lines and symbols visible for road/label overlay

Each mode switch first restores all layers to a clean slate before
hiding the appropriate ones for that mode.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-02 02:19:28 +00:00
4c1921d116 fix: Hide background layer in satellite mode
The background layer type was not being hidden, causing it to cover
the satellite imagery. Now hideVectorFills hides fill, fill-extrusion,
AND background layer types.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-02 02:08:59 +00:00
e786bb8870 feat: Add satellite imagery with Map/Satellite/Hybrid view modes
- Add viewMode state to store with localStorage persistence
- Add satellite layer functions to MapView (ESRI World Imagery via nginx proxy)
- Add view mode segmented control in LayerControl popover
- Add view-mode-control CSS styles
- Hide/show vector fills and lines based on view mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-02 02:01:56 +00:00
5299376fec fix(ui): Move control cluster up to clear attribution and scale
- Control cluster now at bottom: 80px (was 40px)
- Scale bar at bottom: 24px (above attribution)
- Mobile adjusted to bottom: 70px
- Clear visual separation: buttons > scale > attribution

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 23:45:55 +00:00
67779dbbf7 feat(ui): Redesign bottom-right map control cluster
- Increase touch targets from 36px to 44px (meets accessibility guidelines)
- Wrap Locate and Layers buttons in unified .map-controls-br container
- Layer popover now opens LEFT of buttons (avoids collision with Locate)
- Add hover and active states with theme-aware styling
- Proper spacing for scale control below the cluster
- Increased icon sizes from 18px to 20px
- Mobile-responsive with proper max-height on layer popover

Layout:
  [Locate] 44x44
  [Layers] 44x44
  ──────────────
  Scale: 0.5 mi

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 23:17:13 +00:00
9d3b972d81 feat(ui): Show theme name as picker trigger button
Replace palette icon with current theme name as clickable text.
Hover changes from --text-secondary to --text-primary.
Popover behavior unchanged.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 23:00:11 +00:00
66a35d9472 fix(ui): Use 4-column grid for theme picker
8 themes no longer fit in a single row. Changed from flex row
to a 4x2 grid layout so all themes are visible.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 22:59:24 +00:00
948871b9e5 feat(themes): Add Parchment medieval manuscript theme
Old-world cartography style inspired by hand-drawn maps. Medieval
manuscript aesthetic with warm aged parchment land, deep ultramarine
water, dark sepia ink labels, and burnt sienna roads.

Design features:
- IM Fell English font (1672 Fell typeface revival)
- Deep ultramarine water (#1a3a6a), not modern pale blue
- Olive-gold vegetation, NOT modern green
- Brown ink roads by importance
- Parchment-colored halos on all labels
- Warm dramatic hillshade terrain

The feel of a map from a monastery scriptorium or explorer journal.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 22:49:50 +00:00
78dc96551b feat(themes): Add Night Ops red-on-black theme
Tactical night operations display optimized for absolute darkness.
Inspired by military cockpit instruments, submarine control rooms,
and ship bridge displays designed for total darkness.

Design rules:
- ONLY red and black (pure monochrome red)
- Red preserves dark-adapted (scotopic) vision
- Water is pure black, no blue tint
- All features differentiated by brightness only
- Black halos on all labels
- More aggressive than Tactical for ZERO ambient light

Palette: #0a0000 base, #cc3333 primary, #551515 muted

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 22:46:01 +00:00
cc1b25e0b1 feat(themes): Add Tactical green phosphor theme
Military display aesthetic - classic green phosphor monochrome like NVGs,
submarine sonar screens, 1980s radar consoles, and green-screen terminals.

Design rules:
- ONLY green and black (exception: danger status uses orange-red)
- All features differentiated by brightness, not hue
- Water is pure black, not blue-tinted
- Text is phosphor green (#00cc44)
- Black halos on all labels

Named "Tactical" for the recon/military working display identity.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 22:40:58 +00:00
b25d6e575d refactor(themes): rename Tactical → Ranger
Pure rename, no functional changes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 22:29:11 +00:00
04e15bf3dc feat(themes): add Tactical theme - NVG-compatible mil-spec display
Dark olive/charcoal base with sage green text and amber accents.
Designed for night operations and eventual ATAK/iTAK integration:
- Low contrast for night vision compatibility
- Prominent olive-brown contours (topo-first design)
- Subdued amber roads (preserves night vision better than blue/white)
- Muted field-appropriate danger red
- No bright blues or whites anywhere
- Darkened/desaturated satellite mode

Functional, not decorative.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 22:20:06 +00:00
09369011ee fix: direct namedTheme import fixes GeoJSON rendering, guard optional layer queries
Root cause: Vite's bundling of namedTheme through the registry re-export
broke MapLibre's Web Worker, silently preventing all GeoJSON rendering
(routes, boundaries, measure tool). Fixed by importing namedTheme
directly from protomaps-themes-base in MapView.jsx.

Also guards queryRenderedFeatures calls for optional overlay layers
(USFS trails, BLM roads) that may not exist in the current style.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 21:59:04 +00:00
cf55055b62 Revert "fix(PlaceCard): prioritize wikidata path for boundary fetch"
This reverts commit 2e0a885476.
2026-05-01 18:34:36 +00:00
40855e1261 Revert "feat(themes): add theme-aware boundary highlight config"
This reverts commit fef10664c8.
2026-05-01 18:34:36 +00:00
fef10664c8 feat(themes): add theme-aware boundary highlight config
Add highlight section to overlay config for all themes with
theme-appropriate colors:
- dark: muted olive-green (#7a9a6b)
- light: forest green (#4a7040)
- clean: Google blue (#1a73e8)
- cyberpunk: electric cyan (#00f0ff)

Update addBoundaryLayer() to read config from
getOverlayConfig(themeId, "highlight") for consistent styling
across all themes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 18:26:13 +00:00
2e0a885476 fix(PlaceCard): prioritize wikidata path for boundary fetch
When clicking basemap labels with wikidata IDs (cities, parks, etc),
fetchReverse was returning the nearest POI instead of the clicked
entity, blocking the wikidata fallback that returns correct boundaries.

Changes:
- Effect 1: Skip reverse geocode when wikidataId is present
- Effect 3: Always use wikidata path when available, regardless of
  osmType/osmId presence

This fixes missing dashed outline on area feature clicks.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 18:21:20 +00:00
6fb3ee4f49 feat(themes): add Cyberpunk theme with custom fonts
Add a dark, neon-soaked, dystopian command center theme:

Map colors:
- Near-black base (#0a0a14) with blue-purple undertones
- Magenta motorways (#ff2d6b), purple primary roads (#8833aa)
- Inky dark water (#06061a), barely-visible dark teal vegetation
- Cool white labels with dark halos for readability
- Neon POI icons (cyan, magenta, green)

UI styling:
- Dark translucent panels with magenta accent borders
- Custom fonts: Orbitron (headings), Share Tech Mono (body)
- Entire UI renders in monospace terminal aesthetic
- Magenta shadows, cyan route lines, neon status colors
- Pin markers in magenta (origin) and cyan (destination)

Overlay adjustments:
- Dramatic hillshade with darker shadows
- Very subtle contours (opacityMod: 0.5)
- USFS/BLM trails in purple/magenta/cyan family
- Public lands with muted teal fills

Satellite adjustments:
- Darkened (brightnessMax: 0.30), desaturated, purple-shifted

Also adds --font-heading CSS variable to all themes for future
custom heading font support.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 18:06:43 +00:00
a7fd4e4e8c feat(themes): add theme picker with swatch previews and per-theme fonts
PART 1: Add missing CSS variables to all ui objects
- Add --bg-inset, --bg-muted for component backgrounds
- Add --success, --warning as aliases for --status-success/warning
- Add --warning-muted for warning background states
- Each theme now has 32 CSS variables

PART 2: Per-theme font support
- Move --font-sans and --font-mono from :root to ui objects
- Add fontImports array to theme config (for future custom fonts)
- applyThemeUI() now manages <link> tags for font imports
- Existing themes use empty fontImports (system fonts already loaded)

PART 3: Swatch preview colors
- Add swatch array (3 hex colors) to each theme for visual preview
- light: warm tan, sage green, khaki
- dark: dark brown, sage green, tan
- clean: light gray, Google blue, Google green
- themeList() now returns swatch in result shape

PART 4: Theme picker UI
- New ThemePicker component replaces icon toggle in header
- Palette icon trigger opens popover below
- Shows all themes as circular swatches (conic gradient)
- Active theme has accent ring indicator
- Click swatch to apply theme, closes popover
- Click outside or Escape closes popover
- Styled with current theme CSS variables

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 17:42:51 +00:00
7ec87f0945 feat(themes): add Clean theme — Google Maps-inspired style
Add a plain, utilitarian theme focused on readability and wayfinding:
- White/light gray land (#f5f5f5), soft pastel green parks (#c3ecb2)
- Gentle blue water (#aadaff) with classic road hierarchy
- White minor roads, yellow primary (#fbc02d), orange motorway (#f9a825)
- Pure white UI panels with Google-standard gray text
- All 73 protomaps flavor keys + pois + landcover objects
- Full UI CSS custom properties using Google color palette
- Overlay config for hillshade, contours, public lands, trails

Update theme switcher to cycle through all available themes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 16:27:08 +00:00
f0acea33a0 feat(themes): consolidate UI CSS properties into theme registry
- Add darkUI and lightUI objects with all 25 CSS custom properties
- Add applyThemeUI() function to apply CSS vars via JavaScript
- Update useTheme.js to call applyThemeUI() instead of setAttribute
- Remove [data-theme="dark"] and [data-theme="light"] from index.css
- Custom themes can now override individual UI properties with cascade
- Update README.md to document the ui key and cascade behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 16:17:26 +00:00
9530fbbf76 Wire overlay layers to read styling from theme registry
All overlay layer add functions now read colors, opacities, and widths
from the theme registry instead of hardcoded dark/light branches.

registry.js changes:
- Add complete darkOverlay and lightOverlay config objects
- Each overlay layer has its own config section:
  - hillshade: exaggeration, illuminationDirection, shadowColor, highlightColor
  - traffic: opacity
  - contours: colors, opacities, widths (with opacityMod), label styling
  - contoursTest: cascades from contours, overrides colors
  - contoursTest10ft: cascades from contours, overrides colors
  - publicLands: per-category fill/outline colors and opacities, labels
  - usfsTrails: roads/trails colors by use type, labels
  - blmTrails: route colors by use class, labels
- Add getOverlayConfig(themeId, layerKey) function
- Contour variants cascade missing keys from same theme's contours
- Width values use self-documenting object format: { z11: 0.5, z14: 1.0 }

MapView.jsx changes:
- All 8 overlay add functions now take themeId parameter
- Functions call getOverlayConfig() to get merged config
- No hardcoded color/opacity/width values remain in overlay functions
- Theme switching re-adds all active overlays with new theme config

This is a refactor - light and dark themes render identically to before.
Custom themes can now override individual overlay styling values.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 15:48:12 +00:00
c701463283 Add theme registry for custom protomaps flavor support
Introduces src/themes/registry.js with:
- getTheme(id) - lookup theme config by ID
- getThemeColors(id) - get flavor object (namedTheme for built-ins, custom colors for others)
- getThemeSprite(id) - get sprite URL with fallback for custom themes
- themeList() - list available themes for UI

Updates MapView.jsx:
- Import registry functions instead of namedTheme directly
- buildStyle() uses getThemeColors() and getThemeSprite()
- Overlay add functions use isCurrentThemeDark() helper that checks
  registry dark flag instead of string comparison

Reference files:
- dark-flavor-reference.json - full namedTheme('dark') output (73 flat keys + pois + landcover)
- light-flavor-reference.json - full namedTheme('light') output
- README.md - schema documentation for creating custom themes

This is a refactor only - light/dark themes render identically to before.
Custom themes can now be added to registry.js with full flavor objects.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-05-01 15:27:01 +00:00
a39371a7a0 Use more distinct colors for trail types
- 4WD High Clearance: bright orange
- 4WD Low: yellow/gold (was tan)
- ATV: red (was rust)
- Single Track: purple (was dark red)
- 2WD/Easy: light yellow (was light tan)
- Non-motorized: brighter green
- Snow: blue (unchanged)

Colors now spread across spectrum for easier distinction.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 21:34:06 +00:00
9ae1594a4c Brighten and unify USFS/BLM trail styling
- Increase opacity to 0.9 for better visibility
- Thicker lines (2.0 -> 4.0px across zoom levels)
- Unified brighter color palette:
  - Orange: motorized/4WD high clearance
  - Amber/tan: 4WD low, bikes
  - Rust: ATV
  - Green: non-motorized (hiking/horse)
  - Blue: snow routes
- USFS trails now color-coded by allowed use
- Larger label text (11px) with better contrast

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 21:29:55 +00:00
c4750c94ba Filter BLM: exclude urban types, keep unknown/resource
- Exclude ARTERIAL, COLLECTOR, LOCAL, paved, highways
- Keep RESOURCE, UNKNOWN, and empty functional class
- Most BLM data has empty func class, so whitelist was too strict

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 21:09:16 +00:00
6aeaedbcc0 Filter BLM layer to RESOURCE class only
- Only show routes with RESOURCE functional class
- Removes all urban, local, and unknown roads
- Keeps backcountry access routes only

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 21:06:36 +00:00
f788aefae6 Filter out urban roads from BLM layer
- Exclude ARTERIAL and COLLECTOR functional classes
- Exclude any route with HWY_CLASS (highways)
- Keeps RESOURCE, LOCAL, and UNKNOWN in rural areas

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 20:58:58 +00:00
e2d5ca9718 Style BLM routes by surface type and vehicle class
- Filter out SOLID SURFACE (paved roads)
- Color by route use class:
  - Orange: 4WD High Clearance
  - Tan: 4WD Low
  - Red-brown: ATV
  - Dark red: Motorized Single Track
  - Light tan: 2WD Low
  - Green: Non-Mechanized
- Line pattern by surface type:
  - Solid: Natural (dirt)
  - Dashed: Natural Improved (graded)
  - Dotted: Aggregate (gravel)
  - Dash-dot: Snow
  - Dash-dot-dot: Other/Unknown
- Snow routes use distinct blue color

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 20:53:38 +00:00
efebf74522 Add BLM roads/trails layer
- Add BLM routes vector source from pmtiles
- Style: dashed olive/sage lines, distinct from USFS
- Labels at zoom 12+ using ROUTE_PRMRY_NM
- Hit-area layer (14px) for click targets
- Popup showing route name, asset class, transport, surface, length
- "BLM Roads" toggle in Layer Control panel
- Feature-flag gated: has_blm_trails (default false)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 20:40:44 +00:00
e1d56ff925 feat(map): add invisible hit-area layers for USFS trails/roads
- Add 14px wide transparent hit layers below visible styled layers
- Click events now target hit layers for easier selection
- Cursor changes to pointer on hover over hit layers
- Keeps visual styling thin while providing fat click targets

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 17:30:39 +00:00
2b90f8b17a feat(map): add USFS trails and roads layer
- Add USFS trails/roads as toggleable map layer via PMTiles
- Trails: dashed brown lines, roads: solid khaki lines
- Labels at zoom 12+ for trail and road names
- Click handler shows popup with trail/road info
- Feature-flag gated with has_usfs_trails (default false)
- Add Trails toggle to Layer Control panel

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 16:43:30 +00:00
e53ff561e8 feat(keyboard): add Escape key to close/deselect place card
Pressing Escape when a place is selected now:
- Closes the place card
- Clears the selected place state
- Removes the boundary outline from the map
- Clears the selected label highlight

Same behavior as clicking empty map area.
2026-04-30 03:41:22 +00:00
a1a499de07 style(labels): improve label readability with Google Maps-style halos
Apply solid opaque halos to interactive label layers for clean knockout
against any background (parks, water, terrain):

BASE (unhighlighted):
- Text: #2a2a2a (light) / #e0e0e0 (dark)
- Halo: solid white/black, 0.9 opacity, 1.8px width
- Acts as background knockout, not decoration

HOVER:
- Text: pure black/white for focus
- Halo: full opacity (1.0), 2px width
- Subtle emphasis without glowing effect

SELECTED:
- Text: accent color (theme green)
- Halo: solid white/black, full opacity, 2.2px width
- Clear visual distinction for clicked item

Key insight: halo is a readability tool, not visual effect.
Keep it tight, opaque, and matching background intent.
2026-04-30 03:37:04 +00:00
5010b45a7c fix(highlight): use data-driven expressions to target specific features
Instead of changing entire layer paint properties (which highlights all
labels in the layer), use MapLibre case expressions to target only the
specific feature by name. This prevents highlighting ALL labels when
hovering/selecting one.

Expression format:
  ["case", ["==", ["get", "name"], featureName], highlightColor, originalColor]

Fixes text duplication at z14+ on small places.
2026-04-30 03:07:43 +00:00
39996fdafe fix(map): boundary fill opacity and highlight text duplication
Two fixes for rendering at close zoom (z14+):

1. Boundary rendering:
   - Add subtle fill layer with 0.05 opacity (barely visible tint)
   - Insert fill and outline layers BELOW symbol layers using
     firstSymbolId so labels render on top
   - Dashed outline remains primary indicator

2. Highlight text duplication:
   - Remove separate hover-hl-* and selected-hl-* symbol layers
     that were creating duplicate/ghost text
   - Instead, modify ORIGINAL layer paint properties directly using
     setPaintProperty on text-color, text-halo-color, text-halo-width
   - Store original paint values for restoration on clear
   - Single symbol layer per label = no duplication

Test at z14+ on small places like Rock Creek Park - no text ghosting.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 03:03:18 +00:00
68f0a8dff7 fix(map): atomic boundary transition when switching places
Remove the clear-then-set pattern when clicking a new labeled feature.
Previously, clicking Kimberly after Twin Falls would:
1. Clear Twin Falls boundary
2. Set new place
3. Wait for API to return
4. Set Kimberly boundary

This caused the old boundary to disappear before the new one was ready,
requiring two clicks.

Now when clicking a new labeled feature:
1. Set new place immediately
2. When API returns, updateBoundary(newData) replaces old data in-place

The GeoJSON source only holds one dataset - setting new data naturally
replaces old data. Explicit clear only needed when deselecting or
clicking empty map.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-30 01:43:19 +00:00
ac7cec972f fix(map): call updateBoundary directly, remove useEffect
The useEffect-based boundary rendering was unreliable due to React's
state lifecycle - the effect would fire before boundary data arrived
from the API, then not re-trigger properly when data was populated.

New approach:
- Remove the boundary useEffect entirely
- Define updateBoundary function in map load handler
- Store function reference in Zustand store and local ref
- PlaceCard calls updateBoundary(geometry) directly when API returns
- Click handlers call updateBoundary(null) to clear

This bypasses React's render cycle - the map library handles its own
state and we tell it what to draw when we have the data.

Test sequence:
- Click Twin Falls → boundary shows on first click
- Click Kimberly → boundary shows on first click
- Switch between them → old clears, new shows
- Click empty map → boundary clears

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 23:23:11 +00:00
b657c0f000 fix(map): re-trigger boundary render when API data arrives
The boundary useEffect was only triggered when selectedPlace changed,
but boundary data arrives asynchronously from /api/place fetch. By the
time fetchPlaceDetails completed and enriched selectedPlace with
boundary, the useEffect had already fired and saw no boundary.

Fix: add selectedPlace?.boundary to the dependency array so the effect
re-runs when boundary data is populated by the API response.

Test sequence:
- Click Twin Falls → boundary shows on first click
- Click Kimberly → boundary shows on first click (was broken)
- Click empty map → boundary clears
- Click Twin Falls again → boundary shows on first click

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 23:12:37 +00:00
29f995d885 fix(map): boundary lifecycle cleanup on place deselection
Clear boundary source data when:
- Clicking outside the marker circle (deselecting)
- Clicking a new place (before setting new boundary)
- Clicking empty map area (generic map click)

This ensures:
1. Re-clicking the same city after dismissing re-renders boundary
   (selectedPlace is properly cleared, triggering fresh useEffect)
2. Clicking away doesn't leave stale boundary outline
   (boundary source explicitly cleared to empty FeatureCollection)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 23:07:41 +00:00
472ef4d0e8 fix(map): resolve initialization crashes and boundary rendering
Fixes three critical bugs:

1. CRASH: Guard addSource/addLayer calls with existence checks to
   prevent "Source already exists" errors in React strict mode
   double-mount scenarios

2. BOUNDARY: Wrap boundary update logic in a function and properly
   handle async style loading - check isStyleLoaded() and use
   map.once('load') as fallback

3. FONTS: Use 'Noto Sans Regular' for highlight layers instead of
   'Noto Sans Medium'/'Noto Sans Bold' which 404 on protomaps CDN

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 22:47:24 +00:00
4edc453835 fix(map): use filter-based highlights for PMTiles compatibility
Replace feature-state based highlighting with filter-based approach
using dedicated highlight layers. PMTiles don't have feature IDs,
causing setFeatureState to silently fail. The new approach:

- Creates hover-hl-* and selected-hl-* layers per source-layer
- Uses EMPTY_FILTER to hide layers by default
- Updates filter to match feature name when highlighting
- Preserves all existing functionality (zoom, boundary, place card)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 22:33:13 +00:00
b381d8d97f feat(map): add hover and click highlight for interactive features
- Add visual hover feedback on map labels (cities, POIs, regions)
  using MapLibre feature-state paint property expressions
- Hover: cursor pointer + brighter text + subtle halo glow
- Click highlight: accent color text + accent glow halo
- Highlight persists until place card closed or different feature clicked
- Remove DOM overlay marker for feature mode (use native paint instead)
- Consolidate interactive layers into INTERACTIVE_LAYERS constant
- Re-apply styles on theme change

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 21:46:35 +00:00
85a4e71def Redesign wiki links in place card
- Remove redundant "Read more (local)" links from WikiSummarySection
- Summary text now stands alone with population info
- LINKS section now shows Wikipedia/Wikivoyage/Wikidata with brand icons
- Use simple monochrome SVG icons for each wiki service
- Wikipedia and Wikivoyage show (local) indicator when served from Kiwix
- Falls back to wikipedia.org when wiki_url is not available

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 19:19:19 +00:00
bc8db10101 Use local wiki_url in LINKS section when available
When wiki_url is present from the API (has_kiwix_wiki enabled with local
coverage), use it instead of building a wikipedia.org link. Shows article
name with (local) indicator consistent with the Read More link.

Also adds wikivoyage_url link when available.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 19:03:08 +00:00
Ubuntu
497a671504 fix(place): add reverse geocode fallback for place details
When a place is selected without osm_type/osm_id (e.g., clicking
on a basemap label), trigger a reverse geocode to obtain the OSM
identifiers. This enables fetching place details including boundary,
wiki_summary, and other enriched data.

The existing placeDetails useEffect will then fire once the
osm_type/osm_id are available in the selectedPlace.raw object.

Co-Authored-By: Claude <noreply@anthropic.com>
2026-04-29 18:32:41 +00:00
Ubuntu
e42ed06a5c feat(place): add wiki summary display from Kiwix
When place API response includes wiki_summary, display:
- Summary text in PlaceCard and PlaceDetail
- Population with Users icon if wiki_population present
- "Read more" link to wiki_url (local Kiwix article)
- "Travel guide" link if wikivoyage_url present
- (local) indicator on wiki links to signal Kiwix-served content

Gate on has_kiwix_wiki feature flag - no changes when disabled
or when wiki_summary not present in response.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-04-29 17:11:09 +00:00
cb7c6d1497 fix: Save wedge highlights when authenticated 2026-04-29 00:08:08 +00:00
a1f929e10a fix: measure tool — multi-point with segment distances and running total 2026-04-28 23:41:09 +00:00