# Payload — Marketing site Design Spec

> Source: payloadcms.com (live DOM, computed styles + the published `--color-base-*` / `--theme-*` token set), 2026-07-21.
> Coverage: banner, nav, hero grid, CTA cells, colour/type/radius/shadow/motion census across the document. Admin panel not captured (needs login).
> Responsive: breakpoint tokens exist but resolve to unsubstituted SCSS variables; actual behaviour not captured.

## 1. Visual Theme & Atmosphere

Pure black, and **square**. The whole page is drawn as a visible grid of `rgba(255,255,255,.13)` hairline rails, and the hero is assembled from stacked full-width *cells* rather than from a headline plus buttons — the install command and "Get a Demo" are grid rows, 68px and 72px tall, that you click. There is essentially no border-radius in the system (five radii across the entire document, none of them structural), no accent hue in the chrome, and no shadow doing separation work: everything reads as a wireframe drawn in white on black. Type is one family, Untitled Sans, held at weight 500 with a consistent **-5% tracking at every display size**. Colour exists only as a published, fully-laddered token system waiting to be used by status states.

Feels: architectural, precise, engineered, quiet.

## 2. Color Palette & Roles

The site ships a complete token system: a neutral `--color-base-0…1000` ramp in 5% steps, hue ramps for blue / purple / error / success / warning, semantic `-bg/-border/-text` pairs in light and dark variants, and a `--theme-*` set that is **the base ramp reversed** for the dark theme — so `--theme-elevation-0` is `#000000` and `--theme-elevation-1000` is `#ffffff`. "Elevation" here is a *colour step*, not a shadow.

**Text**

| Token | Hex | Role / usage |
|---|---|---|
| `--theme-elevation-1000` | `#ffffff` | All headings, body, nav, CTA labels |
| `--text-dark` | `rgba(255,255,255,.50)` | Muted text on dark |
| `--text-light` | `rgba(0,0,0,.50)` | Muted text on light |

**Surfaces & borders**

| Token | Hex | Role / usage |
|---|---|---|
| `--theme-bg` / `--theme-elevation-0` | `#000000` | Page canvas |
| `--theme-elevation-50` | `#070707` | The most-used panel fill (15 blocks) |
| `--theme-elevation-100` | `#141414` | Raised cell |
| `--theme-elevation-150` | `#222222` | Next step |
| rail | `rgba(255,255,255,.13)` | **The grid hairline — 22 uses, the primary structural device** |
| soft rail | `rgba(255,255,255,.05)` | Interior sub-divider |
| solid rule | `#ffffff` | Emphasis rule (11 uses) |
| tint | `rgba(255,255,255,.10)` | Hover / chip wash |
| inverse | `#ffffff` | Inverted button and inverted sections |

Neutral ramp (`--color-base-*`, 5% steps): `0 #ffffff` · `50 #f5f5f5` · `100 #ebebeb` · `150 #dddddd` · `200 #d0d0d0` · `250 #c3c3c3` · `300 #b5b5b5` · `350 #a8a8a8` · `400 #9a9a9a` · `450 #8d8d8d` · `500 #808080` · `550 #727272` · `600 #656565` · `650 #575757` · `700 #4a4a4a` · `750 #3c3c3c` · `800 #2f2f2f` · `850 #222222` · `900 #141414` · `950 #070707` · `1000 #000000`.

**Hues** (published ramps; on the marketing page only the deep end appears)

| Family | Key steps | Role / usage |
|---|---|---|
| blue | `50 #e5f2f7` → `500 #007fae` → `900 #001923` | Brand/info; `#001923` is the announcement-banner ground with `#e5f2f7` text |
| purple | `50 #fef5fe` → `500 #f799f7` → `900 #311f31` | Secondary hue, unused in chrome |
| error / red | `500 #ff876f`; bg-dark `#331b16`, text-dark `#ffd5cc` | Destructive |
| warning / orange | `500 #f4ac4f`; bg-dark `#332d21`, text-dark `#ffe1a4` | Warning |
| success | `500 #007fae` | Success — **the same blue as info** |

Every hue also ships an on-dark and on-light `-bg` / `-border` / `-text` triple, so a status chip is three matched tokens rather than an improvised alpha.

Rules: **the chrome has no accent colour at all** — emphasis is inversion to `#ffffff`. Blue only appears as the announcement banner and in status roles. Text is `#ffffff` or a 50%-alpha of it, never a grey from the ramp.

## 3. Typography Rules

One family: `untitledSans, "untitledSans Fallback"`. One mono, `GeistMono`, used only for the install command.

| Role | Size/Line | Weight | Tracking |
|---|---|---|---|
| h1 | 64 / 64 | **500** | **-3.2px** |
| h2 | 48 / 48 | 500 | **-2.4px** |
| h3 | 24 / 28.8 | 500 | **-1.2px** |
| Body | 16 / 22.4 | 400 | normal |
| Nav link | 16 / 22.4 | 500 | normal |
| Small / meta | 15 / 18 | 400 | normal |
| Install command (GeistMono) | 14 / 19.6 | 400 | normal |

Patterns: **tracking is exactly -5% of font size at every display role** (-3.2 at 64, -2.4 at 48, -1.2 at 24) and returns to `normal` at 16px and below — a mechanical rule, not a hand-tuned scale. Display line-height is **1.0** at 64 and 48. Nothing goes above weight 500; nothing is uppercase or tracked positive.

## 4. Component Stylings

- **Announcement banner** — ground `#001923` (blue-900), text `#e5f2f7` (blue-100), height 48px, padding `12px 64px`, 16/22.4 at 400, radius **0**, with a `1px` bottom rule in `#e5f2f7` and an arrow-out glyph on the link.
- **Nav** — links 16/22.4 at 500 in `#ffffff`; a GitHub star count; a text-only "Login"; and one filled button.
- **Primary button (Get Started)** — `#ffffff` fill, `#000000` label, radius **4px**, height 28px, padding `4px 8px`, 15/18 at 400, `1px` white border. Small and understated.
- **Install-command cell** — the signature CTA: a full-width grid row 68px tall, transparent, bounded by `1px rgba(255,255,255,.13)` rails, holding `$ npx create-payload-app` in GeistMono 14/19.6 with a copy glyph at the right edge. Radius 0.
- **Demo cell** — the row beneath it, 72px tall, transparent, `1px` top rail, label 16/22.4 at 500 with a trailing arrow-out glyph. Radius 0.
- **Status chip** — built from a hue triple (`-bg-dark`, `-border-dark`, `-text-dark`), e.g. orange `#332d21` / `#f4ac4f` / `#ffe1a4`.
- **Panel** — `#070707` on `#000000`, separated by a rail, no radius, no shadow.

## 5. Layout Principles

A visible rail grid is the layout: vertical and horizontal `rgba(255,255,255,.13)` hairlines bracket the content column and continue through every section, so blocks read as cells in a drawing rather than as cards. The hero is a left column of stacked cells — headline, install command, demo — with a large dark product panel bleeding off the right edge. Spacing is tokenised (`--block-spacing: 5rem`, `--base: 16px`). Nothing floats; nothing is centred except the banner.

## 6. Depth & Elevation

**There is effectively no radius scale.** Across the entire document only five radii occur: `3px` (4 uses), `4px` (3 uses, the Get Started button), `40px` (2), `8px` (2), `100%` (1, an avatar). Everything structural is square.

Three shadow recipes, all rare:

```css
/* keycap bevel — on the copy/keyboard affordance */
box-shadow: rgb(40,45,85) 0 -2px 0 0 inset,
            rgb(81,87,125) 0 0 1px 1px inset,
            rgba(3,4,9,.3) 0 2px 2px;

/* long-throw lift under the floating product panel */
box-shadow: rgba(0,0,0,.5) 0 48px 64px 16px;

/* tight contact */
box-shadow: rgba(0,0,0,.5) 0 0 4px 0;
```

Philosophy: **separation is the rail, not the shadow.** Depth on the page is the `#000000` → `#070707` → `#141414` → `#222222` colour ladder — which is exactly what the `--theme-elevation-*` naming says. One `backdrop-filter: blur(32px)` on floating chrome.

## 7. Motion

The house curve is an **expo-out, `cubic-bezier(0.165, 0.84, 0.44, 1)`**, applied at `0.15s` (85 elements), `0.35s` (10) and `0.45s` (25) — short for hover, long for reveals — with `0.3s ease-in-out` (16) as the odd one out. One `<video>` on the page; no canvas, no WebGL, no animation library detected.

## 8. Backgrounds, Effects & WebGL

Flat solid surfaces. No gradients, no blend modes, no grain, no canvas. The only effects are the single `backdrop-filter: blur(32px)` and one background `<video>` inside the product panel. Atmosphere comes entirely from the rail grid and the near-black elevation ladder.

## 9. Do's and Don'ts

### Do
- Draw the layout as a visible grid of `rgba(255,255,255,.13)` hairlines and let blocks be cells in it.
- Build CTAs as full-width grid rows (68–72px) rather than as buttons where the layout allows.
- Keep everything square — radius 0, with `4px` reserved for the one filled button.
- Set display tracking at exactly -5% of font size, with 1.0 line-height at 48 and 64.
- Cap weight at 500 and use `#ffffff` for all text, dropping to 50% alpha for muted.
- Build status chips from a matched `-bg` / `-border` / `-text` hue triple.
- Step depth through the elevation *colours* (`#000` → `#070707` → `#141414` → `#222222`).

### Don't
- Don't introduce an accent colour into the chrome — emphasis is inversion to white.
- Don't use rounded corners, pills or soft cards.
- Don't separate blocks with a drop shadow; use the rail.
- Don't use greys from the base ramp as text colour on dark — use white at 100% or 50%.
- Don't exceed weight 500, or use uppercase or positive tracking.
- Don't leave tracking at `normal` on a display size, or apply it below 16px.

## 10. Responsive Behavior

Not captured. Breakpoint custom properties (`--breakpoint-xs-width` through `--breakpoint-2xl-width`) exist but resolve to unsubstituted SCSS variable names, so no pixel values can be claimed.

## 11. Agent Prompt Guide

- Canvas `#000000` · Text `#ffffff` · Muted `rgba(255,255,255,.5)` · Border `rgba(255,255,255,.13)` · Accent — **none** (inversion to `#ffffff`)
- Font: Untitled Sans (GeistMono for commands) · Body: 16/22.4 · Radius: **0**, except a 4px filled button · Control height: 28px button, 68–72px CTA cell
- Focus: not captured · Hover fill: `rgba(255,255,255,.10)`

<payload_design_language>
Pure black and strictly square: the layout is drawn as a visible grid of rgba(255,255,255,.13) hairline rails, and the hero is built from stacked full-width CELLS rather than a headline plus buttons — an install command in GeistMono 14/19.6 in a 68px row, a Get-a-Demo label in a 72px row beneath it — so the CTAs are grid rows you click. There is effectively no radius scale (five radii in the whole document, none structural) and separation is never a shadow: depth steps through the elevation COLOURS #000000, #070707, #141414, #222222, which is literally what the published --theme-elevation-* tokens name. One family, Untitled Sans, capped at weight 500, with tracking set mechanically at -5% of font size on every display role (64/64 at -3.2px, 48/48 at -2.4px, 24/28.8 at -1.2px) and normal at 16/22.4 body. The chrome has NO accent colour — emphasis is inversion to #ffffff, and the one filled button is white on black at 28px with a rare 4px radius. Text is #ffffff or a 50% alpha of it, never a grey. Blue #001923 with #e5f2f7 text appears only as the announcement banner; status colours come as matched -bg/-border/-text triples (orange #332d21/#f4ac4f/#ffe1a4). Motion is an expo-out cubic-bezier(.165,.84,.44,1) at 0.15s for hover and 0.45s for reveals. Feels: architectural, precise, engineered, quiet. Avoid: rounded corners, pills, drop-shadow separation, an accent hue in chrome, grey text on dark, weights above 500, or leaving display tracking at normal.
</payload_design_language>
