open-design/design-systems/vercel/tokens.css
chaoxiaoche e62b87b62c
feat(design-systems): add structured tokens for cursor, apple, stripe, airbnb, vercel brands (#1652)
* feat(design-systems): add structured tokens for cursor brand

Introduces design-systems/cursor/tokens.css + components.html, the
third structured brand after default and kami. Brings the prose
DESIGN.md into the schema-checked form so agents picking the cursor
design system get the structured token channel (PR-D #1544) instead
of having to re-derive Cursor's warm-cream palette, three-voice
typography (CursorGothic / jjannon / berkeleyMono), oklab borders,
and depth-based focus from prose every turn.

Why now: PR-D made the structured channel default-on, but it only
materially helps the 2 brands shipping tokens.css today. To expand
batch-design-system-test (#1515) coverage beyond default + kami,
we are hand-authoring 5 high-profile brands (cursor first as
template, then apple / stripe / airbnb / vercel) before the bulk
derive script (PR-B). These five also serve as the byte-identical
oracle the future derive script must reproduce.

Brand-specific schema decisions, captured in the tokens.css header:
- Surface: 3-tier cream ladder (#f2f1ed → #ebeae5 → #e6e5e0).
  --surface-warm binds to a real intermediate tier, not aliased.
- Foreground: 4-tier ramp via rgba(38,37,30,a) at 1.0 / 0.9 / 0.55
  / 0.4 — Cursor genuinely has the richer ramp.
- Borders: oklab origins shipped as rgba fallbacks per DESIGN.md
  §Agent Prompt Guide rule 3.
- --tracking-display: -0.03em (the 72px hero value normalized to
  em). Smaller display sizes scale tracking proportionally inline.
- --elev-raised: signature 28/70px diffused atmospheric shadow.
- --focus-ring: depth-only (0 4px 12px), never the cool-blue halo.
- --ease-standard: ease (per DESIGN.md), not the schema cubic-bezier.
- --danger: warm crimson #cf2d56, used for the brand-signature
  hover-text-shift on buttons.

components.html demonstrates the full surface (hero with 72px
CursorGothic + jjannon serif lead, three-voice typography, warm-
surface CTA with crimson hover, accent-orange pill CTA used once,
oklab-fallback bordered cards, AI timeline signature element with
the warm pastel state colors, jjannon-serif input with 4-12 depth
focus). :root paste is byte-identical to tokens.css.

Verified:
- pnpm guard — 13/13 checks pass, including all 8 design-system
  sub-checks now reporting "3 brands" (default + kami + cursor):
  - token-fixture sync: 3 brand pairs aligned
  - A1/A2/B-slot required tokens: all 3 brands declare
    26 A1 + 26 A2 + 4 B-slot
  - unknown token allowlist: 185 declarations across 3 brands all
    match shared schema or brand extensions
  - flag parity: 146 prose-only brands byte-identical, 3 structured
    diverge as expected

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(design-systems): correct h2/h3 line-height in cursor components fixture

Per DESIGN.md §Hierarchy, 36px section headings use line-height 1.20
and 26px sub-headings use 1.25. The shared h1/h2/h3 rule was locking
all three to --leading-tight (1.10), baking wrong vertical rhythm into
the oracle fixture.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat(design-systems): add structured tokens for apple, stripe, airbnb, vercel brands

Batch follow-up to #1652 (cursor). Adds tokens.css + components.html
for the remaining four high-profile brands, using cursor as the
format/template oracle.

Each brand encodes its specific identity:
- apple: SF Pro tight-compressed display (--leading-tight 1.05),
  system-blue accent, SF Symbols grid, frosted glass surfaces
- stripe: sohne-var weight-300 anti-convention signature, --leading-tight
  1.10 (matches all heading spec values exactly), indigo accent
- airbnb: Cereal weight-700 display with Rausch coral, --leading-tight
  1.20 with per-size overrides (h2→1.18, h3→1.25)
- vercel: Geist 600 compressed display, --leading-tight 1.10 with
  per-size overrides (h2→1.20, h3→1.33 per DESIGN.md §Typography)

pnpm guard: 13/13 checks pass; flag-parity now shows 6 structured
brands and 143 prose-only brands.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: chaoxiaoche <chaoxiaoche@chaoxiaochedeMacBook-Pro.local>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-15 16:53:51 +08:00

270 lines
16 KiB
CSS
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ─────────────────────────────────────────────────────────────────────────
* 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 80120px+ 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.001.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 16px 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: 80120px+ 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 (150250ms) 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;
}