/* * Wallpaper background config. * * Properties: * theme - Active palette theme. One of the keys in window.THEMES * (default 'ash'). The matching CSS file is loaded at * startup. * language - UI / i18n language code (default 'en'). * timeFormat - Format string for the clock using the token set below * (Moment.js-like names, own mini-formatter). * debug - If 1, the right-side debug panel is shown. * units - Object with 'temperature' ('C' or 'F'). * location - Geographic coordinates for sun/moon calculations. Used * by SunCalc (https://github.com/mourner/suncalc). Object * with 'lat' (latitude, -90 to +90) and 'lon' (longitude, * -180 to +180). Positive lat = north, positive lon = east. * Optionally add 'label' (string) to override the * reverse-geocoded city name. * Note: the height grid is axis-aligned (N up); terrain * matches the square ground mosaic and straight flights * (prefetch direction via #fetch=N). Heights: Copernicus * DEM via terrarium tiles (z9, ~200 m). * terrain - 3D ground from real elevation data. Object: * enabled - true (default) / false = flat plane. * exaggeration - vertical scale factor on the DEM * (default 8; 1 would be physically * true and nearly invisible at this * horizontal scale). * weatherSim - If true, ignore open-meteo and cycle through * ['sunny','cloudy','stormy','night'] automatically every * weatherSimInterval ms. Useful for A/B testing every * theme without waiting on the API. * weatherSimInterval - Sim cycle period in ms (default 30000). * orbit - Figure-eight flight (Bernoulli lemniscate) around * CONFIG.location instead of a straight drift. The * eight's self-crossing sits exactly on the configured * coordinate. Each time the aircraft crosses that point * a new random orientation is picked and blended in * over one lobe (spline through the crossing). Object: * radiusKm - lobe tip reach from the centre in km * (~13 km per tile at z11/48deg N). * Clamped (~190 km) so tips + fog horizon * fit inside the 43x43 tile mosaic. * clockwise - travel direction along the eight. * reorient - random re-aim at every crossing * (default true; false keeps the bearing). * Set to null (or remove) for the straight-line flight. * fog - Ground fog / distance haze. Object with 'distanceKm' * (visibility range at which terrain fully blends into * a milky haze; default 120). false/0 disables fog. * clouds - Vertical extent of the cloud deck in world units * (1 unit = ~12.9 km at zoom 11; camera band 15-35 km, * i.e. y ~ 1.16-2.70). Default puts the deck top (~11.6 * km) below the lowest flight altitude. * tiles - All downloads (street tiles, elevation grid, last * weather payload, geo label) live permanently in * IndexedDB and are never re-fetched once cached; a * warm cache = fully offline rendering. Set * expireDays (number > 0) to re-fetch street tiles * periodically (e.g. 90). * * Time format tokens (subset): * YYYY 4-digit year (2026) * MMMM full month name (October) * MM month with leading zero (10) * DD day with leading zero (07) * HH 24-hour hour with zero (18) * mm minute with leading zero (14) * ss second with leading zero (25) * a am/pm lowercase (pm) * A AM/PM uppercase (PM) * dddd full weekday name (lowercase!) * Any other character is emitted verbatim. */ window.CONFIG = { theme: 'ash', language: 'en', timeFormat: 'DD. MMMM, YYYY ‒ HH:mm:SS', debug: 0, units: { temperature: 'C' }, // Data attribution at the bottom of the info box (automatic text // based on the enabled layers). false = hidden. credits: true, // Internal 3D resolution scale (0.3..1, default 1). Lower values // render the clouds/map shader at reduced resolution and upscale // via CSS - use it if fps is low (GPU-bound) despite a quiet CPU. renderScale: 1, // WebGL scene frame cap (default 30; 0 = free-running/vsync). All // scene motion is time-based, so the cap only changes smoothness. maxFps: 30, location: { // Latitude and longitude for sun/moon calculations lat: 48.5667, lon: 13.4319 }, weatherSim: false, weatherSimInterval: 30000, // All downloads (basemap tiles, elevation grid, weather JSON, geo // label) stay in IndexedDB permanently and are never re-fetched once // cached. expireDays (days, > 0) re-enables periodic basemap refresh. tiles: { expireDays: null, // true = draw tile borders + N/S + x/y coords into the ground // texture (debug orientation). Off = clean map. debug: false }, // Ground imagery: 'satellite' = ESRI World_Imagery (aerial, no // labels), 'streets' = ESRI World_Street_Map (with place names). // Both cached permanently (separate cache prefix per style). ground: { style: 'satellite' }, // Figure-eight course around location (lat/lon); the crossing point // sits exactly on the coordinate. null/removed = straight flight. orbit: { radiusKm: 60, // lobe tip: max distance from the centre clockwise: true, reorient: true, // random heading at every crossing pass // Slow vertical bobbing inside the 15-35 km flight band: // centre 25 km (~1.93 world units), amp = half the band // (10 km ~ 0.77); hard clamp at the band limits. // periodS = seconds per cycle, tilt = camera nose reaction to // climb/descent rate. enabled: false = constant 25 km. altBob: { enabled: true, amp: 0.77, periodS: 90, tilt: 0.3 } }, // Ground fog: distance haze. distanceKm = visibility until fully // saturated haze (false/0 = off). fog: { distanceKm: 120 }, // ---- Civil aviation (CONFIG.flights) --------------------------------- // Low-poly jets (CC0 model, vendor/plane3d.js) with randomized target // airports: the destination is rolled at every take-off (hubs weighted // via wHub/wField/wStrip). Paths are gentle Bezier curves resampled to // arc length (constant ground speed) flown as a full profile: take-off // and climb, cruise, descent and landing, a short ground hold, then a // fresh destination. By day sun-lit silhouettes; by night white // strobing position lights with a red beacon. Contrails form above // contrailStartKm on contrailChance of the aircraft and stay visible // for contrailLifeS. All distances in km (world scale: 1 unit = one // z11 tile ~ 12.9 km at 48.6 deg N). flights: { enabled: true, altitudeKm: 14, // cruise altitude climbKm: 100, // climb/descent run to/from cruise altitude count: 84, // max simultaneous aircraft speedKmh: 850, // mean ground speed speedVar: 0.18, // +/- deviation (0..0.5) minLegKm: 60, // shortest leg (no taxi hops) holdMinS: 50, // ground hold at destination (min..max) holdMaxS: 150, wHub: 4, // destination weights: hub / airfield / strip wField: 2, wStrip: 1, contrailChance: 0.6, // share of aircraft with a persistent trail contrailStartKm: 6, // trail formation altitude contrailLifeS: 300, // trail visibility duration contrailWidthM: 310 // full trail width }, // 3D ground from real elevation data (Copernicus DEM, terrarium // tiles). enabled: false = flat plane. exaggeration: vertical // elevation scale (1 = real, nearly invisible; default 8). // wireframe: true = overlay mesh edges as orange lines (debug). // nightLights: NASA VIIRS city-lights layer, cross-faded into the // day map over ~1 h after sunset (dark ground, glowing cities). // One-time fetch (~49 tiles), cached permanently. false = no light // overlay; at night the normal texture stays much brighter (only // gently dimmed). // carLights: moving lights on the real road network (OSM/Overpass // curves, additive over the terrain at night). JSON once, cached. // cityLights: settlement lights - OSM place nodes (city/town/ // village/hamlet) as slightly yellow glow dots from dusk on; // bigger settlements (place class + population tag) get more and // brighter dots. One Overpass query, cached permanently. // Data (c) OpenStreetMap contributors, ODbL. terrain: { enabled: true, exaggeration: 8, wireframe: true, nightLights: false, carLights: true, cityLights: true }, // Day simulation: true = a full 24 h cycle runs in cycleSeconds // (sun rises east, culminates south, sets west). // false = real sun/moon positions via SunCalc. // fixedTime: 'HH:MM' (or a number 0-24) freezes the sim clock at // that time of day (moving objects, clouds, cars and the weather // sim keep running unaffected); null/omitted = the clock advances. day: { simulation: false, cycleSeconds: 20, fixedTime: null }, // Cloud deck in world units (1 unit ~ 12.9 km at zoom 11; flight // band 15-35 km = y ~ 1.16-2.70). Keep the top below the lowest // flight altitude. clouds: { top: 0.9, bottom: -0.3 }, }; // List of available themes. The key is the theme id (used in config.theme), // the value is the CSS file name. Add a new theme by adding a new entry here // and dropping the corresponding CSS file in the same directory. window.THEMES = { 'ash': 'ash.css', 'gruvbox': 'gruvbox.css', 'nord': 'nord.css' };