Station overlay:
- When Ambient Weather station data is present and fresh (<15 min),
its readings replace the model's current conditions: temp, feels-like,
humidity, dewpoint, wind speed/direction, gusts, pressure (inHg→hPa),
UV index, rain today, wind peek summary, and data-panel readouts
- A small "📡 My Station" badge appears in the hero when active
- applyStationOverlay() is called at the end of renderWeather (instant
if station data already loaded) and again whenever station data
refreshes (so the display stays live every 60 s)
- Hourly/daily forecasts continue to use Open-Meteo
Server-side key persistence:
- POST /api/ambient-config saves keys to data/ambient-config.json
(same persistent volume as VAPID and subscriptions)
- GET /api/ambient-config returns {configured: bool} without exposing keys
- /api/ambient checks query params → saved config → env vars in order
- Settings Save button posts keys to server after a successful test;
confirms "saved for all devices" in the status line
- On page load, if no localStorage keys but server is configured,
the station loads automatically on any device
- Persist alertIdsSeen to localStorage so already-seen alerts don't
re-notify every time the PWA is opened; cap stored IDs at 200 entries
- Use serviceWorker.showNotification() for alert notifications so they
work when the app is backgrounded, with fallback to new Notification()
- Add ⛶ fullscreen button to radar embed; uses Fullscreen API and
resizes the MapLibre canvas after toggle
- Fix swipe-to-change-tab: block gesture when touch starts on a map,
hourly scroll row, or radar timeline; also require the gesture to be
more horizontal than vertical (dx > dy*1.5) to avoid conflict with
vertical scrolling