Tokens, type, spacing, grid.
Semantic palette
Every surface in the kit references semantic tokens, never raw hex. Light + dark variants live in src/styles.css and resolve to OKLCH values. Sparse accent use — Swiss-style restraint.
- --backgroundPage surface · Cloud White #fafbfc
- --foregroundDefault ink
- --mutedSubdued surface
- --muted-foregroundSubdued ink
- --primaryAction accent (Swiss-style restraint)
- --destructiveErrors and removal
- --successConfirmation states
- --warningCaution states
- --borderDefault border (1px hairline)
- --hairlineUsed by `.hairline*` utilities
Space Grotesk + DM Sans
Display sizes use Space Grotesk with tight tracking; body uses DM Sans. Eyebrow labels and numerics are on a separate utility (.eyebrow, .num).
- display-xlSchweizer Klarheit
- display-lgFoundations
- display-mdSection heading
- font-display 24/28Subheading
- body 16/24Body text. DM Sans, 16 px, 1.5 line-height. Used for prose, form fields and most UI surfaces.
- body 14/20Secondary text. Use sparingly.
- eyebrow 11/16 trackedN°02 Eyebrow label
- num (tabular)01234 / 56789
8 px baseline
One scale, 8 px baseline. Use the same step in spacing, padding, and gaps so the grid stays calm. Steps: 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96.
- 4px
- 8px
- 12px
- 16px
- 24px
- 32px
- 48px
- 64px
- 96px
12 columns, 24 px gutters
Max width 7xl (1280 px). Outer padding px-6 (24 px). Vertical rhythm in 16 / 24 / 32 / 64 increments.
Lucide · strokeWidth 1.5
Single icon library: lucide-react. Always strokeWidth=1.5 to stay consistent with the hairline borders.
shadcn primitives — sanity check
Installed via bunx shadcn@latest add button label input and then curated to the kit contract: no shadows, rounded-sm radii, hairline borders via .hairline. The file headers in src/components/ui/*.tsx document the deltas so a future shadcn diff surfaces upstream drift.