DoorDash
MIT
Clean, accessible food-delivery system with DoorDash's signature red accent, light neutral palette, and system-font typography—built for rapid product development
Layout StudioImport this kit into a Studio project and start editing.
CLI installRun it in any project. No account needed.
npx @layoutdesign/context install doordash# layout.md — DoorDash Design System
---
## 0. Quick Reference
> Standalone injectable — copy into `CLAUDE.md` or `.cursorrules`
**Stack:** HTML/CSS/React · Token source: reconstructed-from-computed (0 native CSS vars found) · Confidence: low–moderate
**How to apply:** Use as `var(--token-name)` in CSS, `style={{ prop: 'var(--token-name)' }}` in JSX, or `bg-[var(--token-name)]` in Tailwind.
```css
/* ── Core Tokens ── */
--color-text-primary: #313131; /* All headings and body copy */
--color-text-inverse: #ffffff; /* Text on dark/red backgrounds */
--color-surface-page: #f2f2f2; /* Page background */
--color-surface-dark: #1a1a1a; /* Dark nav/footer surfaces */
--color-action-primary: #b20f03; /* DoorDash red — primary CTA bg */
--color-action-primary-hover: #003681;/* CTA hover state */
--color-focus-ring: #4693ff; /* Universal focus outline */
--color-link-default: #0000ee; /* Default link colour */
--color-link-hover-dark: #b9d6ff; /* Link hover on dark bg */
--color-link-hover-light: #003681; /* Link hover on light bg */
--doordash-font-size-xs: 12px; /* Caption, footnote, nav labels */
--doordash-font-size-sm: 16px; /* Body text */
--doordash-font-size-md: 24px; /* Section headings (h2) */
--doordash-font-size-lg: 40px; /* Page title (h1) */
--doordash-font-weight-regular: 400; /* Body, captions */
--doordash-font-weight-medium: 600; /* Headings, CTAs */
--doordash-line-height-tight: 18px; /* xs text */
--doordash-line-height-normal: 30px; /* h2 */
--doordash-line-height-loose: 50px; /* h1 */
--doordash-space-xs: 8px; /* Base grid unit */
--space-sm: 16px; /* Component internal padding */
--space-md: 24px; /* Section inner padding */
--space-lg: 32px; /* Between components */
--space-xl: 48px; /* Between sections */
--font-stack: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
--radius-focus: 2px; /* Focus outline radius */
--ease-default: ease; /* All transitions */
```
```tsx
// Primary CTA Button — correct token usage
<button
className="cta-primary"
style={{
backgroundColor: 'var(--color-action-primary)',
color: 'var(--color-text-inverse)',
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-sm)',
fontWeight: 'var(--doordash-font-weight-medium)',
padding: 'var(--space-sm) var(--space-md)',
border: 'none', borderRadius: '4px', cursor: 'pointer',
transition: 'background-color 0.2s var(--ease-default)',
}}
onMouseEnter={e => e.currentTarget.style.backgroundColor = 'var(--color-action-primary-hover)'}
/>
```
**NEVER rules:**
- NEVER use `Arial`, `Roboto`, or `Inter` as primary font — always start with `system-ui`
- NEVER hardcode `#b20f03` inline — always use `var(--color-action-primary)`
- NEVER omit a `:focus` outline — always use `2px solid var(--color-focus-ring)` with `outline-offset: 2px`
- NEVER use spacing values not on the 8px grid (e.g. `10px`, `15px`, `20px`)
- NEVER use border-radius > `4px` on primary buttons — DoorDash UI is sharp, not pill-shaped
**Full design system → see layout.md**
---
## 1. Design Direction & Philosophy
### Character & Mood
DoorDash's design language is **utilitarian and direct** — designed for speed and clarity under real-world conditions (users ordering food on mobile, often in a hurry). The aesthetic is clean but not decorative; functional but not cold. The DoorDash red (`#b20f03`) is used with restraint as an action signal, not as decoration.
### What This Design Is
- **System-font first:** No custom web font download. `system-ui` ensures native rendering at every OS level — faster, more legible, zero FOIT.
- **High-contrast text:** Near-black `#313131` on white/light surfaces. Dark theme uses `#f2f2f2` reversed on `#1a1a1a`.
- **8px base grid:** All spacing is a multiple of 8px. No exceptions.
- **Accessibility-forward:** Focus states are non-negotiable (`#4693ff` outline, `2px solid`, `2px offset`). Two distinct link themes: light-bg and dark-bg.
- **Sharp, confident UI:** Minimal border-radius. Components feel solid and deliberate.
### What This Design Explicitly Rejects
- **Decorative rounded corners** — no pill buttons, no card radii > 8px without specific reason
- **Warm colour palette** — no yellows, oranges, or peach tones in UI chrome
- **Custom display fonts** — no Google Fonts, no brand-specific typefaces loaded externally
- **Heavy shadows or gradients** — elevation is implied structurally, not through drop shadows
- **Animations for decoration** — motion is reserved for loading states, confirmation, and transitions with semantic meaning
---
## 2. Colour System
### Tier 1 — Primitive Values
```css
/* ── Primitives ── */
--red-700: #b20f03; /* DoorDash brand red — extracted from fade-in-animation keyframe */ /* reconstructed */
--red-900: #7a0a02; /* Deep red — darkened brand red for pressed states */ /* reconstructed */
--navy-900: #003681; /* Deep navy — hover state on light-bg links and CTAs */ /* reconstructed */
--blue-400: #4693ff; /* Focus ring blue — extracted from interactive state rules */ /* extracted: high confidence */
--blue-200: #b9d6ff; /* Hover on dark-bg links */ /* extracted: high confidence */
--grey-900: #313131; /* Primary text — extracted from h1/h2/body computed color */ /* extracted: high confidence */
--grey-800: #262626; /* Hover text on light nav links */ /* extracted: high confidence */
--grey-700: #1a1a1a; /* Dark surface / footer */ /* reconstructed: moderate confidence */
--grey-100: #f2f2f2; /* Page background — extracted from fade-in-animation keyframe */ /* extracted: moderate confidence */
--white: #ffffff; /* Inverse text, light surfaces */
--link-default: #0000ee; /* Browser-default link blue — preserved from computed styles */ /* extracted: high confidence */
```
### Tier 2 — Semantic Aliases
```css
/* ── Semantic Tokens ── */
/* Text */
--color-text-primary: var(--grey-900); /* Body copy, headings — #313131 */ /* reconstructed */
--color-text-muted: var(--grey-800); /* Secondary/nav text — #262626 */ /* reconstructed */
--color-text-inverse: var(--white); /* Text on dark or red surfaces */ /* reconstructed */
--color-text-link: var(--link-default); /* Default hyperlink — #0000ee */ /* reconstructed */
/* Surfaces */
--color-surface-page: var(--grey-100); /* Page/body background — #f2f2f2 */ /* reconstructed */
--color-surface-dark: var(--grey-700); /* Nav bar, footer — #1a1a1a */ /* reconstructed */
--color-surface-white: var(--white); /* Card and modal backgrounds */ /* reconstructed */
/* Actions */
--color-action-primary: var(--red-700); /* Primary CTA bg — #b20f03 */ /* reconstructed */
--color-action-primary-hover: var(--navy-900);/* Primary CTA hover bg — #003681 */ /* reconstructed */
--color-action-primary-pressed: var(--red-900);/* Primary CTA pressed — #7a0a02 */ /* reconstructed */
/* Interactive */
--color-focus-ring: var(--blue-400); /* All :focus/:active outlines — #4693ff */ /* extracted: high confidence */
--color-link-hover-dark: var(--blue-200); /* Link hover on dark bg — #b9d6ff */ /* extracted: high confidence */
--color-link-hover-light: var(--navy-900); /* Link hover on light bg — #003681 */ /* extracted: high confidence */
```
### Tier 3 — Component Tokens
```css
/* ── Component-level Tokens ── */
--btn-primary-bg: var(--color-action-primary);
--btn-primary-bg-hover: var(--color-action-primary-hover);
--btn-primary-text: var(--color-text-inverse);
--btn-focus-outline: 2px solid var(--color-focus-ring);
--btn-focus-offset: 2px;
--nav-bg: var(--color-surface-dark);
--nav-text: var(--color-text-inverse);
--nav-link-hover: var(--color-link-hover-dark);
--link-color: var(--color-text-link);
--link-hover-light: var(--color-link-hover-light);
--link-hover-dark: var(--color-link-hover-dark);
--link-focus-outline: 2px solid var(--color-focus-ring);
--link-focus-radius: 2px;
```
### Colour Mode Notes
The extracted interactive states reveal **two distinct themes** applied via body class:
- `.sZGGP6` → **dark body theme** (dark nav/footer: link hover `#b9d6ff`, text hover `#b9d6ff`)
- `.Tsoxs0` → **light body theme** (light surface: link hover `#003681`, CTA hover `#003681`)
---
## 3. Typography System
NEVER document typography as isolated properties. Always use composite groups.
```css
/* ── Font Stack ── */
--font-stack: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
"Helvetica Neue", Arial, "Noto Sans", sans-serif,
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-stack-mono: monospace; /* Code blocks only */
```
### Composite Typography Tokens
| Token | font-size | font-weight | line-height | Usage |
|---|---|---|---|---|
| `--text-h1` | 40px | 600 | 50px | Page title, hero headline |
| `--text-h2` | 24px | 600 | 30px | Section headings |
| `--text-body` | 16px | 400 | 24px | Body copy, paragraphs |
| `--text-caption` | 12px | 400 | 18px | Labels, footnotes, nav items |
| `--text-code` | 12px (mono) | 400 | 18px | Code blocks |
```css
/* ── Composite Groups (use these, not individual properties) ── */
/* H1 — Page title / hero */
.text-h1 {
font-family: var(--font-stack);
font-size: var(--doordash-font-size-lg); /* 40px */
font-weight: var(--doordash-font-weight-medium); /* 600 */
line-height: var(--doordash-line-height-loose); /* 50px */
letter-spacing: normal;
color: var(--color-text-primary);
}
/* H2 — Section heading */
.text-h2 {
font-family: var(--font-stack);
font-size: var(--doordash-font-size-md); /* 24px */
font-weight: var(--doordash-font-weight-medium); /* 600 */
line-height: var(--doordash-line-height-normal); /* 30px */
letter-spacing: normal;
color: var(--color-text-primary);
margin: var(--doordash-space-xs) 0; /* 8px top/bottom */
}
/* Body — Default paragraph text */
.text-body {
font-family: var(--font-stack);
font-size: var(--doordash-font-size-sm); /* 16px */
font-weight: var(--doordash-font-weight-regular); /* 400 */
line-height: 24px; /* reconstructed: body computed */
letter-spacing: normal;
color: var(--color-text-primary);
margin-bottom: var(--space-lg); /* 32px */
}
/* Caption / Label */
.text-caption {
font-family: var(--font-stack);
font-size: var(--doordash-font-size-xs); /* 12px */
font-weight: var(--doordash-font-weight-regular); /* 400 */
line-height: var(--doordash-line-height-tight); /* 18px */
letter-spacing: normal;
color: var(--color-text-primary);
}
/* Code */
.text-code {
font-family: var(--font-stack-mono);
font-size: var(--doordash-font-size-xs); /* 12px */
font-weight: var(--doordash-font-weight-regular);
line-height: var(--doordash-line-height-tight); /* 18px */
}
```
### Weight Scale
| Token | Value | Usage |
|---|---|---|
| `--doordash-font-weight-regular` | 400 | Body, captions, nav |
| `--doordash-font-weight-medium` | 600 | Headings, buttons, labels |
**No 300 (light), 500 (medium), 700 (bold), or 900 (black) weights are defined in this system.**
---
## 4. Spacing & Layout
**Base unit: 8px.** All spacing is a multiple of `--doordash-space-xs`.
```css
/* ── Spacing Scale (8px grid) ── */
--doordash-space-xs: 8px; /* Base unit — component micro-gaps, margin between labels */ /* extracted: high confidence */
--space-sm: 16px; /* 2× base — button internal padding, tight component gaps */ /* reconstructed */
--space-md: 24px; /* 3× base — card padding, section inner spacing */ /* reconstructed */
--space-lg: 32px; /* 4× base — paragraph margin-bottom, between components */ /* reconstructed */
--space-xl: 48px; /* 6× base — between major page sections */ /* reconstructed */
--space-2xl: 64px; /* 8× base — hero top/bottom padding */ /* reconstructed */
/* ── Grid & Container ── */
--container-max: 1200px; /* Max content width — reconstructed: moderate confidence */
--container-padding: var(--space-md); /* 24px side gutter on desktop */
--container-padding-mobile: var(--doordash-space-xs); /* 8px side gutter on mobile */
/* ── Breakpoints ── */
--bp-sm: 350px; /* Small mobile — extracted from media queries */
--bp-md: 720px; /* Tablet — extracted from media queries */
--bp-lg: 1024px; /* Desktop — extracted from media queries */
/* ── Layout Defaults ── */
--grid-columns-desktop: 12;
--grid-columns-tablet: 8; /* reconstructed: moderate confidence */
--grid-columns-mobile: 4; /* reconstructed: moderate confidence */
--grid-gap: var(--space-md); /* 24px column gap */
```
### Grid & Flex Rules
- **Page containers:** `max-width: var(--container-max)` centred with `margin: 0 auto`
- **Multi-column sections:** Use CSS Grid with `gap: var(--space-md)`
- **Navigation & CTA rows:** Use Flexbox with `align-items: center` and `gap: var(--space-sm)`
- **Single-column mobile:** Stack all grids to 1 column below `720px`
- **No fractional spacing** — `20px`, `10px`, `15px` are forbidden
---
## 5. Page Structure & Layout Patterns
> ⚠️ No screenshots available. All sections inferred from the Layout Digest, computed styles, interactive state data, and DoorDash's known product type (food delivery marketplace). All rows marked **(inferred)** unless anchored to digest data.
### 5.1 Section Map
| # | Section | Layout Type | Approx. Height | Key Elements |
|---|---|---|---|---|
| 1 | **Global Navigation** | Flex row, dark bg | 60–72px | Logo, nav links (dark theme `.sZGGP6`), CTA button (red) |
| 2 | **Hero / Address Entry** (inferred) | Centered column | 400–500px | H1 headline, address/delivery input, primary CTA button |
| 3 | **Category / Cuisine Strip** (inferred) | Horizontal scroll flex | 80–120px | Icon + label tiles, 8px gap |
| 4 | **Feature Grid / Value Props** (inferred) | 3-col grid, desktop; 1-col mobile | 300–400px | H2 + body copy + icon per card |
| 5 | **Restaurant / Merchant Listings** (inferred) | 3–4 col grid | Variable | Restaurant card components |
| 6 | **Promotional Banner** (inferred) | Full-width, dark or red bg | 200–280px | H2, body, CTA button |
| 7 | **App Download CTA** (inferred) | 2-col (text + image) | 300–400px | H2, body, app store badges |
| 8 | **Footer** | Multi-col grid, dark bg | 280–320px | Link columns, legal text (caption), `.sZGGP6` dark theme |
### 5.2 Layout Patterns
**Navigation:**
```
display: flex; justify-content: space-between; align-items: center;
background: var(--color-surface-dark); /* #1a1a1a */
padding: 0 var(--space-md);
height: 64px;
```
Links use dark-theme hover states: `color: var(--color-link-hover-dark)` (`#b9d6ff`) on hover.
**Hero Section (inferred):**
```
display: flex; flex-direction: column; align-items: center;
text-align: center;
padding: var(--space-2xl) var(--space-md);
background: var(--color-surface-page); /* #f2f2f2 */
gap: var(--space-lg); /* 32px between headline, input, CTA */
```
**Feature Grid (inferred):**
```
display: grid;
grid-template-columns: repeat(3, 1fr); /* desktop */
gap: var(--space-md); /* 24px */
@media (max-width: 720px): grid-template-columns: 1fr;
```
**Merchant Card Grid (inferred):**
```
display: grid;
grid-template-columns: repeat(4, 1fr); /* desktop 1024px+ */
grid-template-columns: repeat(2, 1fr); /* tablet 720px–1024px */
grid-template-columns: 1fr; /* mobile <720px */
gap: var(--space-sm); /* 16px */
```
**Footer:**
```
display: grid;
grid-template-columns: repeat(4, 1fr); /* desktop */
gap: var(--space-lg); /* 32px */
background: var(--color-surface-dark);
padding: var(--space-xl) var(--space-md);
color: var(--color-text-inverse);
```
### 5.3 Visual Hierarchy
- **H1** (40px/600) is the dominant visual element — one per page, hero placement
- **H2** (24px/600) anchors section identity; margin `8px 0` keeps it tight to content
- **Primary CTA** (`var(--color-action-primary)` red `#b20f03`) is the single highest-contrast interactive element on every light surface
- **Focus ring** (`#4693ff`, 2px solid) is visible on both dark and light surfaces
- Navigation and footer share the dark surface (`#1a1a1a`), creating visual bookends
- Body text margin-bottom of `32px` creates breathing room between paragraphs without explicit section dividers
### 5.4 Content Patterns
**Repeating pattern — Feature card:**
```
[Icon or Illustration]
[H2 — section heading, 24px/600]
[Body copy — 16px/400, margin-bottom 32px]
[Optional: text link or secondary CTA]
```
**Repeating pattern — Dark banner CTA (inferred):**
```
[H2 — white, on dark surface]
[Body — white, 16px/400]
[Primary button — red #b20f03, white text]
```
**Repeating pattern — Footer link column:**
```
[Column heading — caption 12px/600, white]
[Link list — caption 12px/400, white, hover #b9d6ff]
```
---
## 6. Component Patterns
### 6.1 Primary Button
**Anatomy:** `[button]` → container with text label (no icon by default)
**State table:**
| State | bg | color | border | outline |
|---|---|---|---|---|
| Default | `#b20f03` | `#ffffff` | none | none |
| Hover | `#003681` | `#ffffff` | none | none |
| Focus | `#b20f03` | `#ffffff` | none | `2px solid #4693ff`, offset `2px` |
| Active/Pressed | `#7a0a02` | `#ffffff` | none | none |
| Disabled | `#999999` (reconstructed) | `#cccccc` | none | none |
```tsx
// PrimaryButton.tsx — production-ready with full state handling
import React, { ButtonHTMLAttributes } from 'react';
interface PrimaryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
isLoading?: boolean;
}
export const PrimaryButton: React.FC<PrimaryButtonProps> = ({
children,
isLoading,
disabled,
...props
}) => {
return (
<button
{...props}
disabled={disabled || isLoading}
style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: 'var(--doordash-space-xs)', /* 8px */
backgroundColor: disabled || isLoading
? '#999999' /* reconstructed disabled */
: 'var(--color-action-primary)', /* #b20f03 */
color: disabled || isLoading
? '#cccccc'
: 'var(--color-text-inverse)', /* #ffffff */
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-sm)', /* 16px */
fontWeight: 'var(--doordash-font-weight-medium)', /* 600 */
lineHeight: 'var(--doordash-line-height-tight)', /* 18px */
padding: 'var(--space-sm) var(--space-md)', /* 16px 24px */
border: 'none',
borderRadius: '4px', /* reconstructed: sharp, not pill */
cursor: disabled || isLoading ? 'not-allowed' : 'pointer',
transition: 'background-color 0.2s var(--ease-default)',
outline: 'none',
}}
onMouseEnter={e => {
if (!disabled && !isLoading) {
(e.currentTarget as HTMLButtonElement).style.backgroundColor =
'var(--color-action-primary-hover)'; /* #003681 */
}
}}
onMouseLeave={e => {
if (!disabled && !isLoading) {
(e.currentTarget as HTMLButtonElement).style.backgroundColor =
'var(--color-action-primary)';
}
}}
onFocus={e => {
e.currentTarget.style.outline = '2px solid var(--color-focus-ring)'; /* #4693ff */
e.currentTarget.style.outlineOffset = '2px';
e.currentTarget.style.borderRadius = 'var(--radius-focus)'; /* 2px */
}}
onBlur={e => {
e.currentTarget.style.outline = 'none';
}}
>
{isLoading ? <span aria-label="Loading">•••</span> : children}
</button>
);
};
```
---
### 6.2 Text Link
**Anatomy:** `<a>` with text content, optional underline
**State table:**
| State | color | decoration | outline |
|---|---|---|---|
| Default | `#0000ee` | underline | none |
| Hover (light bg) | `#003681` | underline | none |
| Hover (dark bg) | `#b9d6ff` | underline | none |
| Focus/Active | unchanged | underline | `2px solid #4693ff`, offset `2px`, radius `2px` |
```tsx
// Link.tsx
interface LinkProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
theme?: 'light' | 'dark'; /* light = on light bg, dark = on dark bg */
}
export const Link: React.FC<LinkProps> = ({ theme = 'light', children, ...props }) => (
<a
{...props}
style={{
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-xs)', /* 12px — nav/footer context */
fontWeight: 'var(--doordash-font-weight-regular)',
lineHeight: 'var(--doordash-line-height-tight)', /* 18px */
color: 'var(--color-text-link)', /* #0000ee default */
textDecoration: 'underline',
transition: 'color 0.2s var(--ease-default)',
outline: 'none',
borderRadius: 'var(--radius-focus)', /* 2px — for focus outline */
}}
onMouseEnter={e => {
e.currentTarget.style.color = theme === 'dark'
? 'var(--color-link-hover-dark)' /* #b9d6ff */
: 'var(--color-link-hover-light)'; /* #003681 */
}}
onMouseLeave={e => { e.currentTarget.style.color = 'var(--color-text-link)'; }}
onFocus={e => {
e.currentTarget.style.outline = '2px solid var(--color-focus-ring)';
e.currentTarget.style.outlineOffset = '2px';
}}
onBlur={e => { e.currentTarget.style.outline = 'none'; }}
>
{children}
</a>
);
```
---
### 6.3 Navigation Bar
**Anatomy:** `[nav]` → `[logo]` + `[nav-links flex row]` + `[CTA button]`
```tsx
// NavBar.tsx (inferred structure, anchored to dark theme token values)
export const NavBar: React.FC = () => (
<nav style={{
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
backgroundColor: 'var(--color-surface-dark)', /* #1a1a1a */
padding: `0 var(--space-md)`, /* 0 24px */
height: '64px',
position: 'sticky',
top: 0,
zIndex: 100,
}}>
<a href="/" style={{ color: 'var(--color-text-inverse)', fontWeight: 600 }}>
DoorDash
</a>
<div style={{ display: 'flex', gap: 'var(--space-sm)', alignItems: 'center' }}>
{['Home', 'Pickup', 'DashPass'].map(label => (
<a
key={label}
href="#"
style={{
color: 'var(--color-text-inverse)',
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-xs)', /* 12px */
fontWeight: 'var(--doordash-font-weight-regular)',
textDecoration: 'none',
transition: 'color 0.2s var(--ease-default)',
borderRadius: 'var(--radius-focus)',
outline: 'none',
}}
onMouseEnter={e => { e.currentTarget.style.color = 'var(--color-link-hover-dark)'; /* #b9d6ff */ }}
onMouseLeave={e => { e.currentTarget.style.color = 'var(--color-text-inverse)'; }}
onFocus={e => { e.currentTarget.style.outline = '2px solid var(--color-focus-ring)'; e.currentTarget.style.outlineOffset = '2px'; }}
onBlur={e => { e.currentTarget.style.outline = 'none'; }}
>
{label}
</a>
))}
</div>
<PrimaryButton>Sign up</PrimaryButton>
</nav>
);
```
---
### 6.4 Section Heading Block
**Anatomy:** Optional eyebrow + `<h2>` + body paragraph + optional CTA link
```tsx
export const SectionHeading: React.FC<{
heading: string;
body: string;
}> = ({ heading, body }) => (
<div style={{ maxWidth: '640px' }}>
<h2 style={{
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-md)', /* 24px */
fontWeight: 'var(--doordash-font-weight-medium)',/* 600 */
lineHeight: 'var(--doordash-line-height-normal)',/* 30px */
color: 'var(--color-text-primary)', /* #313131 */
margin: 'var(--doordash-space-xs) 0', /* 8px 0 */
}}>
{heading}
</h2>
<p style={{
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-sm)', /* 16px */
fontWeight: 'var(--doordash-font-weight-regular)',
lineHeight: '24px',
color: 'var(--color-text-primary)',
marginBottom: 'var(--space-lg)', /* 32px */
}}>
{body}
</p>
</div>
);
```
---
### 6.5 Input Field (Address/Search)
**Anatomy:** `[label]` + `[input wrapper]` → `[input]` + optional `[submit button]`
**State table:**
| State | border | outline |
|---|---|---|
| Default | `1px solid #cccccc` | none |
| Focus/Active | `1px solid #4693ff` | `2px solid #4693ff`, offset `2px`, radius `2px` |
| Error (inferred) | `1px solid #b20f03` | none |
```tsx
// The `.qXkva7 input:focus ~ .QiqSW3` rule confirms focus state styling on sibling elements
export const AddressInput: React.FC = () => (
<div style={{ position: 'relative', display: 'flex' }}>
<input
type="text"
placeholder="Enter delivery address"
style={{
fontFamily: 'var(--font-stack)',
fontSize: 'var(--doordash-font-size-sm)', /* 16px */
fontWeight: 'var(--doordash-font-weight-regular)',
lineHeight: 'var(--doordash-line-height-tight)', /* 18px */
color: 'var(--color-text-primary)',
padding: 'var(--space-sm)', /* 16px */
border: '1px solid #cccccc', /* reconstructed */
borderRadius: '4px 0 0 4px',
outline: 'none',
width: '100%',
}}
onFocus={e => {
e.currentTarget.style.outline = '2px solid var(--color-focus-ring)';
e.currentTarget.style.outlineOffset = '2px';
}}
onBlur={e => { e.currentTarget.style.outline = 'none'; }}
/>
<PrimaryButton style={{ borderRadius: '0 4px 4px 0' }}>Find Food</PrimaryButton>
</div>
);
```
---
## 7. Elevation & Depth
```css
/* ── Shadow Scale ── */
/* reconstructed: low confidence — no box-shadow values found in extracted styles */
--shadow-none: none; /* Default state for all elements */
--shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.12); /* Card resting state */ /* reconstructed */
--shadow-md: 0 4px 12px rgba(0, 0, 0, 0.16); /* Modal, dropdown resting */ /* reconstructed */
--shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.20); /* Sticky nav on scroll */ /* reconstructed */
/* ── Border Scale ── */
--border-default: 1px solid #cccccc; /* Input default, card outline */ /* reconstructed */
--border-focus: 2px solid var(--color-focus-ring); /* All focus states */ /* extracted: high confidence */
--border-error: 1px solid var(--color-action-primary); /* Error state border */ /* reconstructed */
/* ── Border Radius Scale ── */
--radius-none: 0px; /* Headings, block elements */
--radius-focus: 2px; /* Focus outline radius — extracted from interactive state rules */ /* extracted: high confidence */
--radius-sm: 4px; /* Buttons, inputs — primary radius */ /* reconstructed: moderate confidence */
--radius-md: 8px; /* Cards — secondary radius */ /* reconstructed: moderate confidence */
/* ── Z-Index Scale ── */
--z-base: 0;
--z-raised: 10; /* Cards on hover */
--z-dropdown: 50; /* Dropdown menus */
--z-sticky: 100; /* Sticky nav */
--z-modal: 200; /* Overlays and modals */
--z-toast: 300; /* Notification toasts */
```
**Key principle:** DoorDash uses **structural hierarchy**, not heavy shadows. Rely on surface colour contrast (`--color-surface-dark` vs `--color-surface-page`) over multiple shadow layers.
---
## 8. Motion
```css
/* ── Timing Functions ── */
--ease-default: ease; /* Universal — extracted: high confidence */
/* Note: no cubic-bezier custom easings extracted. Use native ease for all transitions. */
/* ── Duration Scale ── */
--duration-fast: 150ms; /* Hover colour changes, focus ring appearance */ /* reconstructed */
--duration-base: 200ms; /* Button state transitions, link colour */ /* reconstructed */
--duration-slow: 300ms; /* Panel slides, dropdown reveals */ /* reconstructed */
--duration-page: 400ms; /* Page-level fade-ins */ /* reconstructed */
```
### Named Keyframe Animations
| Token | Keyframe | Use case |
|---|---|---|
| `--motion-fade-in` | `0% opacity:0 → 100% opacity:1` | Page/section entrance |
| `--motion-scale-up-center` | `scale(0.01) → scale(1)` | Modal/popover entrance |
| `--motion-spin` | `rotate 0 → 360deg` | Loading spinner |
| `--motion-lds-ring` | `rotate 0 → 360deg` | Ring-style loader |
| `--motion-fireworks` | `scale + opacity burst` | Confirmation/success celebration |
| `--motion-dots` | content `"" → "." → ".." → "..."` | Text loading state |
| `--motion-fade-in-animation` | fill/stroke colour shift | Icon/SVG state transition |
| `--motion-stroke` | stroke-dashoffset → 0 | SVG draw-on animation |
| `--motion-firework` | opacity + stroke-dashoffset | SVG firework particle |
| `--motion-unspin` | stroke-width fade out | Loader exit |
| `--motion-scale` | none → scale3d(1,1,1) → none | Pulse/bounce effect |
| `--motion-unspin` | stroke fade | Loader completion |
### Motion Rules
- **Loading states** → use `--motion-spin` or `--motion-lds-ring` with `--duration-base` per cycle
- **Confirmations/success** → use `--motion-fireworks` sparingly, once per action
- **Entrances** → use `--motion-fade-in` with `--duration-page` for sections, `--motion-scale-up-center` for modals
- **Hover/focus transitions** → use `transition: background-color var(--duration-base) var(--ease-default)` only
- **NEVER animate layout properties** (`width`, `height`, `margin`, `padding`) — animate `transform` and `opacity` only
- **Respect `prefers-reduced-motion`:**
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}
```
---
## 9. Anti-Patterns & Constraints
1. **NEVER hardcode colour hex values inline.**
→ **Why it fails:** When the DoorDash brand red `#b20f03` appears in 30 components as literals, a single brand update requires a global find-and-replace across the codebase, and AI agents will generate inconsistent variants (`#b10f03`, `#b30f03`) because they interpolate rather than copy-paste.
→ **Instead:** Always use `var(--color-action-primary)`. All colour decisions live in one place.
2. **NEVER use `Arial`, `Roboto`, or `Inter` as the primary font-family.**
→ **Why it fails:** AI agents default to `font-family: 'Inter', sans-serif` because it appears in most training examples. DoorDash uses `system-ui` first — `Inter` adds a network request and renders differently from the native system font, breaking the brand's native-feeling aesthetic.
→ **Instead:** Always start with `var(--font-stack)` which begins with `system-ui`.
3. **NEVER omit `:focus` and `:focus-visible` states.**
→ **Why it fails:** AI agents generate hover states but skip focus because hover is visually obvious in previews. DoorDash's extracted CSS has explicit focus rules on links, inputs, and buttons (`#4693ff` outline). Omitting them breaks keyboard navigation and accessibility compliance.
→ **Instead:** Every interactive element must include `outline: 2px solid var(--color-focus-ring); outline-offset: 2px; border-radius: var(--radius-focus)`.
4. **NEVER use spacing values outside the 8px grid (e.g., `10px`, `15px`, `20px`, `25px`).**
→ **Why it fails:** AI agents generate "visually close" spacing by feel — `margin: 10px` instead of `8px`, `padding: 20px` instead of `16px`. This accumulates across components and breaks visual rhythm. The body element's margin-bottom of `32px` (4×8) and h2's margin of `8px` (1×8) confirm a strict 8px grid.
→ **Instead:** Only use `8px`, `16px`, `24px`, `32px`, `48px`, `64px` or their CSS variable equivalents.
5. **NEVER make primary buttons pill-shaped (border-radius ≥ 50px).**
→ **Why it fails:** AI agents trained on modern UI patterns default to `border-radius: 9999px` for CTAs. DoorDash's focus radius is `2px`, extracted from real CSS. The brand UI is sharp and direct — pill shapes contradict the utilitarian aesthetic.
→ **Instead:** Use `border-radius: var(--radius-sm)` (4px) for buttons.
6. **NEVER use `!important` to override component styles.**
→ **Why it fails:** AI agents use `!important` when specificity conflicts arise, masking genuine architectural problems. On DoorDash, two body themes (`.sZGGP6`, `.Tsoxs0`) handle surface-specific overrides cleanly through class scoping — `!important` would break this cascade.
→ **Instead:** Resolve specificity through component class scoping or CSS custom property overrides.
7. **NEVER construct Tailwind class names dynamically (`bg-[${color}]`).**
→ **Why it fails:** Tailwind's JIT compiler scans for static class strings. Dynamically constructed classes like `bg-[${themeColor}]` are invisible to the scanner and never included in the CSS output — the style silently fails in production.
→ **Instead:** Use `style={{ backgroundColor: 'var(--color-action-primary)' }}` for dynamic values, or map states to static Tailwind classes.
8. **NEVER apply hover state colours as the default state.**
→ **Why it fails:** AI agents sometimes merge hover styles into the default style when consolidating code. For DoorDash, `#003681` (navy) is *only* the hover colour — making it the default colour removes the visual feedback that a link/button is interactive.
→ **Instead:** Keep default and hover states explicit and separate in every component.
9. **NEVER use absolute positioning to create page layout structure.**
→ **Why it fails:** AI agents use `position: absolute` with hardcoded pixel offsets to align multi-column content. This breaks entirely when text reflows across breakpoints (350px, 720px, 1024px). The navigation bar is `sticky`, not absolute.
→ **Instead:** Use CSS Grid for page-level layout, Flexbox for component-level alignment. Reserve `position: absolute` for overlays (tooltips, dropdowns) and decorative pseudo-elements.
10. **NEVER leave link colour as browser default (`#0000ee`) in nav or footer contexts.**
→ **Why it fails:** The browser default blue `#0000ee` extracted from the link styles is the *base* state on body copy, not nav links. Nav links on the dark surface (`--color-surface-dark`) use white (`#ffffff`) by default and `#b9d6ff` on hover. Using the body link colour in nav creates low-contrast unreadable links on dark backgrounds.
→ **Instead:** Use the `theme` prop pattern (see `Link` component) and apply `var(--color-text-inverse)` as the default for dark-surface links.
---
## Appendix A: Complete Token Reference
Every token extracted from the source. §0 CORE TOKENS is the primary AI signal; this appendix is reference material an AI can cross-check against when a curated role is missing.
```css
/* Colours (33) */
--color-text-primary: #313131;
--color-text-inverse: #ffffff;
--color-surface-page: #f2f2f2;
--color-surface-dark: #1a1a1a;
--color-action-primary: #b20f03;
--color-action-primary-hover: #003681;
--color-focus-ring: #4693ff;
--color-link-default: #0000ee;
--color-link-hover-dark: #b9d6ff;
--color-link-hover-light: #003681;
--red-700: #b20f03;
--red-900: #7a0a02;
--navy-900: #003681;
--blue-400: #4693ff;
--blue-200: #b9d6ff;
--grey-900: #313131;
--grey-800: #262626;
--grey-700: #1a1a1a;
--grey-100: #f2f2f2;
--white: #ffffff;
--link-default: #0000ee;
--color-text-muted: var(--grey-800);
--color-text-link: var(--link-default);
--color-surface-white: var(--white);
--color-action-primary-pressed: var(--red-900);
--btn-primary-bg: var(--color-action-primary);
--btn-primary-bg-hover: var(--color-action-primary-hover);
--nav-bg: var(--color-surface-dark);
--link-color: var(--color-text-link);
--border-default: 1px solid #cccccc;
--border-focus: 2px solid var(--color-focus-ring);
--border-error: 1px solid var(--color-action-primary);
--motion-stroke: stroke-dashoffset → 0;
/* Typography (27) */
--font-size-xs: 12px; /* 3 elements — e.g. span "Performance and Secu", a "Cloudflare", a "Privacy" /* mined from computed styles */ */
--font-size-sm: 16px; /* 1 element — e.g. p "This website uses a " /* mined from computed styles */ */
--font-size-md: 24px; /* 1 element — e.g. h2 "Performing security " /* mined from computed styles */ */
--font-size-lg: 40px; /* 1 element — e.g. h1 "www.doordash.com" /* mined from computed styles */ */
--font-weight-regular: 400; /* 4 elements — e.g. p "This website uses a ", span "Performance and Secu", a "Cloudflare" /* mined from computed styles */ */
--font-weight-medium: 600; /* 2 elements — e.g. h1 "www.doordash.com", h2 "Performing security " /* mined from computed styles */ */
--line-height-tight: 18px; /* 3 elements — e.g. span "Performance and Secu", a "Cloudflare", a "Privacy" /* mined from computed styles */ */
--line-height-normal: 30px; /* 1 element — e.g. h2 "Performing security " /* mined from computed styles */ */
--line-height-loose: 50px; /* 1 element — e.g. h1 "www.doordash.com" /* mined from computed styles */ */
--doordash-font-size-xs: 12px;
--doordash-font-size-sm: 16px;
--doordash-font-size-md: 24px;
--doordash-font-size-lg: 40px;
--doordash-font-weight-regular: 400;
--doordash-font-weight-medium: 600;
--doordash-line-height-tight: 18px;
--doordash-line-height-normal: 30px;
--doordash-line-height-loose: 50px;
--font-stack: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, ...emoji;
--btn-primary-text: var(--color-text-inverse);
--nav-text: var(--color-text-inverse);
--font-stack-mono: monospace;
--text-h1: 40px;
--text-h2: 24px;
--text-body: 16px;
--text-caption: 12px;
--text-code: 12px (mono);
/* Spacing (15) */
--space-xs: 8px; /* 3 elements — e.g. div .footer-link-wrapper, div .footer-link-wrapper, div .footer-link-wrapper /* mined from computed styles */ */
--doordash-space-xs: 8px;
--space-sm: 16px;
--space-md: 24px;
--space-lg: 32px;
--space-xl: 48px;
--btn-focus-offset: 2px;
--space-2xl: 64px;
--container-max: 1200px;
--container-padding: var(--space-md);
--container-padding-mobile: var(--doordash-space-xs);
--bp-sm: 350px;
--bp-md: 720px;
--bp-lg: 1024px;
--grid-gap: var(--space-md);
/* Radius (5) */
--radius-focus: 2px;
--link-focus-radius: 2px;
--radius-none: 0px;
--radius-sm: 4px;
--radius-md: 8px;
/* Effects (4) */
--shadow-none: none;
--shadow-sm: 0 1px 3px rgba(0,0,0,0.12);
--shadow-md: 0 4px 12px rgba(0,0,0,0.16);
--shadow-lg: 0 8px 24px rgba(0,0,0,0.20);
/* Motion (12) */
----motion-spin: @keyframes spin {
100% { transform: rotate(360deg); }
}; /* @keyframes spin */
----motion-scale: @keyframes scale {
0%, 100% { transform: none; }
50% { transform: scale3d(1, 1, 1); }
}; /* @keyframes scale */
----motion-stroke: @keyframes stroke {
100% { stroke-dashoffset: 0; }
}; /* @keyframes stroke */
----motion-scale-up-center: @keyframes scale-up-center {
0% { transform: scale(0.01); }
100% { transform: scale(1); }
}; /* @keyframes scale-up-center */
----motion-fade-in: @keyframes fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes fade-in */
----motion-fireworks: @keyframes fireworks {
0% { transform: scale(0); opacity: 0; }
50% { transform: scale(1.5); opacity: 1; }
100% { transform: scale(2); opacity: 0; }
}; /* @keyframes fireworks */
----motion-firework: @keyframes firework {
0% { opacity: 0; stroke-dashoffset: 8; }
30% { opacity: 1; }
100% { stroke-dashoffset: -8; }
}; /* @keyframes firework */
----motion-unspin: @keyframes unspin {
40% { stroke-width: 1px; stroke-linecap: square; stroke-dashoffset: 192; }
100% { stroke-width: 0; }
}; /* @keyframes unspin */
----motion-fade-in-animation: @keyframes fade-in-animation {
0% { fill: rgb(178, 15, 3); stroke: rgb(178, 15, 3); }
100% { fill: rgb(242, 242, 242); stroke: rgb(242, 242, 242); }
}; /* @keyframes fade-in-animation */
----motion-dots: @keyframes dots {
0% { content: ""; }
25% { content: "."; }
50% { content: ".."; }
75% { content: "..."; }
100% { content: ""; }
}; /* @keyframes dots */
----motion-lds-ring: @keyframes lds-ring {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}; /* @keyframes lds-ring */
--ease-default: ease; /* 8 elements — e.g. a, a, a /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```yaml
tokenSource: reconstructed-from-computed
siteUrl: doordash.com
extractionDate: "[TBD - update on re-extraction]"
nativeCSSVarsFound: 0
curatedTokensProvided: 11
totalSynthesisedTokens: ~65
confidenceLevels:
high:
- All font-size, font-weight, line-height values (curated kit, 5+ element matches)
- focus ring colour #4693ff (extracted from 6 distinct interactive state rules)
- link hover dark bg #b9d6ff (extracted from named class rules)
- link hover light bg #003681 (extracted from named class rules)
- CTA hover bg #003681 (extracted from .bqXP8:hover rule)
- body text colour #313131 (extracted from h1/h2/body computed color)
- ease-default: ease (extracted from 8 computed transition values)
moderate:
- brand red #b20f03 (inferred from fade-in-animation keyframe fill value)
- page background #f2f2f2 (inferred from fade-in-animation keyframe fill target)
- dark surface #1a1a1a (inferred from dark text hover #262626 and near-black surface)
- border-radius 4px on buttons (inferred from focus radius 2px + sharp design direction)
- spacing scale 8/16/24/32/48/64px (anchored to body margin-bottom:32px, h2 margin:8px)
- container max-width 1200px (common DoorDash-type marketplace convention)
low:
- box-shadow values (no shadow data in extraction — fabrication risk, mark as [TBD])
- disabled state colours #999999/#cccccc (no disabled state data extracted)
- grid column counts (inferred from breakpoints only)
- section heights (no DOM measurement data)
clusteringMethod: |
Colours clustered by hue family:
- Near-black greys (#313131, #262626, #1a1a1a) → grey scale
- Blues (#0000ee, #4693ff, #b9d6ff, #003681) → interactive/focus blue family
- Reds (#b20f03, from keyframe) → action/brand red
- Whites/lights (#ffffff, #f2f2f2) → surface family
Spacing clustered on 8px grid confirmed by:
- body margin-bottom: 32px (4×8)
- h2 margin: 8px 0 (1×8)
- curated --doordash-space-xs: 8px
Typography: direct extraction from computed styles, no clustering required.
themeSystem: |
Two body-class themes detected:
.sZGGP6 → dark surface theme (nav/footer context)
.Tsoxs0 → light surface theme (page content context)
These are NOT light/dark mode — they are surface-scoped link colour variants.
CSS custom properties absent; theming done via class-scoped overrides.
notes: |
- This is a Cloudflare challenge/security page for doordash.com, NOT the main app UI.
Token extraction reflects the challenge page structure (h1: "www.doordash.com",
h2: "Performing security check"). The main DoorDash product UI may have substantially
richer tokens. Re-extract from an authenticated session for production use.
- The brand red #b20f03 should be validated against official DoorDash brand assets.
- Font: system-ui is confirmed correct — no web font loading detected.
- [TBD - validate shadow tokens against real product screenshots]
```More from the gallery
Browse all kits →You may also like

Contra
MITPlayful yet professional design system with teal and purple accents, bold typography, and vibrant accent surfaces—built for modern SaaS platforms and landing pages
03
lightboldsaaslanding-page

Mercedes-Benz
MITLuxe, minimalist design system with sharp black-and-white contrast and serif typography, crafted for premium automotive and lifestyle brands
05
darkminimalboldecomm

Wise
MITClean, accessible financial design system with lime-green accents and Swiss typography, built for fintech products that prioritise clarity and trust
05
lightfintechminimalsaas