A matched route: the pattern that matched, the concrete path, and any
extracted path params (e.g. /nodes/:id against /nodes/web-01 yields
{id: web-01}).
Hash-based router (#/path) — needs no server rewrites, so the app hosts as
pure static files. Holds the current match observable and translates
browser hashchange events into route updates. The matching logic lives in
route_match.dart (DOM-free, unit-tested on the VM).