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>
This commit is contained in:
Matt 2026-05-01 18:26:13 +00:00
commit fef10664c8
4 changed files with 1485 additions and 1431 deletions

View file

@ -1247,10 +1247,10 @@ function removeBlmTrails(map) {
} }
/** Add boundary polygon layers with computed accent color (MapLibre rejects CSS vars in paint) */ /** Add boundary polygon layers using theme-aware highlight config */
const BOUNDARY_FILL_LAYER = 'boundary-fill-layer' const BOUNDARY_FILL_LAYER = 'boundary-fill-layer'
function addBoundaryLayer(map) { function addBoundaryLayer(map, themeId) {
if (!map || map.getLayer(BOUNDARY_LAYER)) return if (!map || map.getLayer(BOUNDARY_LAYER)) return
if (!map.getSource(BOUNDARY_SOURCE)) { if (!map.getSource(BOUNDARY_SOURCE)) {
map.addSource(BOUNDARY_SOURCE, { map.addSource(BOUNDARY_SOURCE, {
@ -1258,7 +1258,14 @@ function addBoundaryLayer(map) {
data: { type: "FeatureCollection", features: [] }, data: { type: "FeatureCollection", features: [] },
}) })
} }
const accentColor = getComputedStyle(document.documentElement).getPropertyValue("--accent").trim() || "#7a9a6b" // Get highlight config from theme overlay
const highlight = getOverlayConfig(themeId, "highlight") || {}
const lineColor = highlight.lineColor || "#7a9a6b"
const lineWidth = highlight.lineWidth || 2
const lineDash = highlight.lineDash || [4, 4]
const lineOpacity = highlight.lineOpacity || 0.8
const fillColor = highlight.fillColor || lineColor
const fillOpacity = highlight.fillOpacity || 0.08
// Find first symbol layer to insert boundary layers below labels // Find first symbol layer to insert boundary layers below labels
const layers = map.getStyle().layers const layers = map.getStyle().layers
@ -1276,8 +1283,8 @@ function addBoundaryLayer(map) {
type: "fill", type: "fill",
source: BOUNDARY_SOURCE, source: BOUNDARY_SOURCE,
paint: { paint: {
"fill-color": accentColor, "fill-color": fillColor,
"fill-opacity": 0.05, "fill-opacity": fillOpacity,
}, },
}, firstSymbolId) }, firstSymbolId)
@ -1287,10 +1294,10 @@ function addBoundaryLayer(map) {
type: "line", type: "line",
source: BOUNDARY_SOURCE, source: BOUNDARY_SOURCE,
paint: { paint: {
"line-color": accentColor, "line-color": lineColor,
"line-width": 2, "line-width": lineWidth,
"line-opacity": 0.7, "line-opacity": lineOpacity,
"line-dasharray": [3, 2], "line-dasharray": lineDash,
}, },
}, firstSymbolId) }, firstSymbolId)
} }
@ -1498,7 +1505,14 @@ const MapView = forwardRef(function MapView(_, ref) {
type: "geojson", type: "geojson",
data: { type: "FeatureCollection", features: [] }, data: { type: "FeatureCollection", features: [] },
}) })
const accentColor = getComputedStyle(document.documentElement).getPropertyValue("--accent").trim() || "#7a9a6b" // Get highlight config from theme overlay
const highlight = getOverlayConfig(themeId, "highlight") || {}
const lineColor = highlight.lineColor || "#7a9a6b"
const lineWidth = highlight.lineWidth || 2
const lineDash = highlight.lineDash || [4, 4]
const lineOpacity = highlight.lineOpacity || 0.8
const fillColor = highlight.fillColor || lineColor
const fillOpacity = highlight.fillOpacity || 0.08
map.addLayer({ map.addLayer({
id: MEASURE_LINE_LAYER, id: MEASURE_LINE_LAYER,
type: "line", type: "line",
@ -2124,7 +2138,7 @@ const MapView = forwardRef(function MapView(_, ref) {
// Boundary polygon layer for selected places // Boundary polygon layer for selected places
if (!map.getLayer(BOUNDARY_LAYER)) { if (!map.getLayer(BOUNDARY_LAYER)) {
addBoundaryLayer(map) addBoundaryLayer(map, currentThemeRef.current)
} }
// Apply improved base label styling for readability // Apply improved base label styling for readability
@ -2333,7 +2347,7 @@ const MapView = forwardRef(function MapView(_, ref) {
// Boundary polygon layer // Boundary polygon layer
if (!map.getLayer(BOUNDARY_LAYER)) { if (!map.getLayer(BOUNDARY_LAYER)) {
addBoundaryLayer(map) addBoundaryLayer(map, currentThemeRef.current)
} }
// Apply improved base label styling for readability // Apply improved base label styling for readability

View file

@ -1,369 +1,379 @@
/** /**
* Clean Theme for Navi * Clean Theme for Navi
* *
* A plain, familiar, Google Maps-inspired style focused on maximum usability. * A plain, familiar, Google Maps-inspired style focused on maximum usability.
* Clean, neutral, utilitarian. White/light gray land, soft pastel green parks, * Clean, neutral, utilitarian. White/light gray land, soft pastel green parks,
* gentle blue water, classic grayyelloworange road hierarchy. No strong * gentle blue water, classic grayyelloworange road hierarchy. No strong
* personality everything serves readability and wayfinding. * personality everything serves readability and wayfinding.
* *
* The theme equivalent of a rental car: nothing exciting, nothing wrong. * The theme equivalent of a rental car: nothing exciting, nothing wrong.
*/ */
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
// PALETTE // PALETTE
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
// //
// base: #f5f5f5 ← land, app background // base: #f5f5f5 ← land, app background
// surface: #ffffff ← panels, cards, modals // surface: #ffffff ← panels, cards, modals
// surfaceAlt: #f8f9fa ← secondary panels, hover states // surfaceAlt: #f8f9fa ← secondary panels, hover states
// border: #dadce0 ← Google's standard border gray // border: #dadce0 ← Google's standard border gray
// text: #202124 ← primary text (Google dark) // text: #202124 ← primary text (Google dark)
// textSecondary: #5f6368 ← secondary text // textSecondary: #5f6368 ← secondary text
// textMuted: #9aa0a6 ← placeholders, hints // textMuted: #9aa0a6 ← placeholders, hints
// accent: #1a73e8 ← Google blue — links, active states // accent: #1a73e8 ← Google blue — links, active states
// accentHover: #1557b0 ← darker blue hover // accentHover: #1557b0 ← darker blue hover
// success: #34a853 ← Google green // success: #34a853 ← Google green
// warning: #fbbc04 ← Google yellow // warning: #fbbc04 ← Google yellow
// danger: #ea4335 ← Google red // danger: #ea4335 ← Google red
// water: #aadaff ← soft sky blue (Google's water) // water: #aadaff ← soft sky blue (Google's water)
// waterDark: #73b3e8 ← water labels // waterDark: #73b3e8 ← water labels
// vegetation: #c3ecb2 ← pastel green parks // vegetation: #c3ecb2 ← pastel green parks
// forest: #a8dda0 ← slightly deeper green // forest: #a8dda0 ← slightly deeper green
// road: #ffffff ← minor roads — white // road: #ffffff ← minor roads — white
// roadPrimary: #fbc02d ← yellow // roadPrimary: #fbc02d ← yellow
// roadMotorway: #f9a825 ← deeper yellow-orange // roadMotorway: #f9a825 ← deeper yellow-orange
// roadCasing: #e0e0e0 ← light gray casing // roadCasing: #e0e0e0 ← light gray casing
// building: #e8e4de ← warm light gray // building: #e8e4de ← warm light gray
// contour: #c8b8a0 ← subtle warm brown // contour: #c8b8a0 ← subtle warm brown
// //
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
/** /**
* Map flavor colors - protomaps-themes-base schema * Map flavor colors - protomaps-themes-base schema
* All 73 flat keys + pois + landcover nested objects * All 73 flat keys + pois + landcover nested objects
*/ */
const cleanColors = { const cleanColors = {
// Background & earth // Background & earth
background: '#e8e8e8', background: '#e8e8e8',
earth: '#f5f5f5', earth: '#f5f5f5',
// Land use areas // Land use areas
park_a: '#d4ecd0', park_a: '#d4ecd0',
park_b: '#c3ecb2', park_b: '#c3ecb2',
hospital: '#fde8e8', hospital: '#fde8e8',
industrial: '#ebeff1', industrial: '#ebeff1',
school: '#fff3e0', school: '#fff3e0',
wood_a: '#d8ecd4', wood_a: '#d8ecd4',
wood_b: '#a8dda0', wood_b: '#a8dda0',
pedestrian: '#f0f0f0', pedestrian: '#f0f0f0',
scrub_a: '#dcecd8', scrub_a: '#dcecd8',
scrub_b: '#c8e4c0', scrub_b: '#c8e4c0',
glacier: '#f8fcff', glacier: '#f8fcff',
sand: '#f5f0e0', sand: '#f5f0e0',
beach: '#fef8e0', beach: '#fef8e0',
aerodrome: '#eaecef', aerodrome: '#eaecef',
runway: '#d0d0d0', runway: '#d0d0d0',
water: '#aadaff', water: '#aadaff',
zoo: '#d8e8d8', zoo: '#d8e8d8',
military: '#e8e8e8', military: '#e8e8e8',
// Tunnels // Tunnels
tunnel_other_casing: '#d8d8d8', tunnel_other_casing: '#d8d8d8',
tunnel_minor_casing: '#d8d8d8', tunnel_minor_casing: '#d8d8d8',
tunnel_link_casing: '#d8d8d8', tunnel_link_casing: '#d8d8d8',
tunnel_major_casing: '#d8d8d8', tunnel_major_casing: '#d8d8d8',
tunnel_highway_casing: '#d8d8d8', tunnel_highway_casing: '#d8d8d8',
tunnel_other: '#e8e8e8', tunnel_other: '#e8e8e8',
tunnel_minor: '#e8e8e8', tunnel_minor: '#e8e8e8',
tunnel_link: '#f0e0a0', tunnel_link: '#f0e0a0',
tunnel_major: '#f0e0a0', tunnel_major: '#f0e0a0',
tunnel_highway: '#f0d080', tunnel_highway: '#f0d080',
// Pier & buildings // Pier & buildings
pier: '#e0e0e0', pier: '#e0e0e0',
buildings: '#e8e4de', buildings: '#e8e4de',
// Roads & casings // Roads & casings
minor_service_casing: '#e0e0e0', minor_service_casing: '#e0e0e0',
minor_casing: '#e0e0e0', minor_casing: '#e0e0e0',
link_casing: '#d8c080', link_casing: '#d8c080',
major_casing_late: '#d8c080', major_casing_late: '#d8c080',
highway_casing_late: '#d8a860', highway_casing_late: '#d8a860',
other: '#f0f0f0', other: '#f0f0f0',
minor_service: '#ffffff', minor_service: '#ffffff',
minor_a: '#ffffff', minor_a: '#ffffff',
minor_b: '#ffffff', minor_b: '#ffffff',
link: '#fbc02d', link: '#fbc02d',
major_casing_early: '#d8c080', major_casing_early: '#d8c080',
major: '#fbc02d', major: '#fbc02d',
highway_casing_early: '#d8a860', highway_casing_early: '#d8a860',
highway: '#f9a825', highway: '#f9a825',
railway: '#a0a0a0', railway: '#a0a0a0',
boundaries: '#c0c0c0', boundaries: '#c0c0c0',
// Waterway label // Waterway label
waterway_label: '#73b3e8', waterway_label: '#73b3e8',
// Bridges // Bridges
bridges_other_casing: '#d0d0d0', bridges_other_casing: '#d0d0d0',
bridges_minor_casing: '#d0d0d0', bridges_minor_casing: '#d0d0d0',
bridges_link_casing: '#d8c080', bridges_link_casing: '#d8c080',
bridges_major_casing: '#d8c080', bridges_major_casing: '#d8c080',
bridges_highway_casing: '#d8a860', bridges_highway_casing: '#d8a860',
bridges_other: '#f0f0f0', bridges_other: '#f0f0f0',
bridges_minor: '#ffffff', bridges_minor: '#ffffff',
bridges_link: '#fbc02d', bridges_link: '#fbc02d',
bridges_major: '#fbc02d', bridges_major: '#fbc02d',
bridges_highway: '#f9a825', bridges_highway: '#f9a825',
// Labels // Labels
roads_label_minor: '#5f6368', roads_label_minor: '#5f6368',
roads_label_minor_halo: '#ffffff', roads_label_minor_halo: '#ffffff',
roads_label_major: '#5f6368', roads_label_major: '#5f6368',
roads_label_major_halo: '#ffffff', roads_label_major_halo: '#ffffff',
ocean_label: '#73b3e8', ocean_label: '#73b3e8',
peak_label: '#5f6368', peak_label: '#5f6368',
subplace_label: '#5f6368', subplace_label: '#5f6368',
subplace_label_halo: '#ffffff', subplace_label_halo: '#ffffff',
city_label: '#202124', city_label: '#202124',
city_label_halo: '#ffffff', city_label_halo: '#ffffff',
state_label: '#9aa0a6', state_label: '#9aa0a6',
state_label_halo: '#ffffff', state_label_halo: '#ffffff',
country_label: '#5f6368', country_label: '#5f6368',
address_label: '#5f6368', address_label: '#5f6368',
address_label_halo: '#ffffff', address_label_halo: '#ffffff',
// POI icon colors // POI icon colors
pois: { pois: {
blue: '#1a73e8', blue: '#1a73e8',
green: '#34a853', green: '#34a853',
lapis: '#4285f4', lapis: '#4285f4',
pink: '#e91e63', pink: '#e91e63',
red: '#ea4335', red: '#ea4335',
slategray: '#5f6368', slategray: '#5f6368',
tangerine: '#f9a825', tangerine: '#f9a825',
turquoise: '#00bcd4', turquoise: '#00bcd4',
}, },
// Landcover fill colors // Landcover fill colors
landcover: { landcover: {
grassland: 'rgba(200, 232, 192, 1)', grassland: 'rgba(200, 232, 192, 1)',
barren: 'rgba(240, 235, 220, 1)', barren: 'rgba(240, 235, 220, 1)',
urban_area: 'rgba(235, 235, 235, 1)', urban_area: 'rgba(235, 235, 235, 1)',
farmland: 'rgba(216, 240, 210, 1)', farmland: 'rgba(216, 240, 210, 1)',
glacier: 'rgba(250, 252, 255, 1)', glacier: 'rgba(250, 252, 255, 1)',
scrub: 'rgba(220, 236, 216, 1)', scrub: 'rgba(220, 236, 216, 1)',
forest: 'rgba(180, 224, 176, 1)', forest: 'rgba(180, 224, 176, 1)',
}, },
} }
/** /**
* UI CSS custom properties - app chrome styling * UI CSS custom properties - app chrome styling
* Clean Google-inspired white panels with standard gray text * Clean Google-inspired white panels with standard gray text
*/ */
const cleanUI = { const cleanUI = {
// Fonts // Fonts
'--font-sans': "'Inter', system-ui, -apple-system, sans-serif", '--font-sans': "'Inter', system-ui, -apple-system, sans-serif",
'--font-mono': "'JetBrains Mono', ui-monospace, monospace", '--font-mono': "'JetBrains Mono', ui-monospace, monospace",
'--font-heading': "'Inter', system-ui, -apple-system, sans-serif", '--font-heading': "'Inter', system-ui, -apple-system, sans-serif",
// Backgrounds // Backgrounds
'--bg-base': '#f5f5f5', '--bg-base': '#f5f5f5',
'--bg-raised': '#ffffff', '--bg-raised': '#ffffff',
'--bg-overlay': '#ffffff', '--bg-overlay': '#ffffff',
'--bg-input': '#ffffff', '--bg-input': '#ffffff',
'--bg-inset': '#f0f0f0', '--bg-inset': '#f0f0f0',
'--bg-muted': '#f8f9fa', '--bg-muted': '#f8f9fa',
// Text // Text
'--text-primary': '#202124', '--text-primary': '#202124',
'--text-secondary': '#5f6368', '--text-secondary': '#5f6368',
'--text-tertiary': '#9aa0a6', '--text-tertiary': '#9aa0a6',
'--text-inverse': '#ffffff', '--text-inverse': '#ffffff',
// Borders // Borders
'--border': '#dadce0', '--border': '#dadce0',
'--border-subtle': '#e8eaed', '--border-subtle': '#e8eaed',
// Accent // Accent
'--accent': '#1a73e8', '--accent': '#1a73e8',
'--accent-hover': '#1557b0', '--accent-hover': '#1557b0',
'--accent-muted': '#e8f0fe', '--accent-muted': '#e8f0fe',
// Tan // Tan
'--tan': '#f9a825', '--tan': '#f9a825',
'--tan-muted': '#fef7e0', '--tan-muted': '#fef7e0',
// Pins // Pins
'--pin-origin': '#34a853', '--pin-origin': '#34a853',
'--pin-destination': '#ea4335', '--pin-destination': '#ea4335',
'--pin-intermediate': '#5f6368', '--pin-intermediate': '#5f6368',
'--pin-stroke': '#ffffff', '--pin-stroke': '#ffffff',
// Status // Status
'--status-success': '#34a853', '--status-success': '#34a853',
'--status-warning': '#fbbc04', '--status-warning': '#fbbc04',
'--status-danger': '#ea4335', '--status-danger': '#ea4335',
'--success': '#34a853', '--success': '#34a853',
'--warning': '#fbbc04', '--warning': '#fbbc04',
'--warning-muted': '#fef7e0', '--warning-muted': '#fef7e0',
// Route // Route
'--route-line': '#1a73e8', '--route-line': '#1a73e8',
// Shadows // Shadows
'--shadow': '0 1px 3px rgba(60, 64, 67, 0.15), 0 1px 2px rgba(60, 64, 67, 0.1)', '--shadow': '0 1px 3px rgba(60, 64, 67, 0.15), 0 1px 2px rgba(60, 64, 67, 0.1)',
'--shadow-lg': '0 2px 6px rgba(60, 64, 67, 0.2), 0 1px 3px rgba(60, 64, 67, 0.15)', '--shadow-lg': '0 2px 6px rgba(60, 64, 67, 0.2), 0 1px 3px rgba(60, 64, 67, 0.15)',
} }
/** /**
* Overlay configuration overrides * Overlay configuration overrides
* Light shadow hillshade, warm brown contours, standard public lands * Light shadow hillshade, warm brown contours, standard public lands
*/ */
const cleanOverlay = { const cleanOverlay = {
// Hillshade - light and natural // Hillshade - light and natural
hillshade: { hillshade: {
exaggeration: 0.4, exaggeration: 0.4,
illuminationDirection: 315, illuminationDirection: 315,
shadowColor: '#000000', shadowColor: '#000000',
highlightColor: '#ffffff', highlightColor: '#ffffff',
}, },
// Contours - warm brown, subtle // Contours - warm brown, subtle
contours: { contours: {
opacityMod: 0.9, opacityMod: 0.9,
minorColor: '#c8b8a0', minorColor: '#c8b8a0',
minorOpacity: 0.35, minorOpacity: 0.35,
minorWidth: { z11: 0.5, z14: 0.8 }, minorWidth: { z11: 0.5, z14: 0.8 },
intermediateColor: '#c8b8a0', intermediateColor: '#c8b8a0',
intermediateOpacity: 0.55, intermediateOpacity: 0.55,
intermediateWidth: { z8: 0.7, z14: 1.0 }, intermediateWidth: { z8: 0.7, z14: 1.0 },
indexColor: '#a89878', indexColor: '#a89878',
indexOpacity: 0.75, indexOpacity: 0.75,
indexWidth: { z4: 1.0, z14: 1.5 }, indexWidth: { z4: 1.0, z14: 1.5 },
labelColor: '#8a7a60', labelColor: '#8a7a60',
labelHaloColor: '#ffffff', labelHaloColor: '#ffffff',
labelHaloWidth: 1.5, labelHaloWidth: 1.5,
labelOpacity: 0.8, labelOpacity: 0.8,
labelSize: 10, labelSize: 10,
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
}, },
// Contours Test - blue variant // Contours Test - blue variant
contoursTest: { contoursTest: {
minorColor: '#5a9ab8', minorColor: '#5a9ab8',
intermediateColor: '#5a9ab8', intermediateColor: '#5a9ab8',
indexColor: '#3a7a98', indexColor: '#3a7a98',
labelColor: '#3a6a88', labelColor: '#3a6a88',
}, },
// Contours Test 10ft - green variant // Contours Test 10ft - green variant
contoursTest10ft: { contoursTest10ft: {
minorColor: '#4a9a5f', minorColor: '#4a9a5f',
intermediateColor: '#4a9a5f', intermediateColor: '#4a9a5f',
indexColor: '#2a7a4a', indexColor: '#2a7a4a',
labelColor: '#2a5a40', labelColor: '#2a5a40',
}, },
// Public Lands - standard green tints with dark labels // Public Lands - standard green tints with dark labels
publicLands: { publicLands: {
opacityMod: 0.9, opacityMod: 0.9,
// Fill colors per category // Fill colors per category
fillWA: '#8a7a40', fillWA: '#8a7a40',
fillNPS: '#4a8030', fillNPS: '#4a8030',
fillUSFS: '#6a9040', fillUSFS: '#6a9040',
fillBLM: '#d4b880', fillBLM: '#d4b880',
fillFWS: '#5a9068', fillFWS: '#5a9068',
fillSTAT: '#6aa088', fillSTAT: '#6aa088',
fillLOC: '#9ab8a8', fillLOC: '#9ab8a8',
fillDefault: '#b0b0b0', fillDefault: '#b0b0b0',
// Fill opacities // Fill opacities
fillOpacityWA: 0.25, fillOpacityWA: 0.25,
fillOpacityNPS: 0.25, fillOpacityNPS: 0.25,
fillOpacityUSFS: 0.20, fillOpacityUSFS: 0.20,
fillOpacityBLM: 0.18, fillOpacityBLM: 0.18,
fillOpacitySTAT: 0.22, fillOpacitySTAT: 0.22,
fillOpacityLOC: 0.18, fillOpacityLOC: 0.18,
fillOpacityDefault: 0.12, fillOpacityDefault: 0.12,
// Outline colors // Outline colors
outlineWA: '#6a5a28', outlineWA: '#6a5a28',
outlineNPS: '#2a5018', outlineNPS: '#2a5018',
outlineUSFS: '#4a6828', outlineUSFS: '#4a6828',
outlineBLM: '#9a8050', outlineBLM: '#9a8050',
outlineFWS: '#3a6848', outlineFWS: '#3a6848',
outlineSTAT: '#4a7060', outlineSTAT: '#4a7060',
outlineLOC: '#6a8070', outlineLOC: '#6a8070',
outlineDefault: '#808080', outlineDefault: '#808080',
// Outline opacities // Outline opacities
outlineOpacityNPS: 0.65, outlineOpacityNPS: 0.65,
outlineOpacityUSFS: 0.55, outlineOpacityUSFS: 0.55,
outlineOpacityDefault: 0.45, outlineOpacityDefault: 0.45,
// Outline width // Outline width
outlineWidth: { z4: 0.3, z8: 0.8, z12: 1.2 }, outlineWidth: { z4: 0.3, z8: 0.8, z12: 1.2 },
// Labels - dark for readability // Labels - dark for readability
labelColor: '#2a3a28', labelColor: '#2a3a28',
labelHaloColor: '#ffffff', labelHaloColor: '#ffffff',
labelHaloWidth: 1.5, labelHaloWidth: 1.5,
labelOpacity: 0.85, labelOpacity: 0.85,
labelSize: { z10: 10, z14: 13 }, labelSize: { z10: 10, z14: 13 },
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
}, },
// USFS Trails - standard trail colors // USFS Trails - standard trail colors
usfsTrails: { usfsTrails: {
roadsColor: '#c09050', roadsColor: '#c09050',
roadsOpacity: 0.85, roadsOpacity: 0.85,
roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 }, roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 },
trailsMotorized: '#e07030', trailsMotorized: '#e07030',
trailsBicycle: '#d0a030', trailsBicycle: '#d0a030',
trailsHiker: '#50b040', trailsHiker: '#50b040',
trailsDefault: '#b09050', trailsDefault: '#b09050',
trailsOpacity: 0.85, trailsOpacity: 0.85,
trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 }, trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
trailsDash: [2, 1.5], trailsDash: [2, 1.5],
roadsLabelColor: '#5a4a30', roadsLabelColor: '#5a4a30',
roadsLabelHaloColor: '#ffffff', roadsLabelHaloColor: '#ffffff',
roadsLabelHaloWidth: 1.5, roadsLabelHaloWidth: 1.5,
roadsLabelOpacity: 0.85, roadsLabelOpacity: 0.85,
roadsLabelSize: 11, roadsLabelSize: 11,
trailsLabelColor: '#4a3a28', trailsLabelColor: '#4a3a28',
trailsLabelHaloColor: '#ffffff', trailsLabelHaloColor: '#ffffff',
trailsLabelHaloWidth: 1.5, trailsLabelHaloWidth: 1.5,
trailsLabelOpacity: 0.85, trailsLabelOpacity: 0.85,
trailsLabelSize: 11, trailsLabelSize: 11,
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
hitWidth: 14, hitWidth: 14,
}, },
// BLM Trails - standard route colors // BLM Trails - standard route colors
blmTrails: { blmTrails: {
color4wdHigh: '#e07030', color4wdHigh: '#e07030',
color4wdLow: '#d0a030', color4wdLow: '#d0a030',
colorAtv: '#d03030', colorAtv: '#d03030',
colorMotoSingle: '#a060b0', colorMotoSingle: '#a060b0',
color2wdLow: '#e0c060', color2wdLow: '#e0c060',
colorNonMech: '#50b040', colorNonMech: '#50b040',
colorDefault: '#b09050', colorDefault: '#b09050',
colorSnow: '#6090c0', colorSnow: '#6090c0',
lineOpacity: 0.85, lineOpacity: 0.85,
lineOpacityOther: 0.80, lineOpacityOther: 0.80,
lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 }, lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
dashImproved: [4, 2], dashImproved: [4, 2],
dashAggregate: [1, 2], dashAggregate: [1, 2],
dashSnow: [4, 2, 1, 2], dashSnow: [4, 2, 1, 2],
dashOther: [4, 2, 1, 2, 1, 2], dashOther: [4, 2, 1, 2, 1, 2],
labelColor: '#4a3a28', labelColor: '#4a3a28',
labelHaloColor: '#ffffff', labelHaloColor: '#ffffff',
labelHaloWidth: 1.5, labelHaloWidth: 1.5,
labelOpacity: 0.85, labelOpacity: 0.85,
labelSize: 11, labelSize: 11,
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
hitWidth: 14, hitWidth: 14,
}, },
}
// ── Highlight (boundary/selection) ────────────────────────────────────────
/** highlight: {
* Clean theme configuration lineColor: "#1a73e8", // Google blue for selection
*/ lineWidth: 2,
const cleanTheme = { lineDash: [4, 4],
id: 'clean', lineOpacity: 0.7,
name: 'Clean', fillColor: "#1a73e8",
dark: false, fillOpacity: 0.06,
colors: cleanColors, },
satellite: null, // No adjustments — default clear view }
overlay: cleanOverlay,
ui: cleanUI, /**
} * Clean theme configuration
*/
export default cleanTheme const cleanTheme = {
id: 'clean',
name: 'Clean',
dark: false,
colors: cleanColors,
satellite: null, // No adjustments — default clear view
overlay: cleanOverlay,
ui: cleanUI,
}
export default cleanTheme

View file

@ -1,403 +1,413 @@
/** /**
* Cyberpunk Theme for Navi * Cyberpunk Theme for Navi
* *
* Inspired by Mapbox's "Terminal" cyberpunk style, Blade Runner, and Ghost in * Inspired by Mapbox's "Terminal" cyberpunk style, Blade Runner, and Ghost in
* the Shell. A tactical display in a neon-lit command center. Near-black base * the Shell. A tactical display in a neon-lit command center. Near-black base
* with deep blue-purple undertones. Roads glow in hot magenta and electric cyan. * with deep blue-purple undertones. Roads glow in hot magenta and electric cyan.
* Water is inky dark. Vegetation is barely there dark teal hints. Labels are * Water is inky dark. Vegetation is barely there dark teal hints. Labels are
* cool white with colored halos. * cool white with colored halos.
* *
* The whole thing should feel like you're navigating Night City. * The whole thing should feel like you're navigating Night City.
* *
* CUSTOM FONTS: * CUSTOM FONTS:
* - Heading: "Orbitron" geometric, futuristic display font * - Heading: "Orbitron" geometric, futuristic display font
* - Body: "Share Tech Mono" monospaced terminal feel for entire UI * - Body: "Share Tech Mono" monospaced terminal feel for entire UI
*/ */
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
// PALETTE // PALETTE
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
// //
// base: #0a0a14 ← near-black with blue-purple undertone // base: #0a0a14 ← near-black with blue-purple undertone
// surface: #10101e ← panels, cards // surface: #10101e ← panels, cards
// surfaceAlt: #161628 ← secondary surfaces, hover states // surfaceAlt: #161628 ← secondary surfaces, hover states
// border: #1e1e3a ← subtle purple edges // border: #1e1e3a ← subtle purple edges
// text: #d0d0e8 ← cool white text // text: #d0d0e8 ← cool white text
// textSecondary: #8888aa ← lavender-gray // textSecondary: #8888aa ← lavender-gray
// textMuted: #5a5a7a ← dark purple-gray // textMuted: #5a5a7a ← dark purple-gray
// textInverse: #0a0a14 ← text on neon backgrounds // textInverse: #0a0a14 ← text on neon backgrounds
// accent: #ff2d6b ← hot pink/magenta — primary actions // accent: #ff2d6b ← hot pink/magenta — primary actions
// accentHover: #ff4d8b ← lighter magenta // accentHover: #ff4d8b ← lighter magenta
// accentAlt: #00f0ff ← electric cyan — secondary accent // accentAlt: #00f0ff ← electric cyan — secondary accent
// success: #00ff88 ← neon green // success: #00ff88 ← neon green
// warning: #ffaa00 ← amber // warning: #ffaa00 ← amber
// danger: #ff3333 ← neon red // danger: #ff3333 ← neon red
// water: #06061a ← deep dark blue-black // water: #06061a ← deep dark blue-black
// waterLabel: #3a6a8a ← muted blue for water labels // waterLabel: #3a6a8a ← muted blue for water labels
// vegetation: #0a1a12 ← barely-there dark teal-green // vegetation: #0a1a12 ← barely-there dark teal-green
// forest: #0e1e14 ← slightly deeper // forest: #0e1e14 ← slightly deeper
// road: #1a1a3a ← ghost purple minor roads // road: #1a1a3a ← ghost purple minor roads
// roadSecondary: #2a2a5a // roadSecondary: #2a2a5a
// roadPrimary: #8833aa ← purple for primary // roadPrimary: #8833aa ← purple for primary
// roadMotorway: #ff2d6b ← hot magenta for motorways // roadMotorway: #ff2d6b ← hot magenta for motorways
// roadCasing: #0a0a14 ← dark casing // roadCasing: #0a0a14 ← dark casing
// building: #141428 ← dark purple-gray buildings // building: #141428 ← dark purple-gray buildings
// contour: #1e1e3e ← dark lines, just visible // contour: #1e1e3e ← dark lines, just visible
// contourLabel: #5a5a7a // contourLabel: #5a5a7a
// //
// ═══════════════════════════════════════════════════════════════════════════ // ═══════════════════════════════════════════════════════════════════════════
/** /**
* Map flavor colors - protomaps-themes-base schema * Map flavor colors - protomaps-themes-base schema
* All 73 flat keys + pois + landcover nested objects * All 73 flat keys + pois + landcover nested objects
*/ */
const cyberpunkColors = { const cyberpunkColors = {
// Background & earth // Background & earth
background: '#08080f', background: '#08080f',
earth: '#0a0a14', earth: '#0a0a14',
// Land use areas - dark with slight purple undertones // Land use areas - dark with slight purple undertones
park_a: '#0a1a14', park_a: '#0a1a14',
park_b: '#0e1e18', park_b: '#0e1e18',
hospital: '#1a1020', hospital: '#1a1020',
industrial: '#0e0e1a', industrial: '#0e0e1a',
school: '#14101e', school: '#14101e',
wood_a: '#0a1a12', wood_a: '#0a1a12',
wood_b: '#0e1e14', wood_b: '#0e1e14',
pedestrian: '#0c0c18', pedestrian: '#0c0c18',
scrub_a: '#0a1410', scrub_a: '#0a1410',
scrub_b: '#0c1812', scrub_b: '#0c1812',
glacier: '#101020', glacier: '#101020',
sand: '#12101a', sand: '#12101a',
beach: '#14121c', beach: '#14121c',
aerodrome: '#0a0a16', aerodrome: '#0a0a16',
runway: '#1a1a30', runway: '#1a1a30',
water: '#06061a', water: '#06061a',
zoo: '#0c1614', zoo: '#0c1614',
military: '#100a14', military: '#100a14',
// Tunnels - dark purple casings // Tunnels - dark purple casings
tunnel_other_casing: '#0a0a14', tunnel_other_casing: '#0a0a14',
tunnel_minor_casing: '#0a0a14', tunnel_minor_casing: '#0a0a14',
tunnel_link_casing: '#0a0a14', tunnel_link_casing: '#0a0a14',
tunnel_major_casing: '#0a0a14', tunnel_major_casing: '#0a0a14',
tunnel_highway_casing: '#0a0a14', tunnel_highway_casing: '#0a0a14',
tunnel_other: '#161628', tunnel_other: '#161628',
tunnel_minor: '#161628', tunnel_minor: '#161628',
tunnel_link: '#2a2050', tunnel_link: '#2a2050',
tunnel_major: '#4a2870', tunnel_major: '#4a2870',
tunnel_highway: '#801848', tunnel_highway: '#801848',
// Pier & buildings // Pier & buildings
pier: '#1a1a30', pier: '#1a1a30',
buildings: '#141428', buildings: '#141428',
// Roads & casings - glowing neon progression // Roads & casings - glowing neon progression
minor_service_casing: '#0a0a14', minor_service_casing: '#0a0a14',
minor_casing: '#0a0a14', minor_casing: '#0a0a14',
link_casing: '#0a0a14', link_casing: '#0a0a14',
major_casing_late: '#0a0a14', major_casing_late: '#0a0a14',
highway_casing_late: '#0a0a14', highway_casing_late: '#0a0a14',
other: '#1a1a3a', other: '#1a1a3a',
minor_service: '#1a1a3a', minor_service: '#1a1a3a',
minor_a: '#2a2a5a', minor_a: '#2a2a5a',
minor_b: '#1a1a3a', minor_b: '#1a1a3a',
link: '#5a3888', link: '#5a3888',
major_casing_early: '#0a0a14', major_casing_early: '#0a0a14',
major: '#8833aa', major: '#8833aa',
highway_casing_early: '#0a0a14', highway_casing_early: '#0a0a14',
highway: '#ff2d6b', highway: '#ff2d6b',
railway: '#2a2050', railway: '#2a2050',
boundaries: '#4a4a6a', boundaries: '#4a4a6a',
// Waterway label // Waterway label
waterway_label: '#3a6a8a', waterway_label: '#3a6a8a',
// Bridges - same neon colors // Bridges - same neon colors
bridges_other_casing: '#0c0c18', bridges_other_casing: '#0c0c18',
bridges_minor_casing: '#0a0a14', bridges_minor_casing: '#0a0a14',
bridges_link_casing: '#0a0a14', bridges_link_casing: '#0a0a14',
bridges_major_casing: '#0a0a14', bridges_major_casing: '#0a0a14',
bridges_highway_casing: '#0a0a14', bridges_highway_casing: '#0a0a14',
bridges_other: '#1a1a3a', bridges_other: '#1a1a3a',
bridges_minor: '#2a2a5a', bridges_minor: '#2a2a5a',
bridges_link: '#5a3888', bridges_link: '#5a3888',
bridges_major: '#8833aa', bridges_major: '#8833aa',
bridges_highway: '#ff2d6b', bridges_highway: '#ff2d6b',
// Labels - cool white with DARK halos // Labels - cool white with DARK halos
roads_label_minor: '#8888aa', roads_label_minor: '#8888aa',
roads_label_minor_halo: '#0a0a14', roads_label_minor_halo: '#0a0a14',
roads_label_major: '#a0a0c0', roads_label_major: '#a0a0c0',
roads_label_major_halo: '#0a0a14', roads_label_major_halo: '#0a0a14',
ocean_label: '#3a6a8a', ocean_label: '#3a6a8a',
peak_label: '#8888aa', peak_label: '#8888aa',
subplace_label: '#8888aa', subplace_label: '#8888aa',
subplace_label_halo: '#0a0a14', subplace_label_halo: '#0a0a14',
city_label: '#d0d0e8', city_label: '#d0d0e8',
city_label_halo: '#0a0a14', city_label_halo: '#0a0a14',
state_label: '#5a5a7a', state_label: '#5a5a7a',
state_label_halo: '#0a0a14', state_label_halo: '#0a0a14',
country_label: '#7a7a9a', country_label: '#7a7a9a',
address_label: '#8888aa', address_label: '#8888aa',
address_label_halo: '#0a0a14', address_label_halo: '#0a0a14',
// POI icon colors - neon palette // POI icon colors - neon palette
pois: { pois: {
blue: '#00a0ff', blue: '#00a0ff',
green: '#00ff88', green: '#00ff88',
lapis: '#6060ff', lapis: '#6060ff',
pink: '#ff2d6b', pink: '#ff2d6b',
red: '#ff3333', red: '#ff3333',
slategray: '#8888aa', slategray: '#8888aa',
tangerine: '#ffaa00', tangerine: '#ffaa00',
turquoise: '#00f0ff', turquoise: '#00f0ff',
}, },
// Landcover fill colors - very dark, barely visible // Landcover fill colors - very dark, barely visible
landcover: { landcover: {
grassland: 'rgba(10, 26, 18, 1)', grassland: 'rgba(10, 26, 18, 1)',
barren: 'rgba(18, 16, 26, 1)', barren: 'rgba(18, 16, 26, 1)',
urban_area: 'rgba(14, 14, 26, 1)', urban_area: 'rgba(14, 14, 26, 1)',
farmland: 'rgba(12, 24, 16, 1)', farmland: 'rgba(12, 24, 16, 1)',
glacier: 'rgba(16, 16, 32, 1)', glacier: 'rgba(16, 16, 32, 1)',
scrub: 'rgba(12, 20, 16, 1)', scrub: 'rgba(12, 20, 16, 1)',
forest: 'rgba(14, 30, 20, 1)', forest: 'rgba(14, 30, 20, 1)',
}, },
} }
/** /**
* UI CSS custom properties - neon command center aesthetic * UI CSS custom properties - neon command center aesthetic
* Dark translucent panels with magenta/cyan accents * Dark translucent panels with magenta/cyan accents
*/ */
const cyberpunkUI = { const cyberpunkUI = {
// Fonts - monospace terminal feel // Fonts - monospace terminal feel
'--font-sans': "'Share Tech Mono', monospace", '--font-sans': "'Share Tech Mono', monospace",
'--font-mono': "'Share Tech Mono', monospace", '--font-mono': "'Share Tech Mono', monospace",
'--font-heading': "'Orbitron', sans-serif", '--font-heading': "'Orbitron', sans-serif",
// Backgrounds - dark with blue-purple undertone // Backgrounds - dark with blue-purple undertone
'--bg-base': '#0a0a14', '--bg-base': '#0a0a14',
'--bg-raised': '#10101e', '--bg-raised': '#10101e',
'--bg-overlay': '#161628', '--bg-overlay': '#161628',
'--bg-input': '#0c0c18', '--bg-input': '#0c0c18',
'--bg-inset': '#08080f', '--bg-inset': '#08080f',
'--bg-muted': '#12121e', '--bg-muted': '#12121e',
// Text - cool white spectrum // Text - cool white spectrum
'--text-primary': '#d0d0e8', '--text-primary': '#d0d0e8',
'--text-secondary': '#8888aa', '--text-secondary': '#8888aa',
'--text-tertiary': '#5a5a7a', '--text-tertiary': '#5a5a7a',
'--text-inverse': '#0a0a14', '--text-inverse': '#0a0a14',
// Borders - subtle purple edges // Borders - subtle purple edges
'--border': '#1e1e3a', '--border': '#1e1e3a',
'--border-subtle': '#141428', '--border-subtle': '#141428',
// Accent - hot magenta // Accent - hot magenta
'--accent': '#ff2d6b', '--accent': '#ff2d6b',
'--accent-hover': '#ff4d8b', '--accent-hover': '#ff4d8b',
'--accent-muted': '#3a1828', '--accent-muted': '#3a1828',
// Tan becomes cyan in this theme // Tan becomes cyan in this theme
'--tan': '#00f0ff', '--tan': '#00f0ff',
'--tan-muted': '#0a2830', '--tan-muted': '#0a2830',
// Pins - neon colors // Pins - neon colors
'--pin-origin': '#ff2d6b', '--pin-origin': '#ff2d6b',
'--pin-destination': '#00f0ff', '--pin-destination': '#00f0ff',
'--pin-intermediate': '#8833aa', '--pin-intermediate': '#8833aa',
'--pin-stroke': '#0a0a14', '--pin-stroke': '#0a0a14',
// Status - neon signals // Status - neon signals
'--status-success': '#00ff88', '--status-success': '#00ff88',
'--status-warning': '#ffaa00', '--status-warning': '#ffaa00',
'--status-danger': '#ff3333', '--status-danger': '#ff3333',
'--success': '#00ff88', '--success': '#00ff88',
'--warning': '#ffaa00', '--warning': '#ffaa00',
'--warning-muted': '#2a2010', '--warning-muted': '#2a2010',
// Route - cyan for contrast with magenta UI // Route - cyan for contrast with magenta UI
'--route-line': '#00f0ff', '--route-line': '#00f0ff',
// Shadows - subtle magenta glow // Shadows - subtle magenta glow
'--shadow': '0 2px 8px rgba(255, 45, 107, 0.25)', '--shadow': '0 2px 8px rgba(255, 45, 107, 0.25)',
'--shadow-lg': '0 4px 16px rgba(255, 45, 107, 0.35)', '--shadow-lg': '0 4px 16px rgba(255, 45, 107, 0.35)',
} }
/** /**
* Overlay configuration - subtle, muted for dark theme * Overlay configuration - subtle, muted for dark theme
*/ */
const cyberpunkOverlay = { const cyberpunkOverlay = {
// Hillshade - dramatic shadows // Hillshade - dramatic shadows
hillshade: { hillshade: {
exaggeration: 0.6, exaggeration: 0.6,
illuminationDirection: 315, illuminationDirection: 315,
shadowColor: '#000000', shadowColor: '#000000',
highlightColor: '#2a2a4a', highlightColor: '#2a2a4a',
}, },
// Contours - very subtle dark purple-gray // Contours - very subtle dark purple-gray
contours: { contours: {
opacityMod: 0.5, opacityMod: 0.5,
minorColor: '#1e1e3e', minorColor: '#1e1e3e',
minorOpacity: 0.3, minorOpacity: 0.3,
minorWidth: { z11: 0.4, z14: 0.8 }, minorWidth: { z11: 0.4, z14: 0.8 },
intermediateColor: '#2a2a4a', intermediateColor: '#2a2a4a',
intermediateOpacity: 0.4, intermediateOpacity: 0.4,
intermediateWidth: { z8: 0.6, z14: 1.0 }, intermediateWidth: { z8: 0.6, z14: 1.0 },
indexColor: '#3a3a5a', indexColor: '#3a3a5a',
indexOpacity: 0.5, indexOpacity: 0.5,
indexWidth: { z4: 0.8, z14: 1.2 }, indexWidth: { z4: 0.8, z14: 1.2 },
labelColor: '#5a5a7a', labelColor: '#5a5a7a',
labelHaloColor: '#0a0a14', labelHaloColor: '#0a0a14',
labelHaloWidth: 1.5, labelHaloWidth: 1.5,
labelOpacity: 0.6, labelOpacity: 0.6,
labelSize: 10, labelSize: 10,
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
}, },
// Contours Test - cyan variant // Contours Test - cyan variant
contoursTest: { contoursTest: {
minorColor: '#1a3a4a', minorColor: '#1a3a4a',
intermediateColor: '#2a4a5a', intermediateColor: '#2a4a5a',
indexColor: '#3a5a6a', indexColor: '#3a5a6a',
labelColor: '#5a8a9a', labelColor: '#5a8a9a',
}, },
// Contours Test 10ft - purple variant // Contours Test 10ft - purple variant
contoursTest10ft: { contoursTest10ft: {
minorColor: '#2a1a4a', minorColor: '#2a1a4a',
intermediateColor: '#3a2a5a', intermediateColor: '#3a2a5a',
indexColor: '#4a3a6a', indexColor: '#4a3a6a',
labelColor: '#7a6a9a', labelColor: '#7a6a9a',
}, },
// Public Lands - very muted fills // Public Lands - very muted fills
publicLands: { publicLands: {
opacityMod: 0.5, opacityMod: 0.5,
// Fill colors - dark teal/purple tints // Fill colors - dark teal/purple tints
fillWA: '#1a2a20', fillWA: '#1a2a20',
fillNPS: '#0a2a1a', fillNPS: '#0a2a1a',
fillUSFS: '#102820', fillUSFS: '#102820',
fillBLM: '#1a2828', fillBLM: '#1a2828',
fillFWS: '#0a2a2a', fillFWS: '#0a2a2a',
fillSTAT: '#102028', fillSTAT: '#102028',
fillLOC: '#182028', fillLOC: '#182028',
fillDefault: '#1a1a2a', fillDefault: '#1a1a2a',
// Fill opacities - very low // Fill opacities - very low
fillOpacityWA: 0.25, fillOpacityWA: 0.25,
fillOpacityNPS: 0.25, fillOpacityNPS: 0.25,
fillOpacityUSFS: 0.20, fillOpacityUSFS: 0.20,
fillOpacityBLM: 0.15, fillOpacityBLM: 0.15,
fillOpacitySTAT: 0.20, fillOpacitySTAT: 0.20,
fillOpacityLOC: 0.15, fillOpacityLOC: 0.15,
fillOpacityDefault: 0.10, fillOpacityDefault: 0.10,
// Outline colors - subtle // Outline colors - subtle
outlineWA: '#2a3a30', outlineWA: '#2a3a30',
outlineNPS: '#1a3a2a', outlineNPS: '#1a3a2a',
outlineUSFS: '#203830', outlineUSFS: '#203830',
outlineBLM: '#2a3838', outlineBLM: '#2a3838',
outlineFWS: '#1a3a3a', outlineFWS: '#1a3a3a',
outlineSTAT: '#203038', outlineSTAT: '#203038',
outlineLOC: '#283038', outlineLOC: '#283038',
outlineDefault: '#2a2a3a', outlineDefault: '#2a2a3a',
// Outline opacities // Outline opacities
outlineOpacityNPS: 0.5, outlineOpacityNPS: 0.5,
outlineOpacityUSFS: 0.4, outlineOpacityUSFS: 0.4,
outlineOpacityDefault: 0.3, outlineOpacityDefault: 0.3,
// Outline width // Outline width
outlineWidth: { z4: 0.3, z8: 0.6, z12: 1.0 }, outlineWidth: { z4: 0.3, z8: 0.6, z12: 1.0 },
// Labels - muted teal // Labels - muted teal
labelColor: '#5a8a8a', labelColor: '#5a8a8a',
labelHaloColor: '#0a0a14', labelHaloColor: '#0a0a14',
labelHaloWidth: 1.5, labelHaloWidth: 1.5,
labelOpacity: 0.7, labelOpacity: 0.7,
labelSize: { z10: 10, z14: 12 }, labelSize: { z10: 10, z14: 12 },
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
}, },
// USFS Trails - purple/magenta/cyan family instead of earthy browns // USFS Trails - purple/magenta/cyan family instead of earthy browns
usfsTrails: { usfsTrails: {
// Roads - purple // Roads - purple
roadsColor: '#8833aa', roadsColor: '#8833aa',
roadsOpacity: 0.85, roadsOpacity: 0.85,
roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 }, roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 },
// Trails - neon colors by use type // Trails - neon colors by use type
trailsMotorized: '#ff2d6b', trailsMotorized: '#ff2d6b',
trailsBicycle: '#ffaa00', trailsBicycle: '#ffaa00',
trailsHiker: '#00ff88', trailsHiker: '#00ff88',
trailsDefault: '#8833aa', trailsDefault: '#8833aa',
trailsOpacity: 0.85, trailsOpacity: 0.85,
trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 }, trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
trailsDash: [2, 1.5], trailsDash: [2, 1.5],
// Road labels // Road labels
roadsLabelColor: '#a080c0', roadsLabelColor: '#a080c0',
roadsLabelHaloColor: '#0a0a14', roadsLabelHaloColor: '#0a0a14',
roadsLabelHaloWidth: 1.5, roadsLabelHaloWidth: 1.5,
roadsLabelOpacity: 0.85, roadsLabelOpacity: 0.85,
roadsLabelSize: 11, roadsLabelSize: 11,
// Trail labels // Trail labels
trailsLabelColor: '#a080c0', trailsLabelColor: '#a080c0',
trailsLabelHaloColor: '#0a0a14', trailsLabelHaloColor: '#0a0a14',
trailsLabelHaloWidth: 1.5, trailsLabelHaloWidth: 1.5,
trailsLabelOpacity: 0.85, trailsLabelOpacity: 0.85,
trailsLabelSize: 11, trailsLabelSize: 11,
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
// Hit layer // Hit layer
hitWidth: 14, hitWidth: 14,
}, },
// BLM Trails - purple/cyan/magenta family // BLM Trails - purple/cyan/magenta family
blmTrails: { blmTrails: {
// Route colors - neon family // Route colors - neon family
color4wdHigh: '#ff2d6b', color4wdHigh: '#ff2d6b',
color4wdLow: '#cc2288', color4wdLow: '#cc2288',
colorAtv: '#ff3333', colorAtv: '#ff3333',
colorMotoSingle: '#aa44cc', colorMotoSingle: '#aa44cc',
color2wdLow: '#8833aa', color2wdLow: '#8833aa',
colorNonMech: '#00ff88', colorNonMech: '#00ff88',
colorDefault: '#6644aa', colorDefault: '#6644aa',
colorSnow: '#00f0ff', colorSnow: '#00f0ff',
lineOpacity: 0.85, lineOpacity: 0.85,
lineOpacityOther: 0.75, lineOpacityOther: 0.75,
lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 }, lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
// Dash patterns // Dash patterns
dashImproved: [4, 2], dashImproved: [4, 2],
dashAggregate: [1, 2], dashAggregate: [1, 2],
dashSnow: [4, 2, 1, 2], dashSnow: [4, 2, 1, 2],
dashOther: [4, 2, 1, 2, 1, 2], dashOther: [4, 2, 1, 2, 1, 2],
// Labels // Labels
labelColor: '#a080c0', labelColor: '#a080c0',
labelHaloColor: '#0a0a14', labelHaloColor: '#0a0a14',
labelHaloWidth: 1.5, labelHaloWidth: 1.5,
labelOpacity: 0.85, labelOpacity: 0.85,
labelSize: 11, labelSize: 11,
labelFont: ['Noto Sans Regular'], labelFont: ['Noto Sans Regular'],
// Hit layer // Hit layer
hitWidth: 14, hitWidth: 14,
}, },
}
// ── Highlight (boundary/selection) ────────────────────────────────────────
/** highlight: {
* Satellite adjustments - dark, desaturated, purple-shifted lineColor: "#00f0ff", // Electric cyan for selection
*/ lineWidth: 2,
const cyberpunkSatellite = { lineDash: [4, 4],
opacity: 0.8, lineOpacity: 0.9,
brightnessMin: 0.0, fillColor: "#00f0ff",
brightnessMax: 0.30, fillOpacity: 0.1,
contrast: 0.15, },
saturation: -0.6, }
hueRotate: 280,
} /**
* Satellite adjustments - dark, desaturated, purple-shifted
/** */
* Cyberpunk theme configuration const cyberpunkSatellite = {
*/ opacity: 0.8,
const cyberpunkTheme = { brightnessMin: 0.0,
id: 'cyberpunk', brightnessMax: 0.30,
name: 'Cyberpunk', contrast: 0.15,
dark: true, saturation: -0.6,
swatch: ['#0a0a14', '#ff2d6b', '#00f0ff'], hueRotate: 280,
fontImports: [ }
'https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700&display=swap',
'https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap', /**
], * Cyberpunk theme configuration
colors: cyberpunkColors, */
satellite: cyberpunkSatellite, const cyberpunkTheme = {
overlay: cyberpunkOverlay, id: 'cyberpunk',
ui: cyberpunkUI, name: 'Cyberpunk',
} dark: true,
swatch: ['#0a0a14', '#ff2d6b', '#00f0ff'],
export default cyberpunkTheme fontImports: [
'https://fonts.googleapis.com/css2?family=Orbitron:wght@400;500;600;700&display=swap',
'https://fonts.googleapis.com/css2?family=Share+Tech+Mono&display=swap',
],
colors: cyberpunkColors,
satellite: cyberpunkSatellite,
overlay: cyberpunkOverlay,
ui: cyberpunkUI,
}
export default cyberpunkTheme

File diff suppressed because it is too large Load diff