A dark, sharp, OKLCH token system for data-dense dashboards. Link two files, drive the theme from three variables, and every screen ships consistent. No hardcoded values, no drift.
Two stylesheets carry the whole system: fonts, palette, type scale, spacing, and every component on this page. Link them in the head, in this order, then use the tokens.
<link rel="stylesheet" href="https://design.seantippen.com/tokens.css"> <link rel="stylesheet" href="https://design.seantippen.com/components.css">
var(--token) in CSS and tok('--token') in Chart.js. Never paste a hex, rgba, or oklch value. The one exception is Chart.js dataset colors, which the Canvas API cannot resolve from CSS.0 by default; rounded is reserved for pills, toggles, and circular controls. No gradient page or section backgrounds, no gradient text.Stops a reader's dark-mode browser from re-mapping the palette and making the brand look wrong. Add a theme-color meta matching --color-bg for the address bar.
<meta name="color-scheme" content="dark"> <meta name="darkreader-lock">
OKLCH for all custom colors, captioned by the job each one does. Hex only for Chart.js data series (Canvas API). Click any swatch to copy its value. Drive the hue with the generator above and watch every swatch re-derive.
Depth comes from lightness, not shadow. App background through floating overlay.
Four steps, never pure white. Chrome and labels recede to the lower steps so data leads.
Green success, amber warning, red danger, blue info. Amber is a warning state only, never a decorative accent.
Eight hex colors at the same perceived brightness so no series dominates. Hex because the Canvas API cannot read CSS custom properties at paint time.
Recomputed from the active tokens. Drive the generator or toggle the theme and the ratios recalculate.
| Pair | Ratio | Grade |
|---|---|---|
| Body text on canvas | . | |
| Secondary on canvas | . | |
| Muted on canvas | . | |
| Accent on canvas | . |
A committed three-face system: Big Shoulders Display for the one hero header, Inter for everything else, JetBrains Mono for numbers and code. Inter is rationed body in a three-font system, not the only face. Fluid sizing via clamp().
Fluid spacing scales between viewport poles via clamp(). Motion is token-timed, ease-out by default, spring for delight, always behind prefers-reduced-motion.
| Token | Value | Use |
|---|---|---|
| --duration-fast | 150ms | Hover, focus, small state changes |
| --duration-normal | 250ms | Drawers, view transitions |
| --ease-out | decelerate | Default for functional motion |
| --ease-spring | overshoot | Delight only (toast, palette) |
Everything below is rendered from the real components.css classes, the same sheet your dashboard links. Flip any demo to Code and copy the exact markup.
KPIs, charts, and tables. No card wrappers; data lives directly on the surface. Numbers are monospace with tabular figures so columns lock.
Chart.js 4.4.7, colors via tok(), global defaults wired to tokens (square corners, mono ticks).
| Region | Revenue | Growth | Status |
|---|---|---|---|
| Northeast | $842,500 | +12.3% | Growing |
| Southeast | $621,300 | +8.1% | Growing |
| Midwest | $534,700 | +2.4% | Stable |
| West Coast | $412,800 | -3.7% | Declining |
Composite patterns for data-dense surfaces. Every block is a stock component, composed the way a real dashboard composes them. No bespoke CSS.
| Rep | Sold | Revenue |
|---|---|---|
| Avery | 1,284 | $58,210 |
| Mateo | 1,102 | $49,870 |
| Priya | 986 | $44,120 |
| Total | 3,372 | $152,200 |
Delta chips, progress, pills, toolbar, stale timestamps, empty and error states, drawer. All ship in components.css.
Felt, not seen. One orchestrated page-load reveal, native scroll-driven section reveals, View Transitions on theme and accent swaps, and a token-colored cursor spotlight. Everything respects prefers-reduced-motion.
A radial accent glow tracks the pointer. JS writes two CSS variables; the compositor draws the gradient.
Glass is for overlays only (modals, dropdowns, command palette), never flat cards. Shadows convey hierarchy, not decoration.
Quick Triumph builds can reuse this system by swapping the accent hue to the crest colors. The full Triumph dashboard system is separate, at design.greenvilletriumph.club.
What not to do, and what to do instead. These are the lines between an elite, intentional interface and generic AI output.
var(--color-bg), or one position:fixed palette-cohesive field that never moves.oklch(0.70 0.25 350) as a state color.transform: scale() on hover; it is janky and displaces layout.translateY(-2px) lift plus a deeper shadow, or a token-colored spotlight.var(--color-text) or var(--color-accent) with a weight bump.Run this before any dashboard goes live. If every line is true, it ships consistent.
tokens.css before components.cssvar(--token), charts via tok('--token')position:fixed and palette-cohesivetabular-nums on every numeric column and KPItranslateY, never scale()prefers-reduced-motion respectedThe generator tier sits on top: change four variables, re-skin everything. The full set lives in tokens.css.
/* Generator tier, drives the whole system */ --accent-h: 178 --secondary-h: 350 --base-h: 252 --contrast: 1 /* Accent and surface (derived) */ --color-accent --color-accent-hover --color-accent-border --color-secondary --color-bg --color-surface --color-surface-hover --color-surface-raised --color-surface-overlay /* Text hierarchy */ --color-text --color-text-secondary --color-text-muted --color-text-disabled --text-alpha-90 to --text-alpha-15 /* Status */ --color-success --color-warning --color-danger --color-info /* Chart data series (hex, for Chart.js) */ --green --blue --red --amber --purple --cyan --yellow --orange /* Type */ --font-sans --font-mono --font-display --text-xs to --text-4xl /* fluid clamp scale */ /* Spacing / motion / radius */ --space-xs to --space-xl --space-section --duration-fast --ease-out --ease-spring --radius: 0 --radius-full: 9999px
Figures above are computed at runtime from the live sheets, not hardcoded.