Added
- **Flow vs normal on every big river** (559, part of 566), the NOAA National Water Model map for the whole world: every GEOGLOWS v2 reach of Strahler order 5 and up (842,581) coloured by its forecast flow for the day against its own normal for the month ([docs](docs/explorer.mdflow-vs-normal-on-the-rivers)).
- `aquascope.flowstatus`: the climatology, once (`flow-climatology.yml`, by hand): the 10th, 25th, 75th and 90th percentiles of daily flow by calendar month from GEOGLOWS's `retrospective/fdc.zarr` (checked to be 1950 to 2019 against four reaches' daily records), published under `flowstatus/climatology/`. Then daily: `warnings run --day0` keeps each reach's first-day ensemble-mean flow from the chunks Floods ahead already reads, so nothing is downloaded twice, and `flowstatus daily` classes it in the river status layer's five HydroSOS classes and publishes `flowstatus/latest.bin.gz` (sorted river ids as varint gaps and a class byte each), `latest.parquet` and a manifest, writing only under `flowstatus/`.
- `aquascope flowstatus [--bbox W S E N] [--river-id ID]` and the MCP tool `flow_vs_normal`; every number in the sentence comes from the counts.
- In the Explorer: **Colour by flow against normal** in the legend's Rivers row (off by default, `fn=1` in a link) colours the living rivers by feature-state on `riverId` in the river status colours, with the forecast day and the share above and below normal in the key, and says so before the first issue is published. The lit network now takes off only its own feature-state.
- **Subbasins by monthly water balance, replayable** (557, part of 566), the HEC-HMS and QSWAT basin map for the whole world, keyless ([docs](docs/explorer.mdwater-balance)).
- `aquascope.waterbalance`: for each HydroBASINS level-4 subbasin and month since January 1990, ERA5 precipitation and actual evapotranspiration (ERA5 total evaporation; WaPOR covers Africa and the Near East since 2018 only), area-weighted from the public ARCO-ERA5 Zarr read anonymously; the subbasin's own runoff, the GEOGLOWS v2 monthly flow at its outlet reach(es) (`hydrosos/hybas_linkno_pairs.parquet`) minus the inflow from the subbasins upstream (level-4 routing built from the Archive's BasinATLAS level-12 table), in mm over its area, withheld with the reason where that difference cannot be trusted (an outlet reach carrying less than half the inflow, more than a metre of inflow a month over the subbasin, more runoff than rain over the record, or downstream of such an outlet); the closure error P - ET - Q, kept and shown; and every value's anomaly against the 1991-2020 normal for the calendar month. Months on preliminary ERA5T are flagged and recomputed when final.
- The CI cost, measured first: ERA5 is one whole-globe hour per chunk, so a month is about 1,460 chunks and 3.5 GB, and 1990 to now about 1.56 TB; decoding and summing a chunk takes about 2 ms, so reading is the cost. GitHub runners read 74 to 186 MB/s (the backfill: 2.3 to 5.9 hours, one or two dispatches), a home line 55 to 76 s a month. GEOGLOWS's monthly record for the 943 outlet reaches is about 0.5 GB. Level 4 only: level 5 would read the same ERA5 but has no GEOGLOWS outlet pairing.
- `.github/workflows/water-balance.yml` (workflow_dispatch and the 9th of each month) computes the missing months newest first until a time budget and publishes only under `waterbalance/` in the Archive; a smoke input (and a 240-hour smoke on pull requests that touch it, which measures the runner's read rate) never publishes.
- In the Explorer: a **Water balance** layer, off by default, with one legend row that switches between rain, evaporation, runoff and the closure error, as amounts or against normal, coloured on the level-4 subbasins and replayed by the time bar month by month. A click opens the map card with the subbasin's month in words and its year as bars (rain beside evaporation and runoff, the normal rain as a tick). The map card takes a layer's own chart (`chart`).
- `aquascope waterbalance [--basin ID | --at LAT LON] [--month YYYY-MM] [--bbox W S E N]`, the MCP tool `water_balance`, and "turn on water balance" in Ask the map.
- **SWMM models and results read anywhere, the browser included** (560, part of 566): an assessment and a thin reader ([docs](docs/assessments/swmm.md)).
- Tested in Pyodide 314.0.7 on EPA's examples: `swmm-api` 0.4.74 reads `.inp` and SWMM 5.2 `.out` but refuses SWMM 5.1 results; `swmmio` 0.8.6 needs `swmm-toolkit` (compiled C, no WebAssembly wheel) and has no `.out` reader of its own.
- `aquascope.io.swmm`: `read_swmm_inp` (nodes and links with coordinates, placed in lon/lat with a `crs` or a model in degrees), `read_swmm_out` (SWMM 5.0 to 5.2 results, one variable at a time in blocks, numpy only) and `swmm_summary` (the flooding nodes and the largest flows, every number from the files). Identical to `swmm-toolkit`'s own reader on five results files; a 56.7 MB file is summarised in 21 ms in Pyodide.
- `aquascope swmm model.inp model.out [--crs] [--top] [--element] [--json]` and the MCP tool `swmm_summary`. The map view is a follow-up, planned in the doc.
- **What if, on the map** (565, part of 566): "20% less rain and 2 degrees warmer" painted on the rivers, from the map card's **What if…** ([docs](docs/explorer.mdwhat-if-on-the-map)).
- `aquascope.whatif_map.whatif`: the basin draining to a reach (GEOGLOWS v2 routing tables), GR4J with the snow store where it snows, ERA5 at the basin's centre, calibrated on the gauge or on the reach's GEOGLOWS simulated flow. Returns the change in mean flow, low flow (Q95) and a T-year flood at the outlet, each with a range from the parameter sets that do as well on the validation years, and every reach downstream to the third major confluence with the change scaled by area (the simplification is stated in the answer). Basins over 100,000 km² are refused.
- `aquascope.advanced.catchment_model` gains `flood_rp`, `members` (the behavioural range), a scenario `demand_cms`, `params` (reuse a calibration) and `source="geoglows"` (calibrate on a reach's simulated flow). Without them its answer is unchanged.
- Keyless rules read a what-if line (`parse_scenario`); the on-device model or your own key only fill the four parameters, and a number not in the words, used twice, against the words' direction or out of bounds is refused (`parse_scenario_reply`).
- `aquascope whatif`, the MCP tool `whatif_map`.
- In the Explorer: sliders and one line in a small panel; the basin and the river below painted brown to teal by the change, labels at the outlet and each major confluence, a before/after swipe, a map card per reach, every run in the action log with undo. The Thur at 1,729 km² gives −38.3% mean flow in the browser and in the CLI.
- **Review my model results** (564, part of 566): checks by code on a model run dropped on the globe, each a pin with its place, severity, value and source ([docs](docs/mesh.mdreview-my-model-results)).
- `aquascope.mesh_review`: the deepest places (depth and model time; the largest rise of the water surface for a file without bed levels), negative depths, cells wetted only by a film, isolated wet cells, wet and dry flicker, the volume error from HEC-RAS volume accounting, the modelled largest extent against Sentinel-1 radar floods (Microsoft AI for Good, 2014-10 to 2024-09) and Groundsource news floods from the Archive's context mirror (comparing with every month on record, and saying so, when the run is outside them), and the modelled peak against each Archive gauge inside the mesh (timing only), or a line saying there is none. `aquascope.io.mesh.Mesh.values_block(..., raw=True)` gives the depths as the file holds them, negative ones included.
- A model only orders and words the findings: numbers are placeholders filled by code and Explain's claim lock refuses any other; keyless, the templates say it.
- `aquascope mesh review FILE [--offline] [--json]`, the MCP tool `mesh_review`, the WebMCP tool `aquascope_review_model`, and "review my model" in Ask the map.
- In the Explorer: **Review these results** on the model's legend row. Pins coloured by severity flag the cells they are about; each is in the action log, and undoing it takes its flags away. The legend row lists the nine checks. Checked on the Bald Eagle Creek example the mesh viewer used, and on synthetic runs with planted problems (each check finds its own and nothing else).
- **Groundwater on the map: a head surface from the Archive's wells, and your MODFLOW heads** (558, part of 566), the ModelMuse view, keyless ([docs](docs/explorer.mdgroundwater)).
- `aquascope.groundwater.surface`: `surface_from_readings` and `groundwater_surface(bbox, month, mode, compare)` interpolate the Environment Agency's wells in the Archive (heads in m above Ordnance Datum, so a head surface, not a depth to water) for a month, or the change against a year before, by inverse distance weighting on a grid regular in Web Mercator, drawn only where at least 3 wells lie within 20 km (the density mask: cells with one or two wells near are returned as too few), with contours. A month most wells have not reported in yet falls back to the latest one they have, and says so.
- `read_modflow_heads(hds, grid, origin, rotation, crs, cell_size, start_date, sidecars)`: a pure-numpy reader of the MODFLOW-2005 and MODFLOW 6 binary head file (identical to FloPy's `HeadFile` on FloPy's Freyberg examples), grids from `.dis` and `.disv` text, MODFLOW-2005 `.dis` and MODFLOW 6 `.dis.grb`, placed in lon/lat from the files (FloPy's `.nam` georeference, a `.tdis`) or a typed origin, rotation and CRS; heads per layer and time, big grids in blocks. FloPy 3.11.0 does load in Pyodide 314, but pulls about 10 MB of matplotlib, so the reader is our own ([docs](docs/modflow.md)).
- In the Explorer: a **Groundwater** layer, off by default, in the one legend: the surface (level or change over 12 months, with a diverging ramp for the change), the wells as small dots, the too-few-wells areas hatched grey, GRACE suggested beside it, following the time bar, and a map card on click. Drop a `.hds` with its grid on the map (the same drop zone as the mesh viewer, routed by file type) and the heads are drawn on the model grid, in the model's own length unit, layer and time step selectable and played with the time bar; a small form asks where the model sits when its files do not say. The files stay in the browser.
- `aquascope groundwater surface`, `aquascope modflow <file>`, and the MCP tools `groundwater_surface` and `modflow_heads`. "turn on groundwater" works in Ask the map.
- **Your model results on the globe, the Crayfish view** (555, part of 566): drop a HEC-RAS 2D plan file or a UGRID NetCDF mesh result on the Explorer's map (or **Tools**, **Open model results**) and see it on the globe, read in your browser and never uploaded ([docs](docs/explorer.mdyour-model-results-on-the-globe-the-crayfish-view)).
- `aquascope.io.mesh`: `read_ras_plan(path)` and `read_ugrid(path)` (and `read_mesh`, which picks) return one slim structure: the cells in longitude and latitude (reprojected with pyproj from RAS Mapper's projection or the UGRID grid mapping, or a `crs` you give), the model's own times, the depth (water surface less the bed; the water surface, said plainly, when the file has no bed levels), the velocity per cell (for HEC-RAS rebuilt from the face normal velocities by least squares, turned to east and north), and the largest depth and speed per cell. Reads are lazy: one time step or one cell when asked. HEC-RAS and NetCDF-4 through h5py, NetCDF-3 through scipy.
- `aquascope mesh FILE [--crs EPSG] [--json]` and the MCP tool `mesh_summary`, every number computed from the file ([docs](docs/mesh.md)).
- In the Explorer: the largest depth in blues by default, velocity arrows thinned to the screen, optional particle traces, the time bar on the model's own clock ("Model time: 37 steps, …", with **Back to dates**), one legend row named after the file, and the map card on a cell with its depth, velocity and time series. A file without a coordinate system asks for its EPSG code; an unsupported or too large file (over 2 GB or 250,000 cells) gets one plain sentence. The file is mounted read-only in a worker with its own Python (WORKERFS), not copied into memory: a 66 MB plan opens with the same memory as a 1.4 MB one.
- Checked first in Pyodide 314.0.7 on real files: the rashdf test plan of HEC's Bald Eagle Creek example (MIT) and the xugrid sample ADH San Diego mesh (MIT). rashdf 0.12.0 works in the browser but brings geopandas and pyarrow, so h5py is used directly; netCDF4 1.7.4 in Pyodide 314.0.7 cannot open NetCDF-4 files, so h5py reads those too.
- `aquascope.io` imports its names on first use, so `aquascope.io.mesh` loads without pandas in the browser. Floods ahead and Floods past let a click on your own model answer first (`clickClaimed` in `explorer/src/core.js`).
- **Scout** (563, part of 566): one pill beside **Ask the map** drops up to ten numbered pins on what stands out in the view, each with its reason, its number and its source, all in the action log with undo ([docs](docs/explorer.mdscout)).
- `aquascope.map_scout`: fixed rules over the published layers. The largest connected areas much above or below normal in the month's world river status; the Floods ahead reaches with the highest class on the largest rivers, one per river group; the month's strongest groups of floods in the news and seen by radar; groups of gauges much above or below normal today around the most extreme one; gauges where no scored model beats the gauge's mean flow (a model at a hundredth or tenfold of the gauge's volume is left out as a units or matching problem). Ranked kind by kind with a share each, never two pins closer than a pin's height on screen, place names from Photon reverse geocoding (ODbL).
- Every number is formatted by the package into slots. A model (Chrome's built-in model, or the reader's own key) may order the findings and word them, but wording with a digit, a percent sign, a number word or a ranking word outside the slots is refused and the rules' wording kept (`apply_wording`, the claim lock).
- Daily, after the Floods ahead issue, `.github/workflows/flood-warnings.yml` runs `python -m aquascope.map_scout daily` and publishes `scout/latest.json` and a dated copy, writing only under `scout/` (a failed scout neither turns the day's issue red nor publishes an empty file). Each finding has its lat and lon, title, reason, headline `value` and `unit`, all its numbers and its source. It adds record checks: a named region's share much above or below normal against the same calendar month since 1990, and flood cells against the same month since 2000. The Explorer uses it for the half-globe view at the newest month and scans the view in the browser otherwise.
- `aquascope layers scout [--bbox W S E N] [--month] [--published]`, the MCP tool `map_scout`, and the WebMCP tool `aquascope_scout`. Map pins can carry a rank and a kind (`addPin`), and a pin's row in the action log opens its card. Scout and Explain this view take turns on the map (each clears the other's numbered marks), and the pills above the map no longer squeeze onto two lines.
- **Explain this view** (562, part of 566): "what am I seeing?" answered with three to five short notes pinned on the map, each at the place it describes and each naming its source ([docs](docs/explorer.mdexplain-this-view)).
- `aquascope.map_explain`: `view_facts(view, status, warnings, floods_past, gauges)` reads a view (its box, date and the layers that are on) into facts by code, each with value, unit, place and source: the share of the mapped land in each river status class and the largest areas away from normal, the reaches forecast to pass their return-period flows, the gauges furthest from normal today, and where most floods were reported or seen by radar. `template_notes` words them with no model. `check_model_notes` holds a model's notes to the facts: the model chooses, orders and words; the numbers go in by code from placeholders, and a note with any other number, in digits or in words, is refused (the claim lock).
- In the Explorer: an **Explain this view** button beside Ask the map, and "what am I seeing?" in the box. Notes are numbered dots in the colour of what they describe, with cards that keep off each other, the legend and the time bar; the on-device model or the reader's own key words them where one is ready, the fixed wording otherwise. Every note is in the action log with its undo.
- `aquascope layers explain W S E N [--date] [--layers] [--facts] [--llm]` and the MCP tool `explain_view`.
- `aquascope.map_layers.status_classes` can read just the cells of a view, decompressing only their tiles.
- **The month in one line** (part of 543): `aquascope.map_layers.river_status_summary(month)` reads a month of the world river status map and says where the rivers are low or high: for a few named regions (rough boxes such as the Amazon, the Sahel, South Asia), the share of the mapped area below and above normal, weighted by latitude, and a headline naming the regions where at least half is one or the other ("River status, September 2026: much of the Sahel and the Amazon below normal, much of southern Africa above"). `aquascope layers status [YYYY-MM] --summary`, the MCP tool `river_status_summary`, and the Explorer's caption over the globe, which makes the same line from the file its worker has already decoded (a test keeps the two equal).
- **Ask the map** (561, part of 566): tell the map what to show in plain words, and every change it makes is listed in an action log on the map with an undo for each and one for all ([docs](docs/explorer.mdask-the-map)).
- `aquascope.map_commands`: the map's action schema (`fly_to`, `set_time`, `set_layer`, `focus_status`, `set_basemap`, `highlight_river`, `draw_area`, `add_pin`), the checks every action passes before it runs, and a keyless phrase grammar for the common requests ("trace the Nile to the sea", "September 2023", "play the last 5 years", "turn on floods past", "where are rivers much above normal in South Asia last July"), with place names looked up in the search's gazetteer (Photon, OpenStreetMap data, ODbL). `aquascope map "<request>" [--resolve] [--llm]` and the MCP tool `map_command`.
- In the Explorer: one line at the top of the map (the pill, or **/**), read by the rules first, then by the model on the device where one is ready, then by the reader's own key from Ask ✨; the line under it says which answered. Never a key of ours.
- The world river status can paint only some classes, and its legend says which (**show all** puts the rest back).
- Pins with notes for the AI roles to come: `addPin({lat, lon, title, text, facts, source})` and `pins()` in `explorer/src/map-actions.js`, each pin in the log and opening a map card. An assistant in the browser acts through the WebMCP tool `aquascope_map_actions`, into the same log.
- **Forecast points and the ensemble plume, the FEWS view** (556, part of 566). Floods ahead reaches and the Archive's forecast gauges in threshold colours, and one click for the ensemble hydrograph in the map card, as Delft-FEWS and the GloFAS and EFAS viewers show them ([docs](docs/explorer.mdforecast-points-and-the-plume-the-fews-view)).
- `aquascope.nownext.plume(river_id | lat, lon, thresholds, run)`: the reach's 51 GEOGLOWS members averaged to UTC days, then per day the median, the middle half, the full range and the mean (`ensemble_daily`), each day's class by the Floods ahead rule (`threshold_class`), the peak, the first day at the 2-year flow, and how many members reach each return-period flow. It reads the run the map shows (`run`), and the newest when that one does not answer. `forecast_points(rows)` classes the forecast gauges of an issued file against each gauge's own return-period flows. Plain Python, so a light worker runs them.
- `aquascope.rivers.forecast_ensemble(river_id, run)`: a thin fetch of the members from the GEOGLOWS API (about 70 kB, CORS open, checked 2026-10-10).
- `aquascope now --river-id ID --plume` and the MCP tool `forecast_plume`.
- The Floods ahead issue's `latest.geojson` now carries each reach's 5- to 100-year flows too, for the card's threshold lines. Until the next daily issue, the page reads them from `latest.parquet`.
- The Explorer: a click on a Floods ahead reach opens the map card, replacing the old popup. The card gives the class and the peak, then the plume within a few seconds: bands, median, dashed return-period lines in their class colours, a class strip under the days, the run's first day and the map's date. The forecast gauges get rings in the same colours past zoom 7 (a thin slate ring below the 2-year flow) and a row in "On the map" while they are in view, and their card shows the plume corrected to the gauge with its own record before the run (left out, with the day it stops, when it ends more than a week before the run), and says so when the correction scored worse than the raw model on the hindcast. The colours are checked under simulated protanopia, deuteranopia and tritanopia (`explorer/tests/fews-core.test.mjs`).
- **World river status on the globe** (544, part of 543). The Explorer opens on the state of the world's rivers: GEOGLOWS v2's monthly HydroSOS map, every HydroBASINS level-4 basin coloured from much below to much above normal, drawn under the gauges at the newest month (September 2026 today), with a small legend on the map that names the month. The time bar replays it month by month back to January 1990, preloading the next frame so a step never flashes; a month with no map (March 2026 is missing from the series) draws nothing and says so. Each month's GeoTIFF (about 500 kB, CC BY 4.0) is read in a worker with geotiff.js 3.0.5 and laid out on a Web Mercator image, so it sits right on the globe and on the flat map. It fades as you zoom in, keeps the basemap's coast and labels on top, and has its own row, opacity and info panel in the rail; `ws=0` in a link turns it off.
- The basins use the same five brown-to-teal colours as the gauges' "Today vs normal", so a dot and the basin around it mean the same thing; GEOGLOWS's own red-to-blue HydroSOS colours are noted in the info panel.
- `aquascope.map_layers.river_status_month(month)`: the month's COG URL, the legend with the file's colours and percentile bounds, the months that exist (the bucket listed live, cached six hours), the method and the licence. `aquascope layers status [YYYY-MM]` and the MCP tool `river_status_month`.
- **Gauges coloured "Today vs normal" by default** (544): where the daily status snapshot covers a gauge it takes its class colour, and every other gauge keeps its agency colour, which the legend says.
- **Floods past on the globe** (547, part of 543). Where floods were reported in the news and seen by radar, on the Explorer's globe from the moment it opens, following the time bar ([docs](docs/explorer.mdfloods-past)).
- `aquascope.context.floods_past`: Groundsource news events (CC BY 4.0) and Microsoft Sentinel-1 flood detections (MIT, October 2014 to September 2024) rolled into one row per half-degree cell and month, the two sources in separate columns. Built from the published mirror on 2026-10-10: 1,405,624 rows over 314 months (January 2000 to February 2026), `grid.parquet` 5.6 MB, the 314 gzipped month files 5.5 MB together (71 KB the largest), `index.json` 29 KB.
- `flood_events_month(month | start, end, bbox)`: the news events and radar detections in a month or a range (up to 60 months), worldwide with the hotspots, or in a box; a small box (a clicked cell) also lists its news events with their dates and its radar months. `aquascope context --floods-past [--month | --from --to] [--bbox]` and the MCP tool `flood_events_month`.
- The `mirror-context` workflow builds it after the flood mirrors and publishes it under `context/floods/monthly/` only; its `floods_monthly_only` input rebuilds just the grid from what is already published.
- The Explorer's **Floods past** layer, on by default: a heat map at the world view, news circles and shaded radar cells closer in, the twelve months up to the map date (or the latest twelve on record), one month at a time while playing or stepping by month, a range when one is set. Months crossfade (at once with reduced motion). A legend on the map says what the two marks mean, the months and the counts, and the licences, with a replay button and a folded one-line form on phones. Clicking a cell outlines it and lists its events. Turned off with the rail row, the legend's ×, or `fp=0` in the link.
- Map layers outside the overlay catalogue can now follow the date and take clicks (`datedExtras` and `clickLayers` in `core.js`).
- **Floods ahead** (546, part of 543): the river reaches the GEOGLOWS forecast expects to reach their 2-year flow in the next 15 days, on the globe.
- `aquascope.archive.warnings`: once a day, the whole GEOGLOWS v2 global forecast Zarr (51 members, 15 days) for every reach of Strahler order 5 and up and every reach an Archive gauge sits on, the ensemble-mean daily peak against the reach's own 2- to 100-year flows (GEOGLOWS's retrospective return periods, Gumbel on annual maxima of daily flow). Chunks are streamed and reduced (about 54 GB a day, nothing on disk); reaches with a 2-year flow under 5 m3/s are not classed. `classify` and `summarise` are pure and tested.
- Publishes only `forecasts/warnings/` (`latest.parquet`, `latest.geojson`, a dated copy and `manifest.json` with the issue date, counts by class, the method, the thresholds, the licences and what it is not: model output, not an official warning). `.github/workflows/flood-warnings.yml` runs daily at 14:23 UTC; a `smoke` input reads that many chunks and never publishes.
- `aquascope warnings [--bbox W S E N] [--min-rp T]` and the MCP tool `flood_warnings(bbox)`.
- The Explorer's **Floods ahead** layer, on by default: reaches glow in their class colour on the globe and light up along the river when closer, the gauges on them pulse (still under reduced motion), the map's date shows each day's class and **Play the 15 days** walks through them, a card on a clicked reach gives the peak, its day and the members that agree, and a legend says the issue date and that it is a model forecast. Before the first issue it says so.
- **Living rivers** (545, part of 543). The Explorer's globe now shows the rivers themselves.
- The GEOGLOWS v2 river network is on by default, drawn by Strahler order so the great rivers read on the globe and the small streams appear as you zoom, above the raster overlays and below the gauges, in a blue that follows the basemap. `rivers=0` in a link turns it off. Its TDX-Hydro credit (CC BY-SA 4.0) is in the map's attribution line.
- **Flow direction (animated)**: a light glint moves along every river the way the water goes, 16 steps a second, paused while the tab is hidden or while the map settles (a basemap change, the time bar's play, a GIF frame) and off when the system asks for reduced motion. A toggle in the rail.
- **A click lights the river up**: the snapped reach is ringed, everything that drains to it turns blue and its way to the sea orange (feature-state on `riverId`), with a key on the map that says what the colours mean and how many reaches and km² drain there, and a progress line while the basin's routing tables load. The rest of the network fades back. The trace to the sea is drawn in the same orange.
- `aquascope.rivers.upstream_ids(river_id, max_n)` and `downstream_ids(river_id, max_n)`: the reaches that drain to a reach (past `max_n`, the ones that drain the most, with the cut said) and the reaches to its outlet, from the routing tables `upstream_area` and `trace_downstream` read. The upstream walk goes a whole level of the network at a time in numpy: once the tables are read, the Mississippi at St. Louis (123,896 reaches) takes about 0.05 s on a laptop. `aquascope river upstream|downstream` and the MCP tools `upstream_ids` and `downstream_ids`.
- **Map first: a click answers on the map** (548, part of 543). A click on a gauge, a river or any place opens a small card anchored to it: the name, today against normal in one sentence (from the Archive's daily status snapshot, or ranked from the record, or for a river from its simulated record since 1940), one sparkline (the record's last 12 months, or the next 15 days from GEOGLOWS with the middle half of the ensemble shaded), one number (the newest value, or the forecast's peak) and **Details**, **Trace to sea**, **Watch** and **Study**. A click that misses the river offers the river the snap found in one click. It fills as the answers arrive, never behind a wall of spinners, and every line says where it comes from. The side panel is folded away until **Details** opens it on the right tab, and a link with `tab=` still opens it there, as before. On a phone the card is a short sheet at the bottom; Escape closes it, focus moves into it, and it is labelled for a screen reader. Other map layers open a card with their own content through `openCard()` in `explorer/src/map-card.js`.
- **Flood depth where floods are forecast** (554, part of 566): the RAS Mapper view of the forecast, keyless ([docs](docs/explorer.mdflood-depth-where-floods-are-forecast)).
- Where Floods ahead expects a reach to pass its 10-, 25-, 50- or 100-year flow, the Explorer draws the JRC CEMS-GloFAS flood depth map (v2.1.2, about 90 m) of the nearest return period at or below it (10, 20, 50 or 100 years; there are no 2- or 5-year maps) around the reach, in a blue depth ramp, labelled "may flood in the next 15 days, model estimate". It steps up and down with the time bar through the forecast days, leaves to a larger river the pixels nearer to it, and a click opens the map card with the reach, the return period and the depth there. Its key (the honest label, the ramp, the count, the licence) is a row of the shared "On the map" legend, under Floods ahead; a rail row and a credit line.
- The depth is read in a worker with geotiff.js from the Source Cooperative mirror (byte ranges, a few hundred kB per half-degree cell) and kept, so stepping repaints from memory.
- `aquascope.flood_depth.flood_depth_overlay(river_id | bbox, return_period, day)`: the map chosen, the tiles with their windows and a GDAL command, the extent around the reach and its clip, and the depth at the reach, the deepest pixel and the wet share. `aquascope layers depth` and the MCP tool `flood_depth_overlay`. Ask the map (561) knows the layer too ("show the flood depth").
- The licence is confirmed from JRC's own files on 2026-10-10: the copyright notice licenses the dataset under CC BY 4.0 (credit given, changes indicated), and the README says "no restrictions, free and open Copernicus product". Both are recorded with the layer.
Changed
- **Python in the browser: Pyodide 314** (part of 566, unblocks 555 and 558). The Explorer's workers move from Pyodide 0.28.2 (Python 3.13) to 314.0.7 (Python 3.14, the newest stable on 2026-10-11), whose package set has geopandas, pyproj, pyarrow, h5py and netCDF4 for the readers to come. Pyodide 314 no longer runs in classic web workers, so the main worker and the light workers start as module workers and load the runtime with `import()`. The version still lives in one place, `explorer/config.js`, which the Pyodide smoke workflow reads. Measured in headless Chrome: about 30 MB of Python on a first visit (29.8 MB, was 31.3 MB), ready in 14 to 16 s on a fresh browser (was 13 to 15 s) and about 12 s on a repeat visit (unchanged). The page's "about 15 MB, once" now says about 30 MB, which is what it was already. Every result the walk-through compared (every gauge tab, GR4J, and the study's flood numbers) came out the same.
- **The globe, calmer** (part of 543): the first view shows the rivers, not the furniture ([docs](docs/explorer.mdon-the-map-one-legend-one-line)).
- **One legend, "On the map"**, instead of a card per layer: a row per layer in map order (gauges, Floods ahead, rivers, Floods past, river status), each with a visibility toggle and a key that opens; a layer with nothing to draw is one muted line, and a lit river's key is a row on top. On a phone it starts as one small chip and, opened, stays inside a quarter of the screen.
- **Quiet gauge clusters**: small, light and see-through with a small count, where they were large dark-blue bubbles; the gauges with a status today show as small dots in their today-vs-normal colour while the rest are still clustered.
- **Floods past that inform**: only the cells that stand out from the region on screen are drawn (about the top eighth of the cells with any count there, above a small floor), as a soft heat up to the regional view and small translucent marks from zoom 6, so Bangladesh is a few hotspots rather than a grid of equal dots. Clicks on a cell start at zoom 6.
- **Rivers**: the great rivers are a little wider on the globe, and the flow is a light glint walking down the line, 16 steps a second, rather than a dark dash. Floods ahead's glows are smaller and softer on the globe.
- **The month's one line** sits under the Ask the map pill on the world view only (zoomed in, it gives the map back), and while the time bar replays a past month the Gauges row says its dots still show today.
- The **/** key opens Ask the map; the search is a click away in the header.
- A GIF of the time bar credits the layers on it (GEOGLOWS for the river status), not NASA GIBS alone.
- The layers keep one order (river status, Floods past, rivers, Floods ahead, gauges), and Floods past shows the latest twelve months on record when the river status opens the map on a month after them.
- On a phone the map's attribution starts folded to its (i), so the time bar never sits on it.
Fixed
- **A sign against a placeholder got past the claim lock** (562, 564): a model's "-{f1}", "–{f1}", "minus {f1}" or "{f1}0" changes the number code fills in. `aquascope.map_explain.placeholder_touches` finds it, `claim_lock` lists it, and Explain, Scout (`check_wording`) and the mesh review now share this one check (a hyphen joining a word or two placeholders, "mid-{month}" or "{f1}-{f2}", is still wording).
- **A stripped HEC-RAS plan file ended in a KeyError** (555): a `*.p01.timeseries.hdf` holds the results but not the mesh. The reader now says which part is missing and what to do: open the full plan, or give the geometry file the plan was run with, which it then reads with it (`read_mesh(..., geometry=)`, `aquascope mesh FILE --geometry G01_HDF`, `aquascope mesh review ... --geometry`, the MCP tools' `geometry`, and the two files dropped together in the Explorer, which says the same in plain words when the plan comes alone). Checked on HEC's Bald Eagle Creek example (`BaldEagleDamBrk.p18.timeseries.hdf` with `BaldEagleDamBrk.g11.hdf`). A plan without summary output says its largest is over the saved steps only. A plan file with results but no 2D areas (only 1D results or boundary lines) is now called a HEC-RAS file with no 2D flow areas, not a file with no UGRID mesh.
- **Floods ahead counted only what the browser draws.** When the daily file keeps only the strongest 10,000 reaches, the legend row and its class chips now give the published totals (for example "20,071 reaches, strongest 10,000 drawn") instead of the cut count.
- The docs build again: pymdown-extensions 12.2 (released 2026-10-10) changed `Highlight.__init__` and broke mkdocstrings 0.29, so every docs build failed. The docs extra now asks for `pymdown-extensions<12.2`.
- Record the verified v0.26.0 Zenodo DOI (`10.5281/zenodo.23246553`) in release citations, Explorer BibTeX and generated study reports; retain the concept DOI for the project as a whole.
- The world river status credit linked to `https://geoglows.org`, which does not resolve (no DNS record). It now links to `https://www.geoglows.org`.