// design system

agamarora.com v2. One element at a time. Research, reason, lock, move on.

00, What is this

Design system for agamarora.com v2.

12 years across analytics, gaming, D2C retail, logistics, and AI. Looks like chaos on a resume. Makes sense as convergence. This site makes that visible.

Quality bar: Stripe, Linear. Not copying, targeting the same audience. The site is the first artifact they judge.

Why build in public

Every decision made with AI (Claude Code + gstack). None delegated. AI researches, generates specimens, renders demos. I choose, refine, lock. The design system proves AI doesn't replace taste, it amplifies it.

Each section starts unlocked, goes through research and exploration, gets locked with rationale and usage rules. Agents that build the site read these rules. Nothing is arbitrary.

10
design system elements
10
locked
live
in production on agamarora.com

Research. Reason. Lock. Move on.

01, The Mark (locked)
aa., primary (click to replay)
/aa, secondary (click to replay)
aa., on light
aa., nav size

Mark decisions

02, Color Palette (locked: warm neutrals + gold)

Dark mode

WARM NEUTRAL SCALE
50
100
150
200
300
400
500
600
700
800
900
950
TEXT HIERARCHY on #0B0A09

n-900 #E8E4DF, Primary (15.6:1 AAA)

n-800 #C8C0B8, Secondary (11.0:1 AAA)

n-700 #A59D95, Tertiary (7.4:1 AAA)

n-600 #8A817A, Muted (5.2:1 AA)

n-500 #6B6359, Decorative only (3.4:1 AA-lg)

n-400 #403A33, Disabled / invisible (1.8:1)

SURFACE ROLES
bg n-50
surface n-100
elevated n-150
border n-200
GOLD ACCENT, #E5A54B (9.3:1)
Button
Outline
Ghost (gold/12%)
Link
GOLD OPACITY SCALE (blended over #0B0A09)
5%
8%
12%
20%
40%
100%
SEMANTIC on dark
success 6.6:1
error 4.9:1
warning 9.3:1
info 5.8:1
INTERACTIVE STATES
Hover bg
gold/12%
Active bg
gold/20%
Focus ring
gold outline 2px
selected text
::selection gold/25%

Light mode

TEXT HIERARCHY on #F5F3EF

n-50 #0B0A09, Primary (17.9:1 AAA)

n-200 #201D18, Secondary (15.2:1 AAA)

n-400 #403A33, Tertiary (10.1:1 AAA)

n-500 #6B6359, Muted (5.3:1 AA)

n-600 #8A817A, Decorative (3.4:1 AA-lg)

n-700 #A59D95, Disabled (2.4:1)

GOLD ON LIGHT
Button (9.3:1)
Outline
Link #7A5C12 (5.6:1 AA)
Gold #E5A54B is 1.9:1 on light, ONLY for large decorative marks, never body text. Use #7A5C12 for readable gold text.
SEMANTIC on light
success 4.7:1
error 5.7:1
warning 5.6:1
info 5.1:1

Complete token reference

Token Hex Dark role Light role vs Dark vs Light
n-50#0B0A09BackgroundPrimary text1.0:117.9:1
n-100#12110FSurface,1.1:117.0:1
n-150#191714Elevated,1.1:116.1:1
n-200#201D18BorderSecondary text1.2:115.2:1
n-300#2D2924Heavy border,1.4:113.0:1
n-400#403A33Subtle dividerTertiary text1.8:110.1:1
n-500#6B6359Decorative (3.4 AA-lg)Muted text3.4:15.3:1
n-600#8A817AMuted text (AA)Decorative (3.4 AA-lg)5.2:13.4:1
n-700#A59D95Secondary text,7.4:12.4:1
n-800#C8C0B8Strong secondary,11.0:11.6:1
n-900#E8E4DFPrimary textSurface15.6:11.1:1
n-950#F5F3EF,Background17.9:11.0:1
ACCENT
gold#E5A54BAccent, links, markButtons, large marks9.3:11.9:1
gold-text#7A5C12,Links, gold text,5.6:1
SEMANTIC
success#3DA86B6.6:1 AA#2D7A4E 4.7:16.6:14.7:1
error#D4564E4.9:1 AA#A33F39 5.7:14.9:15.7:1
info#5B8FC75.8:1 AA#3D6A94 5.1:15.8:15.1:1

How to use this palette

RULE 1: DARK MODE IS DEFAULT

Build dark first. Background is n-50 #0B0A09. Live site is dark-only. Light mode is documented for print contexts (resume PDF) and as future-state spec — same tokens, reversed (n-950 becomes bg, n-50 becomes text).

RULE 2: TEXT, PICK FROM 4 LEVELS

On dark:

  • n-900, headings, primary body, anything the user MUST read
  • n-700, descriptions, secondary info, supporting copy
  • n-600, captions, timestamps, metadata, labels
  • n-500, decorative text only (counters, watermarks). Not for reading.

On light: use n-50, n-200, n-400, n-500 for the same hierarchy (reversed).

RULE 3: GOLD MEANS SOMETHING

Gold #E5A54B is for interactive or identity elements only: the aa. mark, links, buttons, active states. If gold appears on something the user can't click or that doesn't represent the brand, it's wrong.

On light backgrounds: use #7A5C12 for gold text (passes AA). Use #E5A54B only on buttons or elements larger than 24px.

RULE 4: SURFACES, 3 LEVELS MAX

Don't use more than 3 surface levels on one screen.

  • n-50, page background
  • n-100, cards, panels, grouped content
  • n-150, popover, dropdown, elevated above a card
RULE 5: BORDERS AND DIVIDERS

n-200 #201D18 for standard borders. n-300 #2D2924 for emphasized dividers. Never use a border heavier than n-400.

RULE 6: HOVER / ACTIVE / FOCUS
  • Hover background: gold/12%
  • Active/pressed: gold/20%
  • Focus ring: 2px solid gold, 2px offset
  • Text selection: gold/25% background
RULE 7: SEMANTIC, USE SPARINGLY

Success/error/warning/info colors are for status communication only: form validation, notifications, badges. Never use them decoratively. On dark mode use the bright variants. On light mode use the darkened variants (see token table).

RULE 8: WHEN IN DOUBT

If you're unsure which shade to use, start with the highest contrast option that isn't primary text. n-700 is the safest "I need readable text but it's not the main thing" choice on dark. n-900 is always safe for anything the user needs to read.

03, Typography (locked: Satoshi + JetBrains Mono, Perfect Fourth scale)
Primary, Satoshi
Aa
Variable, self-hosted, 42KB. Geometric with warmth. Indian Type Foundry. Weights 400–700.
Fallback: system-ui, -apple-system, 'Segoe UI', sans-serif
Mono, JetBrains Mono
Aa
Google Fonts. Labels, code, timestamps, technical metadata. Weights 400 + 500.
Mark only, Patrick Hand
aa.
Google Fonts. Used exclusively for the aa. and /aa marks. Never for headings or body.
Type hierarchy on dark (#0B0A09)
DISPLAY · 4.209rem (67px) · w700 · ls: -0.025em · lh: 1.05 · n-900
Building what matters
H1 · 3.157rem (50px) · w700 · ls: -0.02em · lh: 1.1 · n-900
Twelve years of shipping products
H2 · 2.369rem (38px) · w600 · ls: -0.015em · lh: 1.15 · n-800
From analytics to AI leadership
H3 · 1.777rem (28px) · w600 · ls: -0.01em · lh: 1.2 · n-700
The convergence of craft and scale
BODY LG · 1.333rem (21px) · w400 · ls: 0 · lh: 1.55 · n-800
I believe the best products come from people who understand both the technical depth and the human need. Every product I've shipped started with a real problem.
BODY · 1rem (16px) · w400 · ls: 0 · lh: 1.6 · n-700
At AIonOS, I led the product strategy for an enterprise AI platform serving logistics companies across India. The challenge wasn't the AI, it was making AI useful for people who'd never heard of a transformer.
SMALL · 0.75rem (12px) · w500 · ls: +0.01em · lh: 1.5 · n-600
Previously: V2 Games (founded), FarEye (logistics), Nykaa (D2C retail)
CAPTION · 0.6875rem (11px) · w500 · ls: +0.08em · lh: 1.45 · n-500 · uppercase
Last updated May 2026 · Design system v2
Type hierarchy on light (#F5F3EF)
Building what matters
From analytics to AI leadership
At AIonOS, I led the product strategy for an enterprise AI platform. The challenge wasn't the AI, it was making AI useful for people who'd never heard of a transformer.
Previously: V2 Games (founded), FarEye (logistics), Nykaa (D2C retail)
Last updated May 2026 · Design system v2
Weight × Color = Variety (all Satoshi 1rem/16px)
700 + n-900 (primary heading)The convergence of craft and scale
600 + n-900 (secondary heading)The convergence of craft and scale
600 + n-800 (subheading)The convergence of craft and scale
500 + n-700 (emphasis)The convergence of craft and scale
400 + n-700 (body)The convergence of craft and scale
400 + n-600 (muted)The convergence of craft and scale
500 + n-500 (caption)The convergence of craft and scale
700 + gold (accent heading)The convergence of craft and scale
500 + gold (accent label)The convergence of craft and scale
Vertical spacing rhythm
Element Space after Space before (from body) Logic
Display1.5rem (24px),Hero, first element
H11.25rem (20px),Page title, near top
H21rem (16px)3rem (48px)New section break
H30.75rem (12px)2rem (32px)Minor break
Body / Body lg1rem (16px),Paragraph spacing
Small0.5rem (8px),Compact
Caption0.25rem (4px),Minimal

Principle: space before headings > space after. Headings belong to the content below them, not above (Gestalt proximity).

Complete token reference
Token rem px clamp() Weight Tracking LH Dark color Light color
display4.20967clamp(2.25rem, 5vw+1rem, 4.209rem)700-0.025em1.05n-900 #E8E4DFn-50 #0B0A09
h13.15750clamp(1.875rem, 4vw+0.75rem, 3.157rem)700-0.02em1.1n-900 #E8E4DFn-50 #0B0A09
h22.36938clamp(1.5rem, 3vw+0.5rem, 2.369rem)600-0.015em1.15n-800 #C8C0B8n-200 #201D18
h31.77728clamp(1.25rem, 2vw+0.5rem, 1.777rem)600-0.01em1.2n-700 #A59D95n-300 #2D2924
body-lg1.33321clamp(1.125rem, 1vw+0.875rem, 1.333rem)40001.55n-800 #C8C0B8n-300 #2D2924
body1.0161rem (fixed)40001.6n-700 #A59D95n-400 #403A33
small0.75120.75rem (fixed)500+0.01em1.5n-600 #8A817An-500 #6B6359
caption0.6875110.6875rem (fixed)500+0.08em1.45n-500 #6B6359n-500 #6B6359

Scale ratio: Perfect Fourth (1.333). Base: 16px (1rem). Floor: 11px. Max body width: 65ch.

Typography usage rules (for agents)
RULE 1: ONE FONT, MANY VOICES

Satoshi for everything. Weight + color token + size creates hierarchy. Never add another sans-serif font. The fallback stack is: system-ui, -apple-system, 'Segoe UI', sans-serif

RULE 2: PATRICK HAND IS THE MARK ONLY

Never use Patrick Hand for headings, body, or UI text. It appears exclusively in the aa. and /aa marks. Mixing it with body text kills both the mark's specialness and text readability.

RULE 3: JETBRAINS MONO FOR SYSTEM VOICE

Labels, timestamps, code, technical metadata, section headers in the moodboard. Weights 400 (default) and 500 (emphasis). Plus weight 300 used exclusively for the / cursor in the /aa mark. Always pair with loose tracking (+0.05em to +0.12em) when in uppercase.

RULE 4: TRACK TIGHTER AS YOU GO BIGGER

Display: -0.025em. H1: -0.02em. Body: 0. Small: +0.01em. Caps: +0.08em. This is optical compensation from Bringhurst, not style preference. No exceptions.

RULE 5: LEAD LOOSER AS YOU GO SMALLER

Display: 1.05. H1: 1.1. Body: 1.6. At large sizes the eye tracks easily. At small sizes lines blur together without extra leading.

RULE 6: 65CH MAX FOR BODY TEXT

Paragraphs and body-lg never wider than 65 characters (max-width: 65ch). Headings can go wider. Too wide and the eye loses its place on the return sweep (Bringhurst recommends 45-75ch).

RULE 7: WEIGHT MEANS HIERARCHY

700 = headings (display, h1). 600 = subheadings (h2, h3) and inline emphasis in body. 500 = labels and small text emphasis. 400 = body text. Don't use 700 for body. Use 600 (not 700) for bold words within paragraphs.

RULE 8: HEADINGS SCALE, BODY DOESN'T

Display/H1/H2/H3/Body-lg use clamp() for responsive scaling. Body/small/caption are fixed rem values because they're already at readable minimums. Use the clamp values from the token reference, don't invent new ones.

04, Spacing

4px base unit. 11-token scale from 2px to 128px. Spacious density for editorial portfolio. Semantic aliases for common patterns. Informed by Ant Design, Vercel/Geist, Radix, and Material Design 3.

Token scale, visual
--space-1
2px · 0.125rem · hairline, optical tweaks
--space-2
4px · 0.25rem · icon-to-label, caption gaps
--space-3
8px · 0.5rem · related elements within a group
--space-4
12px · 0.75rem · compact grouping, list items
--space-5
16px · 1rem · default, paragraph gaps, form spacing
--space-6
24px · 1.5rem · generous grouping, group-to-group
--space-7
32px · 2rem · section inner padding, card padding
--space-8
48px · 3rem · major content breaks
--space-9
64px · 4rem · section-to-section, landmark breaks
--space-10
96px · 6rem · page-level breathing, hero padding
--space-11
128px · 8rem · expansive, full-section vertical padding

Base: 4px. Scale: 2, 4, 8, 12, 16, 24, 32, 48, 64, 96, 128. Jumps accelerate as values grow (matches human spatial perception). Informed by Ant Design (4px base), Vercel/Geist (4-128px range), Radix (4px base, 9 steps).

Semantic aliases, named shortcuts
Alias Resolves to Value Usage
--gap-tight--space-38pxIcon + label, inline elements
--gap-default--space-516pxStacked siblings, form fields
--gap-loose--space-624pxGroup-to-group within section
--padding-element--space-412pxButtons, tags, small components
--padding-card--space-732pxCards, panels, content containers
--padding-section--space-848pxPage sections, vertical rhythm
--padding-page--space-1096pxHero, viewport sections, top-level
--margin-page-xresponsive24/48/96pxHorizontal page margins (mobile/tablet/desktop)

Agents use aliases, not raw tokens. --padding-card is intent, --space-7 is implementation. The alias layer means we can adjust density globally without touching every component.

Component demo, spacing in action
CARD, --padding-card (32px)
FarEye Platform
Led the 10x scale transformation of a logistics platform serving enterprise customers across India.
B2B SaaS Logistics
32px
STACK, --gap-default (16px)
Analytics at Absolutdata
ML/data foundation
16px
Gaming at V2 Games
ARM framework, engagement
16px
AI at AIonOS
RAG, Voice AI, Copilots
Section spacing, how the page breathes
Hero Section
padding: --padding-page (96px) vertical
--space-9 · 64px
Chapter: Analytics
padding: --padding-section (48px)
--space-9 · 64px
Chapter: Gaming
padding: --padding-section (48px)
--space-9 · 64px
The Convergence
padding: --padding-page (96px) vertical
Responsive compression
Token Desktop (1024px+) Tablet (768px) Mobile (<768px)
1-62-24pxsamesame (fixed)
732px28px24px
848px40px32px
964px48px40px
1096px72px48px
11128px96px64px

Tokens 1-6 are fixed (already at perceptual minimums). Tokens 7-11 compress by ~25% per breakpoint step. Same Gestalt relationships, less absolute space. Like the type scale's clamp().

Density comparison, why spacious
COMPACT (dashboard density)
Card Title
Dense body text with tight spacing between elements.
Tag
SPACIOUS (our density) ✓
Card Title
Same text, generous breathing room. Content floats. Reads editorial, not utilitarian.
Tag

Compact = SaaS dashboard. Spacious = editorial portfolio. Same content, completely different signal. Generous spacing reads as confidence and taste. That's the Stripe/Linear quality bar.

Spacing usage rules (for agents)
RULE 1: NO RAW VALUES

Every margin, padding, and gap uses a named token or semantic alias. Never padding: 20px. Always padding: var(--space-6) or padding: var(--padding-card).

RULE 2: GESTALT PROXIMITY

Elements that belong together get smaller gaps (space-3 to space-5). Unrelated groups get larger gaps (space-7+). The gap size IS the relationship signal. This is the same principle from the typography section applied to all layout.

RULE 3: USE ALIASES, NOT TOKENS

Prefer semantic aliases (--padding-card, --gap-default) over raw tokens (--space-7, --space-5). Aliases express intent. If density changes later, only the alias resolution changes, not every component.

RULE 4: SECTION MINIMUMS

Section padding is --padding-section (48px) minimum on desktop, compressed to 32px on mobile. The convergence scroll sections use --padding-page (96px) to center content in viewport-height frames.

RULE 5: PAGE MARGINS ARE RESPONSIVE

Horizontal page margins: --space-6 (24px) mobile, --space-8 (48px) tablet, --space-10 (96px) desktop. Content floats in a centered column. Never edge-to-edge.

RULE 6: SPACE-1 IS OPTICAL ONLY

--space-1 (2px) is for optical adjustments: nudging alignment, border-adjacent corrections. Never use it for layout spacing. Minimum layout gap is --space-2 (4px).

RULE 7: TYPOGRAPHY SPACING IS ALREADY DEFINED

Vertical spacing between text elements (heading margins, paragraph gaps) follows the typography section's rhythm table. This spacing system covers everything else: component padding, layout gaps, section breaks.

RULE 8: WHEN IN DOUBT, GO BIGGER

Spacious density means: if you're choosing between two adjacent tokens, pick the larger one. Too much space reads as editorial confidence. Too little reads as cramped. The Stripe/Linear pages all err on the side of generous.

RULE 9: CREATING NEW ALIASES

The starter aliases above are not exhaustive. When building a new component that will be reused, create a semantic alias for its spacing. Naming convention: --{padding|gap|margin}-{component}. Examples: --padding-nav, --gap-grid, --margin-footer. Always resolve to an existing --space-N token. Never alias to a raw pixel value. Register new aliases in the CSS :root block alongside the originals so they're discoverable.

RULE 10: ALIAS MAINTENANCE

If a component is removed, remove its alias too. Dead aliases are clutter. If you need to change the density of a component, change the alias resolution (e.g., --padding-card: var(--space-6) instead of var(--space-7)), never override inline. The :root block is the single source of truth for all alias-to-token mappings.

05, Layout (locked: width tiers + content-based breakpoints, no grid)

Three named width tiers instead of a grid system. Content-based breakpoints aligned to where spacing and typography already compress. Manuscript layout for sequential narrative. Informed by Bringhurst (measure theory), Muller-Brockmann (grid theory), Tschichold (proportional canons), NN/g (scroll attention + visual anchoring), Gestalt psychology (proximity ratios).

Width tiers, visual
--width-wide: 1320px
--width-default: 1080px
--width-narrow: 720px

This is where sustained prose lives. At ~65ch in Satoshi at 16px, it sits within Bringhurst's ideal reading measure of 45-75 characters per line. The eye's return sweep stays accurate, reducing regressions and cognitive load. Chapter text, body paragraphs, about sections.

Structural content: hero headings, cards, asymmetric layouts. 1.5x narrow.

Outer content bound. Beyond this: only background color, SVG layers, full-bleed decoration. NN/g: visual anchoring breaks above ~1400px.

Width token reference
--width-narrow
720px
~65ch · prose, chapters, body text · Bringhurst measure
--width-default
1080px
1.5x narrow · hero, cards, structural elements
--width-wide
1320px
outer content bound · nothing wider except backgrounds
Breakpoints, content-based

Breakpoints are set where the layout actually breaks, not where devices start. Each threshold marks a shift in which perceptual constraint dominates: touch targets below 640px, reading measure at 1024px, spatial luxury at 1440px.

--bp-small
640px
Below: fluid single column
All containers collapse to 100% width. Inline padding: --space-6 (24px). Spacing tokens 7-11 compress ~25%. Type clamp() handles scale. Measure drops to ~36ch at 375px, accepted: mobile is scanning mode, not reading mode.
--bp-medium
1024px
Narrow container activates
720px content + side margins fit comfortably. Reading experience stabilizes at proper measure. Default container available if needed for wider structural elements.
--bp-large
1440px
Full spatial luxury
All three width tiers active. Maximum peripheral whitespace as cognitive buffer. Above 1440px: additional space is pure margin, content does not stretch.
Grid decision: none

Muller-Brockmann's grid theory: grids reduce cognitive load by creating predictable spatial relationships for parallel content. A manuscript grid (single column with margins) is correct for sequential, linear content.

This product is a scroll-driven narrative. One thing at a time. No sidebars, no parallel content streams, no data tables. Width tiers + spacing tokens handle all layout needs.

If a future component needs a grid (card arrangement, bento layout), use CSS Grid auto-fit with spacing tokens ad hoc. Do not pre-build a grid system for hypothetical needs.

Vertical section rhythm

Gestalt proximity: the brain reads spatial distance as semantic distance. The ratio between internal spacing and section spacing must be at least 3:1 to signal a clear grouping change. NN/g scroll attention data: generous section spacing creates re-engagement "beats" but too much triggers the "illusion of completeness" where users think the page is done.

Within a component
--space-5 (16px) · 1x base · "same unit"
Between components
--space-6 to --space-7 (24-32px) · 1.5-2x · "related but distinct"
Between sections
--space-9 to --space-10 (64-96px) · 4-6x · "different topic"

100vh chapter sections: 96px padding top/bottom on desktop, compresses to 48px on mobile via spacing responsive rules.

Alignment model

All containers are horizontally centered (margin-inline: auto). Within the default container (1080px), text blocks can be offset left or right. The narrow column (720px) floats within the default, giving ~180px of offset room per side.

The SVG convergence layer is position: fixed, full viewport. Its spatial logic is independent of content containers.

This gives asymmetry within structure. Tschichold: white space is an active element, not a passive background. The offset room is intentional, not leftover.

Mobile behavior (below 640px)

All width tiers collapse. Content is fluid at 100% minus inline padding. Fixed inline padding of --space-6 (24px) on each side.

At 375px (iPhone SE/13 mini): 327px content width, ~36ch in Satoshi. Below Bringhurst's 45ch minimum. This is accepted: Dyson and Shaikh research shows users adapt to shorter line lengths on mobile, reading in shorter bursts. Content structure matters more than measure at this width.

Spacing tokens 7-11 compress ~25% per the spacing spec. Section padding drops from 96px to 48px. No offset/asymmetry: text is left-aligned, edge-to-edge within padding.

Layout usage rules (for agents)
RULE 1: CONTENT NEVER EXCEEDS --width-wide

No text, image, card, or interactive element wider than 1320px. Full-bleed backgrounds (color, SVG, gradients) are fine. Content is not background.

RULE 2: PROSE USES --width-narrow

Any sustained reading (paragraphs, chapter text, about sections) must be constrained to 720px / ~65ch. This is a readability constraint from measure theory, not a style preference.

RULE 3: BREAKPOINTS ARE CONTENT-BASED

Use the documented breakpoints: --bp-small (640px), --bp-medium (1024px), --bp-large (1440px). Section 04 spacing also uses --bp-tablet (768px) as a compression threshold. CSS @media can't read custom properties, so write the literal value with the token name in a comment beside it. Do not invent device-specific breakpoints (375px etc.). If the layout breaks at a width not covered, the content is too wide for its container — fix the content.

RULE 4: NO PRE-BUILT GRID

Do not create grid utility classes or a column system. If a component needs columns, use CSS Grid auto-fit with spacing tokens inline. The product is sequential narrative, not a dashboard.

RULE 5: SECTION SPACING IS 4-6x INTERNAL

Gestalt proximity requires a clear ratio gap between "same group" and "different group" spacing. Internal: --space-5 (16px). Between sections: --space-9 to --space-10 (64-96px). Never use the same spacing token for both.

RULE 6: MOBILE = FLUID + FIXED PADDING

Below --bp-small (640px), all containers are width: 100%; padding-inline: var(--space-6). No offsets, no asymmetry. Left-aligned, edge-to-edge within padding.

RULE 7: CENTERED CONTAINERS, ASYMMETRIC CONTENT

Containers are always centered. Asymmetry happens within the container via margin-inline offsets. The narrow column has ~180px of offset room within the default container. Use this for alternating chapter layouts.

RULE 8: VIEWPORT HEIGHT IS NOT A CONTENT UNIT

Sections can be min-height: 100vh for scroll-driven chapters, but content should not depend on exact viewport height. Use padding and vertical centering. Let content determine natural height, constrained by min-height for the scroll mechanic.

06, Border Radius (locked: 4px-aligned scale)

4-step scale aligned to spacing base. Cognitive research (Bar & Neta, 2006): humans prefer curved contours, sharp corners activate threat detection. Small radii = refined/intentional. Large radii = friendly/casual. For warm editorial: enough softness to match Satoshi's humanist character without drifting into consumer-app territory.

Radius scale, visual
--radius-sm
4px
inputs, tags, chips
--radius-md
8px
cards, containers
--radius-lg
12px
hero cards, featured
--radius-full
9999px
pills, badges (sparingly)

8px is the primary default. Aligns with Stripe/Linear/Vercel's "premium default." Reads as intentionally soft, not accidentally sharp. 4px base matches spacing grid.

07, Motion (locked: perception-anchored durations + expressive decelerate)

Easing and duration conventions rooted in physical-world perception (Disney's 12 Principles, 1981). Objects decelerate into rest, so ease-out on enter feels natural. Duration thresholds from Miller (1968) and Nielsen (1993): <100ms = instant, 100-300ms = responsive, 300-500ms = cinematic, >500ms = narrative. The expressive decelerate curve (0.16, 1, 0.3, 1) pairs with the warm-but-precise aesthetic.

Duration scale
--motion-instant
100ms
ease-out · hover, focus, toggle · feels like direct manipulation
--motion-fast
200ms
ease-out · fade, color shift, small position changes
--motion-moderate
350ms
cubic-bezier(0.16, 1, 0.3, 1) · slide-in, card enter, layout shift
--motion-slow
500ms
cubic-bezier(0.16, 1, 0.3, 1) · page transition, large reveals
--motion-scroll
scrub: 0.8
GSAP power2.out · scroll-driven narrative, convergence animation
What animates vs what doesn't
ANIMATE
  • State changes user triggered (hover, click)
  • Entrance of new content (scroll reveals)
  • Scroll-driven convergence paths
  • Theme transitions (color shifts)
  • The aa. mark stroke-draw
DON'T ANIMATE
  • Content the user is trying to read
  • Repeated/looping decorative motion
  • Anything that blocks interaction
  • Layout shifts during reading
  • prefers-reduced-motion: show final state
08, Imagery / Decoration (locked: material warmth, not decoration)

International Typographic Style (Swiss Design, 1950s): in text-first layouts, visual elements create rhythm and breathing room, not compete with content. For dark editorial: the risk is either looking empty or looking like a gaming site. Subtle texture makes flat digital surfaces feel like a material (Julesz, 1981, pre-attentive texture processing).

Texture and background treatments
Noise overlay
3-4% opacity, monochromatic, ~0.5px grain · visible at 1:1 zoom, invisible at arm's length
Focal glow
Radial gradient, gold (#E5A54B) at 4% opacity, ~60vw radius · behind hero content, creates depth
Dividers
1px, rgba(255,255,255,0.08) default · gold accent for emphasis rules (sparingly)
Whitespace
Generous negative space IS the primary decoration. Let spacing scale do the work.
aa. mark
Already a decorative asset. Use as section anchor or subtle watermark element.
Avoid
  • Visible grid patterns, dot matrices, mesh gradients (2022 trend)
  • Geometric shapes floating in space
  • Abstract blob illustrations
  • Decorative lines that don't divide anything
  • Stock-looking photography. If used: desaturated, warm-graded, consistent treatment.
09, Components (locked: 7-piece minimum set)

Portfolio sites are transient interfaces (Alan Cooper, "About Face"): users scan, evaluate, and leave. The component set optimizes for reading flow and scannability, not interaction variety. Build only what the scroll-driven narrative demands. Every component you don't build is a design decision you don't have to maintain.

Component inventory
Button
Primary (solid gold bg, dark text) + Ghost (1px border, text color). radius-sm. Generous padding (12-16px / 24-32px).
Inline link
Gold text, no underline default. Underline on hover. Tufte principle: no noise until interaction.
Section header
Typography + spacing only. Not a "component." Uses type hierarchy levels directly.
Project card
Part of scroll flow, not a browsing grid. Dark surface (rgba 255,255,255 0.03-0.05). Thin border, no shadow.
Tag/chip
Small, low-emphasis. JetBrains Mono, 11px. radius-sm. For skill labels, tech stack, role indicators.
Nav bar
Minimal: aa. mark + 2-3 links. No mega-menu, no hamburger on desktop. (Theme toggle deferred — site is dark-only.)
Footer
Contact + social links. Simple, low-key. The CTA section above carries the weight.
Button styles, live
Read case study
10, Voice (locked: confident + warm + specific + brief)

NN/g tone research (2016): for professional credibility with enterprise audiences, the highest-trust combination is serious + casual + respectful + matter-of-fact. Tone and typography must match: Satoshi's geometric-humanist character pairs with writing that is clear and direct but not robotic. The formula: write like you're explaining your work to a sharp peer over coffee.

Length rules
Section heads
1-3 words, label-like · "Work" not "Selected Projects & Case Studies"
Subheads
8-15 words, one claim · Poynter EyeTrack: 4-8 words optimal for scanning
Body paragraphs
2-3 sentences, 40-60 words max · Miller (1956): chunking for working memory
CTAs
2-3 words, verb-first · "View project" not "Shall we explore this together?"
Tone register (for the audience)

The audience reads precise documentation daily (Anthropic, Stripe, Linear hiring managers). They value:

DO
Clarity over cleverness. Specificity over superlatives. Confidence without arrogance. Show the thinking.
DON'T
"Dramatically improved." "Passionate about." "Leveraged synergies." Any hedge word. Any superlative without a number.

Examples:

Not: "I dramatically improved the delivery experience"
But: "Reduced delivery time from 60 days to 7. NPS went from 3.6 to 4.7."

Not: "Selected Projects & Case Studies"
But: "Work"

Design system status

Design system complete. All 10 sections locked. Item 11 is a living collection that grows with inspiration.

11, Inspiration & Design Patterns (living collection)

Compositional techniques collected from real sites that push craft. Not tokens or rules, spatial ideas, motion patterns, and layout approaches that inform how the site FEELS. This section grows as inspiration is found. Each pattern has a live demo, source attribution, and implementation notes.

11.1, Background ghost text with overlapping content
Source: bear.plus project sections

Oversized ghost text creates spatial depth. Content cards sit ON TOP of the background word, breaking the flat plane. The background text is not decoration, it's a section label scaled to architecture. Color: #151515 or lower, visible enough to read but never competing with foreground content.

SIGNAL
AIonOS
AI Product Lead
RAG, Voice AI, Multi-Agent Systems.
FarEye
Senior PM
10x platform scale. NPS 3.6 to 4.7.
V2 Games
Founder
18-person team. $75K ARR.
Rules:
1. Background text: Satoshi 800, clamp(5rem, 12vw, 10rem), color #151515, letter-spacing -0.06em
2. Foreground overlaps via negative margin (-40px to -80px)
3. Background z-index: 1, foreground z-index: 2
4. 1-2 word labels only. Reserve for sections needing spatial weight.
11.2, Parallax depth layers
Source: bear.plus homepage, services page 3D scenes

Elements exist at different distances from the viewer. On scroll, layers move at different speeds creating the illusion of depth. Not the 2013 "parallax website" gimmick, this is spatial design. The page is a space you move THROUGH, not a surface you move UP. Bear.plus achieves this with Three.js for 3D objects and GSAP ScrollTrigger for 2D layers at different scroll speeds.

DEPTH
Mid layer
This card moves at medium speed. It sits between the background text and the foreground element.
aa.
scroll-speed: 0.3x (far)
scroll-speed: 0.6x (mid)
scroll-speed: 1.0x (near)
Implementation:
1. GSAP ScrollTrigger with different scrub rates per layer: far=0.3, mid=0.6, near=1.0
2. Far elements: larger, dimmer (#111-#151515), slower scroll. Near elements: smaller, brighter, faster scroll.
3. Optional: slight blur on far elements (filter: blur(1-2px)) to simulate depth of field
4. Optional: opacity variation, far layers at 0.4-0.6, near layers at 1.0
5. On mobile: reduce or disable parallax. Use opacity/scale differences instead for depth cue.
6. Performance: use will-change: transform on parallax layers. Keep to 3 depth layers max.

The difference from gimmick parallax:
- Gimmick: background image moves slower than foreground. One trick repeated.
- Spatial: multiple elements at different depths with consistent physics. You feel like you're moving through a room, not scrolling a page. Every element's speed tells you where it is in space.
More patterns to come

This section grows as you discover inspiration. Each pattern gets a number (11.N), a live demo, source attribution, and implementation notes.