mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-06-10 08:54:38 +02:00
fix: apply theme overlay config to contour layers
addContours() was using hardcoded black/white colors instead of theme-specific overlay config. Now uses getOverlayConfig(themeId, "contours") like other overlay layers (hillshade, publicLands, etc). Also updates cyberpunk contours from dark purple to cyan (#1a5566 → #3a99aa) to contrast with purple roads. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d4e3b68a13
commit
fcc9101239
2 changed files with 447 additions and 430 deletions
|
|
@ -560,9 +560,11 @@ function removePublicLands(map) {
|
|||
}
|
||||
|
||||
/** Add topographic contours via maplibre-contour */
|
||||
function addContours(map) {
|
||||
console.log('[CONTOUR] addContours called, source exists:', !!map?.getSource(CONTOUR_SOURCE), 'demSource:', !!demSourceInstance)
|
||||
function addContours(map, themeId) {
|
||||
console.log("[CONTOUR] addContours called, source exists:", !!map?.getSource(CONTOUR_SOURCE), "demSource:", !!demSourceInstance)
|
||||
if (!map || !demSourceInstance || map.getSource(CONTOUR_SOURCE)) return
|
||||
|
||||
const c = getOverlayConfig(themeId, "contours")
|
||||
const contourThresholds = {
|
||||
3: [5000, 25000],
|
||||
4: [2500, 10000],
|
||||
|
|
@ -579,54 +581,69 @@ function addContours(map) {
|
|||
15: [20, 100],
|
||||
}
|
||||
map.addSource(CONTOUR_SOURCE, {
|
||||
type: 'vector',
|
||||
type: "vector",
|
||||
tiles: [demSourceInstance.contourProtocolUrl({
|
||||
multiplier: 3.28084,
|
||||
thresholds: contourThresholds,
|
||||
})],
|
||||
maxzoom: 16,
|
||||
})
|
||||
console.log('[CONTOUR] protocol URL:', demSourceInstance.contourProtocolUrl({
|
||||
console.log("[CONTOUR] protocol URL:", demSourceInstance.contourProtocolUrl({
|
||||
multiplier: 3.28084,
|
||||
thresholds: contourThresholds,
|
||||
}))
|
||||
console.log('[CONTOUR] source added:', !!map.getSource(CONTOUR_SOURCE))
|
||||
console.log("[CONTOUR] source added:", !!map.getSource(CONTOUR_SOURCE))
|
||||
let beforeId = undefined
|
||||
for (const layer of map.getStyle().layers) {
|
||||
if (layer.type === 'symbol') { beforeId = layer.id; break }
|
||||
if (layer.type === "symbol") { beforeId = layer.id; break }
|
||||
}
|
||||
const isDark = document.documentElement.getAttribute('data-theme') === 'dark'
|
||||
|
||||
// Line layer with theme-aware colors
|
||||
// maplibre-contour level: 0 = minor, 1 = index (major)
|
||||
const opacityMod = c.opacityMod ?? 1
|
||||
map.addLayer({
|
||||
id: CONTOUR_LINE, type: 'line', source: CONTOUR_SOURCE,
|
||||
'source-layer': 'contours',
|
||||
id: CONTOUR_LINE, type: "line", source: CONTOUR_SOURCE,
|
||||
"source-layer": "contours",
|
||||
paint: {
|
||||
'line-color': 'rgba(0,0,0,0.35)',
|
||||
'line-width': [
|
||||
'interpolate', ['linear'], ['zoom'],
|
||||
7, ['match', ['get', 'level'], 1, 1, 0.3],
|
||||
11, ['match', ['get', 'level'], 1, 1.5, 0.6],
|
||||
14, ['match', ['get', 'level'], 1, 2, 0.8],
|
||||
"line-color": [
|
||||
"match", ["get", "level"],
|
||||
1, c.indexColor,
|
||||
c.minorColor
|
||||
],
|
||||
"line-opacity": [
|
||||
"match", ["get", "level"],
|
||||
1, c.indexOpacity * opacityMod,
|
||||
c.minorOpacity * opacityMod
|
||||
],
|
||||
"line-width": [
|
||||
"interpolate", ["linear"], ["zoom"],
|
||||
7, ["match", ["get", "level"], 1, c.indexWidth?.z4 ?? 1.2, c.minorWidth?.z11 ?? 0.5],
|
||||
11, ["match", ["get", "level"], 1, ((c.indexWidth?.z4 ?? 1.2) + (c.indexWidth?.z14 ?? 1.8)) / 2, ((c.minorWidth?.z11 ?? 0.5) + (c.minorWidth?.z14 ?? 1.0)) / 2],
|
||||
14, ["match", ["get", "level"], 1, c.indexWidth?.z14 ?? 1.8, c.minorWidth?.z14 ?? 1.0],
|
||||
],
|
||||
},
|
||||
}, beforeId)
|
||||
|
||||
// Label layer for index contours (level > 0)
|
||||
map.addLayer({
|
||||
id: CONTOUR_LABEL, type: 'symbol', source: CONTOUR_SOURCE,
|
||||
'source-layer': 'contours',
|
||||
filter: ['>', ['get', 'level'], 0],
|
||||
id: CONTOUR_LABEL, type: "symbol", source: CONTOUR_SOURCE,
|
||||
"source-layer": "contours",
|
||||
filter: [">", ["get", "level"], 0],
|
||||
layout: {
|
||||
'symbol-placement': 'line',
|
||||
'text-size': ['interpolate', ['linear'], ['zoom'], 7, 9, 11, 11, 14, 13],
|
||||
'text-field': ['concat', ['number-format', ['get', 'ele'], {}], "'"],
|
||||
'text-font': ['Noto Sans Medium'],
|
||||
'text-max-angle': 25,
|
||||
"symbol-placement": "line",
|
||||
"text-size": c.labelSize ?? 10,
|
||||
"text-field": ["concat", ["number-format", ["get", "ele"], {}], "'"],
|
||||
"text-font": c.labelFont ?? ["Noto Sans Regular"],
|
||||
"text-max-angle": 25,
|
||||
},
|
||||
paint: {
|
||||
'text-color': 'rgba(0,0,0,0.7)',
|
||||
'text-halo-color': 'rgba(255,255,255,0.9)',
|
||||
'text-halo-width': 1.5,
|
||||
"text-color": c.labelColor,
|
||||
"text-halo-color": c.labelHaloColor,
|
||||
"text-halo-width": c.labelHaloWidth ?? 1.5,
|
||||
"text-opacity": (c.labelOpacity ?? 0.85) * opacityMod,
|
||||
},
|
||||
})
|
||||
console.log('[CONTOUR] layers added:', !!map.getLayer(CONTOUR_LINE), !!map.getLayer(CONTOUR_LABEL))
|
||||
console.log("[CONTOUR] layers added:", !!map.getLayer(CONTOUR_LINE), !!map.getLayer(CONTOUR_LABEL))
|
||||
}
|
||||
|
||||
/** Remove contour layers + source */
|
||||
|
|
|
|||
|
|
@ -1,403 +1,403 @@
|
|||
/**
|
||||
* Cyberpunk Theme for Navi
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* cool white with colored halos.
|
||||
*
|
||||
* The whole thing should feel like you're navigating Night City.
|
||||
*
|
||||
* CUSTOM FONTS:
|
||||
* - Heading: "Orbitron" — geometric, futuristic display font
|
||||
* - Body: "Share Tech Mono" — monospaced terminal feel for entire UI
|
||||
*/
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// PALETTE
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
//
|
||||
// base: #0a0a14 ← near-black with blue-purple undertone
|
||||
// surface: #10101e ← panels, cards
|
||||
// surfaceAlt: #161628 ← secondary surfaces, hover states
|
||||
// border: #1e1e3a ← subtle purple edges
|
||||
// text: #d0d0e8 ← cool white text
|
||||
// textSecondary: #8888aa ← lavender-gray
|
||||
// textMuted: #5a5a7a ← dark purple-gray
|
||||
// textInverse: #0a0a14 ← text on neon backgrounds
|
||||
// accent: #ff2d6b ← hot pink/magenta — primary actions
|
||||
// accentHover: #ff4d8b ← lighter magenta
|
||||
// accentAlt: #00f0ff ← electric cyan — secondary accent
|
||||
// success: #00ff88 ← neon green
|
||||
// warning: #ffaa00 ← amber
|
||||
// danger: #ff3333 ← neon red
|
||||
// water: #06061a ← deep dark blue-black
|
||||
// waterLabel: #3a6a8a ← muted blue for water labels
|
||||
// vegetation: #0a1a12 ← barely-there dark teal-green
|
||||
// forest: #0e1e14 ← slightly deeper
|
||||
// road: #1a1a3a ← ghost purple minor roads
|
||||
// roadSecondary: #2a2a5a
|
||||
// roadPrimary: #8833aa ← purple for primary
|
||||
// roadMotorway: #ff2d6b ← hot magenta for motorways
|
||||
// roadCasing: #0a0a14 ← dark casing
|
||||
// building: #141428 ← dark purple-gray buildings
|
||||
// contour: #1e1e3e ← dark lines, just visible
|
||||
// contourLabel: #5a5a7a
|
||||
//
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Map flavor colors - protomaps-themes-base schema
|
||||
* All 73 flat keys + pois + landcover nested objects
|
||||
*/
|
||||
const cyberpunkColors = {
|
||||
// Background & earth
|
||||
background: '#08080f',
|
||||
earth: '#0a0a14',
|
||||
|
||||
// Land use areas - dark with slight purple undertones
|
||||
park_a: '#0a1a14',
|
||||
park_b: '#0e1e18',
|
||||
hospital: '#1a1020',
|
||||
industrial: '#0e0e1a',
|
||||
school: '#14101e',
|
||||
wood_a: '#0a1a12',
|
||||
wood_b: '#0e1e14',
|
||||
pedestrian: '#0c0c18',
|
||||
scrub_a: '#0a1410',
|
||||
scrub_b: '#0c1812',
|
||||
glacier: '#101020',
|
||||
sand: '#12101a',
|
||||
beach: '#14121c',
|
||||
aerodrome: '#0a0a16',
|
||||
runway: '#1a1a30',
|
||||
water: '#06061a',
|
||||
zoo: '#0c1614',
|
||||
military: '#100a14',
|
||||
|
||||
// Tunnels - dark purple casings
|
||||
tunnel_other_casing: '#0a0a14',
|
||||
tunnel_minor_casing: '#0a0a14',
|
||||
tunnel_link_casing: '#0a0a14',
|
||||
tunnel_major_casing: '#0a0a14',
|
||||
tunnel_highway_casing: '#0a0a14',
|
||||
tunnel_other: '#161628',
|
||||
tunnel_minor: '#161628',
|
||||
tunnel_link: '#2a2050',
|
||||
tunnel_major: '#4a2870',
|
||||
tunnel_highway: '#801848',
|
||||
|
||||
// Pier & buildings
|
||||
pier: '#1a1a30',
|
||||
buildings: '#141428',
|
||||
|
||||
// Roads & casings - glowing neon progression
|
||||
minor_service_casing: '#0a0a14',
|
||||
minor_casing: '#0a0a14',
|
||||
link_casing: '#0a0a14',
|
||||
major_casing_late: '#0a0a14',
|
||||
highway_casing_late: '#0a0a14',
|
||||
other: '#1a1a3a',
|
||||
minor_service: '#1a1a3a',
|
||||
minor_a: '#2a2a5a',
|
||||
minor_b: '#1a1a3a',
|
||||
link: '#5a3888',
|
||||
major_casing_early: '#0a0a14',
|
||||
major: '#8833aa',
|
||||
highway_casing_early: '#0a0a14',
|
||||
highway: '#ff2d6b',
|
||||
railway: '#2a2050',
|
||||
boundaries: '#4a4a6a',
|
||||
|
||||
// Waterway label
|
||||
waterway_label: '#3a6a8a',
|
||||
|
||||
// Bridges - same neon colors
|
||||
bridges_other_casing: '#0c0c18',
|
||||
bridges_minor_casing: '#0a0a14',
|
||||
bridges_link_casing: '#0a0a14',
|
||||
bridges_major_casing: '#0a0a14',
|
||||
bridges_highway_casing: '#0a0a14',
|
||||
bridges_other: '#1a1a3a',
|
||||
bridges_minor: '#2a2a5a',
|
||||
bridges_link: '#5a3888',
|
||||
bridges_major: '#8833aa',
|
||||
bridges_highway: '#ff2d6b',
|
||||
|
||||
// Labels - cool white with DARK halos
|
||||
roads_label_minor: '#8888aa',
|
||||
roads_label_minor_halo: '#0a0a14',
|
||||
roads_label_major: '#a0a0c0',
|
||||
roads_label_major_halo: '#0a0a14',
|
||||
ocean_label: '#3a6a8a',
|
||||
peak_label: '#8888aa',
|
||||
subplace_label: '#8888aa',
|
||||
subplace_label_halo: '#0a0a14',
|
||||
city_label: '#d0d0e8',
|
||||
city_label_halo: '#0a0a14',
|
||||
state_label: '#5a5a7a',
|
||||
state_label_halo: '#0a0a14',
|
||||
country_label: '#7a7a9a',
|
||||
address_label: '#8888aa',
|
||||
address_label_halo: '#0a0a14',
|
||||
|
||||
// POI icon colors - neon palette
|
||||
pois: {
|
||||
blue: '#00a0ff',
|
||||
green: '#00ff88',
|
||||
lapis: '#6060ff',
|
||||
pink: '#ff2d6b',
|
||||
red: '#ff3333',
|
||||
slategray: '#8888aa',
|
||||
tangerine: '#ffaa00',
|
||||
turquoise: '#00f0ff',
|
||||
},
|
||||
|
||||
// Landcover fill colors - very dark, barely visible
|
||||
landcover: {
|
||||
grassland: 'rgba(10, 26, 18, 1)',
|
||||
barren: 'rgba(18, 16, 26, 1)',
|
||||
urban_area: 'rgba(14, 14, 26, 1)',
|
||||
farmland: 'rgba(12, 24, 16, 1)',
|
||||
glacier: 'rgba(16, 16, 32, 1)',
|
||||
scrub: 'rgba(12, 20, 16, 1)',
|
||||
forest: 'rgba(14, 30, 20, 1)',
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* UI CSS custom properties - neon command center aesthetic
|
||||
* Dark translucent panels with magenta/cyan accents
|
||||
*/
|
||||
const cyberpunkUI = {
|
||||
// Fonts - monospace terminal feel
|
||||
'--font-sans': "'Share Tech Mono', monospace",
|
||||
'--font-mono': "'Share Tech Mono', monospace",
|
||||
'--font-heading': "'Orbitron', sans-serif",
|
||||
// Backgrounds - dark with blue-purple undertone
|
||||
'--bg-base': '#0a0a14',
|
||||
'--bg-raised': '#10101e',
|
||||
'--bg-overlay': '#161628',
|
||||
'--bg-input': '#0c0c18',
|
||||
'--bg-inset': '#08080f',
|
||||
'--bg-muted': '#12121e',
|
||||
// Text - cool white spectrum
|
||||
'--text-primary': '#d0d0e8',
|
||||
'--text-secondary': '#8888aa',
|
||||
'--text-tertiary': '#5a5a7a',
|
||||
'--text-inverse': '#0a0a14',
|
||||
// Borders - subtle purple edges
|
||||
'--border': '#1e1e3a',
|
||||
'--border-subtle': '#141428',
|
||||
// Accent - hot magenta
|
||||
'--accent': '#ff2d6b',
|
||||
'--accent-hover': '#ff4d8b',
|
||||
'--accent-muted': '#3a1828',
|
||||
// Tan becomes cyan in this theme
|
||||
'--tan': '#00f0ff',
|
||||
'--tan-muted': '#0a2830',
|
||||
// Pins - neon colors
|
||||
'--pin-origin': '#ff2d6b',
|
||||
'--pin-destination': '#00f0ff',
|
||||
'--pin-intermediate': '#8833aa',
|
||||
'--pin-stroke': '#0a0a14',
|
||||
// Status - neon signals
|
||||
'--status-success': '#00ff88',
|
||||
'--status-warning': '#ffaa00',
|
||||
'--status-danger': '#ff3333',
|
||||
'--success': '#00ff88',
|
||||
'--warning': '#ffaa00',
|
||||
'--warning-muted': '#2a2010',
|
||||
// Route - cyan for contrast with magenta UI
|
||||
'--route-line': '#00f0ff',
|
||||
// Shadows - subtle magenta glow
|
||||
'--shadow': '0 2px 8px rgba(255, 45, 107, 0.25)',
|
||||
'--shadow-lg': '0 4px 16px rgba(255, 45, 107, 0.35)',
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay configuration - subtle, muted for dark theme
|
||||
*/
|
||||
const cyberpunkOverlay = {
|
||||
// Hillshade - dramatic shadows
|
||||
hillshade: {
|
||||
exaggeration: 0.6,
|
||||
illuminationDirection: 315,
|
||||
shadowColor: '#000000',
|
||||
highlightColor: '#2a2a4a',
|
||||
},
|
||||
|
||||
// Contours - very subtle dark purple-gray
|
||||
contours: {
|
||||
opacityMod: 0.5,
|
||||
minorColor: '#1e1e3e',
|
||||
minorOpacity: 0.3,
|
||||
minorWidth: { z11: 0.4, z14: 0.8 },
|
||||
intermediateColor: '#2a2a4a',
|
||||
intermediateOpacity: 0.4,
|
||||
intermediateWidth: { z8: 0.6, z14: 1.0 },
|
||||
indexColor: '#3a3a5a',
|
||||
indexOpacity: 0.5,
|
||||
indexWidth: { z4: 0.8, z14: 1.2 },
|
||||
labelColor: '#5a5a7a',
|
||||
labelHaloColor: '#0a0a14',
|
||||
labelHaloWidth: 1.5,
|
||||
labelOpacity: 0.6,
|
||||
labelSize: 10,
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
},
|
||||
|
||||
// Contours Test - cyan variant
|
||||
contoursTest: {
|
||||
minorColor: '#1a3a4a',
|
||||
intermediateColor: '#2a4a5a',
|
||||
indexColor: '#3a5a6a',
|
||||
labelColor: '#5a8a9a',
|
||||
},
|
||||
|
||||
// Contours Test 10ft - purple variant
|
||||
contoursTest10ft: {
|
||||
minorColor: '#2a1a4a',
|
||||
intermediateColor: '#3a2a5a',
|
||||
indexColor: '#4a3a6a',
|
||||
labelColor: '#7a6a9a',
|
||||
},
|
||||
|
||||
// Public Lands - very muted fills
|
||||
publicLands: {
|
||||
opacityMod: 0.5,
|
||||
// Fill colors - dark teal/purple tints
|
||||
fillWA: '#1a2a20',
|
||||
fillNPS: '#0a2a1a',
|
||||
fillUSFS: '#102820',
|
||||
fillBLM: '#1a2828',
|
||||
fillFWS: '#0a2a2a',
|
||||
fillSTAT: '#102028',
|
||||
fillLOC: '#182028',
|
||||
fillDefault: '#1a1a2a',
|
||||
// Fill opacities - very low
|
||||
fillOpacityWA: 0.25,
|
||||
fillOpacityNPS: 0.25,
|
||||
fillOpacityUSFS: 0.20,
|
||||
fillOpacityBLM: 0.15,
|
||||
fillOpacitySTAT: 0.20,
|
||||
fillOpacityLOC: 0.15,
|
||||
fillOpacityDefault: 0.10,
|
||||
// Outline colors - subtle
|
||||
outlineWA: '#2a3a30',
|
||||
outlineNPS: '#1a3a2a',
|
||||
outlineUSFS: '#203830',
|
||||
outlineBLM: '#2a3838',
|
||||
outlineFWS: '#1a3a3a',
|
||||
outlineSTAT: '#203038',
|
||||
outlineLOC: '#283038',
|
||||
outlineDefault: '#2a2a3a',
|
||||
// Outline opacities
|
||||
outlineOpacityNPS: 0.5,
|
||||
outlineOpacityUSFS: 0.4,
|
||||
outlineOpacityDefault: 0.3,
|
||||
// Outline width
|
||||
outlineWidth: { z4: 0.3, z8: 0.6, z12: 1.0 },
|
||||
// Labels - muted teal
|
||||
labelColor: '#5a8a8a',
|
||||
labelHaloColor: '#0a0a14',
|
||||
labelHaloWidth: 1.5,
|
||||
labelOpacity: 0.7,
|
||||
labelSize: { z10: 10, z14: 12 },
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
},
|
||||
|
||||
// USFS Trails - purple/magenta/cyan family instead of earthy browns
|
||||
usfsTrails: {
|
||||
// Roads - purple
|
||||
roadsColor: '#8833aa',
|
||||
roadsOpacity: 0.85,
|
||||
roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 },
|
||||
// Trails - neon colors by use type
|
||||
trailsMotorized: '#ff2d6b',
|
||||
trailsBicycle: '#ffaa00',
|
||||
trailsHiker: '#00ff88',
|
||||
trailsDefault: '#8833aa',
|
||||
trailsOpacity: 0.85,
|
||||
trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
|
||||
trailsDash: [2, 1.5],
|
||||
// Road labels
|
||||
roadsLabelColor: '#a080c0',
|
||||
roadsLabelHaloColor: '#0a0a14',
|
||||
roadsLabelHaloWidth: 1.5,
|
||||
roadsLabelOpacity: 0.85,
|
||||
roadsLabelSize: 11,
|
||||
// Trail labels
|
||||
trailsLabelColor: '#a080c0',
|
||||
trailsLabelHaloColor: '#0a0a14',
|
||||
trailsLabelHaloWidth: 1.5,
|
||||
trailsLabelOpacity: 0.85,
|
||||
trailsLabelSize: 11,
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
// Hit layer
|
||||
hitWidth: 14,
|
||||
},
|
||||
|
||||
// BLM Trails - purple/cyan/magenta family
|
||||
blmTrails: {
|
||||
// Route colors - neon family
|
||||
color4wdHigh: '#ff2d6b',
|
||||
color4wdLow: '#cc2288',
|
||||
colorAtv: '#ff3333',
|
||||
colorMotoSingle: '#aa44cc',
|
||||
color2wdLow: '#8833aa',
|
||||
colorNonMech: '#00ff88',
|
||||
colorDefault: '#6644aa',
|
||||
colorSnow: '#00f0ff',
|
||||
lineOpacity: 0.85,
|
||||
lineOpacityOther: 0.75,
|
||||
lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
|
||||
// Dash patterns
|
||||
dashImproved: [4, 2],
|
||||
dashAggregate: [1, 2],
|
||||
dashSnow: [4, 2, 1, 2],
|
||||
dashOther: [4, 2, 1, 2, 1, 2],
|
||||
// Labels
|
||||
labelColor: '#a080c0',
|
||||
labelHaloColor: '#0a0a14',
|
||||
labelHaloWidth: 1.5,
|
||||
labelOpacity: 0.85,
|
||||
labelSize: 11,
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
// Hit layer
|
||||
hitWidth: 14,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Satellite adjustments - dark, desaturated, purple-shifted
|
||||
*/
|
||||
const cyberpunkSatellite = {
|
||||
opacity: 0.8,
|
||||
brightnessMin: 0.0,
|
||||
brightnessMax: 0.30,
|
||||
contrast: 0.15,
|
||||
saturation: -0.6,
|
||||
hueRotate: 280,
|
||||
}
|
||||
|
||||
/**
|
||||
* Cyberpunk theme configuration
|
||||
*/
|
||||
const cyberpunkTheme = {
|
||||
id: 'cyberpunk',
|
||||
name: 'Cyberpunk',
|
||||
dark: true,
|
||||
swatch: ['#0a0a14', '#ff2d6b', '#00f0ff'],
|
||||
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
|
||||
/**
|
||||
* Cyberpunk Theme for Navi
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
* cool white with colored halos.
|
||||
*
|
||||
* The whole thing should feel like you're navigating Night City.
|
||||
*
|
||||
* CUSTOM FONTS:
|
||||
* - Heading: "Orbitron" — geometric, futuristic display font
|
||||
* - Body: "Share Tech Mono" — monospaced terminal feel for entire UI
|
||||
*/
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
// PALETTE
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
//
|
||||
// base: #0a0a14 ← near-black with blue-purple undertone
|
||||
// surface: #10101e ← panels, cards
|
||||
// surfaceAlt: #161628 ← secondary surfaces, hover states
|
||||
// border: #1e1e3a ← subtle purple edges
|
||||
// text: #d0d0e8 ← cool white text
|
||||
// textSecondary: #8888aa ← lavender-gray
|
||||
// textMuted: #5a5a7a ← dark purple-gray
|
||||
// textInverse: #0a0a14 ← text on neon backgrounds
|
||||
// accent: #ff2d6b ← hot pink/magenta — primary actions
|
||||
// accentHover: #ff4d8b ← lighter magenta
|
||||
// accentAlt: #00f0ff ← electric cyan — secondary accent
|
||||
// success: #00ff88 ← neon green
|
||||
// warning: #ffaa00 ← amber
|
||||
// danger: #ff3333 ← neon red
|
||||
// water: #06061a ← deep dark blue-black
|
||||
// waterLabel: #3a6a8a ← muted blue for water labels
|
||||
// vegetation: #0a1a12 ← barely-there dark teal-green
|
||||
// forest: #0e1e14 ← slightly deeper
|
||||
// road: #1a1a3a ← ghost purple minor roads
|
||||
// roadSecondary: #2a2a5a
|
||||
// roadPrimary: #8833aa ← purple for primary
|
||||
// roadMotorway: #ff2d6b ← hot magenta for motorways
|
||||
// roadCasing: #0a0a14 ← dark casing
|
||||
// building: #141428 ← dark purple-gray buildings
|
||||
// contour: #1e1e3e ← dark lines, just visible
|
||||
// contourLabel: #5a5a7a
|
||||
//
|
||||
// ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
/**
|
||||
* Map flavor colors - protomaps-themes-base schema
|
||||
* All 73 flat keys + pois + landcover nested objects
|
||||
*/
|
||||
const cyberpunkColors = {
|
||||
// Background & earth
|
||||
background: '#08080f',
|
||||
earth: '#0a0a14',
|
||||
|
||||
// Land use areas - dark with slight purple undertones
|
||||
park_a: '#0a1a14',
|
||||
park_b: '#0e1e18',
|
||||
hospital: '#1a1020',
|
||||
industrial: '#0e0e1a',
|
||||
school: '#14101e',
|
||||
wood_a: '#0a1a12',
|
||||
wood_b: '#0e1e14',
|
||||
pedestrian: '#0c0c18',
|
||||
scrub_a: '#0a1410',
|
||||
scrub_b: '#0c1812',
|
||||
glacier: '#101020',
|
||||
sand: '#12101a',
|
||||
beach: '#14121c',
|
||||
aerodrome: '#0a0a16',
|
||||
runway: '#1a1a30',
|
||||
water: '#06061a',
|
||||
zoo: '#0c1614',
|
||||
military: '#100a14',
|
||||
|
||||
// Tunnels - dark purple casings
|
||||
tunnel_other_casing: '#0a0a14',
|
||||
tunnel_minor_casing: '#0a0a14',
|
||||
tunnel_link_casing: '#0a0a14',
|
||||
tunnel_major_casing: '#0a0a14',
|
||||
tunnel_highway_casing: '#0a0a14',
|
||||
tunnel_other: '#161628',
|
||||
tunnel_minor: '#161628',
|
||||
tunnel_link: '#2a2050',
|
||||
tunnel_major: '#4a2870',
|
||||
tunnel_highway: '#801848',
|
||||
|
||||
// Pier & buildings
|
||||
pier: '#1a1a30',
|
||||
buildings: '#141428',
|
||||
|
||||
// Roads & casings - glowing neon progression
|
||||
minor_service_casing: '#0a0a14',
|
||||
minor_casing: '#0a0a14',
|
||||
link_casing: '#0a0a14',
|
||||
major_casing_late: '#0a0a14',
|
||||
highway_casing_late: '#0a0a14',
|
||||
other: '#1a1a3a',
|
||||
minor_service: '#1a1a3a',
|
||||
minor_a: '#2a2a5a',
|
||||
minor_b: '#1a1a3a',
|
||||
link: '#5a3888',
|
||||
major_casing_early: '#0a0a14',
|
||||
major: '#8833aa',
|
||||
highway_casing_early: '#0a0a14',
|
||||
highway: '#ff2d6b',
|
||||
railway: '#2a2050',
|
||||
boundaries: '#4a4a6a',
|
||||
|
||||
// Waterway label
|
||||
waterway_label: '#3a6a8a',
|
||||
|
||||
// Bridges - same neon colors
|
||||
bridges_other_casing: '#0c0c18',
|
||||
bridges_minor_casing: '#0a0a14',
|
||||
bridges_link_casing: '#0a0a14',
|
||||
bridges_major_casing: '#0a0a14',
|
||||
bridges_highway_casing: '#0a0a14',
|
||||
bridges_other: '#1a1a3a',
|
||||
bridges_minor: '#2a2a5a',
|
||||
bridges_link: '#5a3888',
|
||||
bridges_major: '#8833aa',
|
||||
bridges_highway: '#ff2d6b',
|
||||
|
||||
// Labels - cool white with DARK halos
|
||||
roads_label_minor: '#8888aa',
|
||||
roads_label_minor_halo: '#0a0a14',
|
||||
roads_label_major: '#a0a0c0',
|
||||
roads_label_major_halo: '#0a0a14',
|
||||
ocean_label: '#3a6a8a',
|
||||
peak_label: '#8888aa',
|
||||
subplace_label: '#8888aa',
|
||||
subplace_label_halo: '#0a0a14',
|
||||
city_label: '#d0d0e8',
|
||||
city_label_halo: '#0a0a14',
|
||||
state_label: '#5a5a7a',
|
||||
state_label_halo: '#0a0a14',
|
||||
country_label: '#7a7a9a',
|
||||
address_label: '#8888aa',
|
||||
address_label_halo: '#0a0a14',
|
||||
|
||||
// POI icon colors - neon palette
|
||||
pois: {
|
||||
blue: '#00a0ff',
|
||||
green: '#00ff88',
|
||||
lapis: '#6060ff',
|
||||
pink: '#ff2d6b',
|
||||
red: '#ff3333',
|
||||
slategray: '#8888aa',
|
||||
tangerine: '#ffaa00',
|
||||
turquoise: '#00f0ff',
|
||||
},
|
||||
|
||||
// Landcover fill colors - very dark, barely visible
|
||||
landcover: {
|
||||
grassland: 'rgba(10, 26, 18, 1)',
|
||||
barren: 'rgba(18, 16, 26, 1)',
|
||||
urban_area: 'rgba(14, 14, 26, 1)',
|
||||
farmland: 'rgba(12, 24, 16, 1)',
|
||||
glacier: 'rgba(16, 16, 32, 1)',
|
||||
scrub: 'rgba(12, 20, 16, 1)',
|
||||
forest: 'rgba(14, 30, 20, 1)',
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* UI CSS custom properties - neon command center aesthetic
|
||||
* Dark translucent panels with magenta/cyan accents
|
||||
*/
|
||||
const cyberpunkUI = {
|
||||
// Fonts - monospace terminal feel
|
||||
'--font-sans': "'Share Tech Mono', monospace",
|
||||
'--font-mono': "'Share Tech Mono', monospace",
|
||||
'--font-heading': "'Orbitron', sans-serif",
|
||||
// Backgrounds - dark with blue-purple undertone
|
||||
'--bg-base': '#0a0a14',
|
||||
'--bg-raised': '#10101e',
|
||||
'--bg-overlay': '#161628',
|
||||
'--bg-input': '#0c0c18',
|
||||
'--bg-inset': '#08080f',
|
||||
'--bg-muted': '#12121e',
|
||||
// Text - cool white spectrum
|
||||
'--text-primary': '#d0d0e8',
|
||||
'--text-secondary': '#8888aa',
|
||||
'--text-tertiary': '#5a5a7a',
|
||||
'--text-inverse': '#0a0a14',
|
||||
// Borders - subtle purple edges
|
||||
'--border': '#1e1e3a',
|
||||
'--border-subtle': '#141428',
|
||||
// Accent - hot magenta
|
||||
'--accent': '#ff2d6b',
|
||||
'--accent-hover': '#ff4d8b',
|
||||
'--accent-muted': '#3a1828',
|
||||
// Tan becomes cyan in this theme
|
||||
'--tan': '#00f0ff',
|
||||
'--tan-muted': '#0a2830',
|
||||
// Pins - neon colors
|
||||
'--pin-origin': '#ff2d6b',
|
||||
'--pin-destination': '#00f0ff',
|
||||
'--pin-intermediate': '#8833aa',
|
||||
'--pin-stroke': '#0a0a14',
|
||||
// Status - neon signals
|
||||
'--status-success': '#00ff88',
|
||||
'--status-warning': '#ffaa00',
|
||||
'--status-danger': '#ff3333',
|
||||
'--success': '#00ff88',
|
||||
'--warning': '#ffaa00',
|
||||
'--warning-muted': '#2a2010',
|
||||
// Route - cyan for contrast with magenta UI
|
||||
'--route-line': '#00f0ff',
|
||||
// Shadows - subtle magenta glow
|
||||
'--shadow': '0 2px 8px rgba(255, 45, 107, 0.25)',
|
||||
'--shadow-lg': '0 4px 16px rgba(255, 45, 107, 0.35)',
|
||||
}
|
||||
|
||||
/**
|
||||
* Overlay configuration - subtle, muted for dark theme
|
||||
*/
|
||||
const cyberpunkOverlay = {
|
||||
// Hillshade - dramatic shadows
|
||||
hillshade: {
|
||||
exaggeration: 0.6,
|
||||
illuminationDirection: 315,
|
||||
shadowColor: '#000000',
|
||||
highlightColor: '#2a2a4a',
|
||||
},
|
||||
|
||||
// Contours - very subtle dark purple-gray
|
||||
contours: {
|
||||
opacityMod: 1.0,
|
||||
minorColor: "#1a5566",
|
||||
minorOpacity: 0.5,
|
||||
minorWidth: { z11: 0.5, z14: 1.0 },
|
||||
intermediateColor: "#2a7788",
|
||||
intermediateOpacity: 0.65,
|
||||
intermediateWidth: { z8: 0.8, z14: 1.2 },
|
||||
indexColor: "#3a99aa",
|
||||
indexOpacity: 0.8,
|
||||
indexWidth: { z4: 1.2, z14: 1.8 },
|
||||
labelColor: "#55ccdd",
|
||||
labelHaloColor: "#0a0a14",
|
||||
labelHaloWidth: 1.5,
|
||||
labelOpacity: 0.85,
|
||||
labelSize: 10,
|
||||
labelFont: ["Noto Sans Regular"],
|
||||
},
|
||||
|
||||
// Contours Test - cyan variant
|
||||
contoursTest: {
|
||||
minorColor: '#1a3a4a',
|
||||
intermediateColor: '#2a4a5a',
|
||||
indexColor: '#3a5a6a',
|
||||
labelColor: '#5a8a9a',
|
||||
},
|
||||
|
||||
// Contours Test 10ft - purple variant
|
||||
contoursTest10ft: {
|
||||
minorColor: '#2a1a4a',
|
||||
intermediateColor: '#3a2a5a',
|
||||
indexColor: '#4a3a6a',
|
||||
labelColor: '#7a6a9a',
|
||||
},
|
||||
|
||||
// Public Lands - very muted fills
|
||||
publicLands: {
|
||||
opacityMod: 0.5,
|
||||
// Fill colors - dark teal/purple tints
|
||||
fillWA: '#1a2a20',
|
||||
fillNPS: '#0a2a1a',
|
||||
fillUSFS: '#102820',
|
||||
fillBLM: '#1a2828',
|
||||
fillFWS: '#0a2a2a',
|
||||
fillSTAT: '#102028',
|
||||
fillLOC: '#182028',
|
||||
fillDefault: '#1a1a2a',
|
||||
// Fill opacities - very low
|
||||
fillOpacityWA: 0.25,
|
||||
fillOpacityNPS: 0.25,
|
||||
fillOpacityUSFS: 0.20,
|
||||
fillOpacityBLM: 0.15,
|
||||
fillOpacitySTAT: 0.20,
|
||||
fillOpacityLOC: 0.15,
|
||||
fillOpacityDefault: 0.10,
|
||||
// Outline colors - subtle
|
||||
outlineWA: '#2a3a30',
|
||||
outlineNPS: '#1a3a2a',
|
||||
outlineUSFS: '#203830',
|
||||
outlineBLM: '#2a3838',
|
||||
outlineFWS: '#1a3a3a',
|
||||
outlineSTAT: '#203038',
|
||||
outlineLOC: '#283038',
|
||||
outlineDefault: '#2a2a3a',
|
||||
// Outline opacities
|
||||
outlineOpacityNPS: 0.5,
|
||||
outlineOpacityUSFS: 0.4,
|
||||
outlineOpacityDefault: 0.3,
|
||||
// Outline width
|
||||
outlineWidth: { z4: 0.3, z8: 0.6, z12: 1.0 },
|
||||
// Labels - muted teal
|
||||
labelColor: '#5a8a8a',
|
||||
labelHaloColor: '#0a0a14',
|
||||
labelHaloWidth: 1.5,
|
||||
labelOpacity: 0.7,
|
||||
labelSize: { z10: 10, z14: 12 },
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
},
|
||||
|
||||
// USFS Trails - purple/magenta/cyan family instead of earthy browns
|
||||
usfsTrails: {
|
||||
// Roads - purple
|
||||
roadsColor: '#8833aa',
|
||||
roadsOpacity: 0.85,
|
||||
roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 },
|
||||
// Trails - neon colors by use type
|
||||
trailsMotorized: '#ff2d6b',
|
||||
trailsBicycle: '#ffaa00',
|
||||
trailsHiker: '#00ff88',
|
||||
trailsDefault: '#8833aa',
|
||||
trailsOpacity: 0.85,
|
||||
trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
|
||||
trailsDash: [2, 1.5],
|
||||
// Road labels
|
||||
roadsLabelColor: '#a080c0',
|
||||
roadsLabelHaloColor: '#0a0a14',
|
||||
roadsLabelHaloWidth: 1.5,
|
||||
roadsLabelOpacity: 0.85,
|
||||
roadsLabelSize: 11,
|
||||
// Trail labels
|
||||
trailsLabelColor: '#a080c0',
|
||||
trailsLabelHaloColor: '#0a0a14',
|
||||
trailsLabelHaloWidth: 1.5,
|
||||
trailsLabelOpacity: 0.85,
|
||||
trailsLabelSize: 11,
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
// Hit layer
|
||||
hitWidth: 14,
|
||||
},
|
||||
|
||||
// BLM Trails - purple/cyan/magenta family
|
||||
blmTrails: {
|
||||
// Route colors - neon family
|
||||
color4wdHigh: '#ff2d6b',
|
||||
color4wdLow: '#cc2288',
|
||||
colorAtv: '#ff3333',
|
||||
colorMotoSingle: '#aa44cc',
|
||||
color2wdLow: '#8833aa',
|
||||
colorNonMech: '#00ff88',
|
||||
colorDefault: '#6644aa',
|
||||
colorSnow: '#00f0ff',
|
||||
lineOpacity: 0.85,
|
||||
lineOpacityOther: 0.75,
|
||||
lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
|
||||
// Dash patterns
|
||||
dashImproved: [4, 2],
|
||||
dashAggregate: [1, 2],
|
||||
dashSnow: [4, 2, 1, 2],
|
||||
dashOther: [4, 2, 1, 2, 1, 2],
|
||||
// Labels
|
||||
labelColor: '#a080c0',
|
||||
labelHaloColor: '#0a0a14',
|
||||
labelHaloWidth: 1.5,
|
||||
labelOpacity: 0.85,
|
||||
labelSize: 11,
|
||||
labelFont: ['Noto Sans Regular'],
|
||||
// Hit layer
|
||||
hitWidth: 14,
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Satellite adjustments - dark, desaturated, purple-shifted
|
||||
*/
|
||||
const cyberpunkSatellite = {
|
||||
opacity: 0.8,
|
||||
brightnessMin: 0.0,
|
||||
brightnessMax: 0.30,
|
||||
contrast: 0.15,
|
||||
saturation: -0.6,
|
||||
hueRotate: 280,
|
||||
}
|
||||
|
||||
/**
|
||||
* Cyberpunk theme configuration
|
||||
*/
|
||||
const cyberpunkTheme = {
|
||||
id: 'cyberpunk',
|
||||
name: 'Cyberpunk',
|
||||
dark: true,
|
||||
swatch: ['#0a0a14', '#ff2d6b', '#00f0ff'],
|
||||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue