Design System for this website

The tokens, grid, and components that define the visual language of briananders.com — dark-first, mobile-first, 12-column, and driven by CSS custom properties.

Foundations · Tokens

Foundations

Every visual value lives as a CSS custom property on :root in src/styles/system/_tokens.scss. Components read from those tokens rather than hard-coding colours, radii, or motion values — that way a change here ripples through every page automatically.

Color

Dark-first neutrals for surfaces, an orange ramp inherited from the site's existing gradient DNA, and semantic accents. Click any swatch to copy its CSS variable name to the clipboard.

Neutrals & surfaces

Brand — Primary (orange)

Accents & semantic

Typography

Roboto for UI & headings, Source Serif Pro for long-form reading, JetBrains Mono for code. The scale is modular (1.200) and steps up at 960px.

display

Bat Lessons.

h1 · 4xlThe quick brown fox
h2 · 3xlThe quick brown fox
h3 · 2xlThe quick brown fox
h4 · xlThe quick brown fox
body-lgThe quick brown fox jumps over the lazy dog.
bodyThe quick brown fox jumps over the lazy dog.
body-smThe quick brown fox jumps over the lazy dog.
captionThe quick brown fox jumps over the lazy dog.
overlineSection label

Spacing scale

Every space derives from --unit (4px). Never write raw pixel values for padding, margin, or gap.

--space-1 · 4
--space-2 · 8
--space-3 · 12
--space-4 · 16
--space-6 · 24
--space-8 · 32
--space-12 · 48
--space-16 · 64
--space-20 · 80
--space-24 · 96

12-column grid · mobile-first

4 columns below 600px · 8 columns from 600–959px · 12 columns at 960px+. Column-span utilities follow the same tiers: .col-*, .t-col-*, .d-col-*. Press Ctrl+G anywhere on the site to overlay the live grid.

1
2
3
4
5
6
7
8
9
10
11
12

Common layouts — resize the window to watch them collapse.

main · d-col-8
side · d-col-4
card · 4
card · 4
card · 4

Radii & elevation

radius-xs · 4
radius-sm · 8
radius-md · 12
radius-lg · 20
elev-1
Low resting elevation. Cards.
elev-2
Interactive / raised.
elev-3
Modal, drawer, top-level.

Motion

Four durations, one standard easing (and one emphasized for arrows / expand). Interactions use --dur-2. Layout transitions use --dur-3 or --dur-4. Everything respects prefers-reduced-motion.

dur-1
120ms
Micro-feedback
dur-2
200ms
Buttons, links, hover
dur-3
320ms
Panels, tabs
dur-4
480ms
Modal, page-level
Components · Library

Components

Buttons

Minimum 44px tap target. Primary is orange with a soft glow; secondary is a bordered surface; ghost is chromeless.

Play / Pause / PlayPause icons

Add .play, .pause, or .playpause to any button to prefix it with a unicode media-control glyph. Use them for start/pause/toggle actions across post experiments.

The icon-only variant drops the text label. Toggle between .play and .pause in your JS to reflect the current state.

<!-- Text + icon -->
<button class="button play">Start</button>
<button class="button pause">Pause</button>

<!-- Icon-only -->
<button class="button play-pause play" aria-label="Play/pause"></button>

// JS: swap classes when state changes
btn.classList.toggle('play',  !isPlaying);
btn.classList.toggle('pause',  isPlaying);

Column-width tokens

Every column at the desktop tier is 80px wide with 16px gaps. That gives a set of derived max-widths — --max-1-column through --max-12-columns — for capping a card or list to an integer number of grid columns:

.recommended-list {
  max-width: var(--max-8-columns);   /* 752px */
}
--max-1-column
--max-2-columns
--max-3-columns
--max-4-columns
--max-6-columns
--max-8-columns
--max-10-columns
--max-12-columns

Forms

Cards

Post · 2026

Cellular automaton in canvas

A generative pattern that walks a grid, colouring pixels based on neighbourhood rules.

Feature

Elevated variant

Editorial callouts, "new" cards, or above-the-fold highlights.

Badges & pills

Default Primary Live Draft Broken Info

Alerts

ℹ️

Heads up

This is a neutral information message.

Build passed

All 42 tests green in 4.1s.

⚠️

Almost out of budget

Page weight is at 92% of its budget.

Deploy failed

The S3 uploader could not authenticate.

Tabs

Overview

Tabs use ARIA roles and keyboard support: / to move focus, Home/End to jump to ends.

Accordion

A single source of truth for tokens and components across every page on briananders.com.

Add it to the :root block in src/styles/system/_tokens.scss and it will be visible everywhere on the site — including inside shadow-DOM web components.

Yes — override the component's tokens on a wrapper rather than restyling the element.

Toast

Ephemeral feedback — auto-dismisses after 3s.

Progress

42% complete
Indeterminate
Animated (drag the range)

Table

PostCategoryDateStatus
Cellular automatonCanvas2026-01-11Live
Wordle solver v2Puzzles2025-11-04Draft
Polar clockCanvas2025-08-22Live
Sound frequency sliderAudio2025-05-30New

Code & kbd

Inline: const foo = 42;

Keyboard shortcut: press Cmd + K.

// Grid utility
const grid = {
  cols: { mobile: 4, tablet: 8, desktop: 12 },
  breakpoints: ['600px', '960px'],
};
Docs

How to apply this to a page

1. Reference a token

Always reference the CSS variable, never the raw value:

/* ✅ good */
.my-card {
  background: var(--color-surface-1);
  padding:    var(--space-6);
  border-radius: var(--radius-md);
}

/* ❌ bad */
.my-card { background: #12161C; padding: 24px; border-radius: 12px; }

2. Reach for a component

Every existing component name in src/styles/system/mixins/_elements.scss is stable — reach for the mixin from SCSS, or the equivalent class from EJS.

NeedSCSS mixinHTML class
Card surface@include card.card
Card that's a link@include card-link.card-link
Button@include button-link.button, add .primary or .ghost
Inline text link@include inline-link.inline-link
Block-style link@include block-link.block-link
Content container@include content.content / .container

3. Build a layout with the 12-column grid

<div class="container">
  <div class="ds-grid">
    <a class="card card-link col-4 t-col-4 d-col-6" href="…">…</a>
    <a class="card card-link col-4 t-col-4 d-col-6" href="…">…</a>
  </div>
</div>

col-* is 1–4 (mobile), t-col-* is 1–8 (tablet, 600px+), d-col-* is 1–12 (desktop, 960px+). Combine all three tiers to control every breakpoint.

4. Breakpoints

NameMin-widthGrid colsGutter
mobile416 (--space-4)
tablet600px824 (--space-6)
desktop960px1232 (--space-8)
wide1280px1232 (content maxes at 1200px)

5. Debug grid overlay

Press Ctrl+G (or Cmd+G on macOS) anywhere on the site to toggle a translucent overlay showing the current grid — the label at the bottom-right names the active breakpoint tier.

6. Accessibility floor

  • Every interactive element gets a visible :focus-visible ring via --focus-ring.
  • Tap targets are ≥44px on buttons, links, checkboxes, and radios.
  • All text tokens meet WCAG AA on --color-bg.
  • Motion is disabled by prefers-reduced-motion.