Component inventory · April 2026

WRMP Exhibit Design System

The canonical inventory of tokens, components, and patterns behind WRMP's interactive "natural history museum" exhibits on wrmp.org.

Every exhibit is a single-page HTML experience rendered inside a fixed 16:9 frame: a story panel overlays a background layer (map, video, or photo), and a stepper drives the narrative. The specimens below are the pieces that make that up, each labeled with its class names and source files.

Browse the live exhibits in the gallery to see these patterns in context.

Foundations

Radix-backed color tokens, type ramp, spacing scale, and logo marks.

Exhibit Chrome

The story panel, nav bar, and step-level layouts that frame every exhibit.

Content Components

Stat pills, callouts, metric cards, and chart cards that live inside the story panel.

Map Components

Labels, legend chips, and marker popups that sit directly on the Leaflet layer.

Data Viz

Custom charts: species gallery, stacked bar, and the catch composition treemap.

Colors

Active palette maps WRMP semantic tokens to Radix color scales (Cyan, Amber, Orange, Grass, Lime, Sky, Brown) via CDN @radix-ui/colors@3.0.0. Alpha scales (--{color}-a1, --{color}-a2, …) are also imported for subtle tints. Dark scale files redefine the same variable names (--gray-1--gray-12, --cyan-a1 …) under .dark or .dark-theme — they do not add separate --gray-dark-1 names. Wrap dark UI in one of those classes so var(--gray-12) resolves to the dark palette. WRMP original hex values are preserved as --wrmp-*-brand reference tokens below.

Active Semantic Palette — Radix Colors
Teal
--wrmp-teal
Cyan 9
ADA Teal ✓
--wrmp-ada-teal
Cyan 12
Orange
--wrmp-orange
Amber 9
Dark Orange
--wrmp-dark-orange
Orange 9
Green
--wrmp-green
Grass 9
Light Green
--wrmp-light-green
Lime 9
Sky Blue
--wrmp-sky-blue
Sky 9
Earth
--wrmp-earth
Brown 9
Dark
--wrmp-dark
Gray 11
Text
--wrmp-text
Gray 12
Radix Gray — Neutral Scale
Gray 1
--gray-1
App bg
Gray 2
--gray-2
Subtle bg
Gray 3
--gray-3
UI bg
Gray 4
--gray-4
Hover bg
Gray 5
--gray-5
Active bg
Gray 6
--gray-6
Subtle border
Gray 7
--gray-7
Border
Gray 8
--gray-8
Strong border
Gray 9
--gray-9
Solid bg
Gray 10
--gray-10
Solid hover
Gray 11
--gray-11
Lo-contrast text
Gray 12
--gray-12
Hi-contrast text

Below, the same --gray-* slots are shown inside .dark-theme (from gray-dark.css) so you can see the dark scale values.

Gray 1
--gray-1
App bg (dark)
Gray 2
--gray-2
Gray 3
--gray-3
Gray 4
--gray-4
Gray 5
--gray-5
Gray 6
--gray-6
Gray 7
--gray-7
Gray 8
--gray-8
Gray 9
--gray-9
Gray 10
--gray-10
Gray 11
--gray-11
Gray 12
--gray-12
Radix accent scales — dark theme (.dark-theme)

The same step names as light (--cyan-1--cyan-12, etc.); only values change under .dark / .dark-theme. Hover a chip for the token name.

Cyan
Amber
Orange
Grass
Lime
Sky
Brown
WRMP Brand Reference (--wrmp-*-brand)
Teal
--wrmp-teal-brand
#228b9c
ADA Teal ✓
--wrmp-ada-teal-brand
#005e6a
Orange
--wrmp-orange-brand
#e09337
Dark Orange
--wrmp-dark-orange-brand
#d66b2c
Green
--wrmp-green-brand
#379352
Light Green
--wrmp-light-green-brand
#92bb4d
Sky Blue
--wrmp-sky-blue-brand
#00acec
Earth
--wrmp-earth-brand
#664d26
Dark
--wrmp-dark-brand
#4e4e50
Text
--wrmp-text-brand
#272525

Typography

Self-hosted Source Sans Pro. Apply text style classes to any semantic element — .heading-display, .heading-lg, .heading-md, .heading-sm. Add .subtle for de-emphasized color. ADA minimum: 16px body copy. Map overlays (DivIcon labels and marker popups) use the same step scale; they are grouped under Map & marker typography below.

Heading styles
.heading-display
--step-3 · 24–31px
weight 400 · line 1.1
The Bay-Delta Estuary The Bay-Delta Estuary
default · subtle
.heading-lg
--step-2 · 20–25px
weight 400 · line 1.15
Where We're Watching Where We're Watching
default · subtle
.heading-md
--step-1 · 17–20px
weight 600 · line 1.2
Restoration Sites Restoration Sites
default · subtle
.heading-sm
--step-0 · 14–16px
weight 600 · line 1.3
Benchmark vs. Project Benchmark vs. Project
default · subtle
.body-text
--step-0 · 14–16px
weight 400 · line 1.7
Sampling occurs quarterly using standardized gear across Benchmark, Reference, and Project site types. Sampling occurs quarterly using standardized gear across Benchmark, Reference, and Project site types.
default · subtle
Other text roles
Stat Number
--step-1 · 17–20px
font-body · 700
.stat-pill .num
119
Stations
Callout
--step-1 · 17–20px
font-body · 500
.step .callout
Delta Smelt is listed as Threatened under the California Endangered Species Act.
Nav Button
--step-0 · 14–16px
font-body · 600
.nav-bar button
Legend Chip
--step-0 · 14–16px
font-body · 500
.map-legend-chip
South Bay
Body
--step-0 · 14–16px
font-body · 400
.step .body p

Sampling occurs quarterly using standardized gear across Benchmark, Reference, and Project site types.

Kicker
--step--1 · 12–13px
font-body · 700 · caps · ls 4px
.step-header-text .kicker
Station Network
Stat Label
--step--1 · 12–13px
font-body · 500 · caps
.stat-pill .lbl
Project Sites
Caption / Sublabel
--step--1 · 12–13px
font-body · 400
.photo-credit · .stat-pill .sub
Photo: CDFW / Used with permission
Card Subtitle
--step--1 · 12–13px
font-body · 400 · italic
.metrics-card__subtitle

Multi-mesh panel, overnight set, 100m length

Card Title
--step-0 · 14–16px
font-body · 600 · caps · ls 0.04em
.metrics-card__title

Gill Net

Card Stat Number
--step-3 · 24–31px
font-body · 600
.metrics-card__stat-number
13 Stations

Spacing

4/8/16/24/40 scale. All layout and padding uses these tokens.

xs · 4px
--space-xs
sm · 8px
--space-sm
md · 16px
--space-md
lg · 24px
--space-lg
xl · 40px
--space-xl

Logos

ADA variants for all digital use. Dark-mode version on teal/dark backgrounds (nav bar, cover slides, dark panels).

WRMP Logo ADA
Standard ADA · Light bg
WRMP Logo Dark Mode
Dark Mode · Dark bg
WRMP Logo Transparent
Transparent · Any bg
WRMP Icon
Icon mark only

Story Panel

Glassmorphism left panel — 42% width, 16px inset from the exhibit frame edges. Two variants: light (default) and dark. Step copy uses the shared .step-header pattern (icon mark, kicker, title) before the body. Rendered here inside a mock exhibit frame so positioning matches production.

Light panel (default)
Station Network

Where We're Watching

The WRMP network spans 119 stations across three Bay-Delta regions.

Dark panel (.panel-dark)
Station Network

Where We're Watching

The WRMP network spans 119 stations across three Bay-Delta regions.

Exhibit Cover

Full-bleed "title screen" that opens every exhibit. Sits at the top of .exhibit-frame with z-index: 1000 so it always overlays the map, story panel, and any floating chart cards until the visitor taps Step Inside. Hero image is wired via a sibling .exhibit-cover-image div with an inline background-image. The row of step dots previews how many stops lie ahead — the first is pulsing. Source: shared/css/exhibit-cover.css, controller #btn-enter.

Cover — station map hero
WRMP Exhibit · Overview

The Bay: Where We're Watching

Explore how WRMP monitors the San Francisco Estuary across regions, networks, and restoration sites.

5 stops · ~3 min
Cover — How We Monitor hero
WRMP Exhibit · Field Methods

How We Monitor

A field guide to the gear and sampling design behind 14 years of Bay fish data.

4 stops · ~2 min

End Card

The closing bookend to every exhibit. Shares the cover's hero image for visual continuity, but the content block is a glassmorphism panel (backdrop-filter: blur(18px)) so a longer body of links stays legible over a busy photograph. Differences from the cover: step dots are all filled (completion state), a links row presents the Tier-3 data-ecosystem destinations (featured chips use brand teal), and two actions appear — a primary white pill and a ghost-outlined secondary. Modifier class .exhibit-cover--end, controller #btn-restart.

End card — Delta Smelt
Thanks for exploring

The data runs deeper

This exhibit is one layer. WRMP's monitoring lives inside a larger data ecosystem — from the Bay-wide EcoAtlas toolset to the raw datasets scientists work with every day.

Explore the data ecosystem
View all exhibits

Step Dots

Journey-state primitives used by both the Exhibit Cover and the End Card. Three states total. Base (.exhibit-cover-dot) is a semi-transparent white circle — neutral "stop ahead." Pulsing (.is-pulsing) draws the eye to the starting dot on the cover with a soft ring animation. Done (.is-done) is solid white with a faint ring — used on the end card to signal completion. Only reads against a dark backdrop; all three are shown on a matching dark swatch below. The pulsing dot animates live — the @keyframes cover-dot-pulse respects prefers-reduced-motion.

Base
.exhibit-cover-dot — 8×8px, rgba(255,255,255,0.45).
Pulsing (cover, "start here")
.is-pulsing — solid white with a 2.4s ring pulse (@keyframes cover-dot-pulse).
Done (end card, "complete")
.is-done — solid white with a 2px translucent ring for "filled-in" feel.

Step Content

Each step opens with a step header row: the transparent WRMP icon mark (wrmp-logo-2in-mark-crop.png) on the left, then .step-header-text containing the kicker (thematic label, required on every step) and the h2 title. Below that: h3h4 → body → stat pills → callout → caption as needed.

Biodiversity

Native vs. Invasive

The 2014–2015 Drought Shift

Of the 237 species recorded, 113 are native fish and 38 are native invertebrates. A dramatic regime shift occurred during the 2014–2015 drought as salinity and temperature extremes favored non-native species.

South Bay Response

Invasive species now dominate biomass in South Bay and Suisun regions during dry years. Shimofuri goby and yellowfin goby increased by 340% between 2013 and 2016.

237
Species
113
Native Fish
14
Invasive
Delta Smelt detections dropped to near zero in South Bay by 2016 — a sentinel signal for ecosystem-wide stress.
Data: SBOTS 2010–2024 · UC Davis / CDFW

Content Area Overlay

Class: .content-area (toggle .content-area.active). Absolutely positioned region to the right of the story panel inside .exhibit-frame; hosts species gallery, bar charts, etc. Source: exhibits/2026-04-10-native-vs-invasive/index.html (steps 2, 3, 5). Below, the same layout is simulated inside .ds-map-mini (design system only).

In production, place .content-area siblings next to #map under .exhibit-frame (same stacking context as the real exhibit).

.content-area {
  position: absolute;
  top: var(--panel-inset);
  left: calc(var(--panel-width) + var(--panel-inset) + var(--panel-inset));
  right: var(--panel-inset);
  bottom: var(--panel-inset);
  z-index: 5;
  display: none;
  flex-direction: column;
  justify-content: center;
  padding: var(--space-lg);
  overflow: hidden;
}
.content-area.active { display: flex; }

Toggle with JS by adding or removing .active on the content root.

Infographic Background

Class: .infographic-bg (toggle .infographic-bg.active). Full-bleed photo (or image) layer for non-map steps in exhibits/2026-04-10-how-we-look/index.html. ::after adds a left-to-right scrim for panel legibility; optional .photo-credit in the corner. Typically wraps .gear-cards bottom-right.

Set background-image: url('…') on .infographic-bg for production photos (see exhibit index.html).

.infographic-bg {
  position: absolute;
  inset: 0;
  z-index: 2;
  background-size: cover;
  background-position: center;
  display: none;
  align-items: flex-end;
  justify-content: flex-end;
  padding: 24px;
  padding-left: calc(var(--panel-width) + var(--panel-inset) + 24px);
}
.infographic-bg::after { /* scrim */ }
.infographic-bg.active { display: flex; }

In how-we-look, each gear step uses an infographic-step* layer with a JPEG background-image. Toggle with JS via .active.

Stat Pills

No fill — label on top (uppercase, muted), bold number below, optional sublabel. Pills in a row are separated by a vertical divider on :not(:last-child). Optional .sub adds a contextual line below the number.

Light panel context
119
Stations
9
Networks
3
Regions
Dark panel context
237
Species
40
Project Sites
5 more before summer
91
Inverts

Callouts

4px light-green left bar, no fill, medium weight body text. Warning variant uses orange bar. Also shown in dark panel context.

Default (teal)
Delta Smelt is listed as Threatened under the California Endangered Species Act and is considered a sentinel species for ecosystem health.
Warning (orange)
Data collection was suspended at 12 stations during the 2021 drought. Interpret trend lines with caution for this period.
Dark panel context
WRMP partners with CDFW, USGS, and 12 local agencies to maintain this monitoring network.

Metrics Card

Flexible info card from shared/css/metrics-card.css. Slots: colored marker strip, kicker, title, subtitle, stat number, percentage container (trend icon + badge), info list (plain, labeled key-value, color indicator, tag). Omit any slot from the HTML to collapse it — no modifier classes needed. Set --card-marker-color inline to match semantic context; set --percentage-bg / --percentage-color for negative trend states. For media overlays (photo/video), add .metrics-card--dark.dark-theme to switch to the dark glass variant with dark-resolved token text.

Kicker

Gill Net

Multi-mesh panel, overnight set, 100m length

13 Stations
+3.2%

Multi-mesh panel, overnight set, 100m length

Slough

Label

Multi-mesh panel, overnight set, 100m length

Label

tag

Otter Trawl

OT14

82 Stations

Bottom-contact net, 1.5 kts, 5 min tow

Beach Seine

20' Seine

24 Stations

Shoreline enclosure, 37m × 1.2m

Trap

Fyke Trap

100 ft of leads

3' × 6' frame

Two 50' lead nets

First card shows all slots. Remaining cards show the gear variant (kicker + title + stat + plain info items only — unused slots omitted from HTML). Set --card-marker-color inline per card.

Dark Overlay Variant (.metrics-card--dark)

Overlay

Gill Net

Dark treatment over media

13 Stations

Slough

Mode

Dark

Site Chart Card

Classes: .site-chart-card, .site-chart-card.visible, .site-chart-title. Glassmorphism card anchored mid-right on the map; hosts a <canvas> in exhibits/2026-04-10-restoration-network/index.html. Opacity transitions on .visible. Scoped specimen uses real class names inside .ds-map-mini.

Matches restoration-network (right: 24px, blur card over the map). Exhibit-local CSS until promoted to shared CSS.

Map Labels

Non-interactive Leaflet DivIcon labels. .poi-label for key landmarks, .station-label for individual monitoring sites. Type specs (step scale, weights) live with the rest of the ramp in Typography → Map & marker typography.

South Bay
North Bay
ALVS-01
SB-REF-04

Marker Popup

Vanilla JS component — WRMP.makeMarkerPopup(opts) returns an HTMLElement, consistent with the rest of the WRMP.* API. All visual values use tokens.css custom properties. Load marker-popup.css and marker-popup.js alongside the other shared assets. Text role summary (.mp-title, .mp-tag, etc.): Typography → Map & marker typography.

A — image · row · hierarchy
No image

OBP 1 — Outer Bair Restoration

Tidal Pond Slough


Project Site Type
Location
South Bay Bair Island Marsh
B — no image · multi-group · 3-level hierarchy

RST 4 — North Delta Levee Breach

Riparian Corridor


ActiveStatus
142 acAcres

Habitat Types
Wetland Riparian

Location
Sacramento Delta North Sector Zone 3
C — icon tags · grouped attrs

Coyote Creek Fish Passage

Stream Restoration


Classification
IRWMProgram
Keywords
🐟 Fish Passage Monitoring

Watershed
South Bay Coyote Creek
Atoms
MarkerImage
src? · alt? · height?=180
No image
MarkerTitle
name · code?

OBP 1 — Outer Bair Restoration

MarkerCategory
label

Tidal Pond Slough

AttributeLabel
children
Location
AttributeValue
children
Benchmark
AttributeTag
value · icon?
South Bay 🐟 Fish Passage
AttributeChevron
no props
AttributeDivider
no props

JS: shared/js/marker-popup.jsWRMP.makeMarkerPopup(opts) returns an HTMLElement  ·  CSS: shared/css/marker-popup.css · load alongside tokens.css

Map Legend Chips

Floating glassmorphism chips, top-right of the map. Clickable to filter map layers. Three states: default, active (bolder + elevated shadow), dimmed (45% opacity).

South Bay
North Bay
Suisun

States — active: brighter bg + bold weight + stronger shadow  ·  default: standard  ·  dimmed: 45% opacity

Map & Marker Typography

Non-story text that sits on the Leaflet map: fixed DivIcon chips from shared/css/exhibit-frame.css and rich popups from shared/css/marker-popup.css. All use var(--font-body) / var(--font-heading) and the step scale (--step-*). Full layout specimens: Map labels · Marker popup.

Map labels
--step--1 · 12–13px
font-body · 600 · gray-12
.poi-label · .station-label
South Bay
ALVS-01
Popup title
--step-0 · font-heading · 600 · line 1.5
.mp-title · .mp-title-code (700)

OBP 1 — Outer Bair Restoration

Popup category
--step-0 · font-body · 400 · line 1.5
.mp-category · --color-text-subtle

Tidal Pond Slough

Popup image placeholder
--step--1 · font-body
.mp-image-label
No image
Popup attribute row
--step-0 / --step--1 · font-body
.mp-row-label · .mp-row-value
Project Site Type
Popup group label
--step--1 · font-body · 600 · caps · ls 0.08em
.mp-group-label
Location
Popup tags
--step--1 · font-body · 500
.mp-tag · .mp-chevron uses --step-0
South Bay Bair Island Marsh

Stacked Bar Chart

Classes: .bar-group, .bar-label, .bar-sublabel, .bar-track, .bar-segment.native / .bar-segment.invasive, .bar-legend-row, .bar-legend-item, .bar-legend-swatch. Proportional stacked bars for native vs. invasive composition from exhibits/2026-04-10-native-vs-invasive/; segment widths are set inline as percentages. Exhibit-local styles.

South Bay
Tidal marshes · 82 stations
38%
62%
Suisun Bay
Brackish marshes · 24 stations
71%
29%
Native
Invasive

⚠ Styles defined inline above until promoted to exhibit-frame.css — once moved, remove the <style> block from this page.

Species Treemap

Classes: .species-treemap, .species-treemap.active, .species-treemap-card, .species-treemap-title, .species-treemap-canvas. Full-bleed white overlay in exhibits/2026-04-10-how-we-look/index.html; canvas uses a squarify layout (DPR-aware) with habitat colors. Panel offset is applied as left padding on .species-treemap-card.

The specimen canvas is decorative; the exhibit draws cells from catch data. Structure:

<div class="species-treemap" id="species-treemap">
  <div class="species-treemap-card">
    <canvas class="species-treemap-canvas" id="treemap-canvas"></canvas>
  </div>
</div>

Squarify and redraw logic lives in the exhibit script; colors follow :root habitat tokens in that file.