User Interface — Explorer, Filters & Library#

Implementation status: Extended (display layer; no engine-parity impact — every component on this page is presentation over the documented engine) Source: src/components/ScenarioExplorer.tsx, src/components/RouteFilterPanel.tsx, src/map/route-filter.ts, src/map/RouteMapPanel.tsx, src/components/ScenarioLibrary.tsx, src/components/ContributionCards.tsx, src/state/custom-flags.ts, src/components/SidebarPillars.tsx Test evidence: tests/route-filter.spec.ts (14), tests/preset-collections.spec.ts (5), tests/custom-flags.spec.ts (4), tests/display-logic.spec.ts (9)

Route & class display filters#

A compact “Routes & Classes” popover (RouteFilterPanel — CASCADE Location/Route/Aircraft filter parity, single-panel form) filters the 24-route synthetic dataset (Air Traffic Dataset): four size-class master toggles (regional / single-aisle / widebody / freighter), All/None shortcuts, and a searchable per-route include list (case-insensitive match over route id and airport codes). All logic lives in the pure module src/map/route-filter.ts; the panel is a thin shell.

The filter computes a coverage fraction — included 2019 flights ÷ total 2019 flights over the synthetic set. Honest-scope rule: this is a display filter only, never route-level modelling. When the filter is active (fraction < 1), the explorer chart multiplies gross BAU by the coverage fraction and shows an explicit warning label:

“Filtered view (scaled): Traffic (BAU) is multiplied by the route-coverage fraction (×f) — display-only scaling over the synthetic route set, not route-level modelling. Reductions, net and SBTi are unchanged global aggregates.”

Route map panel#

RouteMapPanel draws the synthetic network on a free, token-less basemap (MapLibre GL + CARTO dark-matter style): great-circle arcs from geodesic.ts:greatCircleArc over the route-airports.ts coordinates, coloured per size class, with filter-excluded routes dimmed (kept faintly visible for orientation). The panel carries the same honest caption — “Great-circle arcs over the 24-route synthetic dataset — display filter only, not route-level modelling” — plus a coverage readout (routes and share of 2019 flights). It mounts only while the Map tab is active, so the WebGL context exists only when visible, and unknown airport codes skip an arc rather than crash the view.

Scenario library#

ScenarioLibrary is a full-screen overlay page (CASCADE scenario-library parity) opened from the explorer header:

  • a featured card (the most complete preset, FEATURED_PRESET_KEY);

  • collection tabs — All plus the groups from data/preset-collections.ts (drift-proof: collection tests guard preset/collection consistency);

  • preset cards showing ambition-level chips (per-pillar n/5), source basis and end year, loaded through the same callback the preset dropdown uses (no duplicated apply logic); the currently loaded preset is flagged;

  • “Create new scenario” resets to the canonical defaults.

All library scenarios run to 2050 (the default engine horizon; Traffic Growth).

Contribution cards#

The right rail (ContributionCards, CASCADE right-rail parity) shows a primary “CO₂ Emissions in 2050” card (kpis.net2050, with BAU and SBTi comparison values) followed by one card per reduction lever — aircraft, operations, energy, offsets & removals — showing the 2050 abatement (Mt CO₂-eq) and its percentage of the total reduction. Card accent colours are lifted verbatim from the emissions-wedge segment colours so the rail and the chart always agree.

Custom-settings badges#

Each sidebar pillar carries a “Custom settings applied” chip when the live scenario deviates from the canonical defaults (custom-flags.ts; CASCADE parity). The detection is derived, never hand-maintained: lever → field membership is resolved by regex over the generated scenario-schema keys; for the core numeric fields tracked by url-state.ts:DEFAULTS a lever is flagged when a value differs from default, and for any other schema field its presence counts as a customisation (URL decode and UI patches are both sparse, so such fields only exist when explicitly set). The chip tooltip lists the differing fields.

Known deviations / limitations#

  • The route filter and map are display-only; they do not re-run the engine per route and the scaled-BAU view is labelled as such.

  • Custom-settings badges diff against engine defaults, not against the loaded preset; preset-written parameters therefore register as customisations.

  • The scenario library is an overlay view without routing; scenario state underneath is untouched.