/** Route → ambient 3D weather (particle glow, drift, palette). Mirrors ambientMusic page map. */ export type WeatherVibe = | 'forge-glow' | 'crucible-embers' | 'emberwake-pulse' | 'starfield-dim' | 'medium-drift'; export type WeatherPalette = 'default' | 'crucible' | 'campaign' | 'dim'; export interface PageWeatherConfig { vibe: WeatherVibe; /** 0–1 overall particle glow strength */ intensity: number; /** Velocity multiplier */ speed: number; /** Pulse / twinkle rate multiplier */ pulse: number; /** Particle density multiplier */ density: number; /** Constellation link strength 0–1 */ linkStrength: number; /** CSS grid / sacred-geo layer opacity */ layerOpacity: number; /** Orb float animation duration (seconds; higher = slower) */ orbDrift: number; /** Grid drift animation duration (seconds) */ gridDrift: number; palette: WeatherPalette; /** Campaign-energy sine pulse on emberwake routes */ energyPulse?: boolean; } export const DEFAULT_PAGE_WEATHER: PageWeatherConfig = { vibe: 'medium-drift', intensity: 0.65, speed: 0.5, pulse: 0.65, density: 0.72, linkStrength: 0.7, layerOpacity: 0.55, orbDrift: 14, gridDrift: 48, palette: 'default', }; /** Route → weather profile. Prefix match for nested paths. */ export const PAGE_WEATHER: Record = { '/forge': { vibe: 'forge-glow', intensity: 1, speed: 1, pulse: 1, density: 1, linkStrength: 1, layerOpacity: 0.6, orbDrift: 12, gridDrift: 40, palette: 'default', }, '/builder': { vibe: 'forge-glow', intensity: 1, speed: 1, pulse: 1, density: 1, linkStrength: 1, layerOpacity: 0.6, orbDrift: 12, gridDrift: 40, palette: 'default', }, '/mission-deck': { vibe: 'forge-glow', intensity: 1, speed: 1, pulse: 1.05, density: 1, linkStrength: 1, layerOpacity: 0.62, orbDrift: 11, gridDrift: 38, palette: 'default', }, '/lotl-timeline': { vibe: 'crucible-embers', intensity: 0.82, speed: 0.38, pulse: 0.72, density: 0.88, linkStrength: 0.5, layerOpacity: 0.52, orbDrift: 18, gridDrift: 64, palette: 'crucible', }, '/onion': { vibe: 'crucible-embers', intensity: 0.82, speed: 0.38, pulse: 0.72, density: 0.88, linkStrength: 0.5, layerOpacity: 0.52, orbDrift: 18, gridDrift: 64, palette: 'crucible', }, '/crucible': { vibe: 'crucible-embers', intensity: 0.75, speed: 0.32, pulse: 0.45, density: 0.85, linkStrength: 0.45, layerOpacity: 0.5, orbDrift: 22, gridDrift: 72, palette: 'crucible', }, '/emberwake': { vibe: 'emberwake-pulse', intensity: 0.85, speed: 0.55, pulse: 1.6, density: 0.9, linkStrength: 0.75, layerOpacity: 0.58, orbDrift: 9, gridDrift: 36, palette: 'campaign', energyPulse: true, }, '/spread': { vibe: 'emberwake-pulse', intensity: 0.85, speed: 0.55, pulse: 1.6, density: 0.9, linkStrength: 0.75, layerOpacity: 0.58, orbDrift: 9, gridDrift: 36, palette: 'campaign', energyPulse: true, }, '/settings': { vibe: 'starfield-dim', intensity: 0.22, speed: 0.15, pulse: 0.35, density: 0.45, linkStrength: 0.12, layerOpacity: 0.28, orbDrift: 36, gridDrift: 120, palette: 'dim', }, '/agents': { vibe: 'medium-drift', intensity: 0.68, speed: 0.55, pulse: 0.7, density: 0.75, linkStrength: 0.72, layerOpacity: 0.52, orbDrift: 15, gridDrift: 50, palette: 'default', }, '/dashboard': { vibe: 'medium-drift', intensity: 0.65, speed: 0.5, pulse: 0.65, density: 0.72, linkStrength: 0.7, layerOpacity: 0.55, orbDrift: 14, gridDrift: 48, palette: 'default', }, '/builds': { vibe: 'medium-drift', intensity: 0.55, speed: 0.45, pulse: 0.6, density: 0.65, linkStrength: 0.6, layerOpacity: 0.48, orbDrift: 16, gridDrift: 54, palette: 'default', }, '/pathtracer': { vibe: 'starfield-dim', intensity: 0.35, speed: 0.25, pulse: 0.4, density: 0.5, linkStrength: 0.2, layerOpacity: 0.32, orbDrift: 28, gridDrift: 90, palette: 'dim', }, }; export function resolvePageWeather(pathname: string): PageWeatherConfig { const path = pathname.split('?')[0].replace(/\/$/, '') || '/'; if (PAGE_WEATHER[path] !== undefined) { return PAGE_WEATHER[path]; } for (const [prefix, weather] of Object.entries(PAGE_WEATHER)) { if (prefix !== '/' && path.startsWith(prefix)) return weather; } return DEFAULT_PAGE_WEATHER; } export type GlowColor = { core: string; mid: string; line: string; }; export const WEATHER_PALETTES: Record = { default: [ { core: 'rgba(201, 162, 39, 0.85)', mid: 'rgba(201, 162, 39, 0.25)', line: 'rgba(201, 162, 39, 0.12)' }, { core: 'rgba(0, 232, 245, 0.75)', mid: 'rgba(0, 232, 245, 0.22)', line: 'rgba(0, 232, 245, 0.1)' }, { core: 'rgba(255, 45, 166, 0.7)', mid: 'rgba(255, 45, 166, 0.2)', line: 'rgba(255, 45, 166, 0.09)' }, { core: 'rgba(255, 176, 32, 0.8)', mid: 'rgba(255, 176, 32, 0.22)', line: 'rgba(255, 176, 32, 0.1)' }, ], crucible: [ { core: 'rgba(212, 175, 55, 0.9)', mid: 'rgba(212, 175, 55, 0.28)', line: 'rgba(212, 175, 55, 0.14)' }, { core: 'rgba(232, 93, 74, 0.78)', mid: 'rgba(232, 93, 74, 0.22)', line: 'rgba(232, 93, 74, 0.1)' }, { core: 'rgba(255, 140, 58, 0.82)', mid: 'rgba(255, 140, 58, 0.24)', line: 'rgba(255, 140, 58, 0.11)' }, { core: 'rgba(180, 90, 40, 0.72)', mid: 'rgba(180, 90, 40, 0.2)', line: 'rgba(180, 90, 40, 0.09)' }, ], campaign: [ { core: 'rgba(255, 95, 25, 0.92)', mid: 'rgba(255, 95, 25, 0.3)', line: 'rgba(255, 95, 25, 0.14)' }, { core: 'rgba(255, 176, 32, 0.85)', mid: 'rgba(255, 176, 32, 0.26)', line: 'rgba(255, 176, 32, 0.12)' }, { core: 'rgba(255, 55, 90, 0.7)', mid: 'rgba(255, 55, 90, 0.2)', line: 'rgba(255, 55, 90, 0.09)' }, { core: 'rgba(0, 220, 255, 0.55)', mid: 'rgba(0, 220, 255, 0.16)', line: 'rgba(0, 220, 255, 0.08)' }, ], dim: [ { core: 'rgba(190, 200, 230, 0.42)', mid: 'rgba(190, 200, 230, 0.12)', line: 'rgba(190, 200, 230, 0.05)' }, { core: 'rgba(130, 150, 190, 0.32)', mid: 'rgba(130, 150, 190, 0.1)', line: 'rgba(130, 150, 190, 0.04)' }, { core: 'rgba(201, 162, 39, 0.22)', mid: 'rgba(201, 162, 39, 0.08)', line: 'rgba(201, 162, 39, 0.03)' }, { core: 'rgba(0, 232, 245, 0.18)', mid: 'rgba(0, 232, 245, 0.06)', line: 'rgba(0, 232, 245, 0.03)' }, ], };