Design System

On brand the first time.

A dark, sharp, OKLCH system for data-dense dashboards. Link two files, use the tokens, and every screen comes out consistent, with no hardcoded values and no guesswork.

Tickets · Season 2026 Live 2m ago
Revenue
$284K8.2%
Tickets
8,14212%
Fill
94%flat
Supporters88%
Premium34%
00

Start here

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">

Three rules

01
Tokens, never literals
Use 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.
02
OKLCH, sharp by default
Custom colors are OKLCH for perceptual uniformity. Corners are 0 everywhere except pills and toggles. No gradient page backgrounds, no gradient text.
03
Teal leads, coral supports
One accent per layout. Teal is the signature; coral is the secondary for contrast moments. Never blurple. Amber is a warning state, never decoration.

Lock dark mode on brand-critical pages

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">
01

Colors

OKLCH for all custom colors. Hex only for Chart.js data series (Canvas API). Click any swatch to copy.

Brand Accents

--color-accent
oklch(0.75 0.17 178)oklch(0.52 0.18 178)
--color-secondary
oklch(0.74 0.18 30)oklch(0.55 0.19 30)
--accent-muted
oklch(... / 0.15)oklch(... / 0.12)
--accent-subtle
oklch(... / 0.08)oklch(... / 0.06)

Backgrounds & Surfaces

Base
--color-bg
Surface
--color-surface
Hover
--color-surface-hover
Raised
--color-surface-raised
Overlay
--color-surface-overlay

Text Hierarchy

--color-text
oklch(0.93 0.01 270)oklch(0.16 0.02 270)
--color-text-secondary
oklch(0.75 0.01 270)oklch(0.35 0.015 270)
--color-text-muted
oklch(0.55 0.015 270)oklch(0.50 0.01 250)
--color-text-disabled
oklch(0.40 0.01 270)oklch(0.68 0.005 250)

Status Colors

--color-success
successsuccess
--color-warning
warningwarning
--color-danger
dangerdanger
--color-info
infoinfo
Completed Pending Overdue In Review Active Archived

Data Series (Chart.js Palette)

#4CC97A#2D8E52
#6BA3FF#3B78D0
#F28878#D04F3D
#D4AD42#A88520
#C688E0#9B55B5
#4BC3CA#2A96A0
#E8D44D#B8A620
#E89B4D#B87620

Palette Roles

Where each token earns its place. Click any swatch above to copy its value.

TokenRole
--color-accentPrimary accent. Active states, focus, the one color a layout leans on.
--color-secondaryCoral counterpoint. A second series or a contrast CTA, used sparingly.
--color-bgPage canvas. Flat, never gradient.
--color-surface to -overlayFive-step elevation ladder. Depth comes from lightness, not shadow.
--color-text to -disabledFour-step text hierarchy. Text is never pure white.
--color-success / warning / danger / infoStatus only. Amber is a warning, never decoration.

Contrast

Computed live from the tokens against the current canvas. Toggle the theme and watch it recalculate. Body text holds AA or better.

PairRatioGrade
Body text on canvas
Secondary text on canvas
Muted text on canvas
Accent on canvas
Disabled text on canvas
02

Typography

Inter for all text, JetBrains Mono for data values and code. Fluid sizing via clamp().

Font Specimens

Inter
The quick brown fox jumps
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
JetBrains Mono
$2,847,392.00

Fluid Scale

3XL --text-3xl
2XL --text-2xl
XL --text-xl
LG --text-lg
Base --text-base
SM --text-sm
XS --text-xs

Weight Scale

Regular 400
Medium 500
Semibold 600
Bold 700
Extra Bold 800
03

Spacing

Fluid spacing tokens scale between viewport breakpoints. Bars shown at actual computed size.

--space-xs
clamp(0.25rem, 0.2rem + 0.2vw, 0.5rem)
--space-sm
clamp(0.5rem, 0.4rem + 0.4vw, 0.875rem)
--space-md
clamp(1rem, 0.875rem + 0.5vw, 1.5rem)
--space-lg
clamp(1.5rem, 1.25rem + 1vw, 2.5rem)
--space-xl
clamp(2rem, 1.5rem + 2vw, 4rem)
04

Components

Interactive elements with ripple clicks, stretch toggles, underline focus, and toast notifications.

Buttons

Outline is the preferred selection state. All buttons get ripple on click and lift on hover.

Inputs

Bottom border only. Accent underline grows from center on focus.

Toggle

Stretch toggle — thumb stretches on press

Badges

Completed Pending Overdue In Review
Accent Success Danger

Toasts

Toasts slide from the right. Text colored by type — especially red for danger.

Skeleton Loading

Shimmer animation using surface tokens. Use for any loading state.

05

Data Display

KPIs, charts, and tables. No card wrappers — data lives directly on the surface.

KPI Markers

Total Revenue
$2.4M
Tickets Sold
18,472
Avg. Order
$128
Sell-Through
94.2%

Left-border accent markers — no card wrappers. Each KPI gets a different accent color via nth-child.

Bar Chart

Chart.js 4.4.7. All colors via tok() — hex data series tokens for Canvas compatibility.

Data Table

RegionRevenueGrowthStatus
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
Mountain$289,100+15.2%Emerging

Bare table — no card wrapper. Hover highlights rows. Monospace numbers via font-variant-numeric.

06

Hover Effects

Lift over scale. Move your mouse over each demo to see the effect.

Lift
translateY(-4px)
3D Tilt
perspective + rotateX/Y
Gradient Border
mask-composite trick
Gradient Background
accent → secondary
07

Animations

Click any card to preview the animation. All use ease-out timing.

fadeIn
slideUp
scaleIn
bounceIn
flipIn
shake
pulse
slideLeft
08

Glass & Depth

Frosted glass, neumorphic inset, and three-level shadow elevation.

Frosted Glass

Frosted Panel
backdrop-filter: blur(16px) saturate(1.4). Semi-transparent surface over any background.

Neumorphic Inset

Inset Panel
Inset box-shadow creates a pressed/recessed appearance. Good for input groups.

Shadow Elevation

Shadow SM
Level 1
Shadow MD
Level 2
Shadow LG
Level 3

Three elevation levels. Use sparingly — shadows convey hierarchy, not decoration.

09

Anti-Patterns

What not to do — and what to do instead.

Don't
Use gradient backgrounds — they shift content appearance based on scroll position
Do
Use flat var(--color-bg) + noise grain overlay
Don't
Use large border-radius — puffy, rounded shapes look unprofessional
Do
Sharp edges with border-radius: 0 everywhere
Don't
Use transform: scale() on hover — janky, displaces layout
Do
Use translateY(-2px) lift + shadow increase
Don't
Use gradient text on headers — looks cheap, breaks on some backgrounds
Do
Plain var(--color-text) or var(--color-accent)
Don't
Use purple/blurple secondary colors — generic SaaS look
Do
Coral oklch(0.74 0.18 30) secondary
Don't
Background grids, dots, or decorative patterns
Do
Clean var(--color-bg) — content is the decoration
10

Triumph Color Overrides

Triumph projects swap the accent palette to green/blue. Everything else uses the master system unchanged.

Master
Teal
oklch(0.75 0.17 178)
Coral
oklch(0.74 0.18 30)
Triumph
Green
oklch(0.72 0.19 155)
Blue
oklch(0.69 0.18 255)
11

Dashboards

Composite patterns for data-dense surfaces. Delta chips, stat bands, dense tables with totals, progress, tabs, segmented toggles, drawers, stale timestamps. All ship in components.css; link the sheet and the class names are ready.

Composed Dashboard

No bespoke CSS. Every block below is a stock component, composed the way a real dashboard composes them.

Tickets · Season 2026
Revenue
$284,6108.2%
vs last week
Tickets
8,14212%
sold this month
STH base
2,3574%
season holders
Fill
94.2%flat
last match
RepSoldRevenue
Avery1,284$58,210
Mateo1,102$49,870
Priya986$44,120
Jordan742$33,540
Total4,114$185,740

Delta Chips

12.3% 3.7% 0.0% +$1,240 -$420

Monospace, tabular numerals, arrow glyph. .plain removes the border for inline use next to a value.

Stat Band

Revenue
$2.4M8.2%
vs last week
Tickets
18,47212%
sold this month
AOV
$1282.1%
rolling 30-day
Fill
94.2%flat
last match

Horizontal strip of KPIs with eyebrow, value, optional delta, and context line. For dashboard headers.

Dense Table & Totals Row

MatchSoldRevenueFill
Stone Stadium · 4/263,142$42,58088%
Clemson · 5/092,988$38,21084%
Stone Stadium · 5/172,210$28,44062%
GE Vernova · 6/031,870$23,11052%
Total10,210$132,34072%

Add .dense for tighter rows. Wrap a totals row in tr.total. td.pos / td.neg for colored numerics.

Progress Bars

Supporters Section88%
Family Zone52%
Premium Suite34%
General Admission12%

Status Pills

Live Synced Delayed Failed Queued Draft

Leading dot communicates status at a glance. .live pulses.

Tabs

Underline on active. Horizontal scroll on overflow.

Segmented Toggle

Time-range or mode switcher. Active fill uses the accent.

Toolbar with Filter Chips

Active × All regions Last 30 days
Updated 2m ago

Filters left, actions right. Stale indicator pairs with the actions group.

Sparkline Slot

Weekly revenue
$12,450
Scan rate
86%

Fixed 80×24 slot, pairs with a stat value for trend-at-a-glance. Use .sparkline.lg for 120×36.

Drawer

Right-side slide-in with scrim. For row drill-downs without leaving the page.

Empty & Error States

No matches yet
Once tickets start selling for this event, activity will appear here.
Could not load data
Vivenu API returned a 502. This usually clears in under a minute.

Stale Timestamps

Updated 2m ago Updated 14m ago Updated 2h ago

Fresh, aging, dead. Colored dot signals freshness without reading the number.

Skeleton Table Rows

Shimmer placeholder sized like the table that replaces it.

12

Ship checklist

Run this before any dashboard goes live. If every line is true, it is on brand.

13

Token reference

The names you will reach for most. The full set lives in tokens.css; copy the link from Start Here.

/* Accent and surface */
--color-accent   --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

/* 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
--text-xs to --text-4xl      /* fluid clamp scale */

/* Spacing */
--space-xs to --space-xl     --space-section

/* Motion */
--duration-fast   --duration-normal   --ease-out   --ease-spring

/* Radius (sharp by default) */
--radius: 0      --radius-full: 9999px