Design System
A living reference for the tokens, typography, motion, and components that this portfolio is built from. Everything below is rendered with the same primitives used across every page.
Foundations
Design tokens live as CSS custom properties on :root. A media query seeds them from prefers-color-scheme; an html.light or html.dark class from the theme toggle takes precedence. Tailwind v4’s @theme inline block exposes each variable as a utility (text-fg, bg-bg, border-border).
Three axes: semantic tokens (not hex values) drive every surface, a restrained 8-step spacing grid drives every layout, and five keyframes drive every movement. If something needs a new value, the first question is whether an existing token already covers the intent.
Color
Five tokens, two palettes. The site toggles between light and dark; every component reads from the same names.
Opacity applied to muted and border provides secondary layers without adding new tokens. Typical values: muted/70 for de-emphasised meta, border/15 for quiet rules, fg/10 for subtle hover surfaces.
Typography
One typeface: Google Sans, loaded via Google Fonts. Weights: 400 (regular) and 500 (medium) only. Headings never use 700 or 900.
Spacing
A 4-pixel grid. Every margin, padding, and gap snaps to these steps. Tailwind’s default scale matches closely; the site only reaches for arbitrary values when the grid genuinely doesn’t fit.
Motion
Five keyframes for the whole site. Long-running decorative animations were removed. What remains is functional: entrance, response confirmation, and live-signal pulses.
All timings ease with cubic-bezier(0.16, 1, 0.3, 1). Reduced-motion preferences turn entrance animations off; live-signal pulses remain because they’re informational, not decorative.
Components
Components here are the primitives that actually ship across the site, rendered with mock data so you can see the exact states.
Link row
Selected work / writing list item
Section heading
H2 inside a case study or article
When the data is actually live
Primary link
Underlined fg with muted decoration that deepens on hover
Secondary link
Muted text that brightens to fg on hover
Pill tab
Tab row for chart timeframes, code-review findings, filter modes
Context tag
Inline category marker on work rows
Icons
Hand-rolled SVG, 14×14 viewBox, currentColor, 1.2–1.5 stroke width. No icon library; each icon is a single path or small group inlined where it’s used.
Accessibility
WCAG 2.1 AA is the floor, AAA is the target. The site is keyboard-navigable, respects prefers-reduced-motion, and avoids colour as the only channel for meaning.
Contrast
Principles
- — Never rely on colour alone. Every chart series ships with a line style and marker shape so it reads without colour.
- — Respect motion preference. All entrance animations are disabled under reduced-motion; informational pulses stay.
- — Keyboard first. Every interactive element is reachable and visibly focused.
- — Contrast above AA. Primary text runs above 17:1 in dark and 19:1 in light.