artifact · 5 of 11
System
Color, type, layout, depth, shape, imagery, motion — every value, with the measured contrast numbers.
design/SYSTEM.md · 9,414 B · Phase 3 — Foundation
System — ultraweb showcase ("The Terminal")
All values final unless a checkpoint overturns them. Tokens compiled by tokens into the staged design/tokens.css → becomes app/globals.css at Phase 5. Single dark world per DIRECTION.md — no .dark block exists; color-scheme: dark declared; no ThemeProvider/next-themes (deviation from the default stack recorded here: there is no theme to switch).
§color
Neutral family: warm near-black ramp, hue 50, C 0.012–0.015 (never gray, never navy). ONE accent: terracotta hue 45–50. Data semantics (PASS/FAIL) exist only inside receipt/gate tables, always word-labeled (CVD second channel — color is never the only carrier; red/green ΔL is small so the label rule is load-bearing and non-negotiable).
| Token | Value | Notes |
|---|---|---|
| background | oklch(0.17 0.015 50) | the committed warm black |
| foreground | oklch(0.93 0.01 80) | warm white |
| card | oklch(0.21 0.015 50) | elevation = lightness (+0.04) |
| popover | oklch(0.25 0.015 50) | level 3 (+0.08) |
| well | oklch(0.14 0.012 50) | the terminal pit — inverted elevation, unique to the signature |
| primary | oklch(0.66 0.15 45) | terracotta; buttons, ring, the mark's cursor block |
| primary-foreground | oklch(0.14 0.012 50) | ink on terracotta |
| primary-lift | oklch(0.75 0.12 50) | accent as SMALL text on dark surfaces |
| primary-hover | oklch(0.72 0.14 45) | filled-CTA hover |
| secondary / accent (hover wash) | oklch(0.24 0.015 50) | shadcn semantics; the brand accent is primary |
| muted | oklch(0.22 0.012 50) | |
| muted-foreground | oklch(0.72 0.015 60) | |
| destructive / FAIL | oklch(0.72 0.16 25) | data + error text |
| success / PASS | oklch(0.75 0.13 150) | gate tables only |
| border | oklch(0.93 0.01 80 / 0.10) | hairline (decorative, exempt from 3:1) |
| border-strong | oklch(0.93 0.01 80 / 0.16) | levels 3–4 |
| input | oklch(0.52 0.012 50) | meaningful boundary, ≥3:1 verified |
| ring | oklch(0.66 0.15 45) | = primary |
AA verification (Playwright canvas, gamut-mapped sRGB, 2026-08-14 — script per color skill, run this session):
fg/bg 15.51:1 · fg/card 14.47:1 · fg/popover 12.99:1 · fg/well 16.18:1
muted-fg/bg 7.70:1 · muted-fg/card 7.18:1 · muted-fg/muted 7.00:1
primary-fg/primary 6.07:1 · primary(large/ring)/bg 5.82:1 · ring/card 5.42:1
primary-lift/bg 8.27:1 · primary-lift/card 7.71:1
success/bg 9.04:1 · destructive/bg 7.19:1
input-border/bg 3.45:1 · input-border/card 3.22:1 (≥3:1 non-text)
selection (primary-fg on primary) 6.07:1 · fg-on-primary-hover 7.66:1All text pairs ≥4.5:1, all non-text UI pairs ≥3:1. First candidate for input border (L 0.45 → 2.54:1) FAILED and was tuned to L 0.52 — the tuning is the receipt that the check is real.
§type
Pairing: Space Grotesk (display + UI + body — variable wght, loaded 400–700) + JetBrains Mono (every command, label, timestamp, SHA, datum; 400/500; tabular-nums mandatory on data). Two faces, hard roles, no third — per DIRECTION.md. Self-hosted via next/font/google; lib/fonts.ts exports display (--font-space-grotesk) and mono (--font-jetbrains-mono).
- Scale (fluid 390→1440): base 16→18 · 6xl hero 44→92px (5.1× body at 1440 — clears the 3.5× floor) · full clamp values in tokens.css.
- Display ≥40px: tracking −0.02em, leading 1.0–1.05,
text-wrap: balance,font-feature-settings: 'kern' 1,'liga' 1,'calt' 1;text-box-trim: trim-bothwhere supported. - Body: leading 1.6, measure 60–72ch,
text-wrap: pretty. - Mono caps labels: 11–12px, +0.06em, weight 500.
- Weight pairing: 400 body vs 700 display (500 for UI emphasis; never 500+600 adjacent).
- Breathing Type: not granted (archetype not in the gate's list).
§layout
Containers: --container-prose: 65ch · --container-content: 72rem · --container-wide: 88rem (+ deliberate Edge Bleed breakout). Grid: 12-col, gap-4 mobile / gap-6–8 desktop. Named splits: Heavy 8/4 (media/terminal-led) · Reverse 5/7 (hero: copy 5, terminal 7 bleeding right) · Margin Note 3/9 (reading room + long-form rails, sticky). Rhythm map: compressed (py-12/16) = receipt strips, stat bars, gate tables in-flow · standard (py-20/28) = default · release (py-28/40) = hero exit + pre-install CTA. No three consecutive sections share a size; page arcs to the install CTA. Asymmetry (recurring): Edge Bleed (the terminal and evidence tables run off the right edge — established by the approved mockup) + Offset Split as workhorse; Margin Note is the reading room's structure. Offscreen sections past fold 3 get content-visibility: auto with measured contain-intrinsic-size.
§depth
Stance: flat-minimal — borders lead; elevation is lightness (bg 0.17 → card 0.21 → popover 0.25; the terminal well 0.14 is the single deliberate inversion: a pit, not a float). Persistent structure = 1px hairline; transient = shadow, levels 3–4 only:
--shadow-lg: 0 4px 12px oklch(0.05 0.01 50 / 0.35), 0 12px 32px oklch(0.05 0.01 50 / 0.30);
--shadow-xl: 0 8px 16px oklch(0.05 0.01 50 / 0.35), 0 28px 56px oklch(0.05 0.01 50 / 0.40);Level map: 0 page/sections · 1 cards/inputs (hairline, no shadow) · 2 scrolled sticky header (opaque + 1px bottom hairline — NO shadow, no glass) · 3 dropdowns/tooltips (shadow-lg + border-strong) · 4 ⌘K palette, dialogs (shadow-xl + border-strong + backdrop dim oklch(0.05 0.01 50 / 0.6)). No glass — verdict recorded (DIRECTION bans backdrop-blur outright). Forced colors: every level 1–4 surface carries @media (forced-colors: active) { border: 1px solid CanvasText; box-shadow: none; }.
§shape
Personality: Sharp — --radius-sm: 0.125rem · --radius-md: 0.25rem · --radius-lg: 0.375rem · --radius-xl: 0.5rem. rounded-full only for status dots (data glyphs); never buttons/cards. Concentric formula applies (inner = outer − padding, clamp 0). Motif family: Rule & bracket — placements: (1) corner ticks on the terminal frame, (2) short 2.5rem accent rule under section eyebrows, (3) evidence frames (screenshots/tables) with corner brackets, (4) plus-lattice ground texture. Dividers: space first; 1px fg@10% hairlines; NO statement dividers (surface shifts do the work); no <hr> wallpaper.
§imagery
Stance: zero photography — type, terminal, tables, and SVG diagrams ARE the imagery. Named treatment (the ONE): Framed Evidence — every screenshot/mockup thumbnail sits in a hairline frame with corner-bracket ticks and a JetBrains Mono caption bar (filename · dimensions · date), no filters (evidence stays legible and honest). Texture: parametric lattice (Rule & bracket) — plus-marks on a 32px cell, mark 6px, oklch(0.93 0.01 80 / 0.05), hero + release sections only; knobs recorded here per the parametric rule. No organic grain, no mesh, no scanlines (dated). Generated assets (OG, diagram SVGs) honestly named; no stock anything.
§motion
Intensity: Level 2 — Expressive (rationale: precision-instrument energy; the terminal is the one theatrical element and it is interaction-driven, not scroll-driven; grants stagger, scroll-linked moments, one physics interaction — no page transitions, no pinned sequences). Easing family: Mechanical, durations cut ~20%: --dur-micro: 160ms · --dur-small: 260ms · --dur-section: 450ms; --ease-out: cubic-bezier(0.33,1,0.68,1) · --ease-in-out: cubic-bezier(0.65,0,0.35,1) · --ease-in: cubic-bezier(0.32,0,0.67,0). Exits ≈ 70% of entrance. lib/motion.ts mirror (written at Phase 5): dur = { micro: 0.16, small: 0.26, section: 0.45 }, ease = { out: [0.33,1,0.68,1], inOut: [0.65,0,0.35,1], in: [0.32,0,0.67,0] }. Choreography: reveals once (viewport={{ once: true }}), stagger 50ms cap 6, order container→heading→copy→CTA/media; header/nav static; hero H1 (LCP) never mounts at opacity 0 — the terminal types AFTER the headline is painted. Terminal caret: CSS steps(1) blink, gated prefers-reduced-motion (static full block under reduce). NEVER: focus outlines, body text, form inputs, theme switches (n/a), scroll-tick reactions outside designed moments, living idle (not commissioned). Reduced motion: two layers (CSS opt-in via @media (prefers-reduced-motion: no-preference), JS useReducedMotion()); under reduce: opacity-only ≤200ms or nothing; terminal renders the completed transcript. @property registrations: NONE — no token interpolates (recorded decision; the caret animates opacity, not a custom property).
§identity (summary — full record in design/IDENTITY.md)
Wordmark: lowercase "ultraweb" in Space Grotesk 500 + the ONE custom cut: an appended solid cursor block at x-height in --primary. Monogram: 32×32 block with a rectilinear "u" knocked out — block cursor and "u" in one shape; feeds icon/apple-icon/manifest/OG. Files staged in design/brand/ (→ public/brand/ at scaffold).
§motion amendment (gate-visual round 2, 2026-08-14)
The header's hide-on-scroll-down / return-on-scroll-up (250ms transform, 8px jitter threshold, force-visible on menu-open/focus-within, plain-sticky under reduced motion) is a DESIGNED moment owned by ultraweb:navigation — the recorded exception to "header/nav render static," which continues to govern entrances (the header never animates in). Contract and build now agree.