back home
design system v2.0.0

design.

Premium playful minimalism. Black and white structure, one blue interaction color, and four elemental hues that each own a section.

Every sample here is rendered from src/design/tokens.json. No hardcoded values, so it cannot go stale.

01

color

surface

backgrounds and edges. what things sit on.

#fafafa#0a0a0a

page background base

#f0f4ff#0d0d14

page gradient midpoint

#e8ecf8#0a0f1a

page gradient end

#ffffff#141414

raised card surface

#f1f5f9#1c1c1f

inset wells, code blocks

#e2e8f0#27272a

hairlines, card borders

content

text. three weights of emphasis, all AA on every surface.

#1a1a1a#fafafa

primary text

#5b6674#a1a1aa

secondary text, captions

#626b78#8b8b93

tertiary text, metadata

brand

the one blue. links, CTAs, focus rings.

#2563eb#60a5fa

links, CTAs, focus ring

#1d4ed8#93c5fd

accent text on light surfaces (AA-safe)

#ffffff#0a0a0a

label sitting on an accent fill

section

one hue per bento section. fills and dots, never body text.

#ef4444#f87171

fire. Sights section accent. Fills and dots only.

#38bdf8#7dd3fc

sounds section accent. Fills and dots only.

#f59e0b#fbbf24

air. Curiosity section accent. Fills and dots only.

#34d399#6ee7b7

earth. Creations section accent and live status. Fills and dots only.

#c084fc#d8b4fe

Rare expressive accent. Never body text or a section default.

#ef4444#f87171

destructive fill

#c81e1e#fca5a5

sights TEXT on its own tint (AA-safe)

#227195#7dd3fc

sounds TEXT on its own tint (AA-safe)

#935f07#fbbf24

curiosity TEXT on its own tint (AA-safe)

#1e7857#6ee7b7

creations TEXT on its own tint (AA-safe)

#7f57a6#d8b4fe

spirit TEXT on its own tint (AA-safe)

#c81e1e#fca5a5

destructive TEXT (AA-safe on card)

accent ramp

fixed tints of the blue interaction color. legacy components may still reference the sunrise alias while they migrate to semantic accent utilities.

50
100
200
300
400
500
600
700
800
900
02

type

families

--font-display

Adam Pang . 2026

Space Grotesk 700. Headings.

--font-body

Adam Pang . 2026

Lato 300/400/700. Prose.

--font-mono

Adam Pang . 2026

JetBrains Mono. Numerals, labels.

scale

--text-caption
0.75rem / 1.4

12px. Metadata, footnotes.

--text-label
0.8125rem / 1.4

13px. Eyebrows, nav.

--text-body
1rem / 1.65

16px. Default prose.

--text-lead
1.125rem / 1.6

18px. Intro paragraphs.

--text-h3
1.5rem / 1.2

24px. Card titles.

--text-h2
1.875rem / 1.15

30px. Section titles.

--text-h1
2.25rem / 0.95

36px. Page title. 3rem at sm+.

--text-display-sm
clamp(1.75rem, 4vw, 2.5rem) / 0.95

28-40px fluid. Timeline beats, feature headings.

--text-display
clamp(2.5rem, 6vw, 4.75rem) / 0.92

40-76px fluid. The one big statement per page.

tracking

--tracking-tightest-0.02emdisplay headings
--tracking-tighter-0.01emsubheads
--tracking-label0.12emuppercase eyebrows
--tracking-wide0.22emuppercase kickers
03

space

a 4px base step. mobile gutters and card padding use --space-5, opening to --space-6 at sm+.

--space-1
0.25rem
4px. Icon gap.
--space-2
0.5rem
8px. Inline gap.
--space-3
0.75rem
12px. Tight stack.
--space-4
1rem
16px. Default stack.
--space-5
1.25rem
20px. Card padding, mobile gutter.
--space-6
1.5rem
24px. Card padding at sm+.
--space-8
2rem
32px. Between subsections.
--space-10
2.5rem
40px. Between sections.
--space-14
3.5rem
56px. Page top/bottom at sm+.
04

radius + shadow

radius

--radius-sm
8px
badges, small chips
--radius-md
12px
inputs, small cards
--radius-lg
16px
cards. The default container.
--radius-full
9999px
buttons, pills, avatars

shadow

--shadow-card
resting card
--shadow-card-md
hover lift
--shadow-card-lg
modal, popover
05

components

hover and press the real controls, and tab through them to see :focus-visible, a 2px accent outline at 3px offset set globally. States marked simulated are frozen copies so the styling is visible without a pointer.

button

rounded-full, accent fill. the primary CTA.

default
hover
simulated
active
simulated
focus-visible
simulated
disabled

button . secondary

card surface, hairline border. the alternative action.

default
hover
simulated
active
simulated
focus-visible
simulated
disabled

link

1px underline, hairline decoration until hover.

hover
simulated
visited
simulated
focus-visible
simulated

input

these are real inputs. click and tab through them.

badge

status pill. section hues as fills, never as text.

default
default
live
live
shipping
shipping
building
building

card

--color-card on --color-line at --radius-lg. the standard container.

resting

shadow-card, no transform

live

hover

lift 2px, accent border, shadow-card-lg

live
06

motion

one easing curve everywhere. all of it collapses to 0ms under prefers-reduced-motion: reduce, enforced globally rather than per component.

--motion-easecubic-bezier(0.16, 1, 0.3, 1)the one easing curve
--motion-duration-micro200mshover, color change
--motion-duration-state400msstate transition
--motion-duration-reveal700msscroll reveal
--motion-lift-2pxhover translateY
07

influences

sites studied while building this one, and exactly what was taken from each. a site earns a place here only if a real line of code traces back to it. a site that only shaped the tone, with no artifact to point to, does not qualify.

sive.rsDerek Sivers

measure set in ch, not px. line length that tracks the font instead of a fixed pixel width. his whole site is 2kb of css and one script tag, the standing argument against adding weight here.

landed in src/app/about/page.tsx (max-w-[62ch])

a timeline as a path you travel, not a list you skim. scroll position mapped to a camera, not a wheel handler hijacked. also the color-quarantine move: rainbow hues live only in decoration (a gradient, a rim), never in text.

landed in src/components/JourneyTimeline.tsx . src/lib/journey.ts . src/components/Coin.tsx

ciechanow.skiBartosz Ciechanowski

not a source, a confirmation. arguably the most acclaimed personal technical site on the internet is built almost entirely on scroll-linked interactive diagrams, the same mechanic already in use here. one useful detail worth naming: a fixed accent used sparingly against an otherwise near-monochrome page.

landed in src/components/JourneyTimeline.tsx (validated, not sourced)

brianlovin.comBrian Lovin

a flat list of named side projects, each with one honest line describing it. also the direct source for this page: he keeps his own /sites crediting influences, so this one does too.

landed in src/data/influences.ts (this file)

for agents

building something on-brand?

Fetch the tokens rather than reading hexes off this page. Both files are generated from the same source in the same build, are CORS-open, and carry every value shown above.

curl https://adampang.com/design/tokens.json
curl https://adampang.com/design/tokens.css

three rules that keep work on-brand

  1. 01Reference the variable, never the hex. Write var(--color-fg), not #1a1a1a. Every token is mode-aware, so one reference is correct in both themes. A literal hex is right in one mode and wrong in the other.
  2. 02One accent, one hue per section. --color-accent owns links, CTAs, and focus. Section hues are decorative fills and dots. Never set body text in one: at ~2:1 on white they fail AA, which is why --color-alert-ink exists separately from --color-alert.
  3. 03Three text weights, no opacity. --color-fg, --color-muted, --color-faint. Do not dim text with opacity to invent a fourth. That is exactly what failed AA here: text-ink/55 measured 3.90:1 against a 4.5:1 requirement.

Identity data lives at /api/profile.json and /llms.txt.