Theme × Skin Lab
Two independent axes. Themes answer which colors — swap the palette and everything recolors. Skins answer how surfaces are drawn — backgrounds, borders, shadows, inner highlights, blur, radius. Pick one of each; every demo below redraws instantly.
20 themes × 10 skins = 200 looks from 30 files · no rebuild · no reload
--surface-bg
--surface-border
--surface-radius
--surface-shadow-md
--surface-inset
--surface-backdrop
--surface-canvas
Card + KPI
Token-driven card
This card consumes --surface-bg-elevated, --surface-border, --surface-radius, and --surface-shadow-sm on hover.
Skins
10
+900%looks, one link
Alerts & buttons
ℹ️
Surface variant
This alert follows the active skin.
Dropdown menu (static)
✅
Toast follows the skin too.
Table + pagination
| Token | Axis |
|---|---|
| --color-* | palette (theme) |
| --surface-* | material (skin) |
Inputs
Migration progress100%
Badges & accordion
default
primary
success
danger
How does this work?
One <link> per axis. Skins are token-only files in @layer exsa.skins — no component CSS, no rebuild.
Timeline surfaces follow the skin.
Every value above is computed from --surface-* tokens — the same contract a custom skin uses.
Write your own: a ~25-line :root block in @layer exsa.skins, link it, done.
Full design →