mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 22:54:42 +02:00
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>
This commit is contained in:
parent
cc1b25e0b1
commit
78dc96551b
2 changed files with 331 additions and 0 deletions
329
src/themes/nightops.js
Normal file
329
src/themes/nightops.js
Normal file
|
|
@ -0,0 +1,329 @@
|
||||||
|
/**
|
||||||
|
* Night Ops Theme for Navi
|
||||||
|
*
|
||||||
|
* Black and red tactical night operations display optimized for absolute
|
||||||
|
* darkness. Inspired by military cockpit instruments, submarine control
|
||||||
|
* rooms, and ship bridge displays designed for total darkness.
|
||||||
|
*
|
||||||
|
* Red preserves scotopic (dark-adapted) vision better than any other color.
|
||||||
|
* This is MORE aggressive than Tactical — zero ambient light, eyes fully
|
||||||
|
* dark-adapted, any non-red light is unacceptable.
|
||||||
|
*
|
||||||
|
* Red-on-black rules:
|
||||||
|
* - ONLY red and black. No green, no blue, no amber, no white, no gray.
|
||||||
|
* - Text is red on black, not white on black.
|
||||||
|
* - "Bright" means brighter red (#cc3333), "dim" means darker red (#551111).
|
||||||
|
* - Water is pure black — no blue tint whatsoever.
|
||||||
|
* - Vegetation is very dark red-brown, barely distinguishable from land.
|
||||||
|
* - The ONLY contrast axis is light-red to dark-red to black.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map flavor colors - protomaps-themes-base schema
|
||||||
|
* All 73 flat keys + pois + landcover nested objects
|
||||||
|
*/
|
||||||
|
const nightopsColors = {
|
||||||
|
// Background & earth - pure black with faint red
|
||||||
|
background: "#0a0000",
|
||||||
|
earth: "#080000",
|
||||||
|
|
||||||
|
// Land use areas - very dark red-brown
|
||||||
|
park_a: "#120505",
|
||||||
|
park_b: "#150606",
|
||||||
|
hospital: "#100404",
|
||||||
|
industrial: "#0c0303",
|
||||||
|
school: "#100404",
|
||||||
|
wood_a: "#120505",
|
||||||
|
wood_b: "#150606",
|
||||||
|
pedestrian: "#0a0202",
|
||||||
|
scrub_a: "#100404",
|
||||||
|
scrub_b: "#120505",
|
||||||
|
glacier: "#0c0303",
|
||||||
|
sand: "#0c0303",
|
||||||
|
beach: "#100404",
|
||||||
|
aerodrome: "#0a0202",
|
||||||
|
runway: "#1a0808",
|
||||||
|
water: "#050000",
|
||||||
|
zoo: "#120505",
|
||||||
|
military: "#100404",
|
||||||
|
|
||||||
|
// Tunnels - black casings
|
||||||
|
tunnel_other_casing: "#080000",
|
||||||
|
tunnel_minor_casing: "#080000",
|
||||||
|
tunnel_link_casing: "#080000",
|
||||||
|
tunnel_major_casing: "#080000",
|
||||||
|
tunnel_highway_casing: "#080000",
|
||||||
|
tunnel_other: "#150606",
|
||||||
|
tunnel_minor: "#150606",
|
||||||
|
tunnel_link: "#1a0808",
|
||||||
|
tunnel_major: "#2a0a0a",
|
||||||
|
tunnel_highway: "#3a1010",
|
||||||
|
|
||||||
|
// Pier & buildings - very dark red-brown
|
||||||
|
pier: "#1a0808",
|
||||||
|
buildings: "#150606",
|
||||||
|
|
||||||
|
// Roads & casings - red spectrum by brightness
|
||||||
|
minor_service_casing: "#080000",
|
||||||
|
minor_casing: "#080000",
|
||||||
|
link_casing: "#080000",
|
||||||
|
major_casing_late: "#080000",
|
||||||
|
highway_casing_late: "#080000",
|
||||||
|
other: "#1a0808",
|
||||||
|
minor_service: "#1a0808",
|
||||||
|
minor_a: "#2a0a0a",
|
||||||
|
minor_b: "#1a0808",
|
||||||
|
link: "#3a1010",
|
||||||
|
major_casing_early: "#080000",
|
||||||
|
major: "#551515",
|
||||||
|
highway_casing_early: "#080000",
|
||||||
|
highway: "#772222",
|
||||||
|
railway: "#150606",
|
||||||
|
boundaries: "#3a1010",
|
||||||
|
|
||||||
|
// Waterway label - dim red on black water
|
||||||
|
waterway_label: "#551515",
|
||||||
|
|
||||||
|
// Bridges - same red spectrum
|
||||||
|
bridges_other_casing: "#0a0202",
|
||||||
|
bridges_minor_casing: "#080000",
|
||||||
|
bridges_link_casing: "#080000",
|
||||||
|
bridges_major_casing: "#080000",
|
||||||
|
bridges_highway_casing: "#080000",
|
||||||
|
bridges_other: "#1a0808",
|
||||||
|
bridges_minor: "#2a0a0a",
|
||||||
|
bridges_link: "#3a1010",
|
||||||
|
bridges_major: "#551515",
|
||||||
|
bridges_highway: "#772222",
|
||||||
|
|
||||||
|
// Labels - red with BLACK halos
|
||||||
|
roads_label_minor: "#441111",
|
||||||
|
roads_label_minor_halo: "#0a0000",
|
||||||
|
roads_label_major: "#551515",
|
||||||
|
roads_label_major_halo: "#0a0000",
|
||||||
|
ocean_label: "#551515",
|
||||||
|
peak_label: "#551515",
|
||||||
|
subplace_label: "#441111",
|
||||||
|
subplace_label_halo: "#0a0000",
|
||||||
|
city_label: "#cc3333",
|
||||||
|
city_label_halo: "#0a0000",
|
||||||
|
state_label: "#3a1010",
|
||||||
|
state_label_halo: "#0a0000",
|
||||||
|
country_label: "#551515",
|
||||||
|
address_label: "#441111",
|
||||||
|
address_label_halo: "#0a0000",
|
||||||
|
|
||||||
|
// POI icon colors - ALL red spectrum, differentiated by brightness
|
||||||
|
pois: {
|
||||||
|
blue: "#551515",
|
||||||
|
green: "#882222",
|
||||||
|
lapis: "#441111",
|
||||||
|
pink: "#772222",
|
||||||
|
red: "#cc3333",
|
||||||
|
slategray: "#3a1010",
|
||||||
|
tangerine: "#882222",
|
||||||
|
turquoise: "#551515",
|
||||||
|
},
|
||||||
|
|
||||||
|
// Landcover fill colors - very dark red-brown
|
||||||
|
landcover: {
|
||||||
|
grassland: "rgba(18, 5, 5, 1)",
|
||||||
|
barren: "rgba(12, 3, 3, 1)",
|
||||||
|
urban_area: "rgba(10, 2, 2, 1)",
|
||||||
|
farmland: "rgba(15, 4, 4, 1)",
|
||||||
|
glacier: "rgba(12, 3, 3, 1)",
|
||||||
|
scrub: "rgba(15, 5, 5, 1)",
|
||||||
|
forest: "rgba(21, 6, 6, 1)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UI CSS custom properties - red-on-black terminal
|
||||||
|
*/
|
||||||
|
const nightopsUI = {
|
||||||
|
"--font-sans": "'Inter', system-ui, -apple-system, sans-serif",
|
||||||
|
"--font-mono": "'JetBrains Mono', ui-monospace, monospace",
|
||||||
|
"--font-heading": "'Inter', system-ui, -apple-system, sans-serif",
|
||||||
|
"--bg-base": "#0a0000",
|
||||||
|
"--bg-raised": "#120000",
|
||||||
|
"--bg-overlay": "#1a0505",
|
||||||
|
"--bg-input": "#0c0202",
|
||||||
|
"--bg-inset": "#080000",
|
||||||
|
"--bg-muted": "#150505",
|
||||||
|
"--text-primary": "#cc3333",
|
||||||
|
"--text-secondary": "#882222",
|
||||||
|
"--text-tertiary": "#551515",
|
||||||
|
"--text-inverse": "#0a0000",
|
||||||
|
"--border": "#2a0a0a",
|
||||||
|
"--border-subtle": "#1a0606",
|
||||||
|
"--accent": "#cc3333",
|
||||||
|
"--accent-hover": "#dd4444",
|
||||||
|
"--accent-muted": "#2a0a0a",
|
||||||
|
"--tan": "#aa2222",
|
||||||
|
"--tan-muted": "#1a0606",
|
||||||
|
"--pin-origin": "#cc3333",
|
||||||
|
"--pin-destination": "#aa2222",
|
||||||
|
"--pin-intermediate": "#882222",
|
||||||
|
"--pin-stroke": "#0a0000",
|
||||||
|
"--status-success": "#883322",
|
||||||
|
"--status-warning": "#cc4422",
|
||||||
|
"--status-danger": "#ff2222",
|
||||||
|
"--success": "#883322",
|
||||||
|
"--warning": "#cc4422",
|
||||||
|
"--warning-muted": "#2a0a05",
|
||||||
|
"--route-line": "#cc3333",
|
||||||
|
"--shadow": "0 2px 8px rgba(0, 0, 0, 0.8)",
|
||||||
|
"--shadow-lg": "0 4px 16px rgba(0, 0, 0, 0.9)",
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overlay configuration - monochrome red
|
||||||
|
*/
|
||||||
|
const nightopsOverlay = {
|
||||||
|
hillshade: {
|
||||||
|
exaggeration: 0.2,
|
||||||
|
illuminationDirection: 315,
|
||||||
|
shadowColor: "#000000",
|
||||||
|
highlightColor: "#0a0000",
|
||||||
|
},
|
||||||
|
traffic: {
|
||||||
|
opacity: 0.4,
|
||||||
|
},
|
||||||
|
contours: {
|
||||||
|
opacityMod: 0.8,
|
||||||
|
minorColor: "#2a0808",
|
||||||
|
minorOpacity: 0.5,
|
||||||
|
minorWidth: { z11: 0.5, z14: 1.0 },
|
||||||
|
intermediateColor: "#3a1010",
|
||||||
|
intermediateOpacity: 0.6,
|
||||||
|
intermediateWidth: { z8: 0.8, z14: 1.2 },
|
||||||
|
indexColor: "#441111",
|
||||||
|
indexOpacity: 0.8,
|
||||||
|
indexWidth: { z4: 1.2, z14: 1.8 },
|
||||||
|
labelColor: "#551515",
|
||||||
|
labelHaloColor: "#0a0000",
|
||||||
|
labelHaloWidth: 1.5,
|
||||||
|
labelOpacity: 0.8,
|
||||||
|
labelSize: 10,
|
||||||
|
labelFont: ["Noto Sans Regular"],
|
||||||
|
},
|
||||||
|
contoursTest: {
|
||||||
|
minorColor: "#2a0808",
|
||||||
|
intermediateColor: "#3a1010",
|
||||||
|
indexColor: "#441111",
|
||||||
|
labelColor: "#551515",
|
||||||
|
},
|
||||||
|
contoursTest10ft: {
|
||||||
|
minorColor: "#1a0606",
|
||||||
|
intermediateColor: "#2a0808",
|
||||||
|
indexColor: "#3a1010",
|
||||||
|
labelColor: "#441111",
|
||||||
|
},
|
||||||
|
publicLands: {
|
||||||
|
opacityMod: 0.4,
|
||||||
|
fillWA: "#150606",
|
||||||
|
fillNPS: "#120505",
|
||||||
|
fillUSFS: "#150606",
|
||||||
|
fillBLM: "#100404",
|
||||||
|
fillFWS: "#120505",
|
||||||
|
fillSTAT: "#150606",
|
||||||
|
fillLOC: "#100404",
|
||||||
|
fillDefault: "#0c0303",
|
||||||
|
fillOpacityWA: 0.20,
|
||||||
|
fillOpacityNPS: 0.20,
|
||||||
|
fillOpacityUSFS: 0.18,
|
||||||
|
fillOpacityBLM: 0.15,
|
||||||
|
fillOpacitySTAT: 0.18,
|
||||||
|
fillOpacityLOC: 0.15,
|
||||||
|
fillOpacityDefault: 0.10,
|
||||||
|
outlineWA: "#1a0808",
|
||||||
|
outlineNPS: "#1a0808",
|
||||||
|
outlineUSFS: "#1a0808",
|
||||||
|
outlineBLM: "#150606",
|
||||||
|
outlineFWS: "#1a0808",
|
||||||
|
outlineSTAT: "#1a0808",
|
||||||
|
outlineLOC: "#150606",
|
||||||
|
outlineDefault: "#150606",
|
||||||
|
outlineOpacityNPS: 0.5,
|
||||||
|
outlineOpacityUSFS: 0.4,
|
||||||
|
outlineOpacityDefault: 0.3,
|
||||||
|
outlineWidth: { z4: 0.3, z8: 0.6, z12: 0.9 },
|
||||||
|
labelColor: "#551515",
|
||||||
|
labelHaloColor: "#0a0000",
|
||||||
|
labelHaloWidth: 1.5,
|
||||||
|
labelOpacity: 0.7,
|
||||||
|
labelSize: { z10: 10, z14: 12 },
|
||||||
|
labelFont: ["Noto Sans Regular"],
|
||||||
|
},
|
||||||
|
usfsTrails: {
|
||||||
|
roadsColor: "#3a1010",
|
||||||
|
roadsOpacity: 0.8,
|
||||||
|
roadsWidth: { z10: 1.5, z14: 2.5, z16: 3.5 },
|
||||||
|
trailsMotorized: "#772222",
|
||||||
|
trailsBicycle: "#661818",
|
||||||
|
trailsHiker: "#551515",
|
||||||
|
trailsDefault: "#3a1010",
|
||||||
|
trailsOpacity: 0.8,
|
||||||
|
trailsWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
|
||||||
|
trailsDash: [2, 1.5],
|
||||||
|
roadsLabelColor: "#551515",
|
||||||
|
roadsLabelHaloColor: "#0a0000",
|
||||||
|
roadsLabelHaloWidth: 1.5,
|
||||||
|
roadsLabelOpacity: 0.8,
|
||||||
|
roadsLabelSize: 11,
|
||||||
|
trailsLabelColor: "#551515",
|
||||||
|
trailsLabelHaloColor: "#0a0000",
|
||||||
|
trailsLabelHaloWidth: 1.5,
|
||||||
|
trailsLabelOpacity: 0.8,
|
||||||
|
trailsLabelSize: 11,
|
||||||
|
labelFont: ["Noto Sans Regular"],
|
||||||
|
hitWidth: 14,
|
||||||
|
},
|
||||||
|
blmTrails: {
|
||||||
|
color4wdHigh: "#772222",
|
||||||
|
color4wdLow: "#661818",
|
||||||
|
colorAtv: "#772222",
|
||||||
|
colorMotoSingle: "#661818",
|
||||||
|
color2wdLow: "#551515",
|
||||||
|
colorNonMech: "#551515",
|
||||||
|
colorDefault: "#3a1010",
|
||||||
|
colorSnow: "#661818",
|
||||||
|
lineOpacity: 0.8,
|
||||||
|
lineOpacityOther: 0.7,
|
||||||
|
lineWidth: { z10: 2.0, z14: 3.0, z16: 4.0 },
|
||||||
|
dashImproved: [4, 2],
|
||||||
|
dashAggregate: [1, 2],
|
||||||
|
dashSnow: [4, 2, 1, 2],
|
||||||
|
dashOther: [4, 2, 1, 2, 1, 2],
|
||||||
|
labelColor: "#551515",
|
||||||
|
labelHaloColor: "#0a0000",
|
||||||
|
labelHaloWidth: 1.5,
|
||||||
|
labelOpacity: 0.8,
|
||||||
|
labelSize: 11,
|
||||||
|
labelFont: ["Noto Sans Regular"],
|
||||||
|
hitWidth: 14,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const nightopsSatellite = {
|
||||||
|
opacity: 0.5,
|
||||||
|
brightnessMin: 0.0,
|
||||||
|
brightnessMax: 0.15,
|
||||||
|
contrast: 0.0,
|
||||||
|
saturation: -1.0,
|
||||||
|
hueRotate: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
const nightopsTheme = {
|
||||||
|
id: "nightops",
|
||||||
|
name: "Night Ops",
|
||||||
|
dark: true,
|
||||||
|
swatch: ["#0a0000", "#cc3333", "#551515"],
|
||||||
|
fontImports: [],
|
||||||
|
colors: nightopsColors,
|
||||||
|
satellite: nightopsSatellite,
|
||||||
|
overlay: nightopsOverlay,
|
||||||
|
ui: nightopsUI,
|
||||||
|
}
|
||||||
|
|
||||||
|
export default nightopsTheme
|
||||||
|
|
@ -20,6 +20,7 @@ import cleanTheme from './clean.js'
|
||||||
import cyberpunkTheme from './cyberpunk.js'
|
import cyberpunkTheme from './cyberpunk.js'
|
||||||
import rangerTheme from './ranger.js'
|
import rangerTheme from './ranger.js'
|
||||||
import tacticalTheme from './tactical.js'
|
import tacticalTheme from './tactical.js'
|
||||||
|
import nightopsTheme from './nightops.js'
|
||||||
|
|
||||||
// ═══════════════════════════════════════════════════════════════════════════
|
// ═══════════════════════════════════════════════════════════════════════════
|
||||||
// UI CSS CUSTOM PROPERTIES
|
// UI CSS CUSTOM PROPERTIES
|
||||||
|
|
@ -494,6 +495,7 @@ const themes = {
|
||||||
cyberpunk: cyberpunkTheme,
|
cyberpunk: cyberpunkTheme,
|
||||||
ranger: rangerTheme,
|
ranger: rangerTheme,
|
||||||
tactical: tacticalTheme,
|
tactical: tacticalTheme,
|
||||||
|
nightops: nightopsTheme,
|
||||||
// Custom themes go here. Example:
|
// Custom themes go here. Example:
|
||||||
// 'midnight': {
|
// 'midnight': {
|
||||||
// id: 'midnight',
|
// id: 'midnight',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue