One brand, two surfaces, three layers
A consumer loads the foundation plus exactly one surface. Each surface may redefine a name the other also uses — --gray-500, --space-4, --radius-md, --dur-slow, .sx-eyebrow — and that is intended: the two apps are different, and a page only ever sees one of them. The foundation never collides with either.
Foundation dist/css/foundation.css
The brand everything shares: the exact cobalt --blue-500 and its 300–700 ramp, the two neutral ramps (cool for the landing, navy for the app), the status hues and their tints, the teal and violet secondaries, the six 10-step product palettes, signal yellow and landing gold, shared motion, the 4px unit, and the mark's geometry.
Landing dist/css/landing.css
The marketing surface, Retool-style: Inter standing in for Saans as the page sans, Archivo for the logo, IBM Plex Mono for the old design-system eyebrow. A light hero on cool gray-100, dark sections on --lp-bg-dark, 40px pill buttons, bands in four themes, an editorial type scale, sharp radii and whisper-quiet shadows.
Its tokens are not loaded here; the landing page shows them live on both of its grounds.
Layer 3 · tokens/app/App dist/css/app.css
The product surface, the round-12 rules: one typeface (Inter) with hierarchy by weight, a 16px root on a true 4px grid, bordered 12px cards on a quiet page, a dark default and a light theme, and every data-semantic hue — up/down, six categories, impact, the action-score and DTE ramps, the yellow trio, the payoff pair, eight underlyings.
The accent is exact
The app's stylesheet marks --blue-500 "THE accent — exact, never substitute"; the landing's calls it "the cobalt block". Both surfaces' --accent must resolve to it, and npm run check fails if either stops doing so.
--blue-500
—
Foundation. Exact, never a close-enough periwinkle.
--accent
—
An alias of the step above; the landing's --accent aliases the same step.
--blue-400
—
The app's --accent-bright: the wordmark's S's, the crypto category, the focus ring.
--blue-300
—
The landing's kicker and keyword colour on --lp-bg-dark; both surfaces' --accent-soft.
Where the two apps disagree
The headline differences between the landing and the app, as found in their source. Most are intended — the surfaces are meant to differ — and each surface keeps its own value in its own layer rather than one of them changing silently. Where both values are in the stylesheet this page loads, they are read live; the landing-only values are named and shown live on the landing page.
-
01
The grey ramps differ. The landing's
--gray-*is the cool neutral ramp; the app's--gray-*is navy-tinted so a blue accent sits on it without the page reading as two colour families. The foundation keeps both, as--neutral-cool-*and--neutral-navy-*, and each surface aliases its own.Cool (landing) above, navy (app) below; step 500 is — against —. Both ramps, step for step, on foundation › neutrals. -
02
The all-caps label is tracked 0.14em on the landing and 0.06em in the app. Both call it
--tracking-label. The app's round-12 brief dropped it from 0.14em because "the wide-tracked eyebrow was the loudest terminal-ism in the old system"; the landing's design-system eyebrow still carries the old value. App, live: —. Landing: 0.14em, live on landing › type. -
03
The eyebrow is mono on the landing and Inter in the app. Both surfaces emit a
.sx-eyebrow. The landing's is the old design-system kicker — IBM Plex Mono, 11px, 0.14em caps, muted; the app's is Inter, 11px, 600, 0.06em caps, faint ("never mono — it's a word, not a number"). The app's, live: Settlement calendar. -
04
Two radius scales. The landing is sharp: 0 / 2 / 3 / 5 / 8px and a 999px pill (plus a 12px and a 24px the page CSS used as literals, now
--radius-xland--radius-2xl). The app is distinctly rounder — "roundness is most of what separates a consumer market UI from a trading terminal": — / — / — / — / — / — and —. The same names, different values, one per surface. -
05
The slow duration is 360ms on the landing and 340ms in the app. Fast and base are shared to the digit (—, —, both foundation), and so is the ease-out curve.
--dur-slowis 20ms apart with no stated reason, so it lives in each surface's layer; the app's, live: —. -
06
Containers: 1200 / 1400 on the landing, 1280 in the app. The landing's
--containerand--container-wide(plus a 660px prose measure) against the app's--container-max, live: —, with a gutter that steps 16 → 24 → 32px (now — at this width). -
07
The app's market red is not the brand's oxblood.
--upaliases--sage-500, but--downis a separate, muted red chosen so the breaking-news alarm can be louder than price direction — while the app also declares--oxblood-500and never uses it. Both, live:--down—--oxblood-500—--cat-breaking— -
08
Inter arrives two ways. The landing loads Inter 300–700 from Google Fonts (with Archivo and IBM Plex Mono); the app self-hosts one variable file,
app/fonts/Inter-var.woff2, and exposes it as--font-inter. These reference pages load no webfont for the app surface — the stack below--font-interis what you are reading — and the landing page loads the landing's three faces exactly as the site does. -
09
Two silhouettes of one mark. The four lines are identical everywhere (foundation), but the landing strokes them at — with — caps and the app at — with — caps on a padded viewBox. Neither app says which is canonical. All three on foundation › mark.
The reference
Every swatch shows its label, its CSS variable in the code face (click to copy) and its live resolved value. The app page has a theme toggle; the landing page shows every specimen on both of its grounds.
Foundation
The mark at three sizes in all three strokes, the cobalt ramp, teal and violet, both neutral ramps side by side, status hues and tints, signal yellow and gold, six product palettes, motion with a replay, the 4px unit.
reference/landing.htmlLanding
Type roles with their rendered pixels, pills on both grounds and the hero tile on the hero ground, kicker and section head, the four band themes, a footer, the rail at both widths, the payoff chart and diagram inks, radii, shadows, spacing, breakpoints.
reference/app.htmlApp
Dark and light: the tone stack, the text ramp, borders, market and interactive semantics, categories with their contrast ink, impact, four action palettes and three DTE palettes with sample strips, underlyings, spacing, the type scale, radii, shadows, motion, the component gallery and the ten laws.
Load the foundation and one surface
dist/css/landing.css and dist/css/app.css are each complete: tokens, typography roles and the component recipes, with foundation.css inlined. Link one of them and nothing else. The parts are also published on their own — landing.tokens.css, landing.roles.css, app.tokens.css, app.roles.css — and the app's Tailwind @theme mappings as app.tailwind.css.
The resolved, flat tokens as JSON in dist/json/ and as an ES module with types in dist/js/tokens.mjs, for anything that is not CSS — a chart, a native app, a Figma sync.
The JSON under tokens/. dist/ is generated by npm run build and committed; never hand-edit it. npm run check runs the ten rules — the accent, the 4px grid, WCAG contrast in both themes, unique names, fresh dist, no dangling variables — and npm run serve serves these pages from the repo root.