AICIVSIM · Design system v3

One system, every screen.

The canonical reference for the v3 language — tokens, type, motion, data visualization, components, and voice. Everything on this page is rendered live by the same css/v3.css and js/v3.js that power the site, so the spec can never drift from the product.

Principles

  1. One story per screen. Every screen has a protagonist; everything else supports it or leaves.
  2. The scenario is the product. The four futures are clickable in exactly one place per page, and that control is the legend for every chart.
  3. Layouts resolve. Lists for variable counts, grids only for fixed ones. No orphan cells, no accidental voids.
  4. Hierarchy through scale, not caps. Real type jumps, sentence case; tracked caps live in exactly one tier (the eyebrow).
  5. Motion confirms, never gates. Springs attached to intent — press, switch, arrive. Content is always readable; prefers-reduced-motion collapses everything to instant.
  6. Data carries its own why. Every chart states what its future means in words; every threshold states the consequence of crossing it.

Color

Four jobs, strictly separated: interaction, scenario identity, system identity, and semantic deltas. A hue never moonlights.

Interaction — links, CTAs, active states. The only decorative accent.
Accent#d4622a
Scenario identity — segments, chart series, projected values. Never decoration. Chart moderate is the validated #4a7fd4 (brand surfaces keep #5da5da).
Aggressive#4ecdc4
Moderate#4a7fd4 · charts
As usual#e8a838
Worst#d4622a
System identity — the tick beside a system's name. Marks, never fills.
AI#e8a838
Climate#4ecdc4
Governance#9b87f5
Transition#5da5da
Civilization#e05c7e
Strategy#d4622a
Semantic — deltas only, always paired with ▲▼ glyphs, never color alone. Plus the four-step ink ramp.
Good--good
Bad--bad
Inkprimary text
Ink-2body
Ink-3secondary
Ink-4faint / axis

Type

Space Grotesk for display, Inter for text, JetBrains Mono for every number. Sentence case everywhere; tracked caps in one tier only.

eyebrow · Inter 600 · 11px · .18em capsThe only tracked-caps tier
title-1 · Grotesk 600 · 30–44pxPage headline
title-2 · Grotesk 600 · 28pxSection headline
title-3 · Grotesk 600 · 19pxCard title
lead · Inter 400 · 17pxSection intros argue, they don't label.
body · Inter 400 · 15pxReading text at a readable size.
display · Mono 700 · 56–168px44

Motion

Powered by motion.dev (vanilla build, CDN — the three.js precedent), with a hand-rolled spring integrator for number counting and as full fallback. Everything below is live — try it.

The vocabulary
  1. Press physics — every interactive element squishes to 0.962 under the pointer and springs back with overshoot (stiffness 430, damping 16). Delegated, so re-rendered content keeps it.
  2. Emphasis pop — the element that just gained meaning (chosen segment's dot, newly-active landing dot, a threshold chip that changed state) overshoots ~1.25–1.7× and settles.
  3. Morph — the bold chart line reshapes point-by-point between futures (460ms ease-out); the area fill retints; the end value counts.
  4. Glide — indicators (landing bubble, score-band dot) travel on the shared spring easing, compiled to CSS linear().
  5. Entrance — sections rise 20px on an inView spring (stiffness 130, damping 17), staggered ~55ms by sibling, preloaded 18% below the viewport. One-shot; never re-hides.
  6. Count — numbers arrive via the spring integrator (stiffness 170, damping 26), never fade-swap.
Live demos
Count: 28
DOAttach motion to intent: press, switch, arrive, change of meaning. Respect reduced-motion by collapsing to instant state.
DON'TGate legibility behind animation, animate on scroll position for decoration, or fade-swap a number that could count.

Data visualization — one geometry, six forms

Every chart shares one anatomy: hairline grid, mono axis labels in ink-4, no borders, no per-chart legends — the scenario control is the legend. The form is chosen by the data's job. All live below.

stat — one value + where it's heading
landing — today's tick + all four futures on one rail (hover the dots)
meter — a ratio against a cap, one hue
threshold — a line with a consequence
  1. Emphasis, not category soup. The chosen future is bold with an end value; the other three are ghosts with name labels. Identity is never color-alone.
  2. Scenario hues only on scenario identity. Single-measure charts use one neutral hue; semantic green/red only on deltas, always with ▲▼.
  3. One tooltip. Crosshair + year label + all four values, sorted, active row emphasized — identical on every chart.
  4. End labels own the right rail. Axis ticks yield to them; collision chains stay inside the plot.

Components

The scenario control (live — it drives this page too), and the rule that governs it.

scenario segmented control — compact (deck) form

The one-control rule: the four futures are clickable in exactly one place per page. Pages with their own scenario instrument (Pathways) suppress the deck's segment via deck.noSeg. Cards that reflect the choice are display-only.

navigation menus — the one-menu rule

Hover a group in the top bar to open it; the menus are the site's only disclosure component, so their behavior is specified tightly:

  1. Exactly one menu is open, ever. Opening one always closes the other first. A single state variable in v3.js owns visibility — hover, click, and keyboard focus all route through it.
  2. Never open a menu from CSS :focus-within. A clicked trigger keeps focus, so a focus-based rule holds that menu open while hover opens a second — two menus at once. This was a real bug; the CSS carries a comment so it isn't reintroduced.
  3. Open instantly, switch instantly, close on a 160ms grace. Sweeping the bar leaves no trail; a stray pointer exit doesn't kill the menu you were reaching for. An invisible bridge spans the trigger→menu gap.
  4. Every gesture closes it: hovering a menu-less item, clicking the trigger again, Escape, pointer-down anywhere outside, or tabbing out.
the rest of the kit

Stat tiles · landing tracks · trajectory cards · threshold cards · milestone rail · composition stack · income-bridge calculator · impact rows · ledger — all specified by their live use: see Climate (thresholds, nine metrics), AI (risks, milestones), Governance (boards, stack, audit), Transition (bridge calculator), Pathways (route instrument, slopes).

Voice

DOSentence case. Headlines that argue («Planetary systems don't negotiate»). Every metric answers "so what" in its chosen future's own words. Numbers in mono, always.
DON'TLabel sections with nouns («Metrics»), stack tracked-caps tiers, or present a number without its consequence.

Using the system

  1. Files: css/v3.css (tokens + components) · css/v3-bridge.css (translates the original design's class vocabulary — for long-form docs like the paper) · css/v3-instrument.css (HUD skin for the full-screen 3D instruments) · js/v3.js (chrome, scenario store, motion, chart kit) · js/v3-data.js (machine-extracted page data — regenerate, don't hand-edit) · motion.dev UMD from jsdelivr before v3.js.
  2. Every page belongs to one of three tiers: native (v3.css + v3.js — all content pages), bridged (v3.css + v3-bridge.css, for documents written against the old vocabulary), or instrument (own canvas UI + v3-instrument.css). Nothing loads the retired style.css.
  3. Scenario contract: default is always Business as usual; a user's choice persists sitewide via aicivsim-scenario + URL hash. Theme via aicivsim-theme.
  4. Every consumer degrades gracefully: no Motion CDN → spring fallback; no live-data network → baked baselines; no JS → content still readable (reveals are JS-gated).
  5. Cache rule: bump the ?v= token on every deploy-bound change — same golden rule as the live site.