RainViewer's satellite feed is empty, so the Clouds toggle never drew anything and ground
radar doesn't reach open ocean. Use NASA GIBS GOES-West/East infrared tiles instead,
auto-enabled when flying to a storm, default off otherwise.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Main app
- No backdrop-filter over the live map, animated sky, or sticky headings (it re-blurs every
frame; on iPhone that is a classic stutter/lock-up); top/bottom bars keep a light 8px blur
- Sky effect only draws while the hero is on screen and the Now tab is active, ~30fps cap,
fewer particles on phones; fixed a stale animation-frame id that could stop restarts
Dashboard
- Charts are built only when the Charts tab is opened (was ~11 charts on every page load),
and the 2-minute refresh no longer rebuilds them in the background
- On phones: max 360 points per chart (was 720), no entry animation, device pixel ratio capped at 2
- Lighter header blur, none on small buttons/cards
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- 'What is this station?' card: a personal weather station measuring real conditions on site
(not a forecast), how it differs from the Now tab, update cadence, what Live/Offline mean
- Lists the instruments this station actually reports (temp/humidity, wind, rain, pressure,
sun, indoor), using the station's real name
- Open for new visitors, remembers once closed; empty state and Now-tab badge/tab hover explain it too
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The ⌖ button reported 'Location access denied' for every failure, including timeouts and
no-GPS-fix errors that have nothing to do with permission.
- Specific messages for denied / no fix / timeout, with the exact iPhone steps (Safari tab vs
installed web app) and the error code for diagnosis
- One patient high-accuracy retry for slow or cold GPS fixes (a real denial is not retried)
- Live permission status line under the search row (allowed / not asked / blocked)
- Mentions Safari content blockers as a possible cause
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A reverse proxy in front of the app serves stale copies of static files for hours (live app.js and
sw.js were old next to new HTML). iOS also showed a letter tile (N / S) because its separate
icon download failed.
- HTML pages are served through a versioner: every local script/stylesheet/icon/manifest gets a
content-hash query (app.js?v=…), so any change is a URL no proxy or phone has cached
- Service worker URL versioned too; SW offline lookups tolerate the query string; cache v15
- The 180px apple-touch-icon is embedded in each page as a data: URI, so the Home Screen icon
no longer depends on a second network request
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
iOS showed a letter tile ('N') when adding to the Home Screen. The live files were fine, but a
reverse proxy in front of the app serves static files with a long cache lifetime (live icon.svg
and sw.js were stale) and iOS remembers a failed icon per URL.
- New versioned URLs no proxy/phone has cached; old paths kept for existing installs
- apple-touch-icon declared at 180/167/152/120 (opaque 8-bit RGB PNGs) for app and dashboard
- 180px icon also listed in both manifests; notification icons and root fallbacks use v2
- Service worker cache bumped
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- setup/recover/settings pages now declare the dashboard touch icon and 'Station' title
- /apple-touch-icon.png, /apple-touch-icon-precomposed.png and /favicon.ico serve real icons
(iOS falls back to these when a page declares none; they used to 404/204)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Redrawn sun-and-cloud icon in the current palette; artwork sits inside the maskable safe zone
(the old one was clipped by round/squircle masks and used the old warm colours)
- Separate 'any' and 'maskable' manifest entries; opaque iOS touch icons
- Station Dashboard gets its own chart icon so both installed apps are distinguishable
- Vector favicon + PNG fallback; icons verified served by both manifests
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Hurricane / tropical storm fixes
- NHC intensity is in knots: show real mph (80 kt = 92 mph) instead of mislabelled 'mph'
- Real Saffir-Simpson category from wind (was always cat 1); subtropical, post-tropical and
potential-cyclone types no longer shown as 'depression'; each storm shows movement
(direction + mph, previously a non-existent field), distance from you, update time, advisory link
- Forecast track points coloured by their own forecast strength (not the current class)
- Map click handlers registered once (popups stacked on every refresh); overlays wait for the
map to settle instead of silently not drawing while tiles load; stale renders superseded
- Subtropical/tropical advice added to alert guidance; escaped storm names
Alert cards (active alerts only)
- What it's for, area, window, time remaining, plain-language meaning, what to do, and a
Full details expander (headline, text, instructions, severity/urgency/certainty, issuer)
- No longer drops alerts beyond 6 per severity group; expired alerts are filtered out
- Shared plain-language alert glossary (alert-info.js, 64 products incl. tropical and surge)
now used by both the app and the dashboard history
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Map fills everything between the top bar and bottom nav; no page scroll on this tab
- Floating round controls (layers, my location, full screen), readout chips top-left,
layers sheet beside the controls, weather summary + radar timeline floating at the bottom
- Safe-area aware in full-screen mode; zoom buttons tucked away on touch devices
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Map fills the screen (was a 56vh strip); timeline and details sit below it
- No longer snaps back to the main-page radar's location/zoom on every refresh or tab switch;
starts as a wider regional view, remembers pan/zoom, and recentres only when the location changes
- New 'My location' button
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Resolves ZIP (default 24550) to the nearest NWS observation station; logs every observation
(normalised imperial values + raw METAR), back-fills ~7 days, snapshots the hourly forecast
every 3h, and logs alerts for that point
- Chart overlay (temp, humidity/dew point, wind, pressure) with an NWS toggle in the History bar
- 'Official NWS observation' card on the Now tab comparing against your station
- Settings: change the reference ZIP and see logging status
- Exact-unit conversions for NWS values (verified against known conversions)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Install banner (phones), Settings guide and dialog with iPhone/iPad and Android steps,
native Install button where supported; steps also on the dashboard Account page
- apple-touch-icon now a PNG (iOS ignores SVG icons)
- Shared pwa-safe.css: dark cap behind the status bar/Dynamic Island in the installed app,
inset-aware offline banner, pull-to-refresh, bottom bars, full-screen map, dialogs
- Landscape-aware content gutters; measured top-bar height; viewport-fit=cover on every page
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Plain-language meaning for common NWS products, shown in the row and expanded view
- Details column: reason, area, severity, effective window; click for full text/instructions
- New alerts log area, severity, urgency, certainty and sender
- Older entries are filled in from NWS by alert id (cached in data/alert-details.json);
alerts NWS no longer serves fall back to the built-in meaning
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Wettest/driest/hottest/coldest/windiest month and wettest/hottest/coldest/windiest year,
each naming the period (e.g. 'September 2026') and flagging partial periods
- Average-based records prefer complete periods; counterparts say what they're waiting for
- 'Records by calendar month (any year)' table with the date/year of each record
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- /api/station/history?range=all returns everything on disk, bucketed (cached 60s)
- Year-aware axis labels for 1y/2y/3y/All
- Pressure tendency widens its change window to the bucket size on long ranges and says so
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- overscroll-behavior moved from <body> to <html>: with html+body both overflow-x:hidden,
body is a scroll container and the rule blocked wheel scrolling from reaching the page
- sunTimes returned the neighbouring day's sunrise/sunset (julian-day rounding), so midday
looked like night; align results to the requested local day
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- One slate/blue palette across the app, dashboard, account/login pages (data colours
stay orange = warm, blue = cool on the dashboard)
- Slim sticky top bar with location chip, gear (settings) and ? (learn); 4-tab nav
(Now, Station, Map, Alerts) with a thumb-reach bottom bar on phones
- Hero sky gradient by condition/time with rain, storm, snow and star effects
(respects reduced motion); keeps the searched city and badges when temps come from your station
- One-line summary, 'Next 2 hours' bars and rain countdown from 15-minute precipitation,
rain/cold-aware 'Bring' chips; yesterday + 'vs usual' context from the station
- Scrubbable hourly chart (temp, rain chance, wind), 7-day range bars, AQI gauge,
details tiles instead of drawers, taller radar with location marker + alert polygons
- Skeleton loading instead of a full-screen spinner, sticky section headers, safe areas
- Server: minutely_15 precipitation, public /api/station/summary
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- New Station tab (top tabs, bottom nav, swipe order) carrying the old /conditions look:
radar-ring hero, condition pill, wind compass, atmosphere/precip/solar cards, indoor
- Scoped sl-* styles and station-live.js; units follow the app's metric/imperial setting
- Empty/error states when no station is connected
- /conditions now 301-redirects to /?tab=station; removed conditions.html,
/api/conditions/public and the old My Station drawer
- /api/ambient-config also returns the station name
- Dashboard and settings links updated; SW cache v8; manifest shortcut for Station
- Drops an indoor-temp block in applyStationOverlay that referenced an out-of-scope helper
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- data/users.json store; existing single account migrates to first admin
- Roles: admin (settings, import, users) and viewer (read-only, own password)
- Live role/disabled lookup; per-user session epoch so password changes,
resets and disabling sign that user out everywhere
- Login brute-force lockout (5 fails -> 5 min), constant-time unknown-user check
- /api/users CRUD with last-admin and self-lockout safeguards
- Account page (own password + admin user management); role-aware header
- Min password length 8; recovery token resets the primary admin and clears lockouts
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Keep per-day extremes in data/records.json (merge-only) and derive all-time,
notable-day, monthly and yearly records from it; rebuild from raw files at startup
- Use station maxdailygust for true gust extremes
- Add /api/station/backup.jsonl, records-backup.json and records/rebuild
- Dashboard: safe-area insets, 44px touch targets, scrollable nav/range bars,
chart touch-action, standalone PWA manifest + apple meta tags
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Share a disk-backed per-day dateutc set between live recorder and backfill
- Validate timestamps before saving; dedupe existing files at startup and on read
- Use station-local day (not UTC) for rain totals, streaks, degree days and
monthly summary so dailyrainin resets line up (Sept rain was 4.37in vs 2.24in)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
- Move renderHurricaneOverlay call to after track layers so position
circles render on top of the track line and dots
- Add map.loaded() guard to avoid overlay being silently skipped
if the map style hasn't finished initializing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Parse NHC forecast advisory text (FORECAST VALID / OUTLOOK VALID lines)
to extract real forecast positions at 9–117h intervals with wind speeds
- Render forecast track as dashed line + clickable dots (wind on click)
- Auto-fit map bounds to show the full 5-day track after loading
- Fix buildStyle to use OpenFreeMap vector tile URLs without API key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace CARTO basemap tiles (now require API key) with OpenFreeMap
vector tiles (positron for light, liberty for dark) — no key needed
- Add click handlers on hurricane panel cards to fly to storm on map
- Add flyToHurricane(): switches to map tab, enables hurricane overlay,
flies to storm coords, shows popup with storm details
- Add /api/hurricanes/track proxy to fetch NHC GIS 5-day forecast track
line and render it as a dashed overlay on the map
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The alert history log was only populated inside the subscriber loop,
so it stayed empty when no push subscriptions existed. Now the cron
always checks and logs active NWS alerts for the dashboard location
before the subscriber early-return.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Show a prompt linking to Settings instead of silently hiding the
alerts section when no lat/lon is saved
- Clear the alert cache when location is saved so alerts appear
immediately without waiting for the 5-minute cache to expire
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extracts API keys, alert thresholds, station name/location, data
export/import, and password change into a standalone settings page.
Dashboard gains a Settings nav link; the accordion at the bottom
is removed along with its now-orphaned JS and CSS.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GET /api/dashboard/alert-history?days=N reads daily .jsonl files from
data/alerts/ and returns entries newest-first. Dashboard gets a lazy-loaded
collapsible panel with a table showing time, type (NWS/threshold badge),
event name, and details, with 7d/30d/90d range selector.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
NWS alerts and all threshold firings are now appended to daily .jsonl
files in data/alerts/ (same pattern as data/station/). NWS alerts are
deduplicated by alert ID across subscribers to avoid duplicate log lines.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves workflow to .gitea/workflows/ and updates container registry
from ghcr.io to git.necloud.us using REGISTRY_USER/REGISTRY_TOKEN secrets.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Visual enhancements:
- Sticky header: backdrop-filter blur + box-shadow on scroll
- Live green pulsing dot next to Updated timestamp
- Section cards: gradient border (accent→border→cool via padding-box trick)
- Stat tiles: hover lift (translateY -2px + shadow)
- Skeleton shimmer on all stat tiles until first data arrives
- Value flash animation (fade+slide up) on every data refresh
- Hero temperature: count-up animation when value changes
- Fix set() to preserve trend arrow spans (was being wiped by textContent=)
- Wind rose petals: entrance animation growing in over 650ms
- Chart cards + today bar: hover lift
- Records panel: gold border + ★ badge on records set within last 30 days
- Range/refresh/settings buttons: already had press+glow from prior commit
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Range buttons, refresh, and settings action buttons now get:
- backdrop-filter: blur(10px) frosted glass base
- cubic-bezier(.2,0,0,1) iOS-style easing
- box-shadow glow ring on hover
- scale(0.95) press effect on :active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- :active scale(0.95) press feel on all nav buttons
- box-shadow glow ring on hover (accent @ 20% opacity)
- cubic-bezier(.2,0,0,1) iOS-style snap easing on all transitions
- backdrop-filter: blur(10px) frosted glass base on all buttons
- Dashboard → arrow wraps in <span class="arr"> and slides 2px right on hover
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
color-mix(accent 18%, transparent) keeps text readable and gives a
ghost-button tint instead of a full solid fill.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace plain text/opacity links with bordered pill buttons that fill
with accent color on hover — consistent across main app, conditions,
and dashboard headers.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Main app: split tagline into attribution + Station/Dashboard nav pills (always visible, styled with border/hover)
- Conditions page: add Dashboard → link and ← App back-link in header
- Dashboard: add Conditions link, rename App → ← Weather in header nav
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
drawWindRose used canvas.width (physical pixels) for coordinates while
the context was already pre-scaled by devicePixelRatio. On iPhones
(dpr=2/3) this placed the entire rose off-screen. Fix by dividing by
dpr to get CSS dimensions before computing cx/cy/R.
Also make sWindDir stat always show a value ('—' fallback when winddir
is null) and add null guards on sEventRainTile/sTotalRainTile to
prevent a silent throw from aborting updateLatest() early.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Restore tempinf/humidityin tiles from PWS data on index.html (removed
with thermostat cleanup but still available from Ambient station)
- Dashboard: replace two flat secondary-stat grids with labeled section
cards — Wind, Precipitation, Climate, Indoor — for clearer visual
hierarchy and category separation
- Indoor section card includes Ecobee portal link; appears only when
station reports indoor sensor data
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ecobee API is closed to new developer registrations and iOS sub-daily
automations are no longer available, making the HomeKit push approach
unworkable. Removes all related code:
- server.js: HomeKit push endpoints, token management, data files
- dashboard.html: thermostat section card, indoor stat tiles, indoor
charts, HomeKit settings panel, HVAC badge CSS, all related JS
- index.html: Indoor Temp stat card
- app.js: indoor sensor display logic
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move wind direction to its own line below "mph" so it doesn't
wrap or get clipped on narrow stat tiles.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Hero section with 5.5rem temperature, feels-like, live wind description
- Humidity, pressure, solar radiation, wind sparklines drawn from history data
- Today at a glance bar: today's high/low temp, rain total, peak gust
- Tile color tinting by value: temp (hot/warm/cool/cold), UV severity, wind, rain rate
- Wind cardinal direction shown in hero subtitle and secondary wind tile
- Chart lines now have subtle gradient area fill (non-dashed series only)
- Chart height increased from 200px to 240px; cards get hover shadow
- Section cards with light headers group conditions, totals, and history
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Max Gust Today tile (maxdailygust from Ambient)
- Feels Like In tile (feelsLikein, Ambient-computed)
- Use Ambient's dewPointin directly instead of computing from tempinf/humidityin
- Event Rain tile (eventrainin, shows only when > 0)
- Total Rain lifetime tile (totalrainin)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- NWS active alerts shown as color-coded cards at top of dashboard (5-min cache), auto-refresh every 5 min
- Station location (lat/lon) configurable in settings; falls back to push subscription coordinates
- Consecutive dry/wet streak tile in extended stats (60-day lookback, 0.01" rain threshold)
- Indoor sensor tiles (Temp In, Humidity In, Dew Point In) auto-show when station reports tempinf/humidityin
- Indoor temperature and humidity history charts when indoor data is present in selected range
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Alerts (server):
- Station temp high/low threshold alerts via push + ntfy
- Freeze warning at ≤34°F (station reading)
- Station wind gust threshold alert from real readings
- Station offline alert when no data for >20 min (auto-clears on reconnect)
Dashboard:
- Trend arrows (▲/▼/–) on temp, humidity, dew, wind, pressure, UV, solar tiles
comparing current vs 1h ago via new /api/station/trend endpoint
- Offline banner when station last reported >15 min ago
- Monthly summary table (avg temp, high temp, max gust, total rain, readings)
- Temperature calendar heatmap — GitHub-style year grid, blue→orange scale
- Alert threshold settings UI: temp high/low, wind gust, rain rate
saved to all push subscriptions via new /api/subscriptions/thresholds
- Station name setting — persisted in auth file, served on conditions page
- Change password form in settings (no recovery flow needed)
Server:
- GET/POST /api/dashboard/station-name
- POST /api/dashboard/change-password
- GET /api/station/monthly-summary
- GET /api/station/trend
- GET /api/subscriptions, POST /api/subscriptions/thresholds
- /api/conditions/public includes stationName field
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- getDailyRecoveryToken(): HMAC of SESSION_SECRET + current day — changes
every 24h, requires no extra storage
- Logs token to console on startup (visible in CasaOS container logs)
- GET/POST /dashboard/recover: validates token, sets new password
- dashboard-recover.html: enter token + new password, with instructions
- dashboard-login.html: 'Forgot password?' link + success message after recovery
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replaces implicit station-name link with a visible '← App' nav link
in the accent color, keeping station name as non-interactive label.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Tagline in header links to /conditions and /dashboard on desktop.
Settings tab adds a Station section with both links for mobile access.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Full-bleed hero with animated radar sweep ring, dot-grid background, and a
giant temperature number that shifts color by value (ice blue → amber → red).
Canvas compass with N/S/E/W ticks and wind arrow in the Wind section.
Atmosphere, Wind, and Precipitation+Solar sections with Barlow Condensed data
tiles. Full light/dark theme support.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Dashboard: account-protected station data recorder with PBKDF2 auth and
HMAC-signed sessions; Chart.js time-series charts with 1h–3y range selectors;
wind rose canvas; auto-refresh every 2 min; 1-min polling cron
- Analytics endpoints: all-time records, rain totals (7d/30d/YTD), heating/cooling
degree days, CSV export, year-over-year overlay, hourly anomaly detection
- Dashboard UI: pressure trend arrow, rain tile row, HDD/CDD tiles, anomaly tile,
YoY toggle, collapsible records panel, CSV export, backfill progress bar
- Public conditions page at /conditions (no auth) with auto-refresh every 2 min
- Rain rate push alert via web-push and ntfy when threshold exceeded
- Station data stored as per-day JSONL files; backfill imports up to 1yr from Ambient
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- POST /api/station/backfill: pages backward through Ambient's historical API
at 1 req/sec, deduplicates against existing JSONL records, writes to daily files
- GET /api/station/backfill/status: polls live progress (days done, readings inserted)
- Dashboard settings panel: day-range selector (7d/30d/90d/180d/1y), Import button,
progress bar with live count; auto-reloads charts when complete
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Station API Keys section at bottom of dashboard (auto-opens if unconfigured)
- Shows configured/missing status on load
- Fields for Ambient API Key and Application Key; saves via existing endpoint
- POST /api/ambient-config now requires dashboard auth
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Protected /dashboard route with PBKDF2 password + HMAC-signed cookies
- First-run setup flow at /dashboard/setup
- Records Ambient station readings to daily JSONL files in app/data/station/
- Deduplicates on dateutc so 1-min polling never writes duplicate rows
- Dashboard charts: temp, humidity/dew, wind+gusts, wind rose, pressure,
rain rate, rain accumulation, UV, solar radiation
- History range selector: 1h / 6h / 24h / 7d / 30d / 90d / 1y / 2y / 3y
- Auto-downsamples to 720 points for long ranges
- Cron interval changed from 10 min to 1 min (with dedup guard)
- app/data/ added to .gitignore (contains keys and session secret)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When station keys are configured and the last reading is < 15 min old,
the alert cron uses windgustmph and tempf from the station instead of
Open-Meteo model values. AQI still comes from Open-Meteo (no station
equivalent). Alert bodies now include "(station)" or "(forecast model)"
so the source is visible in the notification.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When configured, a new "Use as primary source" toggle appears in Settings
under Ambient Weather Station (defaults on). When on, the location header
shows the station name and "Ambient Weather Station" subtitle instead of the
city; the hero badge is hidden as redundant. Toggling off restores the city
name immediately and re-shows the hero badge.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add fullscreen toggle button (⛶/✕) to Map tab controls row
- CSS class `map-fs` hides header/nav and expands map to fill screen
- Drop unreliable requestFullscreen() API (blocked on iOS/PWA) in favor of pure CSS approach
- Fix button state desync: syncBtn() runs on init so stale ✕ state can't persist across reloads
- Shrink embedded radar height on mobile (220px) and tune dvh calculations for safe-area insets
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace Leaflet with MapLibre GL JS v4.7.1 across all map instances
- CARTO dark/light and Esri satellite raster basemaps (no API key)
- All overlays (hurricane, wildfire, SPC, wind arrows) ported to GeoJSON sources/layers
- AQI, alert, temp, sun/moon markers via maplibregl.Marker with custom HTML
- Radar animation pre-loads all frames on load for smoother playback
- Compact loc-header: tighter padding and font sizes, all info preserved
- Search bar moved from header to Settings tab under Location section
- Service worker bumped to weather-v7
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>