Headspace
MIT
Wellness-focused design system with vibrant accent colours and rounded, approachable typography; ideal for meditation, mental health and wellbeing applications
Layout StudioImport this kit into a Studio project and start editing.
CLI installRun it in any project. No account needed.
npx @layoutdesign/context install headspace# layout.md — Headspace Design System
---
## 0. Quick Reference
**Stack:** Next.js · CSS-in-JS (Emotion, hashed classnames) · No native CSS custom properties — tokens reconstructed from computed styles.
**How to apply:** Use as `var(--headspace-*)` in CSS, `style={{ prop: 'var(--headspace-*)' }}` in JSX, or `bg-[var(--headspace-*)]` in Tailwind.
```css
:root {
/* ── Colours ── */
--headspace-bg-surface: rgb(0, 97, 239); /* Primary blue — hero/CTA backgrounds */
--headspace-accent: rgb(255, 206, 0); /* Yellow — section accent backgrounds */
--headspace-bg-app: rgb(255, 161, 204);/* Pink — feature section backgrounds */
--headspace-color-purple: rgb(59, 25, 127); /* Purple — bedtime/sleep sections */
--headspace-text-primary: rgb(45, 44, 43); /* Near-black — all body & heading text */
--headspace-text-muted: rgb(75, 76, 77); /* Muted grey — nav, alert, secondary text */
--headspace-surface-white:rgb(255, 255, 255);/* White — cards, inputs, modals */
--headspace-border: rgb(226, 222, 217);/* Warm grey — button/input borders */
--headspace-focus-ring: rgb(0, 64, 234); /* Keyboard focus outline colour */
/* ── Typography ── */
--headspace-font-family: "Headspace Apercu", sans-serif;
--headspace-font-size-xs: 12px;
--headspace-font-size-sm: 16px;
--headspace-font-size-md: 18px;
--headspace-font-size-lg: 20px;
--headspace-font-size-xl: 24px;
--headspace-font-size-2xl:32px;
--headspace-font-size-3xl:40px;
--headspace-font-size-h2: 52px; /* Page-level headings only */
/* ── Spacing ── */
--headspace-space-xs: 24px;
--headspace-space-sm: 32px;
--headspace-space-md: 40px;
--headspace-space-lg: 48px;
/* ── Radius ── */
--headspace-radius-sm: 2px;
--headspace-radius-md: 8px;
--headspace-radius-lg: 24px;
--headspace-radius-full: 32px; /* pill — primary CTA buttons */
/* ── Motion ── */
--headspace-duration-fast: 0.15s;
--headspace-duration-base: 0.3s;
--headspace-duration-slow: 0.4s;
--headspace-ease-default: cubic-bezier(0.32, 0, 0.67, 0);
}
```
```tsx
// Primary CTA Button — all states
<button
className="hs-btn-primary"
style={{
fontFamily: 'var(--headspace-font-family)',
fontSize: 'var(--headspace-font-size-sm)',
borderRadius: 'var(--headspace-radius-full)',
backgroundColor: 'var(--headspace-bg-surface)',
color: 'var(--headspace-surface-white)',
padding: '14px 32px',
transition: `background-color var(--headspace-duration-base) var(--headspace-ease-default)`,
}}
>Try for free</button>
```
**NEVER rules:**
- NEVER use Inter, Roboto, or system-ui — always `"Headspace Apercu", sans-serif`
- NEVER use rounded corners > 32px on buttons (pill = 32px, not `9999px`)
- NEVER hardcode `#0061ef` — always `var(--headspace-bg-surface)`
- NEVER omit a `focus-visible` outline — use `2px solid var(--headspace-focus-ring)`
- NEVER use warm green `rgb(2, 135, 62)` as body text — it is a section background only
- NEVER construct Tailwind classes dynamically (e.g. `bg-[${color}]`)
- NEVER use arbitrary spacing not in the scale (24/32/40/48px)
**Full design system → see layout.md**
<!-- Quick Reference truncated to fit the 75-line cap. See later sections for the full design system. -->
## 1. Design Direction & Philosophy
### Character & Mood
Headspace is a **calm, confident, and playful wellness brand**. The visual language communicates approachability without being childish, and clarity without being clinical. Colour is used structurally — large saturated section backgrounds create emotional zones (blue = action/trust, yellow = energy/positivity, pink = warmth, purple = rest). White space and generous padding signal unhurried ease.
### What This Design Is
- **Bold type on saturated colour** — headings are heavy (700) at large sizes; sections use full-bleed colour fields rather than borders or cards to separate content zones
- **Rounded but not bubbly** — pill-shaped buttons (32px radius) feel modern and approachable; content cards use 8px or 24px radius, not infinite rounding
- **Restrained palette** — five expressive brand colours, each assigned to a semantic section type; never mixed arbitrarily
- **Apercu as identity** — the proprietary `Headspace Apercu` typeface is non-negotiable brand identity; it is never substituted
### What This Design Explicitly Rejects
- Drop shadows as decorative elements (shadows are used sparingly, only on modals: `rgba(20,19,19,0.2) 0px 1px 8px 0px`)
- Gradients on text or backgrounds (no `background-image` gradients found)
- All-caps labels or tracking-heavy type
- Hard edges — every interactive element has at minimum `--headspace-radius-md` (8px)
- Generic sans-serif fallbacks (Arial, Helvetica, system-ui) as primary type
- Dark mode (no dark-mode media query detected; light surface is canonical)
- Dense layouts — sections breathe with 40–48px gaps minimum
---
## 2. Colour System
### Tier 1 — Primitives
```css
:root {
/* Blues */
--primitive-blue-500: rgb(0, 97, 239); /* Brand blue */
--primitive-blue-600: rgb(0, 64, 234); /* Hover/focus blue */
--primitive-blue-700: rgb(0, 0, 219); /* Active/pressed blue */
--primitive-blue-400: rgb(56, 96, 190); /* Link hover */
/* Yellows */
--primitive-yellow-400: rgb(255, 206, 0);
/* Pinks */
--primitive-pink-300: rgb(255, 161, 204);
/* Purples */
--primitive-purple-700: rgb(59, 25, 127);
/* Greens */
--primitive-green-600: rgb(2, 135, 62); /* Section background only */
/* Neutrals */
--primitive-neutral-900: rgb(45, 44, 43);
--primitive-neutral-700: rgb(75, 76, 77);
--primitive-neutral-600: rgb(68, 66, 63);
--primitive-neutral-200: rgb(226, 222, 217);
--primitive-neutral-100: rgb(210, 213, 222);
--primitive-neutral-50: rgb(249, 244, 242);
--primitive-white: rgb(255, 255, 255);
--primitive-black: rgb(0, 0, 0);
}
```
### Tier 2 — Semantic Aliases
```css
:root {
/* ── Backgrounds ── */
--headspace-bg-surface: var(--primitive-blue-500); /* Primary brand section bg; "Try for free" hero */
--headspace-accent: var(--primitive-yellow-400); /* Highlight/accent section bg */
--headspace-bg-app: var(--primitive-pink-300); /* Feature section bg — feel-good/library */
--headspace-color-purple: var(--primitive-purple-700); /* Bedtime/sleep section bg */
--headspace-color-green: var(--primitive-green-600); /* Exercise/movement section bg */
--headspace-surface-white: var(--primitive-white); /* Card, modal, input backgrounds */
--headspace-surface-subtle: var(--primitive-neutral-50); /* Disabled state background */
/* ── Text ── */
--headspace-text-primary: var(--primitive-neutral-900);/* Body copy, headings */
--headspace-text-muted: var(--primitive-neutral-700);/* Navigation, secondary labels */
--headspace-text-inverse: var(--primitive-white); /* Text on coloured backgrounds */
--headspace-text-on-input: var(--primitive-black); /* Input field text */
/* ── Borders ── */
--headspace-border: var(--primitive-neutral-200);/* Default button/card border */
--headspace-border-input: var(--primitive-neutral-100);/* Input field border */
--headspace-border-focus: var(--primitive-black); /* OneTrust / cookie focus rings */
/* ── Interactive ── */
--headspace-focus-ring: var(--primitive-blue-600); /* Keyboard focus outline — brand UI */
--headspace-btn-hover-bg: var(--primitive-blue-600); /* Primary button hover state */
--headspace-btn-active-bg: var(--primitive-blue-700); /* Primary button active/pressed state */
/* ── Shadow ── */
--headspace-shadow-modal: rgba(20, 19, 19, 0.2) 0px 1px 8px 0px;
}
```
### Colour Palette Reference
| Token | Value | Usage |
|---|---|---|
| `--headspace-bg-surface` | `rgb(0, 97, 239)` | Hero, primary CTA, action sections |
| `--headspace-accent` | `rgb(255, 206, 0)` | Highlight/energy sections |
| `--headspace-bg-app` | `rgb(255, 161, 204)` | Feature/library sections |
| `--headspace-color-purple` | `rgb(59, 25, 127)` | Sleep/bedtime sections |
| `--headspace-color-green` | `rgb(2, 135, 62)` | Exercise/movement sections |
| `--headspace-text-primary` | `rgb(45, 44, 43)` | All body text, headings |
| `--headspace-text-muted` | `rgb(75, 76, 77)` | Nav links, secondary copy |
| `--headspace-surface-white` | `rgb(255, 255, 255)` | Cards, inputs, modals |
| `--headspace-focus-ring` | `rgb(0, 64, 234)` | Keyboard focus outline |
> **Note:** The five brand surface colours (`blue`, `yellow`, `pink`, `purple`, `green`) are each assigned to a specific content zone. They are NEVER used interchangeably or mixed as gradients.
---
## 3. Typography System
### Font Stack
```css
/* Primary — always use this */
font-family: "Headspace Apercu", sans-serif;
/* Monospace variant — code, data labels only */
font-family: "Apercu Pro Mono", monospace;
```
**Weight scale:** `200` (Light) · `400` (Regular) · `500` (Medium) · `600` (Medium/Semibold in font, maps to `font-weight:600`) · `700` (Bold)
Note: The font file named "Medium" is loaded at `weight: 600` — use `font-weight: 600` when you want the "medium" optical weight from the font files.
### Composite Type Scales
```css
/* ── Display / H1 equivalent ── */
.type-display {
font-family: "Headspace Apercu", sans-serif;
font-size: 52px; /* --headspace-font-size-h2 (largest extracted) */
font-weight: 700;
line-height: 57.2px; /* ~1.1 ratio */
letter-spacing: -1.56px;
color: var(--headspace-text-primary);
/* reconstructed: high confidence — directly from h2 computed styles */
}
/* ── Heading 3 / Section Title ── */
.type-h3 {
font-family: "Headspace Apercu", sans-serif;
font-size: 40px; /* --headspace-font-size-3xl */
font-weight: 700;
line-height: 46px; /* ~1.15 ratio */
letter-spacing: -1.2px;
color: var(--headspace-text-primary);
/* extracted: high confidence */
}
/* ── Heading 4 / Card Title ── */
.type-h4 {
font-family: "Headspace Apercu", sans-serif;
font-size: 32px; /* --headspace-font-size-2xl */
font-weight: 700;
line-height: 38.4px; /* --headspace-line-height-loose */
letter-spacing: -0.96px; /* reconstructed: moderate confidence, scaled from h3 ratio */
color: var(--headspace-text-primary);
}
/* ── Subheading / Feature Title ── */
.type-h5 {
font-family: "Headspace Apercu", sans-serif;
font-size: 24px; /* --headspace-font-size-xl */
font-weight: 700;
line-height: 28px; /* reconstructed: moderate confidence */
letter-spacing: -0.48px;
color: var(--headspace-text-primary);
}
/* ── Body Large ── */
.type-body-lg {
font-family: "Headspace Apercu", sans-serif;
font-size: 20px; /* --headspace-font-size-lg */
font-weight: 500;
line-height: 28px; /* reconstructed: moderate confidence */
letter-spacing: -0.2px;
color: var(--headspace-text-primary);
}
/* ── Body Default ── */
.type-body {
font-family: "Headspace Apercu", sans-serif;
font-size: 18px; /* --headspace-font-size-md */
font-weight: 500;
line-height: 26px; /* extracted: high confidence */
letter-spacing: -0.18px;
color: var(--headspace-text-primary);
}
/* ── Body Small / UI Text ── */
.type-body-sm {
font-family: "Headspace Apercu", sans-serif;
font-size: 16px; /* --headspace-font-size-sm */
font-weight: 400;
line-height: 22px; /* from link computed styles */
letter-spacing: -0.16px;
color: var(--headspace-text-primary);
}
/* ── Label / Form Label ── */
.type-label {
font-family: "Headspace Apercu", sans-serif;
font-size: 14px; /* reconstructed: moderate confidence, between xs and sm */
font-weight: 500;
line-height: 18px; /* extracted from label computed styles */
letter-spacing: -0.14px;
color: var(--headspace-text-primary);
}
/* ── Caption / Legal ── */
.type-caption {
font-family: "Headspace Apercu", sans-serif;
font-size: 12px; /* --headspace-font-size-xs */
font-weight: 400;
line-height: 16px; /* reconstructed: moderate confidence */
letter-spacing: 0px;
color: var(--headspace-text-muted);
}
/* ── Navigation Link ── */
.type-nav {
font-family: "Headspace Apercu", sans-serif;
font-size: 16px;
font-weight: 400;
line-height: 18.4px; /* --headspace-line-height-tight */
letter-spacing: normal;
color: var(--headspace-text-muted);
}
```
### Typography Pairing Rules
- **Headings on coloured sections:** always `color: var(--headspace-text-inverse)` (white) when section bg is a brand colour
- **Headings on white sections:** always `color: var(--headspace-text-primary)` (`rgb(45,44,43)`)
- **Body copy weight on coloured bg:** prefer `400` (Regular) for contrast clarity
- **NEVER** mix heading weights on the same hierarchy level — h2 is always 700, body is always 400–500
- **NEVER** use `Apercu Pro Mono` for body or heading copy — monospace is decorative/data only
---
## 4. Spacing & Layout
```css
:root {
/* ── Spacing Scale (8px-adjacent, anchored to 24px base) ── */
/* Note: scale starts at 24px — smaller values inferred from component padding */
--headspace-space-2xs: 8px; /* reconstructed: high confidence — label margin, input padding unit */
--headspace-space-xs: 24px; /* --space-xs | section sub-elements, card internal padding */
--headspace-space-sm: 32px; /* --space-sm | heading bottom margin, modal padding */
--headspace-space-md: 40px; /* --space-md | section vertical padding */
--headspace-space-lg: 48px; /* --space-lg | modal gap, major section padding */
/* ── Component-level micro-spacing ── */
--headspace-space-btn-y: 14px; /* reconstructed: moderate confidence — button vertical pad */
--headspace-space-btn-x: 32px; /* reconstructed: moderate confidence — button horizontal pad */
--headspace-space-input-pt: 24px; /* extracted: input top padding (floating label space) */
--headspace-space-input-pb: 8px; /* extracted: input bottom padding */
--headspace-space-input-x: 16px; /* extracted: input horizontal padding */
}
```
### Grid & Breakpoints
```css
/* ── Breakpoints ── */
/* reconstructed: high confidence — extracted from media queries */
--breakpoint-xs: 400px; /* Small mobile */
--breakpoint-sm: 530px; /* Mobile landscape / large mobile */
--breakpoint-md: 768px; /* Tablet portrait */
--breakpoint-lg: 1024px; /* Desktop */
--breakpoint-xl: [TBD - extract manually]; /* Large desktop — not confirmed in extracted MQs */
/* ── Container ── */
/* reconstructed: moderate confidence */
max-width: 1200px; /* inferred — common for Next.js marketing sites at this scale */
padding-inline: var(--headspace-space-xs); /* 24px side padding on mobile */
```
### Layout Decision Rules
- **Full-bleed section backgrounds:** each marketing section uses `width: 100vw` background colour, with inner content constrained to the container max-width
- **Flex for nav and button internals:** `display: flex; flex-direction: row; justify-content: space-between; align-items: center`
- **Grid for feature cards:** inferred 2–3 column grid at ≥768px, single column below
- **Modal layout:** `display: flex; flex-direction: row; gap: 48px; padding: 32px 48px` (extracted)
- **Section vertical rhythm:** use `var(--headspace-space-md)` (40px) to `var(--headspace-space-lg)` (48px) between sections
---
## 5. Page Structure & Layout Patterns
> All rows marked "(inferred)" are derived from the component inventory and layout digest — not visually confirmed from screenshots.
### 5.1 Section Map
| # | Section | Layout Type | Approx. Height | Key Elements |
|---|---|---|---|---|
| 1 | **Navigation / Header** | `display: block` → inner flex row | ~72px | Logo, nav links, "Try for free" CTA (blue pill button) |
| 2 | **Hero** (inferred) | Full-bleed blue (`--headspace-bg-surface`) flex column | ~560px | H2 52px bold, body 18px, primary CTA button, illustration |
| 3 | **Feature Selector** (inferred) | Flex row tab/chip row | ~120px | `radius-lg` chips (24px) — "AI guidance", "Guided meditations", "Sleep resources" |
| 4 | **Feature Panel — Stress/Anxiety** (inferred) | Two-column flex or grid | ~480px | `radius-md` (8px) content cards "Stress less", "Sleep soundly", "Manage anxiety" |
| 5 | **Always-there Support** | Full-bleed yellow (`--headspace-accent`) | ~400px | H3 40px bold, body copy, illustration |
| 6 | **Feel-good Library** | Full-bleed pink (`--headspace-bg-app`) | ~400px | H3/H4, content count copy, media thumbnails |
| 7 | **Bedtime Essentials** | Full-bleed purple (`--headspace-color-purple`) | ~400px | H3, sleep resource list, illustration |
| 8 | **Do-anywhere Exercises** | Full-bleed green (`--headspace-color-green`) | ~400px | H3, exercise CTAs |
| 9 | **Social Proof / Logos** (inferred) | Flex row, centered | ~200px | H2 "Over 4,000 leading organisations…", logo strip |
| 10 | **Pricing / Try Free CTA** (inferred) | Centered column, white bg | ~360px | H2, plan cards, primary CTA |
| 11 | **FAQ** (inferred) | Single column accordion | ~480px | H2 "Frequently asked questions", accordion items |
| 12 | **Modal / Overlay** | Flex row, gap 48px | ~auto | White card, `border-radius: 0 0 24px 24px`, shadow |
| 13 | **Footer** (inferred) | Multi-column flex/grid | ~280px | Nav links 4 columns, legal, copyright |
### 5.2 Layout Patterns
**Navigation:**
```
display: block (outer wrapper)
inner: display: flex; flex-direction: row; justify-content: space-between; align-items: center
padding: 0 var(--headspace-space-xs)
```
Nav links use `type-nav` (16px/400/18.4px line-height), colour `--headspace-text-muted`.
**Full-bleed Colour Sections (Sections 2–8):**
- Background: one of the five brand surface colours
- Inner content: `max-width: ~1200px; margin: 0 auto; padding: var(--headspace-space-lg) var(--headspace-space-xs)`
- Two-column split at ≥768px (text left, illustration/media right); single column below
- Inferred column ratio: ~1:1 or ~55:45 for hero panels
**Feature Chip Row (Section 3):**
- `display: flex; flex-direction: row; gap: var(--headspace-space-2xs); flex-wrap: wrap`
- Each chip: `border-radius: var(--headspace-radius-lg)` (24px), `padding: 8px 20px`
- Active chip: `background-color: var(--headspace-bg-surface)`; inactive: white with border
**Content Cards (Section 4):**
- `border-radius: var(--headspace-radius-md)` (8px)
- `background-color: var(--headspace-surface-white)`
- `padding: var(--headspace-space-xs)` (24px)
**Modal:**
- `display: flex; flex-direction: row; gap: 48px; padding: 32px 48px`
- `border-radius: 0 0 24px 24px` (top edge flush with top of viewport or parent)
- `box-shadow: var(--headspace-shadow-modal)`
### 5.3 Visual Hierarchy
- **Primary CTA** is always the blue pill button (`--headspace-bg-surface`, `radius-full: 32px`) — appears in nav and hero
- **Section headlines** (H2/H3 at 52px/40px bold) are the dominant visual anchors; no competing decorative elements
- **Colour zones carry emotional intent** — each section's background colour signals content type before the user reads copy
- **White space is generous** — minimum 40px vertical padding per section; no cramped content blocks
- **Illustrations/media** appear to the right of text on desktop, below on mobile (inferred from typical Headspace layouts)
### 5.4 Content Patterns
**Text + CTA pattern (repeated across coloured sections):**
```
[H2/H3 — bold, large]
[Body paragraph — 18px/500]
[Pill CTA button]
[Supporting illustration — right column or below]
```
**Chip navigation + panel pattern (feature selector):**
```
[Row of pill chips — select content category]
[Animated panel below — shows category content]
```
**Card grid pattern:**
```
[Section heading left-aligned]
[2–3 column grid of white rounded cards]
[Each card: thumbnail + label + description]
```
---
## 6. Component Patterns
### 6.1 Primary Button
**Anatomy:** Container `<button>` → `[icon?]` + `[label text]`
**Token mappings:**
| State | Background | Text | Border | Radius | Other |
|---|---|---|---|---|---|
| Default | `--headspace-bg-surface` (`rgb(0,97,239)`) | `--headspace-text-inverse` (white) | none | `--headspace-radius-full` (32px) | — |
| Hover | `--headspace-btn-hover-bg` (`rgb(0,64,234)`) | white | none | 32px | `transition: background-color 0.3s` |
| Focus | `rgb(0,64,234)` bg | white | `2px solid rgb(0,64,234)` outline | 32px | `outline-offset: 2px` |
| Active | `--headspace-btn-active-bg` (`rgb(0,0,219)`) | white | none | 32px | `translateY(2px)` |
| Disabled | `--headspace-bg-surface` | white | none | 32px | `opacity: 1; cursor: not-allowed` |
> Note: Disabled state for the primary button keeps full opacity (extracted: `opacity: 1`), not the conventional `0.5`. Only the `cursor` signals disabled state.
```tsx
// Primary Button — complete with all states
import React from 'react';
interface HeadspaceButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
loading?: boolean;
}
export const HeadspaceButton: React.FC<HeadspaceButtonProps> = ({
children,
disabled,
loading,
...props
}) => {
return (
<button
disabled={disabled || loading}
style={{
fontFamily: 'var(--headspace-font-family)',
fontSize: 'var(--headspace-font-size-sm)', /* 16px */
fontWeight: 400,
lineHeight: '18.4px',
letterSpacing: 'normal',
color: 'var(--headspace-text-inverse)',
backgroundColor: 'var(--headspace-bg-surface)',
borderRadius: 'var(--headspace-radius-full)', /* 32px */
padding: '14px 32px',
border: 'none',
cursor: disabled || loading ? 'not-allowed' : 'pointer',
transition: `background-color var(--headspace-duration-base) var(--headspace-ease-default),
transform var(--headspace-duration-fast) var(--headspace-ease-default),
box-shadow var(--headspace-duration-fast) var(--headspace-ease-default)`,
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
/* opacity stays 1 even when disabled — per extracted styles */
opacity: 1,
}}
onMouseEnter={e => {
if (!disabled && !loading) {
(e.target as HTMLButtonElement).style.backgroundColor = 'var(--headspace-btn-hover-bg)';
}
}}
onMouseLeave={e => {
(e.target as HTMLButtonElement).style.backgroundColor = 'var(--headspace-bg-surface)';
}}
onMouseDown={e => {
if (!disabled && !loading) {
(e.target as HTMLButtonElement).style.backgroundColor = 'var(--headspace-btn-active-bg)';
(e.target as HTMLButtonElement).style.transform = 'translateY(2px)';
}
}}
onMouseUp={e => {
(e.target as HTMLButtonElement).style.backgroundColor = 'var(--headspace-btn-hover-bg)';
(e.target as HTMLButtonElement).style.transform = 'translateY(0)';
}}
{...props}
>
{loading ? <span aria-label="Loading…">⏳</span> : children}
</button>
);
};
// CSS for focus-visible state (add to global stylesheet):
// .hs-btn-primary:focus-visible {
// outline: 2px solid var(--headspace-focus-ring);
// outline-offset: 2px;
// border-radius: var(--headspace-radius-full);
// }
```
---
### 6.2 Ghost / Secondary Button
**Anatomy:** `<button>` → label text (no fill, has border)
| State | Background | Text | Border |
|---|---|---|---|
| Default | transparent | `--headspace-text-muted` | `2px solid --headspace-border` |
| Hover | transparent | `--headspace-text-muted` | `2px solid --headspace-text-primary` |
| Focus | transparent | `--headspace-text-muted` | `2px solid --headspace-focus-ring` (outline) |
| Disabled | transparent | `--headspace-text-muted` | `2px solid --headspace-border` / `opacity: 0.7` |
```css
/* extracted from button_primary computed styles */
.hs-btn-secondary {
font-family: var(--headspace-font-family);
font-size: var(--headspace-font-size-sm); /* 16px */
font-weight: 400;
line-height: 18.4px;
color: var(--headspace-text-muted);
background-color: var(--headspace-surface-white);
border-radius: var(--headspace-radius-md); /* 8px — content selector buttons */
padding: 8px 24px;
border: 2px solid var(--headspace-border);
transition: border var(--headspace-duration-base);
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
.hs-btn-secondary:hover {
border-color: var(--headspace-text-primary);
}
.hs-btn-secondary:focus-visible {
outline: 2px solid var(--headspace-focus-ring);
outline-offset: 2px;
}
.hs-btn-secondary:disabled {
opacity: 0.7;
cursor: not-allowed;
pointer-events: none;
}
```
---
### 6.3 Feature Chip Button
**Anatomy:** `<button>` → label text (category selector)
```css
/* e.g. "AI guidance", "Guided meditations", "Sleep resources" */
.hs-chip {
font-family: var(--headspace-font-family);
font-size: var(--headspace-font-size-sm); /* 16px */
font-weight: 400;
border-radius: var(--headspace-radius-lg); /* 24px */
padding: 8px 20px;
border: none;
background-color: var(--headspace-surface-white);
color: var(--headspace-text-primary);
transition: background-color var(--headspace-duration-fast);
cursor: pointer;
}
.hs-chip[aria-selected="true"],
.hs-chip.active {
background-color: var(--headspace-bg-surface);
color: var(--headspace-text-inverse);
}
.hs-chip:focus-visible {
outline: 2px solid var(--headspace-focus-ring);
outline-offset: 2px;
}
```
---
### 6.4 Text Input (Floating Label)
**Anatomy:** `<div>` wrapper → `<input>` + `<label>` (label floats above when focused/filled)
| State | Border | Background | Text |
|---|---|---|---|
| Default | `1px solid rgb(210,213,222)` | white | `rgb(0,0,0)` |
| Focus | `1px solid rgb(0,0,0)` (OneTrust pattern) / brand: `2px solid --headspace-focus-ring` | white | `rgb(0,0,0)` |
| Disabled | `1px solid --headspace-border` | `--headspace-surface-subtle` | `opacity: 0.5` |
| Error | `1px solid [TBD - extract manually]` | white | `[TBD - extract manually]` |
```css
.hs-input-wrapper {
position: relative;
width: 100%;
}
.hs-input {
font-family: var(--headspace-font-family);
font-size: var(--headspace-font-size-sm); /* 16px */
font-weight: 400;
line-height: 24px;
color: var(--headspace-text-on-input);
background-color: var(--headspace-surface-white);
border: 1px solid var(--headspace-border-input);
border-radius: var(--headspace-radius-md); /* 8px */
padding: 24px 16px 8px; /* top space reserves room for floating label */
width: 100%;
transition: all var(--headspace-duration-base);
outline: none;
}
.hs-input:focus {
border-color: var(--headspace-focus-ring);
box-shadow: 0 0 0 2px rgba(0, 64, 234, 0.15);
}
.hs-input:disabled {
background-color: var(--headspace-surface-subtle);
opacity: 0.5;
cursor: not-allowed;
}
.hs-label {
font-family: var(--headspace-font-family);
font-size: 14px;
font-weight: 500;
line-height: 18px;
letter-spacing: -0.14px;
color: var(--headspace-text-primary);
position: absolute;
top: 0;
left: 16px;
margin-top: 0;
/* floating label behaviour via JS class toggle */
}
```
---
### 6.5 Navigation Bar
**Anatomy:** `<nav>` → `[logo]` + `[nav links flex row]` + `[CTA button]`
```css
.hs-nav {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 0 var(--headspace-space-xs); /* 0 24px */
background-color: var(--headspace-surface-white);
/* no shadow at rest — shadow appears on scroll (inferred) */
}
.hs-nav-link {
font-family: var(--headspace-font-family);
font-size: var(--headspace-font-size-sm); /* 16px */
font-weight: 400;
line-height: 18.4px;
color: var(--headspace-text-muted);
text-decoration: none;
padding: 16px 0;
transition: all var(--headspace-duration-base);
}
.hs-nav-link:hover {
font-weight: 700; /* extracted from .css-x9wj7b:hover, .css-17s3ayp:hover */
}
.hs-nav-link:focus-visible {
outline: 2px solid var(--headspace-focus-ring);
outline-offset: 2px;
}
```
---
### 6.6 Modal
**Anatomy:** `<div>` backdrop → `<div>` modal content → `[left column content]` + `[right column content]`
```css
.hs-modal {
font-family: var(--headspace-font-family);
font-size: var(--headspace-font-size-sm);
font-weight: 400;
line-height: 18.4px;
color: var(--headspace-text-on-input);
background-color: var(--headspace-surface-white);
border-radius: 0 0 24px 24px; /* top flush, bottom rounded */
padding: var(--headspace-space-sm) var(--headspace-space-lg); /* 32px 48px */
box-shadow: var(--headspace-shadow-modal);
display: flex;
flex-direction: row;
gap: var(--headspace-space-lg); /* 48px */
}
.hs-modal-backdrop {
position: fixed;
inset: 0;
background-color: rgba(45, 44, 43, 0.5);
z-index: 100;
}
```
---
### 6.7 Badge / Label Pill
**Anatomy:** `<span>` → text label
```css
.hs-badge {
font-family: var(--headspace-font-family);
font-size: var(--headspace-font-size-md); /* 18px — "Featured", "Popular", "Sleep" */
font-weight: 400;
line-height: 21.6px; /* --headspace-line-height-normal */
color: var(--headspace-text-primary);
background-color: var(--headspace-surface-white);
border-radius: var(--headspace-radius-lg); /* 24px */
padding: 4px 12px;
display: inline-block;
}
```
---
## 7. Elevation & Depth
```css
:root {
/* ── Shadows ── */
--headspace-shadow-none: none;
--headspace-shadow-modal: rgba(20, 19, 19, 0.2) 0px 1px 8px 0px;
/* extracted: high confidence — from modal computed styles */
/* ── Borders ── */
--headspace-border-width-default: 1px;
--headspace-border-width-emphasis: 2px; /* interactive/focus states */
--headspace-border-color-default: var(--headspace-border); /* rgb(226,222,217) */
--headspace-border-color-input: var(--headspace-border-input); /* rgb(210,213,222) */
--headspace-border-color-focus: var(--headspace-focus-ring); /* rgb(0,64,234) */
/* ── Z-index Scale ── */
--headspace-z-below: -1; /* background decorative layers */
--headspace-z-base: 0; /* default document flow */
--headspace-z-raised: 10; /* sticky nav, floating labels */
--headspace-z-modal: 100; /* modal backdrop */
--headspace-z-overlay: 110; /* modal content above backdrop */
--headspace-z-toast: 200; /* notifications above modals */
}
```
### Layering Principles
- **Shadows are minimal** — only one shadow value extracted (`modal`). Do not add decorative card shadows not present in the source.
- **Depth is created through colour and size**, not shadows — full-bleed coloured sections create visual planes without box-shadow
- **Modals use bottom-radius only** (`border-radius: 0 0 24px 24px`) — indicating they drop down from the top of the screen
- **Nav background is `surface-white`** — sits above page content via z-index `--headspace-z-raised`, not by shadow
---
## 8. Motion
```css
:root {
/* ── Duration ── */
--headspace-duration-fast: 0.15s; /* Micro-interactions: hover bg flash, icon state */
--headspace-duration-base: 0.3s; /* Standard transitions: button bg, border, nav */
--headspace-duration-slow: 0.4s; /* Panel/section reveals, modal entry */
/* ── Easing ── */
--headspace-ease-default: cubic-bezier(0.32, 0, 0.67, 0);
/* Deceleration curve — fast start, slow finish. Appropriate for elements entering view. */
/* reconstructed: high confidence — 85 elements use this value */
}
```
### Motion Rules
| Interaction | Duration | Property |
|---|---|---|
| Button background (hover/focus) | `0.3s` | `background-color` |
| Button press (active) | `0.15s` | `transform: translateY(2px)`, `box-shadow` |
| Border colour change (input focus) | `0.3s` | `border-color` |
| Panel reveal (feature selector) | `0.4s` | `opacity`, `transform` |
| Nav link weight change | `0.3s` | `font-weight` (note: weight change is abrupt, transition has no visual midpoint) |
| Modal entry | `0.4s` | `transform: translateY(...)` (inferred) |
### When NOT to Animate
- **Never** animate `font-size` or `letter-spacing` (reflow cost, no extracted usage)
- **Never** use `transition: all` in new code — even though it appears in extracted styles, it is a performance liability; enumerate specific properties
- **Respect `prefers-reduced-motion`:** wrap all transitions in `@media (prefers-reduced-motion: no-preference)` — especially for section reveals and modal animations
```css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}
```
---
## 9. Anti-Patterns & Constraints
1. **Using a generic fallback font as the primary typeface → AI agents default to `Inter` or `system-ui` when no font is specified, producing completely off-brand output. → Always declare `font-family: "Headspace Apercu", sans-serif` on every component. The `sans-serif` fallback is only for font-load failure; it should never be the rendering reality.**
2. **Hardcoding hex/RGB colour values inline → AI agents frequently write `color: rgb(0, 97, 239)` directly in JSX `style` props. This bypasses the token system, making theme consistency impossible and breaking search-replace refactoring. → Always use `var(--headspace-bg-surface)` etc. Hardcoded values are a bug, not a style.**
3. **Applying `border-radius: 50%` or `border-radius: 9999px` to pill buttons → AI agents over-generalise "pill button" to mean infinite radius. Headspace's pill radius is exactly `32px` (`--headspace-radius-full`). Using `9999px` breaks the design token system and will visually mismatch non-square buttons. → Use `var(--headspace-radius-full)` (32px) exclusively.**
4. **Using arbitrary spacing values not on the scale → AI agents often emit `padding: 20px` or `gap: 16px` because these feel natural. The Headspace scale starts at 24px — values like 16px, 20px exist only inside components (button padding, input padding) not as layout spacing. → For layout spacing, use only `24px / 32px / 40px / 48px` from the token scale.**
5. **Constructing Tailwind class names dynamically → `className={`bg-[${brandColor}]`}` causes Tailwind's JIT to not generate the class at build time, producing broken styles in production. → Use CSS custom properties with `bg-[var(--headspace-bg-surface)]` or apply a static class name.**
6. **Omitting `:focus-visible` styles → AI agents frequently generate hover states but skip keyboard focus. Headspace's brand UI uses `outline: 2px solid var(--headspace-focus-ring)` (`rgb(0,64,234)`) on all interactive elements. Missing this is an accessibility failure. → Every `<button>`, `<a>`, and `<input>` MUST have an explicit `:focus-visible` rule.**
7. **Using the green brand colour (`rgb(2, 135, 62)`) as text colour → It was mapped to `--headspace-text-primary` in the low-confidence curated token extraction, but this is incorrect. The extracted colour census clearly shows it is a section background colour for the exercise section, not a text colour. Text primary is `rgb(45, 44, 43)`. → NEVER use `--headspace-color-green` on text; it fails WCAG contrast on white.**
8. **Adding decorative `box-shadow` to cards → The extraction found zero card shadows. Headspace uses colour as the depth signal. AI agents add `box-shadow: 0 4px 12px rgba(0,0,0,0.1)` to cards by default because it's a common pattern. This makes Headspace feel like a generic SaaS product. → Only `--headspace-shadow-modal` is permitted.**
9. **Using `transition: all` in authored code → Extracted styles show `transition: all` on many elements, but this is a computed default, not an intentional design decision. Writing `transition: all` in new code causes performance regressions (triggers layout recalculation on every property change). → Enumerate specific properties: `transition: background-color 0.3s, border-color 0.3s`.**
10. **Placing the green (`--headspace-color-green`) or purple (`--headspace-color-purple`) section backgrounds on UI components → These colours are full-bleed section backgrounds, not component-level colours. AI agents may apply them to buttons, badges, or cards because they appear in the colour token set. → Only `--headspace-bg-surface` (blue) is the action/CTA colour. Purple and green are zone colours only.**
11. **Mixing button radius values (e.g. 8px secondary button for a CTA) → The primary CTA uses `radius-full` (32px); secondary/ghost buttons use `radius-md` (8px). Swapping these makes the visual hierarchy illegible — the "important" button looks the same as a filter. → Primary call-to-action = always `--headspace-radius-full`; content selectors/secondary = `--headspace-radius-md` or `--headspace-radius-lg`.**
---
## 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 (79) */
--headspace-color-text-primary: #2d2c2b;
--headspace-color-text-secondary: #4b4c4d;
--headspace-color-action-primary: #0040ea;
--headspace-color-action-hover: #0040ea;
--headspace-color-action-active: #0000db;
--headspace-color-surface: #ffffff;
--headspace-color-surface-subtle: #f9f4f2;
--headspace-color-border: #e2ded9;
--headspace-color-border-input: #d2d5de;
--headspace-color-focus-ring: #0040ea;
--hs-primitive-neutral-900: #2d2c2b;
--hs-primitive-neutral-700: #4b4c4d;
--hs-primitive-neutral-600: #44423f;
--hs-primitive-neutral-500: #3a3938;
--hs-primitive-neutral-200: #e2ded9;
--hs-primitive-neutral-150: #d2d5de;
--hs-primitive-neutral-050: #f9f4f2;
--hs-primitive-white: #ffffff;
--hs-primitive-black: #000000;
--hs-primitive-blue-700: #0000db;
--hs-primitive-blue-600: #0040ea;
--hs-primitive-blue-500: #0061ef;
--hs-primitive-blue-400: #3860be;
--hs-primitive-blue-300: #2285f7;
--hs-primitive-blue-200: #1faede;
--hs-primitive-blue-100: #1eaedb;
--headspace-color-text-on-action: #ffffff;
--headspace-color-text-inverse: #ffffff;
--headspace-color-surface-overlay: rgba(0,0,0,0.5);
--headspace-color-action-disabled: #0061ef;
--headspace-color-action-ghost: transparent;
--headspace-color-border-focus: var(--hs-primitive-blue-600);
--hs-btn-primary-bg: var(--headspace-color-action-primary);
--hs-btn-primary-bg-hover: var(--headspace-color-action-hover);
--hs-btn-primary-bg-active: var(--headspace-color-action-active);
--hs-btn-primary-bg-disabled: var(--headspace-color-action-disabled);
--hs-btn-primary-color: var(--headspace-color-text-on-action);
--hs-btn-ghost-bg: var(--headspace-color-action-ghost);
--hs-btn-ghost-bg-disabled: var(--headspace-color-surface-subtle);
--hs-btn-ghost-color: var(--hs-primitive-neutral-600);
--hs-input-bg: var(--headspace-color-surface);
--hs-input-border: var(--headspace-color-border-input);
--hs-input-border-focus: var(--hs-primitive-black);
--hs-card-border: var(--headspace-color-border);
--headspace-border-default: 1px solid #e2ded9;
--headspace-border-input: rgb(210, 213, 222);
--headspace-border-card: 2px solid #e2ded9;
--headspace-border-focus: var(--primitive-black);
--headspace-transition-color: color var(--headspace-duration-fast) var(--headspace-ease-default),
background-color var(--headspace-duration-base) var(--headspace-ease-default);
--headspace-transition-border: border var(--headspace-duration-base);
--headspace-color-surface-accent: #ffce00;
--headspace-bg-surface: rgb(0, 97, 239);
--headspace-bg-app: rgb(255, 161, 204);
--headspace-color-purple: rgb(59, 25, 127);
--headspace-border: rgb(226, 222, 217);
--primitive-blue-500: rgb(0, 97, 239);
--primitive-blue-600: rgb(0, 64, 234);
--primitive-blue-700: rgb(0, 0, 219);
--primitive-blue-400: rgb(56, 96, 190);
--primitive-yellow-400: rgb(255, 206, 0);
--primitive-pink-300: rgb(255, 161, 204);
--primitive-purple-700: rgb(59, 25, 127);
--primitive-green-600: rgb(2, 135, 62);
--primitive-neutral-900: rgb(45, 44, 43);
--primitive-neutral-700: rgb(75, 76, 77);
--primitive-neutral-600: rgb(68, 66, 63);
--primitive-neutral-200: rgb(226, 222, 217);
--primitive-neutral-100: rgb(210, 213, 222);
--primitive-neutral-50: rgb(249, 244, 242);
--primitive-white: rgb(255, 255, 255);
--primitive-black: rgb(0, 0, 0);
--headspace-color-green: rgb(2, 135, 62);
--headspace-btn-hover-bg: rgb(0, 64, 234);
--headspace-btn-active-bg: rgb(0, 0, 219);
--headspace-border-width-default: 1px;
--headspace-border-width-emphasis: 2px;
--headspace-border-color-default: var(--headspace-border);
--headspace-border-color-input: var(--headspace-border-input);
--headspace-border-color-focus: var(--headspace-focus-ring);
/* Typography (33) */
--font-size-xs: 12px; /* 7 elements — e.g. p "By signing up, you’r", span "0:00", span "5:15" /* mined from computed styles */ */
--font-size-sm: 16px; /* 36 elements — e.g. p "Get personalized con", p "Help kids settle in ", p "Bring your attention" /* mined from computed styles */ */
--font-size-md: 18px; /* 30 elements — e.g. p "Featured", p "Popular", p "Sleep" /* mined from computed styles */ */
--font-size-lg: 20px; /* 15 elements — e.g. p "Support your team to", p "Headspace is your li", p "Headspace was founde" /* mined from computed styles */ */
--font-size-xl: 24px; /* 20 elements — e.g. h4 "Get some Headspace", h4 "Our content", h4 "About us" /* mined from computed styles */ */
--font-size-2xl: 32px; /* 22 elements — e.g. h2 "What kind of headspa", h5 "Meet Ebb", h5 "Wiggle to Wind Down" /* mined from computed styles */ */
--font-size-3xl: 40px; /* 7 elements — e.g. h2 "Over 4,000 leading o", h2 "Frequently asked que", h3 "Always-there support" /* mined from computed styles */ */
--font-weight-regular: 400; /* 96 elements — e.g. p "Stress less", p "Sleep soundly", p "Manage anxiety" /* mined from computed styles */ */
--font-weight-medium: 500; /* 32 elements — e.g. p "Support your team to", p "Be the first to get ", p "By signing up, you’r" /* mined from computed styles */ */
--font-weight-semibold: 700; /* 64 elements — e.g. h2 "all with Headspace", h2 "What kind of headspa", h2 "The mental health ap" /* mined from computed styles */ */
--line-height-tight: 18.4px; /* 20 elements — e.g. span "What is Headspace?", span "What is Headspace’s ", span "How do I download th" /* mined from computed styles */ */
--line-height-normal: 21.6px; /* 24 elements — e.g. p "Featured", p "Popular", p "Sleep" /* mined from computed styles */ */
--line-height-loose: 38.4px; /* 22 elements — e.g. h2 "What kind of headspa", h5 "Meet Ebb", h5 "Wiggle to Wind Down" /* mined from computed styles */ */
--headspace-font-family-base: "Headspace Apercu", sans-serif;
--headspace-font-size-xs: 12px;
--headspace-font-size-sm: 16px;
--headspace-font-size-md: 18px;
--headspace-font-size-lg: 20px;
--headspace-font-size-xl: 24px;
--headspace-font-size-2xl: 32px;
--headspace-font-size-3xl: 40px;
--headspace-font-size-hero: 52px;
--headspace-font-family-mono: "Apercu Pro Mono", monospace;
--headspace-font-weight-regular: 400;
--headspace-font-weight-medium: 500;
--headspace-font-weight-semibold: 600;
--headspace-line-height-tight: 18.4px;
--headspace-line-height-normal: 21.6px;
--headspace-line-height-loose: 38.4px;
--headspace-font-family: "Headspace Apercu", sans-serif;
--headspace-font-size-h2: 52px;
--headspace-font-weight-light: 200;
--headspace-font-weight-bold: 700;
/* Spacing (56) */
--space-xs: 24px; /* 2 elements — e.g. section .css-4bhmzh, section .css-4bhmzh /* mined from computed styles */ */
--space-sm: 32px; /* 2 elements — e.g. section .css-4bhmzh, section .css-4bhmzh /* mined from computed styles */ */
--space-md: 40px; /* 1 element — e.g. footer .css-1sy39w9 /* mined from computed styles */ */
--space-lg: 48px; /* 2 elements — e.g. header .css-75xqdg, header .css-75xqdg /* mined from computed styles */ */
--headspace-space-xs: 24px;
--headspace-space-sm: 32px;
--headspace-space-md: 40px;
--headspace-space-lg: 48px;
--headspace-duration-fast: 0.15s;
--headspace-duration-base: 0.3s;
--headspace-duration-slow: 0.4s;
--headspace-ease-default: cubic-bezier(0.32, 0, 0.67, 0);
--headspace-space-2: 2px;
--headspace-space-4: 4px;
--headspace-space-8: 8px;
--headspace-space-12: 12px;
--headspace-space-16: 16px;
--headspace-space-24: 24px;
--headspace-container-max: 1280px;
--headspace-container-gutter: 24px;
--headspace-grid-columns: 12;
--headspace-grid-gap: 24px;
--headspace-z-base: 0;
--headspace-z-raised: 10;
--headspace-z-dropdown: 100;
--headspace-z-sticky: 200;
--headspace-z-modal: 100;
--headspace-z-toast: 200;
--headspace-z-overlay: 110;
--headspace-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--headspace-ease-in: cubic-bezier(0.67, 0, 0.84, 1);
--headspace-ease-linear: linear;
--headspace-transition-all: all var(--headspace-duration-base) var(--headspace-ease-default);
--headspace-transition-modal: transform var(--headspace-duration-slow) var(--headspace-ease-out),
opacity var(--headspace-duration-slow) var(--headspace-ease-default);
--headspace-space-32: 32px;
--headspace-space-40: 40px;
--headspace-space-48: 48px;
--headspace-accent: rgb(255, 206, 0);
--headspace-text-primary: rgb(45, 44, 43);
--headspace-text-muted: rgb(75, 76, 77);
--headspace-surface-white: rgb(255, 255, 255);
--headspace-focus-ring: rgb(0, 64, 234);
--headspace-surface-subtle: rgb(249, 244, 242);
--headspace-text-inverse: rgb(255, 255, 255);
--headspace-text-on-input: rgb(0, 0, 0);
--headspace-space-2xs: 8px;
--headspace-space-btn-y: 14px;
--headspace-space-btn-x: 32px;
--headspace-space-input-pt: 24px;
--headspace-space-input-pb: 8px;
--headspace-space-input-x: 16px;
--breakpoint-xs: 400px;
--breakpoint-sm: 530px;
--breakpoint-md: 768px;
--breakpoint-lg: 1024px;
--headspace-z-below: -1;
/* Radius (13) */
--radius-sm: 2px; /* 4 elements — e.g. button .onetrust-close-btn-handler, button .ot-link-btn "Back Button", button .save-preference-btn-handler "Confirm My Choices" /* mined from computed styles */ */
--radius-md: 8px; /* 7 elements — e.g. div .css-vxtmj8 "Stress less", div .css-vxtmj8 "Sleep soundly", div .css-vxtmj8 "Manage anxiety" /* mined from computed styles */ */
--radius-lg: 24px; /* 10 elements — e.g. button .css-pfyzmk "AI guidance", button .css-1n1dghu "Guided meditations", button .css-1n1dghu "Sleep resources" /* mined from computed styles */ */
--radius-full: 32px; /* 1 element — e.g. button .css-1qi2pw5 /* mined from computed styles */ */
--headspace-radius-sm: 2px;
--headspace-radius-md: 8px;
--headspace-radius-lg: 24px;
--headspace-radius-full: 32px;
--hs-btn-primary-radius: var(--headspace-radius-full);
--hs-btn-ghost-radius: var(--headspace-radius-full);
--hs-input-radius: var(--headspace-radius-md);
--hs-card-radius: var(--headspace-radius-md);
--hs-chip-radius: var(--headspace-radius-lg);
/* Effects (8) */
--hs-primitive-shadow-base: rgba(20, 19, 19, 0.2);
--hs-btn-primary-opacity-disabled: 1;
--hs-btn-ghost-opacity-disabled: 0.5;
--headspace-shadow-none: none;
--headspace-shadow-sm: rgba(20,19,19,0.2) 0px 1px 8px 0px;
--headspace-shadow-md: rgba(20,19,19,0.15) 0px 4px 16px 0px;
--headspace-shadow-lg: rgba(20, 19, 19, 0.12) 0px 8px 32px 0px;
--headspace-shadow-modal: rgba(20,19,19,0.2) 0px 1px 8px 0px;
/* Motion (4) */
--duration-fast: 0.15s; /* 75 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-base: 0.3s; /* 16 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-slow: 0.4s; /* 10 elements — e.g. button, button, button /* mined from computed styles */ */
--ease-default: cubic-bezier(0.32; /* 85 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```
tokenSource: reconstructed-from-computed
site: headspace.com
extractionDate: [TBD - record at extraction time]
confidence: low-to-high (mixed per token, see inline annotations)
nativeCSSVars: 0 found
```
### Confidence Notes
| Token Group | Confidence | Method |
|---|---|---|
| Font sizes (xs–3xl) | **High** | Directly extracted from computed styles; 7–36 elements per value |
| Font weights (400, 500, 700) | **High** | Directly extracted; high element counts |
| Font family | **High** | Directly extracted from `@font-face` declarations |
| Line heights (tight/normal/loose) | **High** | Extracted from computed styles; confirmed across 20–24 elements each |
| Colour — blue/yellow/pink | **High** | Extracted from colour token census; confirmed on multiple named elements |
| Colour — purple/green | **Medium** | Extracted from colour census; each on only 1 element |
| Colour — text-primary (`rgb(45,44,43)`) | **High** | Computed from h2, h3, body, label — consistent |
| Colour — text-muted (`rgb(75,76,77)`) | **High** | Extracted from nav, alert, button — consistent |
| Button interactive states | **High** | Extracted from CSS rule `.css-1pkjg4r` hover/focus/active/disabled |
| Spacing scale (24/32/40/48px) | **High** | Extracted from multiple component computed paddings/margins/gaps |
| Radius scale | **High** | Extracted from border-radius census (22 elements across 4 values) |
| Motion tokens | **High** | Extracted from 75–85 elements each |
| H2 display type (52px) | **High** | Directly from h2 computed styles |
| Label font size (14px) | **Medium** | Extracted from label computed styles; intermediate value not in the curated scale |
| Container max-width | **Low** | Not extracted — common Next.js marketing default; **verify manually** |
| Button padding (14px/32px) | **Medium** | Reconstructed from visual inference; extracted button used 8px/16px for secondary pattern |
| Modal border-radius top | **High** | Extracted: `border-radius: 0px 0px 24px 24px` |
### Clustering Method
Colours were grouped by hue family and validated against element context (section backgrounds vs text vs borders). The `--headspace-text-primary` mapping to green (`rgb(2,135,62)`) in the low-confidence curated extraction was **rejected** — the colour census clearly shows it as a section background, not text. Spacing was clustered on a non-standard scale anchored at 24px (not the common 4px/8px grid), consistent with a design tool–generated system rather than a utility CSS system.
### Libraries Detected
- **Next.js** — SSR/SSG React framework
- **Bootstrap** — detected but likely legacy or partial; CSS-in-JS (Emotion) appears dominant for component styles
- **Emotion (CSS-in-JS)** — inferred from hashed class names (`.css-vxtmj8`, `.css-1pkjg4r`, etc.)
### Tokens Requiring Manual Extraction
- `--breakpoint-xl` (large desktop container width)
- Error state colours for inputs/buttons
- Exact nav height
- Animation keyframes for section reveal transitions
- Dark mode (if any — none detected but could be behind a user preference toggle)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

DoorDash
MITClean, accessible food-delivery system with DoorDash's signature red accent, light neutral palette, and system-font typography—built for rapid product development
03
lightecommsaasmobile

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