Headspace
MIT
Wellness-focused design system with vibrant accent colours and rounded, approachable typography; ideal for meditation, mental health and wellbeing applications
Colour (79)
color.hsinputbgvar(--headspace-color-surface)
color.hsbtnghostbgvar(--headspace-color-action-ghost)
color.hscardbordervar(--headspace-color-border)
color.hsinputbordervar(--headspace-color-border-input)
color.headspacebgapprgb(255, 161, 204)
color.hsbtnprimarybgvar(--headspace-color-action-primary)
color.primitiveblackrgb(0, 0, 0)
color.primitivewhitergb(255, 255, 255)
color.headspaceborderrgb(226, 222, 217)
color.hsbtnghostcolorvar(--hs-primitive-neutral-600)
color.hsprimitiveblack#000000
color.hsprimitivewhite#ffffff
color.primitiveblue400rgb(56, 96, 190)
color.primitiveblue500rgb(0, 97, 239)
color.primitiveblue600rgb(0, 64, 234)
color.primitiveblue700rgb(0, 0, 219)
color.primitivepink300rgb(255, 161, 204)
color.hsbtnprimarycolorvar(--headspace-color-text-on-action)
color.primitivegreen600rgb(2, 135, 62)
color.headspacebgsurfacergb(0, 97, 239)
color.hsinputborderfocusvar(--hs-primitive-black)
color.hsprimitiveblue100#1eaedb
color.hsprimitiveblue200#1faede
color.hsprimitiveblue300#2285f7
color.hsprimitiveblue400#3860be
color.hsprimitiveblue500#0061ef
color.hsprimitiveblue600#0040ea
color.hsprimitiveblue700#0000db
color.primitiveneutral50rgb(249, 244, 242)
color.primitivepurple700rgb(59, 25, 127)
color.primitiveyellow400rgb(255, 206, 0)
color.headspacebordercard2px solid #e2ded9
color.headspacebtnhoverbgrgb(0, 64, 234)
color.headspacecolorgreenrgb(2, 135, 62)
color.hsbtnprimarybghovervar(--headspace-color-action-hover)
color.primitiveneutral100rgb(210, 213, 222)
color.primitiveneutral200rgb(226, 222, 217)
color.primitiveneutral600rgb(68, 66, 63)
color.primitiveneutral700rgb(75, 76, 77)
color.primitiveneutral900rgb(45, 44, 43)
color.headspaceborderfocusvar(--primitive-black)
color.headspaceborderinputrgb(210, 213, 222)
color.headspacebtnactivebgrgb(0, 0, 219)
color.headspacecolorborder#e2ded9
color.headspacecolorpurplergb(59, 25, 127)
color.hsbtnghostbgdisabledvar(--headspace-color-surface-subtle)
color.hsbtnprimarybgactivevar(--headspace-color-action-active)
color.headspacecolorsurface#ffffff
Spacing (56)
spacing.headspacezbelow-1
spacing.headspacezbase0
spacing.headspacefocusringrgb(0, 64, 234)
spacing.headspaceeaselinearlinear
spacing.headspacetextoninputrgb(0, 0, 0)
spacing.headspacetransitionallall var(--headspace-duration-base) var(--headspace-ease-default)
spacing.headspacetransitionmodaltransform var(--headspace-duration-slow) var(--headspace-ease-out),
opacity var(--headspace-duration-slow) var(--headspace-ease-default)
spacing.headspacedurationfast0.15s
spacing.headspaceeaseoutcubic-bezier(0.16, 1, 0.3, 1)
spacing.headspacedurationbase0.3s
spacing.headspaceeasedefaultcubic-bezier(0.32, 0, 0.67, 0)
spacing.headspacedurationslow0.4s
spacing.headspaceeaseincubic-bezier(0.67, 0, 0.84, 1)
spacing.headspacespace22px
spacing.headspacespace44px
spacing.headspacespace88px
spacing.headspacespace2xs8px
spacing.headspacespaceinputpb8px
spacing.headspacezraised10
spacing.headspacespace1212px
spacing.headspacegridcolumns12
spacing.headspacespacebtny14px
spacing.headspacespace1616px
spacing.headspacespaceinputx16px
spacing.spacexs24px
spacing.headspacegridgap24px
spacing.headspacespace2424px
spacing.headspacespacexs24px
spacing.headspacespaceinputpt24px
spacing.headspacecontainergutter24px
spacing.spacesm32px
spacing.headspacespace3232px
spacing.headspacespacesm32px
spacing.headspacespacebtnx32px
spacing.spacemd40px
spacing.headspacespace4040px
spacing.headspacespacemd40px
spacing.headspacetextprimaryrgb(45, 44, 43)
spacing.spacelg48px
spacing.headspacespace4848px
spacing.headspacespacelg48px
spacing.headspacetextmutedrgb(75, 76, 77)
spacing.headspacezmodal100
spacing.headspacezdropdown100
spacing.headspacezoverlay110
spacing.headspaceztoast200
spacing.headspacezsticky200
spacing.headspacesurfacesubtlergb(249, 244, 242)
spacing.headspaceaccentrgb(255, 206, 0)
spacing.headspacetextinversergb(255, 255, 255)
spacing.headspacesurfacewhitergb(255, 255, 255)
spacing.breakpointxs400px
spacing.breakpointsm530px
spacing.breakpointmd768px
spacing.breakpointlg1024px
spacing.headspacecontainermax1280px
Radius (13)
hscardradiusvar(--headspace-radius-md)
hschipradiusvar(--headspace-radius-lg)
hsinputradiusvar(--headspace-radius-md)
hsbtnghostradiusvar(--headspace-radius-full)
hsbtnprimaryradiusvar(--headspace-radius-full)
radiussm2px
headspaceradiussm2px
radiusmd8px
headspaceradiusmd8px
radiuslg24px
headspaceradiuslg24px
radiusfull32px
headspaceradiusfull32px
Shadow (8)
effect.headspaceshadowlgrgba(20, 19, 19, 0.12) 0px 8px 32px 0px
effect.headspaceshadowmdrgba(20,19,19,0.15) 0px 4px 16px 0px
effect.headspaceshadowsmrgba(20,19,19,0.2) 0px 1px 8px 0px
effect.headspaceshadownonenone
effect.headspaceshadowmodalrgba(20,19,19,0.2) 0px 1px 8px 0px
effect.hsprimitiveshadowbasergba(20, 19, 19, 0.2)
effect.hsbtnghostopacitydisabled0.5
effect.hsbtnprimaryopacitydisabled1
# 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

Vercel
MITClean, minimal developer-focused design system built on Geist typography with light surfaces, precise spacing, and fast interactions for modern web applications
00
lightminimaldeveloper-toolsaas

OpenAI
MITClean, minimal design system for AI-native products built on Next.js and Tailwind, featuring a light monochromatic palette with precise token-based spacing and typography
02
lightminimalsaasdeveloper-tool

Duolingo
MITVibrant, playful design system with bright green accents and light blue surfaces, built for engaging educational and language-learning products
00
lightboldcontent-firstmobile