feat: IMAP mail sync with thread-to-contact matching (PRD §6.1)

Real IMAP connection via imapflow library:
- Connects to IMAP server (IMAPFlow, TLS on port 993)
- Fetches recent messages (configurable limit, default 20)
- Extracts: from, fromEmail, subject, date, snippet (200 chars)
- Thread-to-contact matching (PRD §6.1):
  1. Match sender email against persons table
  2. If no person match, extract domain and match against company.website
  3. Returns matchedCompany + matchedPerson for each email
- Audit-logged (action: crm.mailsync:imap)
- Zod validated (host, port, user, password, folder, limit)
- 502 on IMAP connection failure with detail
- 400 on validation failure

Tested: invalid creds → 502 'IMAP connection failed', missing host → 400
This commit is contained in:
Z User committed 2026-10-27 22:50:50 +00:00
1 parent 7acc0c5451
commit e45b68bb8b
1089 files changed
+260614

No files matched your search

@@ -0,0 +1,736 @@
---
version: alpha
name: Vercel
description: "An inspired interpretation of Vercel's design language — a developer-platform brand whose surface is a stark black-and-ink duet on near-white canvas, broken at hero scale by a multi-color mesh gradient (cyan / blue / magenta / amber) that acts as the entire decorative system, paired with a custom geometric sans for headlines and a monospaced caption face for technical labels."
colors:
primary: "#171717"
on-primary: "#ffffff"
ink: "#171717"
body: "#4d4d4d"
mute: "#888888"
hairline: "#ebebeb"
hairline-strong: "#a1a1a1"
canvas: "#ffffff"
canvas-soft: "#fafafa"
canvas-soft-2: "#f5f5f5"
link: "#0070f3"
link-deep: "#0761d1"
link-bg-soft: "#d3e5ff"
success: "#0070f3"
error: "#ee0000"
error-soft: "#f7d4d6"
error-deep: "#c50000"
warning: "#f5a623"
warning-soft: "#ffefcf"
warning-deep: "#ab570a"
violet: "#7928ca"
violet-soft: "#d8ccf1"
violet-deep: "#4c2889"
cyan: "#50e3c2"
cyan-soft: "#aaffec"
cyan-deep: "#29bc9b"
highlight-pink: "#ff0080"
highlight-magenta: "#eb367f"
gradient-develop-start: "#007cf0"
gradient-develop-end: "#00dfd8"
gradient-preview-start: "#7928ca"
gradient-preview-end: "#ff0080"
gradient-ship-start: "#ff4d4d"
gradient-ship-end: "#f9cb28"
selection-bg: "#171717"
selection-fg: "#f2f2f2"
typography:
display-xl:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 48px
fontWeight: 600
lineHeight: 48px
letterSpacing: -2.4px
display-lg:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 32px
fontWeight: 600
lineHeight: 40px
letterSpacing: -1.28px
display-md:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 24px
fontWeight: 600
lineHeight: 32px
letterSpacing: -0.96px
display-sm:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 20px
fontWeight: 600
lineHeight: 28px
letterSpacing: -0.6px
body-lg:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 18px
fontWeight: 400
lineHeight: 28px
letterSpacing: 0px
body-md:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 16px
fontWeight: 400
lineHeight: 24px
body-md-strong:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 16px
fontWeight: 500
lineHeight: 24px
body-sm:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 14px
fontWeight: 400
lineHeight: 20px
letterSpacing: -0.28px
body-sm-strong:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 14px
fontWeight: 500
lineHeight: 20px
letterSpacing: -0.28px
caption:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 12px
fontWeight: 400
lineHeight: 16px
caption-mono:
fontFamily: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace
fontSize: 12px
fontWeight: 400
lineHeight: 16px
code:
fontFamily: Geist Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, monospace
fontSize: 13px
fontWeight: 400
lineHeight: 20px
button-md:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 14px
fontWeight: 500
lineHeight: 20px
button-lg:
fontFamily: Geist, Inter, system-ui, -apple-system, sans-serif
fontSize: 16px
fontWeight: 500
lineHeight: 24px
rounded:
none: 0px
xs: 4px
sm: 6px
md: 8px
lg: 12px
xl: 16px
pill-sm: 64px
pill: 100px
full: 9999px
spacing:
xxs: 4px
xs: 8px
sm: 12px
md: 16px
lg: 24px
xl: 32px
2xl: 40px
3xl: 48px
4xl: 64px
5xl: 96px
6xl: 128px
section: 192px
components:
nav-bar:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-sm}"
height: 64px
padding: "{spacing.sm} {spacing.lg}"
nav-link:
textColor: "{colors.body}"
typography: "{typography.body-sm}"
rounded: "{rounded.full}"
padding: "{spacing.xs} {spacing.sm}"
nav-cta-signup:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.body-sm-strong}"
rounded: "{rounded.sm}"
padding: "0px {spacing.xs}"
height: 28px
nav-cta-login:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-sm-strong}"
rounded: "{rounded.sm}"
padding: "0px {spacing.xs}"
height: 28px
nav-cta-ask-ai:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.hairline}"
typography: "{typography.body-sm-strong}"
rounded: "{rounded.sm}"
padding: "0px {spacing.xs}"
height: 28px
button-primary:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.button-lg}"
rounded: "{rounded.pill}"
padding: "0px {spacing.sm}"
button-secondary:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.button-lg}"
rounded: "{rounded.pill}"
padding: "0px {spacing.sm}"
button-primary-sm:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.button-md}"
rounded: "{rounded.pill}"
padding: "0px {spacing.xs}"
button-secondary-sm:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.button-md}"
rounded: "{rounded.pill}"
padding: "0px {spacing.xs}"
tab-ghost:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-sm}"
rounded: "{rounded.pill-sm}"
padding: "0px {spacing.md}"
icon-button-circular:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.hairline}"
rounded: "{rounded.full}"
card-marketing:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-md}"
rounded: "{rounded.md}"
padding: "{spacing.lg}"
card-marketing-large:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-md}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
card-soft:
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.ink}"
typography: "{typography.body-md}"
rounded: "{rounded.md}"
padding: "{spacing.lg}"
template-card:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-md}"
rounded: "{rounded.md}"
padding: "{spacing.md}"
code-editor-mockup:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.code}"
rounded: "{rounded.md}"
padding: "{spacing.lg}"
form-input:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.hairline}"
typography: "{typography.body-sm}"
rounded: "{rounded.sm}"
padding: "0px {spacing.sm}"
height: 40px
form-input-sm:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.hairline}"
typography: "{typography.body-sm}"
rounded: "{rounded.sm}"
padding: "0px {spacing.sm}"
height: 32px
form-input-lg:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
borderColor: "{colors.hairline}"
typography: "{typography.body-md}"
rounded: "{rounded.sm}"
padding: "0px {spacing.sm}"
height: 48px
badge-secondary:
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.body}"
typography: "{typography.caption}"
rounded: "{rounded.full}"
padding: "0px {spacing.xs}"
pricing-card:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.body-md}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
pricing-card-featured:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.body-md}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
logo-strip:
backgroundColor: "{colors.canvas}"
textColor: "{colors.body}"
typography: "{typography.body-sm}"
padding: "{spacing.lg} {spacing.xl}"
hero-band:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-xl}"
padding: "{spacing.4xl} {spacing.lg}"
feature-mesh-band:
backgroundColor: "{colors.canvas}"
textColor: "{colors.ink}"
typography: "{typography.display-lg}"
padding: "{spacing.5xl} {spacing.lg}"
showcase-band-light:
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.ink}"
typography: "{typography.display-lg}"
padding: "{spacing.5xl} {spacing.lg}"
showcase-band-dark:
backgroundColor: "{colors.primary}"
textColor: "{colors.on-primary}"
typography: "{typography.display-lg}"
padding: "{spacing.5xl} {spacing.lg}"
footer:
backgroundColor: "{colors.canvas}"
textColor: "{colors.body}"
typography: "{typography.body-sm}"
padding: "{spacing.4xl} {spacing.lg}"
link-inline:
textColor: "{colors.link}"
typography: "{typography.body-md}"
banner-marketing:
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.body}"
typography: "{typography.body-sm}"
rounded: "{rounded.full}"
padding: "{spacing.xs} {spacing.sm}"
# ─── Examples (illustrative) — auto-derived; resolve any TO_FILL markers below ───
ex-pricing-tier:
description: "Default tier card. Mirrors pricing-card chrome on canvas-soft surface with a hairline border."
backgroundColor: "{colors.canvas-soft}"
textColor: "{colors.ink}"
borderColor: "{colors.hairline}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
ex-pricing-tier-featured:
description: "Featured tier — polarity-flipped to ink primary with white text and white CTA."
backgroundColor: "{colors.ink}"
textColor: "{colors.on-primary}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
ex-product-selector:
description: "What's Included summary card — repurposed for the brand's GPU / inference / Pro feature tiers."
backgroundColor: "{colors.canvas-soft}"
rounded: "{rounded.md}"
padding: "{spacing.lg}"
ex-cart-drawer:
description: "Subscription summary — line items per add-on (NOT a literal e-commerce cart)."
backgroundColor: "{colors.canvas}"
rounded: "{rounded.md}"
padding: "{spacing.lg}"
item-divider: "{colors.hairline}"
ex-app-shell-row:
description: "Sidebar nav row. Active state uses brand primary as a left-edge indicator bar."
backgroundColor: "{colors.canvas}"
activeIndicator: "{colors.primary}"
rounded: "{rounded.sm}"
padding: "{spacing.xs} {spacing.sm}"
ex-data-table-cell:
description: "Mirrors the brand's table chrome. Header uses caption-mono uppercase mono; body uses body-sm."
headerBackground: "{colors.canvas-soft}"
headerTypography: "{typography.caption-mono}"
bodyTypography: "{typography.body-sm}"
cellPadding: "{spacing.xs} {spacing.sm}"
rowBorder: "{colors.hairline}"
ex-auth-form-card:
description: "Sign-in / sign-up card. Mirrors card-marketing-large chrome with form-input primitives inside."
backgroundColor: "{colors.canvas-soft}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
ex-modal-card:
description: "Modal dialog surface — same chrome as card-marketing-large with Level 5 modal shadow."
backgroundColor: "{colors.canvas}"
rounded: "{rounded.lg}"
padding: "{spacing.xl}"
ex-empty-state-card:
description: "Empty-state illustration frame. Generous padding on canvas-soft."
backgroundColor: "{colors.canvas-soft}"
rounded: "{rounded.lg}"
padding: "{spacing.3xl}"
captionTypography: "{typography.body-md}"
ex-toast:
description: "Toast notification surface — flat-cornered card-marketing chrome with Level 4 shadow."
backgroundColor: "{colors.canvas}"
rounded: "{rounded.md}"
padding: "{spacing.sm} {spacing.md}"
typography: "{typography.body-sm}"
---
## Overview
Vercel is a developer-platform brand — the page is a deployment dashboard's marketing surface, written for engineers who already know the syntax. It earns that posture with one of the cleanest stark systems on the web: near-white `{colors.canvas-soft}` body background, ink-near-black `{colors.ink}` text, a 200-step gray scale that gives every divider, border, and disabled state its own deliberate step. The only place the brand introduces colour at marketing scale is the multi-stop mesh gradient (`{colors.gradient-develop-start}` → `{colors.gradient-preview-end}` → `{colors.gradient-ship-start}` → cyan / magenta / amber) that floats in atmospheric backdrops, never miniaturised to a swatch. That gradient is the entire decoration system.
Type is the second decisive voice. The brand's own custom geometric sans (Geist) carries display, body, button — everything narrative — at weight 600 for display, 500 for buttons, 400 for body. A matching monospaced face (Geist Mono) carries technical labels: terminal mockups, code blocks, sometimes filename captions. Headlines are sentence-case with aggressive negative letter-spacing (`-2.4px` at 48 px hero) — the brand never letter-spaces positively, never goes uppercase outside of mono labels.
Surfaces use a four-step ladder: `{colors.canvas}` (pure white for cards), `{colors.canvas-soft}` 98% (the page body), `{colors.canvas-soft-2}` 95% (occasional inset region), `{colors.primary}` (the deep ink-near-black used as the polarity-flipped band when a section needs the dark mode treatment). Shadows are exceptionally subtle — every elevated card carries a stacked shadow built from `0px 1px 1px #00000005` + `0px 2px 2px #0000000a` + an inset border. Cards never float on heavy drop-shadow; they sit on the page held by hairline + soft glow.
**Key Characteristics:**
- A single black-ink primary CTA `{colors.primary}` carries every conversion target, paired with white-on-white `button-secondary` for the secondary action. The brand uses 100 px pill shape for marketing CTAs and a tight 6 px square shape for in-app nav buttons.
- A multi-stop mesh gradient (cyan-blue-magenta-amber) is the only decorative chrome — used at hero scale and inside feature-band atmospheric backdrops. It is the brand.
- Every section eyebrow and small label uses the monospace face `{typography.caption-mono}` or `{typography.code}`; everything else is in the geometric sans.
- Subtle stacked-shadow elevation — three offsets layered with 4-12 % black opacity — never a single heavy drop-shadow.
- A complete 100–1000 gray + blue + red + amber + green + teal + purple + pink colour scale exists as a system token set, but the marketing surface uses only the `100`, `1000`, and `700`-level tones; the rest stay in the design-system tokens for in-product surfaces.
- An "Active CPU" pricing rhythm: `pricing-card` lays out 3-up on the pricing page with `pricing-card-featured` (Pro tier) polarity-flipped to `{colors.primary}` against white-card siblings.
## Colors
### Brand & Accent
- **Ink** (`{colors.primary}` — `#171717`): The single primary CTA color. Black-near-pure ink that carries every Sign Up pill, every footer CTA, the dark-band polarity-flip. Used as text color throughout the page on light surfaces. (Resolved from `--ds-gray-1000`.)
- **Cyan** (`{colors.cyan}` — `#50e3c2`): A signature mint-cyan used in the brand gradient and inside Geist-system spotlight tokens. Visible inside the hero gradient stops.
- **Highlight Pink** (`{colors.highlight-pink}` — `#ff0080`): The brand's highlight magenta, used as the high-saturation stop in the preview-gradient pair.
- **Violet** (`{colors.violet}` — `#7928ca`): The deep purple used as the start of the preview-gradient and inside developer-console highlights.
- **Link Blue** (`{colors.link}` — `#0070f3`): The brand's primary link color and the legacy `--geist-success` semantic.
### Surface
- **Canvas** (`{colors.canvas}` — `#ffffff`): The pure-white card / dialog / modal surface.
- **Canvas Soft** (`{colors.canvas-soft}` — `#fafafa`): The default page background — 98 % white. Almost every section sits on this tone.
- **Canvas Soft 2** (`{colors.canvas-soft-2}` — `#f5f5f5`): A slightly deeper inset surface for "code editor inner background", template-card hover states, and dropdown menus.
- **Hairline** (`{colors.hairline}` — `#ebebeb`): 1 px dividers — table rows, card borders, input borders.
- **Hairline Strong** (`{colors.hairline-strong}` — `#a1a1a1`): The 500-level gray, used as the slightly-stronger divider on light bands and as the deemphasised text color.
### Text
- **Ink** (`{colors.ink}` — `#171717`): Every heading and body paragraph on light surfaces.
- **Body** (`{colors.body}` — `#4d4d4d`): Secondary text — sub-headings, body captions, nav-link inactive text, footer column body.
- **Mute** (`{colors.mute}` — `#888888`): Lowest-priority text — placeholder text, fine print, low-key labels.
- **On Primary** (`{colors.on-primary}` — `#ffffff`): All text on `{colors.primary}` surfaces.
### Semantic
- **Success / Link** (`{colors.success}` — `#0070f3`): The brand's legacy success indicator doubles as the primary link color. Visible underline-on-hover for inline body links.
- **Link Deep** (`{colors.link-deep}` — `#0761d1`): The pressed / visited tone for inline links.
- **Link Bg Soft** (`{colors.link-bg-soft}` — `#d3e5ff`): Soft pastel blue fill for "what's new" pill banners and informational badges.
- **Error** (`{colors.error}` — `#ee0000`): Validation red for destructive actions and form errors.
- **Error Soft** (`{colors.error-soft}` — `#f7d4d6`): Soft pastel red for destructive-state backgrounds.
- **Error Deep** (`{colors.error-deep}` — `#c50000`): Pressed / deep destructive state.
- **Warning** (`{colors.warning}` — `#f5a623`): Caution / pending status indicator.
- **Warning Soft** (`{colors.warning-soft}` — `#ffefcf`) / **Warning Deep** (`{colors.warning-deep}` — `#ab570a`): Background + pressed variants.
### Brand Gradient
The brand's signature decoration is a three-pair gradient stack:
- **Develop** (`{colors.gradient-develop-start}` `#007cf0` → `{colors.gradient-develop-end}` `#00dfd8`) — the blue-to-teal pair used to mark the "deploy" / "develop" rhythm.
- **Preview** (`{colors.gradient-preview-start}` `#7928ca` → `{colors.gradient-preview-end}` `#ff0080`) — the violet-to-pink pair used for "preview" surfaces.
- **Ship** (`{colors.gradient-ship-start}` `#ff4d4d` → `{colors.gradient-ship-end}` `#f9cb28`) — the coral-to-amber pair used for "ship" surfaces.
The three pairs collapse into a single multi-color mesh gradient when used as the hero atmospheric backdrop. Treat the gradient as one unified object — do not crop down to a single colour, do not reorder the stops, and do not miniaturise. Used at hero scale only.
## Typography
### Font Family
Two custom faces carry the entire system:
1. **A custom geometric sans** (extracted as `Geist`) for every display, body, button, link, and label. Weights 400 / 500 / 600 are the working set; the face never appears in 700 or heavier. Display sizes are tracked aggressively negative (`-2.4 px` at 48 px hero, `-1.28 px` at 32 px section); body stays at neutral or slightly-negative tracking.
2. **A custom monospaced face** (extracted as `Geist Mono`) for terminal mockups, code blocks, and small mono-caption labels — anything that wants to signal "technical." Weight 400 only at 12 – 13 px. Tracking neutral.
A condensed display sans (`Space Grotesk`) is loaded as a third face for occasional editorial moments but does not render as the primary face anywhere in the captured surfaces.
### Hierarchy
| Token | Size | Weight | Line Height | Letter Spacing | Use |
|---|---|---|---|---|---|
| `{typography.display-xl}` | 48px | 600 | 48px | -2.4px | Hero headline ("Build and deploy on the AI Cloud."). |
| `{typography.display-lg}` | 32px | 600 | 40px | -1.28px | Section headlines ("Your frontend, delivered.", "A compute model for all workloads."). |
| `{typography.display-md}` | 24px | 600 | 32px | -0.96px | Card-cluster headlines, pricing-tier names. |
| `{typography.display-sm}` | 20px | 600 | 28px | -0.6px | Inline display micro-headings. |
| `{typography.body-lg}` | 18px | 400 | 28px | 0 | Lead paragraphs under section headlines. |
| `{typography.body-md}` | 16px | 400 | 24px | 0 | Default body paragraph. |
| `{typography.body-md-strong}` | 16px | 500 | 24px | 0 | Bolded inline body. |
| `{typography.body-sm}` | 14px | 400 | 20px | -0.28px | Secondary body, nav-link text, button-md labels. |
| `{typography.body-sm-strong}` | 14px | 500 | 20px | -0.28px | Nav CTA labels, table-row emphasis. |
| `{typography.caption}` | 12px | 400 | 16px | 0 | Footer secondary lines, badge labels. |
| `{typography.caption-mono}` | 12px | 400 | 16px | 0 | Section eyebrows and label captions that want a technical voice. |
| `{typography.code}` | 13px | 400 | 20px | 0 | Inline code, terminal mockups, command snippets. |
| `{typography.button-md}` | 14px | 500 | 20px | 0 | Small / nav-scale button labels. |
| `{typography.button-lg}` | 16px | 500 | 24px | 0 | Marketing-scale pill button labels. |
### Principles
- **Negative tracking is part of the voice.** Display sizes use aggressive `-2.4` to `-0.6` px tracking. Reverting to default tracking breaks the brand.
- **Sentence-case headlines, period-terminated.** Headlines like "Build and deploy on the AI Cloud." end with a deliberate period — that punctuation is part of the brand's voice.
- **Mono for the technical layer only.** Section eyebrows, code blocks, terminal mockups. Body paragraphs never set in mono.
- **Weight 600 is the display ceiling.** The geometric sans never appears at 700 / 800. The brand reads as a calmer system because of this.
### Note on Font Substitutes
The two primary faces are proprietary (custom-cut for the brand). Open-source substitutes:
- **Geometric sans** — *Inter* (400 / 500 / 600) is the closest stylistic match; `font-feature-settings: "ss01", "ss02"` enables the geometric alternates. *Satoshi* is a passable second choice.
- **Monospace** — *JetBrains Mono* (400) at 12 – 13 px matches the technical voice. *IBM Plex Mono* is the second-best option.
## Layout
### Spacing System
- **Base unit**: 4 px. The brand's `--geist-space` token is exactly 4 px and every captured value is a multiple of 4.
- **Tokens**: `{spacing.xxs}` 4 px · `{spacing.xs}` 8 px · `{spacing.sm}` 12 px · `{spacing.md}` 16 px · `{spacing.lg}` 24 px · `{spacing.xl}` 32 px · `{spacing.2xl}` 40 px · `{spacing.3xl}` 48 px · `{spacing.4xl}` 64 px · `{spacing.5xl}` 96 px · `{spacing.6xl}` 128 px · `{spacing.section}` 192 px.
- **Section padding**: marketing bands use `{spacing.4xl}` to `{spacing.5xl}` top/bottom. Hero bands stretch to `{spacing.section}` to give the mesh gradient room to breathe.
- **Card interior padding**: marketing cards sit at `{spacing.lg}` to `{spacing.xl}`; template-grid cards stay tighter at `{spacing.md}` because they sit in a denser grid.
- **Inline gap**: button rows, nav rows, and chip rows use `{spacing.sm}` to `{spacing.md}` between siblings. The brand's `--geist-gap` is exactly 24 px.
### Grid & Container
- **Max width**: ~1400 px (`--ds-page-width`); the legacy `--geist-page-width` is 1200 px and still appears on some marketing surfaces. Content centres with horizontal gutters of `{spacing.lg}` 24 px on desktop, `{spacing.md}` 16 px on mobile.
- **Column patterns**:
- Three-feature row: 3-up at desktop, 1-up at mobile (rows like "Web Apps / Composable Commerce / Multi-tenant Platforms").
- Tab pill row: 5-up centred row of `tab-ghost` pills.
- Template-grid cluster: 5-up at desktop, scaling to 1-up at mobile.
- Pricing tier grid: 3-up at desktop with the middle tier polarity-flipped.
- Logo strip: ~5 logos wide, single row.
### Whitespace Philosophy
The mesh gradient does most of the heavy decorative lifting; whitespace separates the bands. Section spacing is generous — `{spacing.4xl}` to `{spacing.5xl}` between bands lets the gradient breathe. Inside a card, the headline/paragraph stack is tight (`{spacing.xs}` 8 px gap), then a wider gap before the CTA cluster. The page reads as engineered — large gaps + tight interior, never the other way around.
### Responsive Strategy
#### Breakpoints
| Name | Width | Key Changes |
|---|---|---|
| Mobile | < 600px | Hero stacks; nav collapses to hamburger; 3-up feature grids drop to 1-up; tab pill row enables horizontal scroll. |
| Tablet | 600–959px | 3-up grids drop to 2-up; nav still horizontal. |
| Desktop | 960–1199px | Full 3-up grids; pricing 3-up. |
| Wide | 1200–1399px | Container caps at 1400 px content width. |
| Ultra-wide | ≥ 1400px | Content stays centred at 1400 px; bands stretch edge-to-edge in colour but content holds the max-width. |
#### Touch Targets
The `button-primary` pill renders at ~32 px tall in nav and ~48 px tall in marketing contexts. Marketing CTAs comfortably meet WCAG AAA at all breakpoints; nav buttons inflate touch area through `{spacing.xs}` padding on mobile to meet the 44 × 44 px floor.
#### Collapsing Strategy
- **Nav**: full link row + Ask AI / Log In / Sign Up pills at desktop. Collapses to logo + hamburger at mobile with the menu opening as a full-overlay.
- **Hero**: mesh gradient stays centred; headline + body stack vertically at all breakpoints (the brand doesn't use a split-hero pattern).
- **Three-feature row**: 3-up → 2-up → 1-up at the breakpoints above; cards keep their `{rounded.md}` 8 px shape across all viewports.
- **Pricing card grid**: 3-up at desktop, vertical stack at mobile with `pricing-card-featured` always sitting in the middle.
- **Template grid**: 5-up → 3-up → 2-up → 1-up. Each `template-card` keeps its 16:9 aspect on the image.
#### Image Behavior
- **Mesh gradient**: rendered as inline SVG or canvas-painted gradient; scales fluidly with the hero container; never crops, never tiles.
- **Customer logos**: rendered as monochrome SVGs in the logo strip; consistent 24 px height.
- **Code editor mockup**: dark `{colors.primary}` rectangle with mono text rendered inside; treated as an image at the layout level.
- **Template thumbnails**: 16:9 landscape inside `{rounded.md}` card chrome; lazy-loaded; consistent grayscale palette in the placeholder state.
## Elevation & Depth
| Level | Treatment | Use |
|---|---|---|
| Level 0 — Flat | No shadow, no border. | Full-bleed hero bands and the polarity-flipped dark sections. |
| Level 1 — Inset Hairline | `0 0 0 1px #00000014` inset 1 px border. | Default card chrome — the brand's universal "you can see this card" cue. |
| Level 2 — Subtle Drop | `0px 1px 1px #00000005, 0px 2px 2px #0000000a` plus inset hairline. | Slightly elevated cards (template-grid, marketing-card). |
| Level 3 — Soft Stack | `0px 2px 2px #0000000a, 0px 8px 8px -8px #0000000a` plus inset hairline. | The "medium" elevation — feature-grid cards. |
| Level 4 — Float Stack | `0px 2px 2px #0000000a, 0px 8px 16px -4px #0000000a` plus inset hairline. | "Large" elevation — pricing cards, callout panels. |
| Level 5 — Modal | `0px 1px 1px #00000005, 0px 8px 16px -4px #0000000a, 0px 24px 32px -8px #0000000f` plus inset hairline. | Modal / dialog surfaces and dropdown menus. |
The brand uses STACKED shadows — multiple small offsets layered to fake natural light — never a single 8-px-blur generic drop. Inset hairline rings are always added so the card edge stays crisp.
### Decorative Depth
- **Mesh gradient as atmospheric depth**: the hero's multi-stop gradient is the brand's only "atmospheric" effect — applied as a flat 2-D backdrop rather than a 3-D illustration.
- **Polarity-flipped dark band as section-depth**: switching the surface from `{colors.canvas-soft}` to `{colors.primary}` (the deep ink) is the brand's chief depth cue between bands.
- **Inset-shadow + drop-shadow combo**: the cards' combination of an inset 1 px ring and a multi-stop drop produces a "card sits on the page" effect without ever feeling material-heavy.
## Shapes
### Border Radius Scale
| Token | Value | Use |
|---|---|---|
| `{rounded.none}` | 0px | Full-bleed hero / footer bands. |
| `{rounded.xs}` | 4px | Tightest inline pill — the `nav-cta-signup` 6-px-radius button (mapped to `xs/sm`). |
| `{rounded.sm}` | 6px | The brand's `--geist-radius` token — base UI radius for in-app buttons, form inputs, dropdown menus. |
| `{rounded.md}` | 8px | The brand's `--geist-marketing-radius` token — feature cards, template cards. |
| `{rounded.lg}` | 12px | Slightly larger card chrome (pricing-card variants). |
| `{rounded.xl}` | 16px | Largest card chrome — when a card hosts a hero image cap. |
| `{rounded.pill-sm}` | 64px | Tab-ghost pills inside the "AI Apps / Web Apps / Ecommerce / Marketing / Platforms" row. |
| `{rounded.pill}` | 100px | The marketing CTA pill — `button-primary`, `button-secondary`, "Start Deploying" pill. |
| `{rounded.full}` | 9999px | Icon-button circular containers, nav-link ghost pills. |
### Photography Geometry
- **Mesh gradient**: full-bleed 2-D atmospheric backdrop, never cropped to a frame; treated as the page's wallpaper.
- **Customer logos**: monochrome SVG, consistent 24 px height in a flex row.
- **Code editor mockup**: 16:10 dark rectangle, `{rounded.md}` corners.
- **Template thumbnails**: 16:9 landscape inside `{rounded.md}` chrome.
- **Showcase imagery**: 2:1 or 16:9 inside `{rounded.lg}` to `{rounded.xl}` chrome with a stacked shadow.
## Components
### Buttons
**`button-primary`** — the canonical 100-px-radius black pill, marketing scale.
- Background `{colors.primary}`, text `{colors.on-primary}`, label set in `{typography.button-lg}`, padding `0px {spacing.sm}` 12 px, shape `{rounded.pill}` 100 px. Renders ~48 px tall when paired with the marketing flex layout.
**`button-secondary`** — the white pill paired with the black primary inside marketing bands.
- Background `{colors.canvas}`, text `{colors.ink}`, same typography + padding as `button-primary`, shape `{rounded.pill}`.
**`button-primary-sm`** — the smaller-scale primary pill used inside nav and pricing-card CTAs.
- Background `{colors.primary}`, text `{colors.on-primary}`, label set in `{typography.button-md}` (14 px / 500), shape `{rounded.pill}`.
**`button-secondary-sm`** — the smaller-scale white pill paired with `button-primary-sm`.
- Background `{colors.canvas}`, text `{colors.ink}`, same typography + shape as `button-primary-sm`.
**`tab-ghost`** — the centred-row tab pill ("AI Apps / Web Apps / Ecommerce / Marketing / Platforms").
- Background `{colors.canvas}`, text `{colors.ink}`, label set in `{typography.body-sm}`, padding `0px {spacing.md}`, shape `{rounded.pill-sm}` 64 px.
**`icon-button-circular`** — the circular icon container (often a "?" or arrow inside).
- Background `{colors.canvas}`, dark icon, 1 px solid hairline border, shape `{rounded.full}`.
**Nav CTAs:**
**`nav-cta-signup`** — the small black "Sign Up" button in the nav row.
- Background `{colors.primary}`, text `{colors.on-primary}`, label `{typography.body-sm-strong}`, padding `0px {spacing.xs}`, height 28 px, shape `{rounded.sm}` 6 px (the brand's `--geist-radius`).
**`nav-cta-login`** — the white "Log In" button in the nav.
- Background `{colors.canvas}`, text `{colors.ink}`, same typography / height / shape as `nav-cta-signup`.
**`nav-cta-ask-ai`** — the small "Ask AI" button with a faint border.
- Background `{colors.canvas}`, text `{colors.ink}`, 1 px solid `{colors.hairline}` border (extracted as `0px solid rgb(235, 235, 235)`), same typography / height / shape.
### Cards & Containers
**`card-marketing`** — the canonical marketing feature card (3-up section cards).
- Background `{colors.canvas}`, text `{colors.ink}`, padding `{spacing.lg}` 24 px, shape `{rounded.md}` 8 px (the `--geist-marketing-radius`). Carries Level 3 soft-stack shadow.
**`card-marketing-large`** — the larger marketing card used for "compute model" / "AI Gateway" callouts.
- Background `{colors.canvas}`, text `{colors.ink}`, padding `{spacing.xl}`, shape `{rounded.lg}` 12 px. Carries Level 4 float-stack shadow.
**`card-soft`** — the soft-tinted card used inside cluster groups (lighter than canvas-soft).
- Background `{colors.canvas-soft}`, text `{colors.ink}`, padding `{spacing.lg}`, shape `{rounded.md}`.
**`template-card`** — the deploy-template card in the "Deploy your first app" grid.
- Background `{colors.canvas}`, text `{colors.ink}`, padding `{spacing.md}` 16 px, shape `{rounded.md}` 8 px. Hosts a 16:9 thumbnail at the top.
**`code-editor-mockup`** — the dark code-preview surface inside marketing bands.
- Background `{colors.primary}`, text `{colors.on-primary}`, body in `{typography.code}` (13 px / Geist Mono), padding `{spacing.lg}` 24 px, shape `{rounded.md}` 8 px.
**`pricing-card`** — the default pricing-tier card.
- Background `{colors.canvas}`, text `{colors.ink}`, padding `{spacing.xl}` 32 px, shape `{rounded.lg}` 12 px. Inside: tier name in `{typography.display-md}`, price in `{typography.display-xl}`, feature list in `{typography.body-md}` rows, CTA at the bottom.
**`pricing-card-featured`** — the polarity-flipped "Pro" tier card.
- Background `{colors.primary}`, text `{colors.on-primary}`, same shape + padding as `pricing-card`. CTA inverts to `button-secondary-sm` (white pill on black card).
### Inputs & Forms
**`form-input`** — the canonical text input.
- Background `{colors.canvas}`, text `{colors.ink}`, 1 px solid `{colors.hairline}` border, body in `{typography.body-sm}` (14 px), padding `0px {spacing.sm}`, height 40 px (the brand's `--geist-form-height`), shape `{rounded.sm}` 6 px.
**`form-input-sm`** — small-height variant (32 px tall) for tight forms.
- Same as `form-input` but height 32 px (the `--geist-form-small-height`).
**`form-input-lg`** — large-height variant (48 px tall) for hero CTAs.
- Same as `form-input` but height 48 px (the `--geist-form-large-height`); body in `{typography.body-md}` 16 px.
### Navigation
**`nav-bar`** — the sticky top nav.
- Background `{colors.canvas}`, text `{colors.ink}`, height 64 px (the brand's `--header-height`), padding `{spacing.sm} {spacing.lg}`. Layout: logo left, link row centre, "Ask AI / Log In / Sign Up" cluster right.
**`nav-link`** — the centred link row inside `nav-bar`.
- Text `{colors.body}`, set in `{typography.body-sm}`, padding `{spacing.xs} {spacing.sm}`, shape `{rounded.full}` (ghost pill — visible only on hover or active, but the radius is documented).
**`footer`** — the bottom 4-column nav.
- Background `{colors.canvas}`, text `{colors.body}`, padding `{spacing.4xl} {spacing.lg}`. Eyebrow column labels in `{typography.caption-mono}` (uppercase mono effect); link rows in `{typography.body-sm}`.
### Signature Components
**`hero-band`** — the white hero with the mesh gradient backdrop.
- Background `{colors.canvas}` (or `{colors.canvas-soft}` on some surfaces), text `{colors.ink}`, padding `{spacing.4xl} {spacing.lg}`. Inside: a small mono badge above the headline, the headline in `{typography.display-xl}` (sentence-case, period-terminated), a body lead in `{typography.body-lg}`, then a CTA row with `button-primary` + `button-secondary`. The mesh gradient sits behind, scaled to occupy roughly the top half of the band.
**`feature-mesh-band`** — the secondary section that hosts a mesh-gradient atmospheric backdrop with feature copy on top.
- Background `{colors.canvas}`, text `{colors.ink}`, padding `{spacing.5xl} {spacing.lg}`. Section headline in `{typography.display-lg}`; supporting body in `{typography.body-md}`.
**`showcase-band-light`** — a soft-canvas section ("Deploy your first app in seconds").
- Background `{colors.canvas-soft}`, text `{colors.ink}`, padding `{spacing.5xl} {spacing.lg}`.
**`showcase-band-dark`** — the polarity-flipped dark band ("A compute model for all workloads").
- Background `{colors.primary}`, text `{colors.on-primary}`, padding `{spacing.5xl} {spacing.lg}`. Section headline in `{typography.display-lg}` (white on black). Often contains a `code-editor-mockup` flush with the band.
**`logo-strip`** — the customer-logo wrapping row near the top of the page.
- Background `{colors.canvas}`, text `{colors.body}`, padding `{spacing.lg} {spacing.xl}`. Logos rendered as monochrome SVGs at consistent height.
**`badge-secondary`** — the small inline metadata pill ("New", "Beta", "Live").
- Background `{colors.canvas-soft}`, text `{colors.body}`, body in `{typography.caption}`, padding `0px {spacing.xs}`, shape `{rounded.full}`.
**`banner-marketing`** — the "Introducing X" announcement pill at the top of pages.
- Background `{colors.canvas-soft}`, text `{colors.body}`, body in `{typography.body-sm}`, padding `{spacing.xs} {spacing.sm}`, shape `{rounded.full}`.
**`link-inline`** — body-copy inline links.
- Text `{colors.link}` (`#0070f3`), body in `{typography.body-md}`, underlined.
### Examples (illustrative)
> Auto-derived kit-mirror demonstration surfaces (`scripts/derive-examples-block.mjs`). Each `ex-*` entry references brand-native primitives so downstream consumers (`/preview-design`, `/generate-kit`) re-skin the same 10 surfaces consistently. `TO_FILL` markers indicate missing primitives — resolve in the LLM judgment pass.
**`ex-pricing-tier`** — Default Pricing tier card. Re-uses feature-card chrome with brand canvas-soft surface.
- Properties: `backgroundColor`, `textColor`, `borderColor`, `rounded`, `padding`
**`ex-pricing-tier-featured`** — Featured/highlighted tier — polarity-flipped surface (dark fill + light text in light mode, light fill + dark text in dark mode).
- Properties: `backgroundColor`, `textColor`, `rounded`, `padding`
**`ex-product-selector`** — What's Included summary card — re-purposed for SaaS / B2B verticals (NOT a literal product gallery).
- Properties: `backgroundColor`, `rounded`, `padding`
**`ex-cart-drawer`** — Subscription summary — re-purposed for SaaS / B2B (line items per add-on, not literal cart).
- Properties: `backgroundColor`, `rounded`, `padding`, `item-divider`
**`ex-app-shell-row`** — Sidebar nav row inside the App Shell example. Active state uses brand primary as the indicator.
- Properties: `backgroundColor`, `activeIndicator`, `rounded`, `padding`
**`ex-data-table-cell`** — Default data-table th + td chrome. Header uses mono-caps eyebrow typography; body uses body-sm.
- Properties: `headerBackground`, `headerTypography`, `bodyTypography`, `cellPadding`, `rowBorder`
**`ex-auth-form-card`** — Sign-in / sign-up card. Re-uses feature-card chrome with text-input primitives inside.
- Properties: `backgroundColor`, `rounded`, `padding`
**`ex-modal-card`** — Modal dialog surface — same chrome as feature-card with elevated shadow.
- Properties: `backgroundColor`, `rounded`, `padding`
**`ex-empty-state-card`** — Empty-state illustration frame.
- Properties: `backgroundColor`, `rounded`, `padding`, `captionTypography`
**`ex-toast`** — Toast notification surface — feature-card shape + medium shadow.
- Properties: `backgroundColor`, `rounded`, `padding`, `typography`
## Do's and Don'ts
### Do
- Reserve `{colors.primary}` (`#171717`) for primary CTAs across the page. Black ink IS the conversion target.
- Use `{rounded.pill}` 100 px for every marketing-scale CTA and `{rounded.sm}` 6 px for nav-scale buttons. The two pill scales coexist deliberately.
- Set every headline in `{typography.display-*}` weight 600, sentence-case, often period-terminated. Aggressive negative tracking is part of the voice.
- Use the brand mesh gradient as atmospheric decoration at hero scale only — never miniaturise it to an icon, never reduce to a single colour.
- Layer stacked shadows (multiple small offsets with inset hairline) rather than single heavy drops. The brand's elevation is calmer than Material.
- Cycle page surfaces in `{colors.canvas-soft}` → `{colors.canvas}` → `{colors.primary}` polarity-flipped bands; the dark band IS the depth cue.
- Set every code block and technical eyebrow in `{typography.code}` / `{typography.caption-mono}`. Mono is the voice of the platform.
### Don't
- Don't introduce a sixth accent colour. The brand operates with ink + gray + the four-pair gradient palette; new accents flatten the voice.
- Don't render headlines in all-caps. Sentence-case + negative tracking is non-negotiable.
- Don't drop a single heavy drop-shadow on cards. The brand's elevation is built from stacked small offsets + inset hairline rings.
- Don't render the brand gradient at icon scale or in a single-colour reduced form. The gradient lives at hero scale only.
- Don't promote the geometric sans to weight 700. The brand's display ceiling is 600.
- Don't pair the marketing 100-px pill CTA shape with the 6-px nav radius on the same screen — pick a scale and stay there.
- Don't set body paragraphs in the mono face. The mono is for code + technical labels only.
@@ -0,0 +1,5 @@
# Vercel Inspired Design System
Design system details have been moved to: https://getdesign.md/vercel/design-md
You can also view previews, dark mode examples, and download options on getdesign.md.
@@ -0,0 +1,839 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Vercel — reference components</title>
<meta
name="description"
content="Reference fixture for design-systems/vercel. Every visible
value comes from tokens.css; the page itself follows Vercel's
rules — near-white canvas, near-black text, blue reserved for
the chromatic moments, shadow-as-border instead of CSS border,
Geist with tight negative tracking on display."
/>
<style>
/* :root paste — sourced verbatim from design-systems/vercel/tokens.css. */
:root {
--bg: #ffffff;
--surface: #ffffff;
--surface-warm: var(--surface);
--fg: #171717;
--fg-2: #4d4d4d;
--muted: #666666;
--meta: #808080;
--border: rgba(0, 0, 0, 0.08);
--border-soft: rgba(0, 0, 0, 0.04);
--accent: #0070f3;
--accent-on: #ffffff;
--accent-hover: color-mix(in oklab, var(--accent), black 8%);
--accent-active: color-mix(in oklab, var(--accent), black 14%);
--success: #16a34a;
--warn: #eab308;
--danger: #dc2626;
--font-display: "Geist", "Geist Sans", -apple-system, "Segoe UI", Arial, sans-serif;
--font-body: "Geist", "Geist Sans", -apple-system, "Segoe UI", Arial, sans-serif;
--font-mono: "Geist Mono", ui-monospace, "SF Mono", "Roboto Mono", Menlo, Monaco, "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace;
--text-xs: 12px;
--text-sm: 14px;
--text-base: 16px;
--text-lg: 20px;
--text-xl: 24px;
--text-2xl: 32px;
--text-3xl: 40px;
--text-4xl: 48px;
--leading-body: 1.5;
--leading-tight: 1.1;
--tracking-display: -0.05em;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-12: 48px;
--section-y-desktop: 96px;
--section-y-tablet: 64px;
--section-y-phone: 48px;
--radius-sm: 6px;
--radius-md: 8px;
--radius-lg: 12px;
--radius-pill: 9999px;
--elev-flat: none;
--elev-ring: 0 0 0 1px var(--border);
--elev-raised:
0 0 0 1px rgba(0, 0, 0, 0.08),
0 2px 2px rgba(0, 0, 0, 0.04),
0 8px 8px -8px rgba(0, 0, 0, 0.04),
0 0 0 1px #fafafa;
--focus-ring: 0 0 0 2px var(--accent);
--motion-fast: 150ms;
--motion-base: 200ms;
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
--container-max: 1200px;
--container-gutter-desktop: 24px;
--container-gutter-tablet: 16px;
--container-gutter-phone: 12px;
}
/* ─── Reset (minimal) ─────────────────────────────────────── */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
background: var(--bg);
color: var(--fg);
font-family: var(--font-body);
font-size: var(--text-base);
line-height: var(--leading-body);
font-weight: 400;
/* OpenType ligatures globally — DESIGN.md §3: "Every Geist
text element enables `liga`. Ligatures aren't decorative —
they're structural." */
font-feature-settings: "liga" 1;
-webkit-font-smoothing: antialiased;
text-rendering: optimizeLegibility;
}
/* ─── Layout primitives ─────────────────────────────────── */
.container {
max-width: var(--container-max);
margin-inline: auto;
padding-inline: var(--container-gutter-desktop);
}
section {
padding-block: var(--section-y-desktop);
}
section + section {
/* DESIGN.md §5: full-dark divider between major sections —
a "1px solid #171717" line. Modeled as a single-pixel top
border via the foreground token so the brand voice
(engineered hairline, no fade) survives token rebinding. */
border-top: 1px solid var(--fg);
}
@media (max-width: 1023px) {
.container { padding-inline: var(--container-gutter-tablet); }
section { padding-block: var(--section-y-tablet); }
}
@media (max-width: 639px) {
.container { padding-inline: var(--container-gutter-phone); }
section { padding-block: var(--section-y-phone); }
}
/* ─── Typography ────────────────────────────────────────────
* The Geist principle: hierarchy comes from size + tracking,
* not weight. Three weights only — 400 (read), 500 (interact),
* 600 (announce). Display sizes use the negative em tracking
* from `--tracking-display`; smaller scales relax toward 0. */
h1, h2, h3, h4 {
font-family: var(--font-display);
line-height: var(--leading-tight);
margin: 0;
color: var(--fg);
}
h1 {
font-size: var(--text-4xl);
font-weight: 600;
letter-spacing: var(--tracking-display);
}
h2 {
font-size: var(--text-3xl);
font-weight: 600;
/* 40px Section Heading: line-height 1.20 per DESIGN.md §Typography.
Overrides the shared 1.10 (--leading-tight) set on h1/h2/h3 above. */
line-height: 1.20;
letter-spacing: var(--tracking-display);
}
h3 {
font-size: var(--text-xl);
font-weight: 600;
/* 24px Card Title: line-height 1.33 per DESIGN.md §Typography.
Overrides the shared 1.10 (--leading-tight) set on h1/h2/h3 above. */
line-height: 1.33;
/* Card title tracking from DESIGN.md §3: -0.96px at 24px ≈ -0.04em */
letter-spacing: -0.04em;
}
h4 {
font-size: var(--text-lg);
font-weight: 600;
letter-spacing: -0.02em;
}
p { margin: 0; }
.lede {
font-size: var(--text-lg);
line-height: 1.6;
color: var(--fg-2);
}
.body-muted { color: var(--fg-2); }
.body-meta { color: var(--muted); font-size: var(--text-sm); }
.body-sm { font-size: var(--text-sm); }
/* Eyebrow uses Geist Mono uppercase — DESIGN.md §3: "Geist
Mono in uppercase with tnum or liga serves as the developer
console voice — compact technical labels that connect the
marketing site to the product." */
.eyebrow {
font-family: var(--font-mono);
font-size: var(--text-xs);
font-weight: 500;
line-height: 1;
color: var(--muted);
text-transform: uppercase;
letter-spacing: 0.08em;
}
.stack-3 > * + * { margin-block-start: var(--space-3); }
.stack-4 > * + * { margin-block-start: var(--space-4); }
.stack-6 > * + * { margin-block-start: var(--space-6); }
/* ─── Buttons ───────────────────────────────────────────────
* Vercel's primary CTA is BLACK, not the accent color — the
* brand voice is monochrome-with-blue-restraint, so the
* primary button uses `--fg` as background and the accent
* stays reserved for links and focus. Secondary buttons use
* the shadow-as-border technique (`box-shadow` edge) instead
* of a CSS border so the rectangle aligns with the fill at
* any radius. */
.btn {
display: inline-flex;
align-items: center;
gap: var(--space-2);
padding: 8px 16px;
border: none;
border-radius: var(--radius-sm);
font-family: var(--font-display);
font-size: var(--text-sm);
font-weight: 500;
line-height: 1.43;
cursor: pointer;
text-decoration: none;
background: transparent;
color: inherit;
transition:
background-color var(--motion-fast) var(--ease-standard),
color var(--motion-fast) var(--ease-standard),
box-shadow var(--motion-fast) var(--ease-standard);
}
.btn:focus-visible {
outline: none;
box-shadow: var(--focus-ring);
}
.btn-primary {
background: var(--fg);
color: var(--bg);
}
.btn-primary:hover {
background: color-mix(in oklab, var(--fg), white 14%);
}
.btn-primary:focus-visible {
/* Layered: keep the dark fill, lay the accent ring outside. */
box-shadow: var(--focus-ring);
}
.btn-secondary {
background: var(--surface);
color: var(--fg);
box-shadow: 0 0 0 1px var(--border);
}
.btn-secondary:hover {
background: color-mix(in oklab, var(--bg), var(--fg) 2%);
box-shadow: 0 0 0 1px color-mix(in oklab, var(--fg), transparent 84%);
}
.btn-ghost {
background: transparent;
color: var(--fg-2);
padding-inline: var(--space-3);
}
.btn-ghost:hover {
color: var(--fg);
background: color-mix(in oklab, var(--bg), var(--fg) 2%);
}
/* ─── Inputs ────────────────────────────────────────────────
* Border via shadow technique — DESIGN.md §4: "Border: via
* shadow technique, not traditional border." On focus the
* shadow ring intensifies into the 2px accent ring. */
.field {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.field label {
font-size: var(--text-sm);
font-weight: 500;
color: var(--fg);
}
.field input {
padding: 8px 12px;
border: none;
border-radius: var(--radius-sm);
background: var(--surface);
color: var(--fg);
font-family: inherit;
font-size: var(--text-sm);
line-height: 1.43;
outline: none;
box-shadow: 0 0 0 1px var(--border);
transition: box-shadow var(--motion-fast) var(--ease-standard);
}
.field input::placeholder { color: var(--meta); }
.field input:hover { box-shadow: 0 0 0 1px color-mix(in oklab, var(--fg), transparent 84%); }
.field input:focus-visible {
box-shadow: var(--focus-ring);
}
.field-help {
font-size: var(--text-xs);
color: var(--muted);
}
/* ─── Cards ─────────────────────────────────────────────────
* The multi-layer shadow card — DESIGN.md §6 Level 3 — uses
* `--elev-raised` directly. No `border:` rule; the shadow
* stack carries every edge AND the inner `#fafafa` glow.
* Image cards (`.card-image`) use a real 1px border because
* the top corners clip the image and need a clean edge. */
.card {
background: var(--surface);
border-radius: var(--radius-md);
padding: var(--space-6);
display: flex;
flex-direction: column;
gap: var(--space-3);
box-shadow: var(--elev-raised);
transition: box-shadow var(--motion-base) var(--ease-standard);
}
.card:hover {
/* Layered: keep the elev-raised stack, lift the ring tier. */
box-shadow:
0 0 0 1px color-mix(in oklab, var(--fg), transparent 84%),
0 4px 12px color-mix(in oklab, var(--fg), transparent 94%),
0 12px 24px -12px color-mix(in oklab, var(--fg), transparent 94%),
0 0 0 1px color-mix(in oklab, var(--bg), var(--fg) 2%);
}
.card-image {
background: var(--surface);
border: 1px solid var(--border);
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
overflow: hidden;
}
/* ─── Badges ────────────────────────────────────────────────
* Pill badges — DESIGN.md §4: "Background #ebf5ff, text
* #0068d6, 9999px radius". We tint the accent over white at
* ~92% transparency to land near #ebf5ff, and use a slightly
* darker accent for the label so it reads against the tint. */
.badge {
display: inline-flex;
align-items: center;
gap: var(--space-1);
padding: 2px 10px;
border-radius: var(--radius-pill);
font-size: var(--text-xs);
font-weight: 500;
line-height: 1.5;
font-family: var(--font-display);
}
.badge-accent {
color: color-mix(in oklab, var(--accent), black 14%);
background: color-mix(in oklab, var(--accent), white 92%);
}
.badge-muted {
color: var(--fg-2);
background: color-mix(in oklab, var(--bg), var(--fg) 2%);
box-shadow: 0 0 0 1px var(--border);
}
.badge-success {
color: var(--success);
background: color-mix(in oklab, var(--success), white 92%);
}
.badge-dot {
width: 6px;
height: 6px;
border-radius: 50%;
background: currentColor;
}
/* ─── Links ─────────────────────────────────────────────────
* Underlined by default — DESIGN.md §2: "Primary link color
* with underline decoration." Underline offset relaxes the
* line away from the descenders so it doesn't crowd Geist's
* compressed forms. */
a {
color: var(--accent);
text-decoration: underline;
text-underline-offset: 3px;
text-decoration-thickness: 1px;
}
a:hover { text-decoration-thickness: 2px; }
a:focus-visible {
outline: none;
border-radius: 2px;
box-shadow: var(--focus-ring);
}
/* ─── Kbd ───────────────────────────────────────────────────
* Geist Mono, hairline shadow-border edge. Vercel uses kbd
* forms in docs and product tooltips with the same restraint. */
kbd {
font-family: var(--font-mono);
font-size: var(--text-xs);
padding: 2px 6px;
border-radius: 4px;
background: var(--surface);
color: var(--fg-2);
box-shadow: 0 0 0 1px var(--border);
}
/* ─── Distinctive: Workflow pipeline ────────────────────────
* Vercel's signature three-step pipeline (Develop → Preview
* → Ship). DESIGN.md §4 documents each step with a brand-
* specific accent color (Develop Blue, Preview Pink, Ship
* Red); those colors are NOT part of the shared token schema
* and would each need to be promoted to a C-extension before
* we could express them here. This fixture renders the
* pipeline LAYOUT — three shadow-bordered cards, separated by
* mono arrow glyphs, with mono uppercase eyebrows — and
* leaves the chromatic stage labels to brand-specific
* extensions that ship later. The numbered tag in each
* eyebrow still communicates ordering. */
.pipeline {
display: grid;
grid-template-columns: 1fr auto 1fr auto 1fr;
align-items: stretch;
gap: var(--space-4);
margin-block-start: var(--space-8);
}
.pipeline-step {
background: var(--surface);
border-radius: var(--radius-md);
padding: var(--space-5) var(--space-5) var(--space-4);
display: flex;
flex-direction: column;
gap: var(--space-2);
box-shadow: var(--elev-raised);
}
.pipeline-step .eyebrow {
letter-spacing: 0.1em;
color: var(--accent);
}
.pipeline-step .step-title {
font-family: var(--font-display);
font-size: var(--text-xl);
font-weight: 600;
line-height: 1.33;
letter-spacing: -0.04em;
color: var(--fg);
}
.pipeline-step .step-body {
font-size: var(--text-sm);
color: var(--fg-2);
line-height: 1.5;
}
.pipeline-arrow {
align-self: center;
font-family: var(--font-mono);
font-size: var(--text-base);
color: var(--meta);
line-height: 1;
}
@media (max-width: 1023px) {
.pipeline {
grid-template-columns: 1fr;
gap: var(--space-3);
}
.pipeline-arrow { display: none; }
}
/* ─── Distinctive: Metric row ───────────────────────────────
* DESIGN.md §4 "Metric Cards": large display number at
* Geist W600, description below in --fg-2. Tabular-nums so
* columns of metrics align across the row. The metric IS the
* marker — no eyebrow, no icon, no decoration. */
.metric-row {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-8);
margin-block-start: var(--space-8);
}
@media (max-width: 639px) {
.metric-row { grid-template-columns: 1fr; gap: var(--space-6); }
}
.metric {
display: flex;
flex-direction: column;
gap: var(--space-2);
}
.metric-value {
font-family: var(--font-display);
font-size: var(--text-4xl);
font-weight: 600;
line-height: 1;
letter-spacing: var(--tracking-display);
color: var(--fg);
font-variant-numeric: tabular-nums;
}
.metric-label {
font-size: var(--text-base);
color: var(--fg-2);
}
/* ─── Section-specific layout ─────────────────────────────── */
.hero {
text-align: left;
position: relative;
overflow: hidden;
}
/* Atmospheric hero gradient — DESIGN.md §1: "Conic gradients
are a Vercel signature". A monochromatic conic of accent
tints layered behind the headline at low opacity reads as
an atmospheric wash rather than a decoration. We stay
token-clean by mixing `var(--accent)` over `var(--bg)` at
five intensities; agents extending the brand can swap in
workflow C-extensions once those promote into the schema. */
.hero::before {
content: "";
position: absolute;
inset: -40% -10% auto -10%;
height: 70%;
background: conic-gradient(
from 220deg at 50% 50%,
color-mix(in oklab, var(--accent), var(--bg) 30%) 0deg,
color-mix(in oklab, var(--accent), var(--bg) 60%) 90deg,
color-mix(in oklab, var(--accent), var(--bg) 85%) 180deg,
var(--bg) 270deg,
color-mix(in oklab, var(--accent), var(--bg) 30%) 360deg
);
filter: blur(120px);
opacity: 0.18;
z-index: 0;
pointer-events: none;
}
.hero > * { position: relative; z-index: 1; }
.hero .eyebrow { margin-block-end: var(--space-4); }
.hero h1 { max-width: 18ch; }
.hero .lede {
max-width: 56ch;
margin-block-start: var(--space-5);
}
.hero-actions {
display: flex;
gap: var(--space-3);
margin-block-start: var(--space-8);
align-items: center;
flex-wrap: wrap;
}
.hero-meta {
display: inline-flex;
align-items: center;
gap: var(--space-2);
margin-block-start: var(--space-6);
color: var(--muted);
font-size: var(--text-sm);
}
.features-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: var(--space-5);
margin-block-start: var(--space-8);
}
@media (max-width: 1023px) {
.features-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 639px) {
.features-grid { grid-template-columns: 1fr; }
}
.form-row {
display: grid;
grid-template-columns: 1.2fr 1fr;
gap: var(--space-12);
align-items: start;
margin-block-start: var(--space-8);
}
@media (max-width: 1023px) {
.form-row { grid-template-columns: 1fr; }
}
.form {
display: flex;
flex-direction: column;
gap: var(--space-4);
max-width: 440px;
padding: var(--space-6);
background: var(--surface);
border-radius: var(--radius-md);
box-shadow: var(--elev-raised);
}
.form-actions {
display: flex;
gap: var(--space-3);
margin-block-start: var(--space-2);
align-items: center;
}
.row-between {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-3);
}
.icon { width: 16px; height: 16px; flex-shrink: 0; }
</style>
</head>
<body>
<main class="container">
<!-- ════════════════════════════════════════════════════════════
HERO — exercises: conic-gradient atmospheric wash (the
Vercel signature on hero), h1 at 48px Geist W600 with
-0.05em tracking, .lede in --fg-2, .btn-primary (black-on-
white), .btn-secondary (shadow-as-border edge), .badge-
muted (status pill), kbd (hairline shadow). Single-column
layout — Vercel heroes don't asymmetric-split; the page IS
the column.
═══════════════════════════════════════════════════════════════ -->
<section class="hero" data-od-id="hero">
<p class="eyebrow">Reference fixture · Vercel</p>
<h1>Build, preview, and ship without rebuilding the platform underneath.</h1>
<p class="lede">
A token block distilled from Vercel's published design
system — Geist Sans with -0.05em display tracking, shadow-
as-border throughout, blue reserved for the chromatic
moments. The fixture you are reading paints from the same
<code style="font-family: var(--font-mono); font-size: 0.95em">:root</code>
block agents inline into every Vercel artifact.
</p>
<div class="hero-actions">
<a href="./tokens.css" class="btn btn-primary">
View tokens
<svg
class="icon"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="1.75"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path d="M5 12h14M13 6l6 6-6 6" />
</svg>
</a>
<a href="./DESIGN.md" class="btn btn-secondary">Read the spec</a>
<a href="#pipeline" class="btn btn-ghost">See the pipeline</a>
</div>
<p class="hero-meta">
<span class="badge badge-muted">
<span class="badge-dot" aria-hidden="true" style="color: var(--success)"></span>
v0.1 · stable
</span>
<span>Press <kbd>⌘</kbd> <kbd>K</kbd> to search tokens.</span>
</p>
</section>
<!-- ════════════════════════════════════════════════════════════
PIPELINE + METRICS — Vercel's distinctive three-step
workflow (Develop → Preview → Ship) rendered as token-
pure cards with shadow-as-border arrows in Geist Mono.
Workflow accents (Develop Blue, Preview Pink, Ship Red)
are deliberately deferred — they would each become C-
extensions in this brand's tokens.css, and the schema
rule forbids inventing C-extensions inside the fixture.
The metric row below uses --text-4xl + --tracking-display
to demonstrate Geist's compression at the display tier.
═══════════════════════════════════════════════════════════════ -->
<section data-od-id="pipeline" id="pipeline">
<p class="eyebrow">The Vercel workflow</p>
<h2 style="max-width: 22ch; margin-block-start: var(--space-3)">
Three steps, one platform.
</h2>
<p class="body-muted" style="margin-block-start: var(--space-4); max-width: 56ch">
DESIGN.md gives each stage its own workflow accent
(Develop Blue, Preview Pink, Ship Red). Those colors are
deliberately deferred here — they are pipeline labels, not
brand accents, and would each promote in as a C-extension
rather than ride on the shared accent slot.
</p>
<div class="pipeline">
<article class="pipeline-step">
<p class="eyebrow">01 · Develop</p>
<p class="step-title">Write the code.</p>
<p class="step-body">
Local dev with hot-reload that mirrors the production
runtime. No surprises between localhost and the deploy.
</p>
</article>
<div class="pipeline-arrow" aria-hidden="true">&rarr;</div>
<article class="pipeline-step">
<p class="eyebrow">02 · Preview</p>
<p class="step-title">Share the branch.</p>
<p class="step-body">
Every push gets a preview URL. Stakeholders review
against the same runtime that will serve production.
</p>
</article>
<div class="pipeline-arrow" aria-hidden="true">&rarr;</div>
<article class="pipeline-step">
<p class="eyebrow">03 · Ship</p>
<p class="step-title">Promote, atomically.</p>
<p class="step-body">
One click promotes the previewed build. Rollback is the
same one click in reverse.
</p>
</article>
</div>
<div class="metric-row">
<div class="metric">
<div class="metric-value">10×</div>
<div class="metric-label">faster cold starts at the edge</div>
</div>
<div class="metric">
<div class="metric-value">≤2</div>
<div class="metric-label">accent uses per screen (lint enforced)</div>
</div>
<div class="metric">
<div class="metric-value">56</div>
<div class="metric-label">tokens declared in this :root</div>
</div>
</div>
</section>
<!-- ════════════════════════════════════════════════════════════
FEATURE CARDS — exercises: .card (multi-layer Vercel
shadow stack including the inner #fafafa glow), h3 with
-0.04em tracking, .body-muted, link, .features-grid.
Three cards per row at desktop, collapses on mobile.
═══════════════════════════════════════════════════════════════ -->
<section data-od-id="features">
<div class="stack-3">
<p class="eyebrow">What this fixture exercises</p>
<h2 style="max-width: 28ch">
Every component below pulls from <code style="font-family: var(--font-mono); font-size: 0.92em">var(--*)</code> — no raw hex, no off-token type.
</h2>
</div>
<div class="features-grid">
<article class="card">
<span class="badge badge-accent">Surface</span>
<h3>Achromatic canvas, one accent.</h3>
<p class="body-muted body-sm">
Pure white for the page, pure white for cards, no warm
tier. The whole system stays achromatic until the
accent moment — links, focus rings, badge tints.
</p>
<a href="./tokens.css" class="body-sm">Inspect tokens &rarr;</a>
</article>
<article class="card">
<span class="badge badge-accent">Shadows</span>
<h3>Edges live in the shadow layer.</h3>
<p class="body-muted body-sm">
<code style="font-family: var(--font-mono); font-size: 0.95em">box-shadow: 0 0 0 1px rgba(0,0,0,.08)</code>
replaces traditional borders throughout. Cards layer
four shadows — ring, close, far, and inner glow — into
a single elevation.
</p>
<a href="./DESIGN.md" class="body-sm">Read the rule &rarr;</a>
</article>
<article class="card">
<span class="badge badge-accent">Type</span>
<h3>Geist runs tight.</h3>
<p class="body-muted body-sm">
Display tracking is <code style="font-family: var(--font-mono); font-size: 0.95em">-0.05em</code>
— the most aggressive negative tracking of any major
design system. Three weights only: 400 reads, 500
interacts, 600 announces.
</p>
<a href="./tokens.css" class="body-sm">Inspect typography &rarr;</a>
</article>
</div>
</section>
<!-- ════════════════════════════════════════════════════════════
FORM — exercises: .field with shadow-border inputs,
focus-visible swap to the 2px accent ring, .btn-primary
and .btn-secondary reuse. Form sits inside its own
multi-layer-shadow card so the input edges read as
recessed beneath the form surface.
═══════════════════════════════════════════════════════════════ -->
<section data-od-id="form">
<p class="eyebrow">Form components</p>
<h2 style="margin-block-start: var(--space-3); max-width: 28ch">
Inputs inherit the same tokens.
</h2>
<div class="form-row">
<div class="stack-4">
<p class="body-muted" style="max-width: 48ch">
Focus rings, edges, placeholder color — all derive from
<code style="font-family: var(--font-mono); font-size: 0.95em">--accent</code>
and <code style="font-family: var(--font-mono); font-size: 0.95em">--border</code>.
The submit button reuses
<code style="font-family: var(--font-mono); font-size: 0.95em">.btn-primary</code>
unchanged — black fill, white label, 6px radius.
</p>
<p class="body-muted body-sm">
No new token is introduced for this section. The form
card uses
<code style="font-family: var(--font-mono); font-size: 0.95em">--elev-raised</code>
directly so the input shadow-borders read as recessed
beneath the form's outer ring.
</p>
<p class="body-meta">
Full reference at <a href="./tokens.css">tokens.css</a> ·
spec at <a href="./DESIGN.md">DESIGN.md</a>.
</p>
</div>
<form class="form" onsubmit="event.preventDefault();">
<div class="row-between">
<p class="eyebrow">Get the spec</p>
<span class="badge badge-success">
<span class="badge-dot" aria-hidden="true"></span>
Open
</span>
</div>
<div class="field">
<label for="email">Work email</label>
<input
id="email"
type="email"
placeholder="you@team.dev"
autocomplete="email"
required
/>
<p class="field-help">
We'll send the spec PDF and nothing else.
</p>
</div>
<div class="form-actions">
<button type="submit" class="btn btn-primary">
Send the spec
</button>
<button type="button" class="btn btn-secondary">
Skip for now
</button>
</div>
</form>
</div>
</section>
</main>
</body>
</html>
@@ -0,0 +1,270 @@
/* ─────────────────────────────────────────────────────────────────────────
* design-systems/vercel/tokens.css
*
* Structured token bindings for "Vercel" — the engineering-as-design
* thesis of frontend deployment: a near-white canvas, near-black text,
* one saturated blue accent, and a shadow-as-border philosophy that
* replaces the box-model edge with a layered box-shadow stack.
*
* This file pre-compiles the values described in `DESIGN.md` into the
* shared schema. Agents generating an artifact for Vercel should paste
* the `:root` block verbatim into the first `<style>` of the artifact,
* then reference everything via `var(--*)`.
*
* Brand-specific schema decisions (each one bends a schema convention
* to match Vercel's voice rather than the cross-brand default):
*
* 1. `--accent` is the Vercel/Console blue (#0070f3), not Vercel Black.
* Black is already `--fg`; the brand expresses primary CTAs by
* using `--fg` as the button background, not `--accent`. The
* `--accent` slot is reserved for the chromatic moments — links,
* focus rings, badge tints — exactly where Vercel's blue appears
* in product. Treating black as both `--fg` and `--accent` would
* collapse two distinct intents into one name and break the
* lint's "≤2 accent uses per screen" semantic.
*
* 2. `--fg` is `#171717` (Vercel Black), not `#000000`. The micro-
* warmth at the top of the gray ramp is part of the brand — pure
* black against pure white reads as harsh, and the rest of the
* neutral scale (gray-600 / 500 / 400 / 100 / 50) is calibrated
* against `#171717` not `#000000`. Bind the full four-level
* foreground ramp (#171717 → #4d4d4d → #666666 → #808080) so
* cross-brand components targeting `--fg-2` and `--meta` resolve
* to Vercel's actual gray-600 / gray-400 instead of collapsing.
*
* 3. `--border` is `rgba(0, 0, 0, 0.08)` — the literal Vercel
* shadow-as-border alpha, NOT a solid hex. DESIGN.md §1 names
* this single value as "the signature" that "replaces traditional
* borders throughout". Binding `--border` to the alpha lets
* `--elev-ring` (`0 0 0 1px var(--border)`) reproduce the Vercel
* hairline by default, and lets components reach the same value
* via `border: 1px solid var(--border)` when a real border is
* structurally necessary (e.g. image cards). `--border-soft`
* drops to `0.04` for inner-row separators that must not compete.
*
* 4. `--elev-raised` is the full multi-layer Vercel card stack
* (`0 0 0 1px rgba(0,0,0,0.08), 0 2px 2px rgba(0,0,0,0.04),
* 0 8px 8px -8px rgba(0,0,0,0.04), 0 0 0 1px #fafafa`), not the
* schema's single soft blur. The inner `#fafafa` ring at the
* bottom of the stack is the "subtle inner glow" DESIGN.md §6
* calls out — without it, Vercel cards lose the built-not-
* floating quality. The fourth layer's `#fafafa` is the only
* raw hex inside the `:root` block, justified because the value
* is structural to the shadow layer, not a recolorable surface.
*
* 5. `--focus-ring` is a solid 2px ring at `var(--accent)`, not the
* schema's 3px alpha glow. Vercel's `--ds-focus-color` focus
* outline is `2px solid hsla(212, 100%, 48%, 1)` everywhere;
* reproducing it as a sharp 2px box-shadow keeps keyboard focus
* legible against the white canvas without the soft halo that
* would dilute the engineered feel.
*
* 6. The type scale tops out at 48px (`--text-4xl`), not 64px+.
* DESIGN.md §3 caps display at 48px Geist W600 with
* `letter-spacing: -2.4px` (which expresses as `-0.05em` in
* `--tracking-display`). Vercel reads HUGE because the tracking
* compresses, not because the px count climbs. `--leading-tight`
* drops to `1.1` to match — display lines run shorter than the
* schema default's 1.2.
*
* 7. Section rhythm is generous: `96px` desktop, `64px` tablet,
* `48px` phone (`--section-y-*`). DESIGN.md §5 describes the
* "gallery emptiness" of 80–120px+ vertical padding between
* sections — the whitespace is the design. Container caps at
* `1200px` (Vercel's documented max content width).
*
* Source contracts:
* - Standard token names: design-systems/_schema/tokens.schema.ts
* - A2 fallback parity: design-systems/_schema/defaults.css
* - Lint enforcement: apps/daemon/src/lint-artifact.ts
*
* Keep this file additive: never invent token names not also
* documented in DESIGN.md or the schema. The Geist family does not
* need a CDN reference here — the font stack lists OS fallbacks so
* that artifacts render acceptably even when Geist is not loaded,
* and any host that wants the real Geist face links it externally.
* ─────────────────────────────────────────────────────────────────── */
:root {
/* ─── Surface (3 levels — schema slot) ─────────────────────────────
* Vercel's canvas is famously achromatic: pure white page, pure
* white cards, no warm tier. `--surface-warm` aliases to surface
* because the brand explicitly forbids background-color variation
* between sections — depth comes from shadow layering, not from
* tinting one surface warmer than another. (DESIGN.md §5: "White
* sections alternate with white sections — there's no color
* variation between sections.") */
--bg: #ffffff;
--surface: #ffffff;
--surface-warm: var(--surface); /* alias — Vercel has no warm tier */
/* ─── Foreground ramp (4 levels) ──────────────────────────────────
* Gray 900 → 600 → 500 → 400, the documented neutral scale from
* DESIGN.md §2. `#171717` instead of `#000000` matters — the
* yellow-undertone warmth is what keeps the page from reading as
* harsh. `--fg-2` and `--meta` are independently bound (not aliased)
* because Vercel genuinely uses four distinct text tiers: heading
* black, body description gray, tertiary caption gray, and
* placeholder/disabled gray. */
--fg: #171717; /* Gray 900 — headings, primary text */
--fg-2: #4d4d4d; /* Gray 600 — body description */
--muted: #666666; /* Gray 500 — captions, tertiary text */
--meta: #808080; /* Gray 400 — placeholder, disabled */
/* ─── Border (2 levels) ──────────────────────────────────────────
* Shadow-as-border is THE signature: `rgba(0, 0, 0, 0.08)` at 1px
* spread replaces traditional borders throughout. Binding `--border`
* to the alpha (not a solid hex) lets `--elev-ring` reproduce the
* Vercel hairline by default, and lets `border: 1px solid var(--border)`
* paint the same value when a real border is structurally required
* (e.g. image-card top edge per DESIGN.md §4). `--border-soft`
* drops to 0.04 alpha for inner row separators that should not
* visually compete with the card edge. */
--border: rgba(0, 0, 0, 0.08); /* signature shadow-as-border alpha */
--border-soft: rgba(0, 0, 0, 0.04); /* inner row separator */
/* ─── Accent ─────────────────────────────────────────────────────
* The single chromatic move: Vercel/Console Blue. Used in links,
* focus rings, pill-badge tints, and console syntax highlighting.
* Hard cap of ≤2 visible uses per screen — DESIGN.md §7 forbids
* decorative use ("Color is functional, never decorative — workflow
* colors (Red/Pink/Blue) mark pipeline stages only").
*
* Primary CTAs in Vercel are BLACK, not blue. components.html
* encodes that pattern via `background: var(--fg)` on the primary
* button, so `--accent` stays reserved for the chromatic moments
* where blue actually appears. */
--accent: #0070f3; /* Vercel Blue / Console Blue */
--accent-on: #ffffff; /* white label on saturated blue */
--accent-hover: color-mix(in oklab, var(--accent), black 8%);
--accent-active: color-mix(in oklab, var(--accent), black 14%);
/* ─── Semantic ───────────────────────────────────────────────────
* Vercel's marketing surface rarely renders state. We inherit the
* schema defaults (no warm-shift) because the brand has no defined
* success/warn/danger palette of its own; the workflow accents
* (Ship Red, Preview Pink, Develop Blue from DESIGN.md §2) are
* pipeline labels, not status colors, and intentionally do NOT
* bind here. */
--success: #16a34a;
--warn: #eab308;
--danger: #dc2626;
/* ─── Typography ─────────────────────────────────────────────────
* Geist Sans is Vercel's open-source typeface — `--font-display`
* and `--font-body` share the stack; size, weight, and tracking
* carry hierarchy, not face. The Arial/system fallbacks come from
* DESIGN.md §3 and ensure artifacts render legibly even when Geist
* is not loaded. Geist Mono for code and technical labels
* preserves the "developer console voice" that connects the
* marketing site to the product. */
--font-display: "Geist", "Geist Sans", -apple-system, "Segoe UI", Arial, sans-serif;
--font-body: "Geist", "Geist Sans", -apple-system, "Segoe UI", Arial, sans-serif;
--font-mono: "Geist Mono", ui-monospace, "SF Mono", "Roboto Mono", Menlo, Monaco, "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace;
/* Type scale (px) — derived from DESIGN.md §3 hierarchy table.
* The scale tops out at 48px (display hero); Vercel reads BIG
* because of -0.05em compression on display, not because of a
* larger px ceiling. */
--text-xs: 12px; /* caption, metadata, tags */
--text-sm: 14px; /* button, link, small UI */
--text-base: 16px; /* body small, navigation */
--text-lg: 20px; /* body large, introductions */
--text-xl: 24px; /* card title */
--text-2xl: 32px; /* sub-heading, large card */
--text-3xl: 40px; /* section heading */
--text-4xl: 48px; /* display hero */
/* `--leading-tight` is 1.1 (DESIGN.md says 1.00–1.17 at display),
* `--leading-body` is 1.5 (the documented 16px / 24px ratio).
* `--tracking-display` is `-0.05em`, the em-relative form of
* Vercel's `-2.4px at 48px` — letter-spacing in em scales
* proportionally with size, matching DESIGN.md §3's principle
* that "tracking scales with font size". */
--leading-body: 1.5;
--leading-tight: 1.1;
--tracking-display: -0.05em;
/* ─── Spacing ────────────────────────────────────────────────────
* 4px-grid base scale. Vercel's documented spacing (DESIGN.md §5)
* uses 1–6px sub-tier increments for micro-padding (button
* `0px 6px`, etc.); those are inlined per-component because they
* are too fine to belong in the shared schema. The 4/8/12/16/20/
* 24/32/48 tier covers the structural rhythm. */
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-12: 48px;
/* Section rhythm — DESIGN.md §5: 80–120px+ vertical padding between
* sections desktop, collapsing to 48px on mobile. We sit in the
* middle at 96px desktop, drop to 64px on tablet (still generous),
* and 48px on phone (the documented mobile floor). */
--section-y-desktop: 96px;
--section-y-tablet: 64px;
--section-y-phone: 48px;
/* ─── Radius ─────────────────────────────────────────────────────
* DESIGN.md §5 radius scale: 2/4/6/8/12/64/100/9999. We bind the
* four schema tiers to: 6 (button/input/functional), 8 (card),
* 12 (image/featured card), 9999 (badge/pill). The 64px and
* 100px "navigation pill" radii from DESIGN.md are component-
* specific and not part of the shared schema. */
--radius-sm: 6px; /* buttons, inputs, functional */
--radius-md: 8px; /* cards, modals */
--radius-lg: 12px; /* image cards, featured */
--radius-pill: 9999px; /* badges, status pills */
/* ─── Elevation (3 levels) ───────────────────────────────────────
* Vercel's depth system is shadow-LED, not blur-led. Three levels:
*
* --elev-flat no shadow (page background, text blocks)
* --elev-ring the signature 1px shadow-as-border (most surfaces)
* --elev-raised the multi-layer Vercel card stack (featured cards)
*
* `--elev-raised` is reproduced VERBATIM from DESIGN.md §6 Level 3,
* including the inner `#fafafa` 1px ring that DESIGN.md calls out
* as "the glow that makes the system work" — never drop the last
* layer when overriding this token. The four layers compose:
* ring (1px shadow-as-border, sits on top)
* close (2px 2px soft elevation, just below the surface)
* far (8px blur -8px spread, ambient depth at distance)
* inner (1px #fafafa ring, the subtle highlight) */
--elev-flat: none;
--elev-ring: 0 0 0 1px var(--border);
--elev-raised:
0 0 0 1px rgba(0, 0, 0, 0.08),
0 2px 2px rgba(0, 0, 0, 0.04),
0 8px 8px -8px rgba(0, 0, 0, 0.04),
0 0 0 1px #fafafa;
/* ─── Focus ring ─────────────────────────────────────────────────
* Vercel's `--ds-focus-color` is `hsla(212, 100%, 48%, 1)`; the
* outline is `2px solid` on every interactive element. We
* reproduce that as a sharp 2px box-shadow at `var(--accent)`,
* NOT the schema's 3px alpha glow — Vercel's focus is engineered,
* not atmospheric. */
--focus-ring: 0 0 0 2px var(--accent);
/* ─── Motion ─────────────────────────────────────────────────────
* Two durations + one easing curve, per anti-ai-slop's "short,
* purposeful transitions (150–250ms) with stable easing". Vercel
* transitions are quick and unobtrusive — never a long-form
* choreographed entrance. */
--motion-fast: 150ms;
--motion-base: 200ms;
--ease-standard: cubic-bezier(0.2, 0, 0, 1);
/* ─── Layout ─────────────────────────────────────────────────────
* 1200px max content width per DESIGN.md §5. Gutters narrow on
* mobile to preserve the line-length-as-craft feel — Vercel does
* NOT edge-bleed body copy on phones, only screenshots. */
--container-max: 1200px;
--container-gutter-desktop: 24px;
--container-gutter-tablet: 16px;
--container-gutter-phone: 12px;
}