Design System
The design system behind this portfolio. Color tokens and typography are defined as CSS custom properties and composition classes in globals.css. Layout, spacing, and responsive behavior use Tailwind v3 utility classes. Toggle the theme to see both modes.
Color Tokens
Defined as CSS custom properties in globals.css with light and dark values. Mapped to Tailwind via tailwind.config.js so utilities like text-fg and bg-surface resolve to the active theme.
Background
Background Subtle
Surface
Foreground
Secondary
Accent
On Accent
Border
Noise overlay
A fractal noise SVG texture covers all surfaces at 2.5% opacity via .noise::after, adding analog grain to flat backgrounds. Color picker values will differ from token hex values by 1-2 units due to compositing.
Accessibility
Every text and background combination used on this site meets WCAG 2.1 AA. Accessibility is structural, not an afterthought.
Light theme
Dark theme
Implementation
Skip link
"Skip to main content" hidden until keyboard focus. Lets screen reader and keyboard users bypass the nav.
Focus-visible
Accent-colored ring on keyboard focus only. No ring on mouse click. Consistent across all interactive elements.
Reduced motion
All animations and transitions disabled via prefers-reduced-motion: reduce. No partial reductions.
VoiceOver-safe animations
data-animate-y uses translateY only (no opacity) so headings are always discoverable by screen readers.
ARIA labels
Dynamic labels on theme toggle, hamburger menu, and email copy button. States update on interaction.
Semantic landmarks
nav, main, footer with aria-label on navigation regions. Sitemap uses labeled nav.
Focus trap
Mobile nav overlay traps keyboard focus within links and the hamburger button. Escape closes the overlay.
Color never alone
Status and emphasis always pair color with text or shape. No information conveyed through color alone (WCAG 1.4.1).
Typography
Composition classes defined in @layer components in globals.css. Display sizes use fluid clamp() for smooth scaling across viewports. Body sizes step at the md breakpoint (16px to 20px).
Display 2XL
The quick brown fox
Display XL
The quick brown fox
Display LG
The quick brown fox
Display MD
The quick brown fox
Display SM
The quick brown fox
Body
The quick brown fox
Label
UPPERCASE LABEL TEXT
Link
Inline link style
Badge
The quick brown fox
Meta
Font families
Aa
Cabinet Grotesk
Display headings
Aa
Areal
Body, UI, labels
Aa
Ogg
Editorial accent
Code
The code element inherits its parent's font size and uses --fg-secondary text on a --surface background with a subtle border.
Example: use globals.css for token definitions and tailwind.config.js for utility mapping.
Layout
Responsive layout using Tailwind utilities. No custom grid system.
Container
All page content wraps in a Container component: max-w-7xl (1280px), centered with mx-auto, and px-6 (24px) side padding. On viewports narrower than 1280px, the max-width has no effect and the padding creates the gutter.
Default (lg)
Medium (md)
Small (sm)
Breakpoints
sm (640px)
md (768px)
Three-layer structure
Every page uses three background layers. Shadows mark the transitions between them. Cards sit on the middle layer.
Spacing
4px base grid using the standard Tailwind numeric scale. All spacing uses utility classes (gap-4, p-6, mb-8).
4px t-1 8px t-2 12px t-3 16px t-4 24px t-6 32px t-8 48px t-12 64px t-16 96px t-24 Components
Astro components in src/components/ui/. Styled with Tailwind utilities and design tokens. No client-side JavaScript shipped for any component.
Button
Badge
Card
Card
Surface background with border for elevation. Shadows are reserved for section boundaries.
Media card
Tinted container for images and video.
Animations
CSS only. No JS animation libraries. Respects prefers-reduced-motion.
Scroll reveal
data-animate (fade + translateY) and data-animate-y (translateY only, VoiceOver safe for headings).
Theme transition
All color properties transition over 300ms. Toggle the theme to see it.