Design system · v1
The system behind this site.
Everything below renders from the same tokens and components as the rest of the site. Colour values and contrast ratios are read from the live CSS, so this page can't drift out of date.
Ink, paper & electric cobalt
Seven semantic tokens, stored as RGB channels so Tailwind can apply opacity (bg-fg/10). Components only reference roles, never raw colours.
Dark mode swaps cobalt for a lighter periwinkle to keep contrast, and accent-inverse covers the inverted panels where the accent sits on ink. Click any swatch to copy its hex.
light
.lightContrast · WCAG 2.2
- fg / bgBody copy—
- muted / bgDescriptions, labels—
- accent / bgItalic accent headings—
- accent-fg / accentPrimary button, hover rows—
- bg / fgMarquee, CTA panel—
- accent-inverse / fgAccent inside CTA panel—
dark
.darkContrast · WCAG 2.2
- fg / bgBody copy—
- muted / bgDescriptions, labels—
- accent / bgItalic accent headings—
- accent-fg / accentPrimary button, hover rows—
- bg / fgMarquee, CTA panel—
- accent-inverse / fgAccent inside CTA panel—
Bricolage Grotesque
Display & body
font-display / font-sans
Instrument Serif
Italic accents
font-serif
JetBrains Mono
Labels, data, code
font-mono
text-mega
clamp(52px → 160px) · 0.88 · -0.045em
Mega
text-huge
clamp(40px → 88px) · 0.95 · -0.035em
Huge headline
text-5xl
48px · statements
Statement copy
text-3xl
30px · role titles
Senior Developer
text-xl
20px · lead
Lead paragraph for introductions.
text-base
16px · body
Body copy for descriptions and supporting detail.
.eyebrow
12px mono · 0.18em · uppercase
01 — Section label
Pairing in use
Grotesque for weight, serif for voice.
Headlines lead in a heavy grotesque; one or two words switch to an italic serif in the accent colour to add emphasis and personality.
Radius
rounded-md
6px
Skill chips
rounded-xl
12px
Inputs
rounded-2xl
16px
Skill cards
rounded-[1.5rem]
24px
Form panel
rounded-[2rem]
32px
CTA panel
rounded-full
9999px
Buttons, tags, nav
Layout & rhythm
- px-5 → px-1220 → 48pxPage gutter (mobile → desktop)
- py-24 → py-3296 → 128pxSection rhythm
- max-w-7xl1280pxContent width
- gap-416pxCard grids
Button
<Button variant=… />Hover the primary button for the lift and accent glow. Press Tab to see real focus rings.
Text input
<TextInput />Textarea
<Textarea />Tags & chips
Section eyebrow
<Section index label />Every section opens with a numbered mono label and a hairline rule, giving the page an editorial index.
Quick, confident, never in the way.
Motion is reserved for feedback and a little personality. Everything ambient (the marquee and the pulsing status dot) stops under prefers-reduced-motion.
- Hover fillscale-y 0 → 1 · 500ms · cubic-bezier(0.22, 1, 0.36, 1)Project rows
- LifttranslateY(-2px) + accent glow · 200msPrimary button
- MarqueetranslateX(0 → -50%) · 40s linear ∞ · pauses on hoverTech stack strip; static wrapped list under reduced motion
- Arrow turnrotate(45deg) · 300msProject link icons
- Theme swapcolors · 300msBody, all tokens
Try it · hover on desktop, press on touch
00Hover fillMarquee · hover to pause
- Tokens
- Type
- Shape
- Components
- Motion
- Contrast
- Dark mode
- Accessibility