Past minute 30 of the wall clock the next forecast hour is closer to
utc_now() than the current hour, so the picker would land on (e.g.)
19:00Z when the user is at 18:43Z. HRRR has 19:00Z, but the HRDPS
chain only seeds the *current* hour (18:00Z), so the dual-source map
showed an empty Canadian half whenever we crossed the half-hour mark.
Switch to "most-recent valid_time <= now", with a fallback to the
closest future when nothing on disk is yet at-or-before now (cold
start). Hoist the picker into a public function so it can be unit-
tested deterministically — anchoring the integration test on
DateTime.utc_now() truncated to the hour would have only verified the
new behavior past minute 30.
/weather-ca delegates to the same picker so the two maps agree on
"current."
The 1-hour valid_time filter inherited from /weather is wrong for
HRDPS: the model publishes 4x/day with 3-4h publication latency and
the chain step adds ~13 min on top, so the freshest data on disk is
routinely 4-6h old. With the 1h cutoff in place, /weather-ca's
timeline was empty whenever there wasn't an active chain step running,
which left the JS hook with nothing to fetch. The sidebar already
shows the selected valid_time prominently — users can see for
themselves how stale the data is and don't need the page to hide it.
New LiveView at /weather-ca duplicates the /weather UI but defaults the
viewport to central Canada (55N, -100W, z=4) and renders the map div
with data-source="hrdps". The JS hook reads that attribute and appends
&source=hrdps to every cell fetch; the WeatherTileController routes
those reads through Weather.weather_grid_hrdps_at/2, which only reads
the <vt>.hrdps scalar dir and skips HRRR merging entirely. Timeline is
sourced from ScalarFile.list_valid_times_hrdps/0 so HRDPS-only hours
show up even when no HRRR file exists for the same valid_time.
Also drops "— Unified" from the algo.md H1.