MIT
Friendly, accessible messaging interface with bright green accents and warm neutrals, designed for global communication apps and messaging platforms
Colour (63)
color.navbgrgb(255, 255, 255)
color.navactivebgrgb(17, 27, 33)
color.btnoutlinebgvar(--whatsapp-bg-dark)
color.btnprimarybgvar(--whatsapp-accent)
color.brandsurface1rgb(252, 245, 235)
color.brandsurface2rgb(17, 27, 33)
color.brandsurface3rgb(230, 255, 218)
color.navactivetextrgb(255, 255, 255)
color.whatsappbgapprgb(230, 255, 218)
color.whatsappbgnavrgb(255, 255, 255)
color.btnoutlinetextrgb(255, 255, 255)
color.primitivewhitergb(255, 255, 255)
color.whatsappaccentrgb(37, 211, 102)
color.whatsappbgdarkrgb(17, 27, 33)
color.whatsappborderrgb(255, 255, 255)
color.brandprimaryctargb(37, 211, 102)
color.whatsappbghovervar(--whatsapp-accent-hover)
color.whatsappsuccessrgb(37, 211, 102)
color.btnoutlineborderrgb(255, 255, 255)
color.primitivedarkmidrgb(34, 34, 34)
color.primitivegrey200rgb(240, 244, 249)
color.primitivegrey300rgb(205, 208, 213)
color.primitivegrey600rgb(94, 94, 94)
color.primitivemint100rgb(230, 255, 218)
color.primitivenavy900rgb(17, 27, 33)
color.whatsapptextbodyrgb(28, 30, 33)
color.whatsapptextdarkrgb(28, 30, 33)
color.btnoutlinebghovervar(--whatsapp-accent)
color.btnprimarybghovervar(--whatsapp-accent-hover)
color.primitivecharcoalrgb(28, 30, 33)
color.primitivecream100rgb(252, 245, 235)
color.primitivegreen400rgb(37, 211, 102)
color.primitivegreen500rgb(67, 205, 102)
color.primitivegreen700rgb(0, 128, 62)
color.primitivegreen900rgb(16, 57, 40)
color.whatsappbgsurfacergb(252, 245, 235)
color.whatsappbordernav0px none
color.whatsappbgselectedrgb(17, 27, 33)
color.whatsappbordercard0px none
color.whatsappdisabledbgrgb(205, 208, 213)
color.whatsapptextondarkrgb(255, 255, 255)
color.whatsappaccenthoverrgb(67, 205, 102)
color.whatsapptextprimaryrgb(17, 27, 33)
color.btnoutlinebgdisabledinherit
color.btnprimarybgdisabledvar(--whatsapp-disabled-bg)
color.whatsappborderstrongvar(--whatsapp-accent)
color.whatsappdisabledtextrgb(94, 94, 94)
color.whatsapptextdisabledrgb(205, 208, 213)
Spacing (13)
spacing.whatsappgridgapvar(--whatsapp-space-sm)
spacing.spacexs16px
spacing.whatsappspacexs16px
spacing.spacesm32px
spacing.whatsappspacesm32px
spacing.spacemd56px
spacing.whatsappspacemd56px
spacing.spacelg70px
spacing.whatsappspacelg70px
spacing.spacexl88px
spacing.whatsappspacexl88px
spacing.whatsappspace2xl1200px
spacing.whatsappcontainermax1200px
Radius (6)
radiusmd50px
radiussm50%
whatsappradiuslg50px
whatsappradiusmd50px
whatsappradiussm50%
whatsappradiusfull50%
Shadow (4)
effect.whatsappshadowlgnone
effect.whatsappshadowmdnone
effect.whatsappshadowsmnone
effect.whatsappshadownonenone
# layout.md — WhatsApp.com Design System
---
## 0. Quick Reference
**Stack:** Vanilla HTML/CSS, custom font (`WhatsApp Sans Var`), no CSS framework detected.
**Token source:** Reconstructed from computed styles. All tokens marked `/* reconstructed */` unless high-confidence extraction confirmed.
**How to apply:** Use as `var(--whatsapp-*)` in CSS, `style={{ prop: 'var(--whatsapp-accent)' }}` in JSX, or `bg-[var(--whatsapp-accent)]` in Tailwind.
```css
/* ── CORE TOKENS ── */
:root {
/* Colours */
--whatsapp-accent: rgb(37, 211, 102);
--whatsapp-bg-app: rgb(230, 255, 218);
--whatsapp-border: rgb(255, 255, 255);
--whatsapp-success: rgb(37, 211, 102);
--whatsapp-bg-hover: var(--whatsapp-accent-hover);
--whatsapp-bg-surface: rgb(252, 245, 235);
--whatsapp-bg-selected: rgb(17, 27, 33);
--whatsapp-accent-hover: rgb(67, 205, 102);
--whatsapp-text-primary: rgb(17, 27, 33);
--whatsapp-border-strong: var(--whatsapp-accent);
--whatsapp-text-secondary: rgb(94, 94, 94);
--whatsapp-accent-foreground: rgb(17, 27, 33);
/* Other */
--whatsapp-space-lg: 70px;
--whatsapp-space-md: 56px;
--whatsapp-space-sm: 32px;
--whatsapp-space-xl: 88px;
--whatsapp-space-xs: 16px;
--whatsapp-font-sans: "WhatsApp Sans Var", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
--whatsapp-radius-lg: 50px;
--whatsapp-radius-md: 50px;
--whatsapp-radius-sm: 50%;
--whatsapp-shadow-lg: none;
--whatsapp-shadow-md: none;
--whatsapp-shadow-sm: none;
--whatsapp-space-2xl: 1200px;
--whatsapp-radius-full: 50%;
--whatsapp-ease-default: ease;
--whatsapp-font-size-lg: 32px;
--whatsapp-font-size-md: 18px;
--whatsapp-font-size-sm: 16px;
--whatsapp-font-size-xl: 48px;
--whatsapp-font-size-xs: 12px;
--whatsapp-duration-base: 0.5s;
--whatsapp-duration-fast: 0.33s;
--whatsapp-font-size-2xl: 60px;
--whatsapp-font-size-3xl: 80px;
--whatsapp-font-weight-bold: 700;
--whatsapp-font-weight-medium: 500;
--whatsapp-line-height-normal: 25px;
--whatsapp-font-weight-regular: 400;
}
```
```tsx
// Primary pill button — correct token usage
const CTAButton = ({ disabled, children }) => (
<button
disabled={disabled}
style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '16px', fontWeight: 500,
backgroundColor: disabled ? 'var(--whatsapp-disabled-bg)' : 'var(--whatsapp-accent)',
color: disabled ? 'var(--whatsapp-disabled-text)' : 'var(--whatsapp-text-primary)',
borderRadius: 'var(--whatsapp-radius-md)',
padding: '16px 28px', border: 'none', cursor: disabled ? 'not-allowed' : 'pointer',
transition: `background-color var(--whatsapp-duration-fast) var(--whatsapp-ease-default)`,
}}
>{children}</button>
);
```
**NEVER rules:**
- **NEVER** use any font family other than `WhatsApp Sans Var` (with system-ui fallback).
- **NEVER** use border-radius values other than `50%` or `50px` — no 4px, 8px, or 12px rounded corners.
- **NEVER** hardcode hex/rgb colour values — always use `var(--whatsapp-*)` tokens.
- **NEVER** use spacing values not derived from the `--whatsapp-space-*` scale.
- **NEVER** use font-weight `700` (bold) for headings — WhatsApp headings are `400` (regular weight).
- **NEVER** use warm colours (orange, red, yellow) for interactive elements — all CTAs are green (`--whatsapp-accent`).
- **NEVER** add box-shadow or card elevation — WhatsApp.com uses a flat, shadowless aesthetic.
> Full design system → see `layout.md`
---
## 1. Design Direction & Philosophy
### Character & Aesthetic Intent
WhatsApp.com projects **calm authority through deliberate restraint**. The visual language is clean, open, and frictionless — optimised for global comprehension across cultures and languages. The design conveys trust without corporate coldness: warm off-white backgrounds (`rgb(252, 245, 235)`) soften what could be a sterile tech product, while the signature green (`rgb(37, 211, 102)`) carries all the energy.
Typography is set in a **proprietary variable font** (WhatsApp Sans Var) at regular weight (`400`) even for the largest display headings — this is intentional. The brand avoids typographic aggression. Text is large, airy, and confident rather than bold and urgent.
### Mood
- **Safe, open, connected** — the palette references nature (green, cream, mint)
- **Global / culturally neutral** — no decorative motifs, no region-specific visual metaphors
- **Quietly confident** — hero text at 80px with weight 400 signals self-assurance without shouting
### What This Design Explicitly Rejects
- ❌ Drop shadows, card elevation, glassmorphism, gradients
- ❌ Bold or black font weights for headings
- ❌ Rounded corners in the 4–16px range (corners are either sharp `0px`, perfect circle `50%`, or full-pill `50px`)
- ❌ Warm accent colours (red, orange, yellow CTA buttons)
- ❌ Dense information layouts — sections breathe with `56px–88px` vertical padding
- ❌ Decorative borders, dividers, or ruled lines
- ❌ Serif typefaces or mixed type families
---
## 2. Colour System
### Tier 1 — Primitives
```css
/* Raw hue values — never reference these directly in components */
:root {
--primitive-green-400: rgb(37, 211, 102); /* WhatsApp brand green */
--primitive-green-500: rgb(67, 205, 102); /* Slightly muted green, hover underline accent */
--primitive-green-700: rgb(0, 128, 62); /* Deep green, text link hover */
--primitive-green-900: rgb(16, 57, 40); /* Darkest green, dark-surface button hover bg */
--primitive-mint-100: rgb(230, 255, 218); /* Lightest mint, app preview bg */
--primitive-cream-100: rgb(252, 245, 235); /* Warm off-white, main page surface */
--primitive-navy-900: rgb(17, 27, 33); /* Near-black, primary text & dark surfaces */
--primitive-charcoal: rgb(28, 30, 33); /* h2/body text, nav text */
--primitive-dark-mid: rgb(34, 34, 34); /* Alt dark text (hover states) */
--primitive-white: rgb(255, 255, 255); /* Pure white */
--primitive-grey-200: rgb(240, 244, 249); /* Disabled input background */
--primitive-grey-300: rgb(205, 208, 213); /* Disabled border / text */
--primitive-grey-600: rgb(94, 94, 94); /* Disabled button text on filled bg */
}
```
### Tier 2 — Semantic Aliases
```css
:root {
/* Surfaces */
--whatsapp-bg-surface: var(--primitive-cream-100); /* Main page/section background */
--whatsapp-bg-app: var(--primitive-mint-100); /* App UI preview, feature section bg */
--whatsapp-bg-nav: var(--primitive-white); /* Navigation bar background */
--whatsapp-bg-dark: var(--primitive-navy-900); /* Dark hero / dropdown overlay bg */
/* Text */
--whatsapp-text-primary: var(--primitive-navy-900); /* h3, dark-bg body text */
--whatsapp-text-body: var(--primitive-charcoal); /* h2, p, nav link default */
--whatsapp-text-on-dark: var(--primitive-white); /* Text on dark hero/dropdown */
--whatsapp-text-on-accent: var(--primitive-navy-900); /* Label on green CTA button */
--whatsapp-text-link-hover: var(--primitive-green-700); /* Text link hover colour */
--whatsapp-text-disabled: var(--primitive-grey-300); /* Any disabled text label */
/* Interaction */
--whatsapp-accent: var(--primitive-green-400); /* CTA button bg, active states */
--whatsapp-accent-hover: var(--primitive-green-500); /* CTA hover (lighter green) */
--whatsapp-accent-dark-hover: var(--primitive-green-900); /* Dark-surface CTA button hover */
/* Disabled */
--whatsapp-disabled-bg: var(--primitive-grey-300); /* Filled button disabled bg */
--whatsapp-disabled-border: var(--primitive-grey-300); /* Outlined button disabled border */
--whatsapp-disabled-text: var(--primitive-grey-600); /* Label on filled disabled */
--whatsapp-disabled-bg-input: var(--primitive-grey-200); /* Input disabled background */
}
```
### Tier 3 — Component Tokens
```css
:root {
/* Button — filled primary */
--btn-primary-bg: var(--whatsapp-accent);
--btn-primary-bg-hover: var(--whatsapp-accent-hover);
--btn-primary-text: var(--whatsapp-text-on-accent);
--btn-primary-bg-disabled: var(--whatsapp-disabled-bg);
--btn-primary-text-disabled: var(--whatsapp-disabled-text);
/* Button — outlined (dark bg variant) */
--btn-outline-bg: var(--whatsapp-bg-dark);
--btn-outline-border: var(--primitive-white);
--btn-outline-text: var(--primitive-white);
--btn-outline-bg-hover: var(--whatsapp-accent);
--btn-outline-border-hover: var(--whatsapp-accent);
--btn-outline-bg-disabled: inherit;
--btn-outline-border-disabled: var(--whatsapp-disabled-border);
--btn-outline-text-disabled: var(--whatsapp-text-disabled);
/* Nav */
--nav-bg: var(--whatsapp-bg-nav);
--nav-text: var(--whatsapp-text-body);
--nav-text-hover: var(--primitive-charcoal);
--nav-active-bg: var(--primitive-navy-900);
--nav-active-text: var(--primitive-white);
}
```
### Colour Usage Table
| Token | Value | Usage |
|---|---|---|
| `--whatsapp-accent` | `rgb(37, 211, 102)` | All primary CTA buttons |
| `--whatsapp-bg-surface` | `rgb(252, 245, 235)` | Page background, most sections |
| `--whatsapp-bg-app` | `rgb(230, 255, 218)` | App mockup/preview section bg |
| `--whatsapp-text-primary` | `rgb(17, 27, 33)` | h3, dark-surface body text |
| `--whatsapp-text-body` | `rgb(28, 30, 33)` | h2, paragraphs, nav links |
| `--whatsapp-text-on-dark` | `rgb(255, 255, 255)` | Hero text, text on dark bg |
| `--whatsapp-disabled-bg` | `rgb(205, 208, 213)` | Disabled filled button bg |
| `--whatsapp-disabled-text` | `rgb(94, 94, 94)` | Disabled button label |
---
## 3. Typography System
**Font:** `WhatsApp Sans Var` — a proprietary variable font. Always include system-ui fallback. **Bold (700) is NEVER used for headings.**
```css
:root {
--whatsapp-font: "WhatsApp Sans Var", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
}
```
### Composite Type Tokens
```css
/* ── Display / Hero ── */
.type-display {
/* h1 — hero headline */
font-family: var(--whatsapp-font);
font-size: 80px; /* --whatsapp-font-size-3xl */
font-weight: 400; /* --whatsapp-font-weight-regular */
line-height: 80px; /* 1:1 — tight leading for large display */
letter-spacing: normal;
color: var(--whatsapp-text-on-dark); /* always on dark hero bg */
}
/* ── Section Heading ── */
.type-section-heading {
/* h2 — section titles */
font-family: var(--whatsapp-font);
font-size: 60px; /* --whatsapp-font-size-2xl; most h2s use 60px */
font-weight: 400;
line-height: 1;
letter-spacing: normal;
color: var(--whatsapp-text-body);
text-align: center;
}
/* ── Section Heading Alt (smaller variant) ── */
.type-section-heading-sm {
/* h2 alt — used for single emphasis section */
font-family: var(--whatsapp-font);
font-size: 48px; /* --whatsapp-font-size-xl */
font-weight: 400;
line-height: 48px;
letter-spacing: normal;
color: var(--whatsapp-text-body);
text-align: center;
}
/* ── Sub-heading ── */
.type-subheading {
/* h3 — feature/card headings */
font-family: var(--whatsapp-font);
font-size: 32px; /* --whatsapp-font-size-lg */
font-weight: 400;
line-height: normal;
letter-spacing: normal;
color: var(--whatsapp-text-primary);
display: inline-block;
}
/* ── Body ── */
.type-body {
font-family: var(--whatsapp-font);
font-size: 18px; /* --whatsapp-font-size-md */
font-weight: 400;
line-height: 25px; /* --whatsapp-line-height-normal */
letter-spacing: normal;
color: var(--whatsapp-text-body);
}
/* ── UI / Button Label ── */
.type-ui {
font-family: var(--whatsapp-font);
font-size: 16px; /* --whatsapp-font-size-sm */
font-weight: 500; /* --whatsapp-font-weight-medium — only weight on CTAs */
line-height: 19.2px;
letter-spacing: normal;
}
/* ── Link / Nav ── */
.type-nav-link {
font-family: var(--whatsapp-font);
font-size: 16px;
font-weight: 400;
line-height: 19.2px;
letter-spacing: normal;
color: var(--whatsapp-text-body);
text-decoration: none;
}
/* ── Caption / Badge ── */
.type-caption {
font-family: var(--whatsapp-font);
font-size: 12px; /* --whatsapp-font-size-xs */
font-weight: 400;
line-height: 16.08px;
letter-spacing: normal;
}
/* ── Dropdown Label (bold variant) ── */
.type-dropdown-label {
font-family: var(--whatsapp-font);
font-size: 16px;
font-weight: 700; /* Bold ONLY used for dropdown/nav selectors */
line-height: normal;
letter-spacing: normal;
color: var(--whatsapp-text-on-dark);
}
```
### Typography Pairing Rules
| Context | Token | Notes |
|---|---|---|
| Hero heading | `type-display` | White text, dark bg, weight 400 |
| Section title | `type-section-heading` | Centred, weight 400, NOT bold |
| Feature headline | `type-subheading` | Left-aligned, 32px |
| Body copy | `type-body` | 18px/25px, weight 400 |
| CTA button label | `type-ui` | **Only place weight 500 is used** |
| Nav links | `type-nav-link` | 16px, weight 400 |
| Small labels / badges | `type-caption` | 12px, weight 400 |
| Dropdown selectors | `type-dropdown-label` | **Only place weight 700 is used** |
> **Weight rule:** `400` everywhere except CTA button labels (`500`) and dropdown selectors (`700`). Never use 700 for headings.
---
## 4. Spacing & Layout
### Base Unit & Scale
WhatsApp.com uses a **16px base unit** with an irregular scale that does not follow a strict 4px or 8px grid — the extracted spacing tokens show jumps at 16, 32, 56, 70, 88. Note: `70px` is the single off-grid value (rounds to 72 on an 8px grid) preserved from the extracted token.
```css
:root {
/* ── Spacing Scale ── */
--whatsapp-space-xs: 16px; /* Tight padding: button horizontal, component internal */
--whatsapp-space-sm: 32px; /* Component padding, gap between inline elements */
--whatsapp-space-md: 56px; /* Section internal vertical padding */
--whatsapp-space-lg: 70px; /* Nav top padding (mobile nav offset) */
--whatsapp-space-xl: 88px; /* Section-to-section vertical spacing */
/* ── Derived Layout Values ── */
--whatsapp-container-max: 1200px; /* Max page width (from breakpoint ceiling) */
--whatsapp-container-pad: var(--whatsapp-space-sm); /* 32px horizontal page padding */
/* ── Grid ── */
--whatsapp-grid-cols-desktop: 12;
--whatsapp-grid-gap: var(--whatsapp-space-sm); /* 32px column gap */
}
```
### Breakpoints
Extracted breakpoints collapsed into a practical scale:
```css
/* ── Responsive Breakpoints ── */
/* mobile-sm */ @media (max-width: 399px) { /* < 400px — smallest phones */ }
/* mobile */ @media (max-width: 639px) { /* 400–639px */ }
/* tablet-sm */ @media (min-width: 640px) { /* 640–767px */ }
/* tablet */ @media (min-width: 768px) { /* 768–1023px */ }
/* desktop-sm */ @media (min-width: 1024px) { /* 1024–1095px */ }
/* desktop */ @media (min-width: 1096px) { /* 1096–1199px */ }
/* desktop-xl */ @media (min-width: 1200px) { /* ≥ 1200px — max container */ }
```
### Layout Decision Rules
- **Flex column** → navigation sidebar/drawer (confirmed from `role_navigation` computed: `display:flex`, `flex-direction:column`)
- **List layout** → card/feature items (confirmed: `display:list-item`)
- **Centred container** → all sections, max-width `1200px`, `32px` horizontal padding
- **Full-width** → hero section background extends full viewport; content is contained
- **No CSS Grid** detected in computed styles; flex and list-item patterns dominate
---
## 5. Page Structure & Layout Patterns
> **Note:** No screenshots available. All sections inferred from the Layout Digest, computed styles, component inventory, and colour token census. Rows marked **(inferred)** are not visually confirmed.
### 5.1 Section Map
| # | Section | Layout Type | Approx. Height | Key Elements | Status |
|---|---|---|---|---|---|
| 1 | Navigation / Header | `flex row`, full-width sticky | 70px | Logo, nav links, Download CTA (pill button), Language selector | inferred |
| 2 | Hero | Full-bleed dark bg (`--whatsapp-bg-dark`) | 600–700px | H1 display text (80px, white), subheading (body 18px, white), primary CTA pill button (green), app mockup image | inferred |
| 3 | Features / Cards Grid | `list-item` layout, contained | variable | H2 section title (centred, 60px), feature cards with H3 (32px) + body (18px/25px) | inferred |
| 4 | App Preview Section | Full-bleed mint bg (`--whatsapp-bg-app`) | 400–600px | H2 heading, body copy, phone/app UI mockup image | inferred |
| 5 | Secondary Feature Rows | Alternating flex rows, contained | variable | H2 or H3 + body + image pairs (text + visual columns) | inferred |
| 6 | CTA / Download Section | Centred, full-bleed cream bg | 300–400px | H2, body copy, green pill CTA button, app store badges | inferred |
| 7 | Footer | Flex row, full-width, dark or cream bg | 200–300px | Nav links (12px caption), language selector, legal links | inferred |
### 5.2 Layout Patterns
**Navigation:**
- `display: flex`, `flex-direction: column` confirmed for mobile drawer
- Top padding: `70px` (`--whatsapp-space-lg`) — accounts for fixed header height
- Desktop: likely `flex-direction: row` with logo left, links centred/right, CTA rightmost
- Background: `rgb(255, 255, 255)` — pure white nav bar
**Hero Section:**
- Full-bleed background: `rgb(17, 27, 33)` (`--whatsapp-bg-dark`)
- Text: white (`--whatsapp-text-on-dark`), H1 at 80px/80px line-height
- CTA: pill button (`border-radius: 50px`), green fill (`--whatsapp-accent`), label in navy
- No box shadows, no image overlays, no gradients
**Feature Cards:**
- `display: list-item` — rendered as a semantic list
- Padding: `0px` (internal padding handled by parent container)
- Text: body 18px/25px, H3 32px
- Gap between list items anchored to `--whatsapp-space-md` (56px) (inferred)
- Background: inherits page surface (`--whatsapp-bg-surface`)
**App Preview Section:**
- Background: `rgb(230, 255, 218)` (`--whatsapp-bg-app`) — mint green
- Likely 2-column: text left + app screenshot right (inferred from single `section` element with this bg)
**CTA Section:**
- Background: `--whatsapp-bg-surface` (warm cream)
- Centred layout, single green pill CTA + app store badges (circular `50%` radius buttons)
### 5.3 Visual Hierarchy
1. **H1 hero text** (80px, white on dark) — commanding visual entry point
2. **Primary CTA button** (green pill, nav + hero) — immediately after headline
3. **H2 section headings** (48–60px, centred, on cream) — section landmarks
4. **App mockup images** — visual anchors in feature/preview sections
5. **Body copy** (18px, `--whatsapp-text-body`) — supporting reading layer
6. **Footer nav links** (12px) — lowest hierarchy
**CTA colour:** All primary CTAs use `rgb(37, 211, 102)` (`--whatsapp-accent`) confirmed from button census (2 filled green buttons detected).
**Whitespace rhythm:** Sections separated by `--whatsapp-space-xl` (88px) vertical spacing.
### 5.4 Content Patterns
**Pattern A — Hero block:**
Dark full-bleed bg → large display headline → short subheading → green pill CTA → app mockup
**Pattern B — Feature card list:**
Centred H2 → list of feature items (H3 + body paragraph), no card borders or shadows
**Pattern C — Split row (text + image):**
2-column flex: `50% text / 50% image` or `60/40`, alternating which side text falls on (inferred)
**Pattern D — Full-bleed accent section:**
Mint bg (`--whatsapp-bg-app`) → H2 heading + body copy + screenshot — used to visually break up cream sections
**Pattern E — CTA footer block:**
Centred heading + body + pill CTA button + circular app-store badge buttons — cream bg
---
## 6. Component Patterns
### 6.1 Button — Filled Primary (Pill)
**Anatomy:** `<button>` or `<a>` → `[icon optional]` + `[label span]`
**Token Mappings:**
| State | Background | Border | Text | Cursor |
|---|---|---|---|---|
| Default | `--whatsapp-accent` | none | `--whatsapp-text-primary` | pointer |
| Hover | `rgb(67, 205, 102)` | `1px solid rgb(37,211,102)` | `--whatsapp-text-primary` | pointer |
| Focus | `--whatsapp-accent` | `2px solid --whatsapp-text-on-dark` (ring) | `--whatsapp-text-primary` | pointer |
| Active | `--whatsapp-accent` | none | `--whatsapp-text-primary` | pointer |
| Disabled | `--whatsapp-disabled-bg` | `--whatsapp-disabled-bg` | `--whatsapp-disabled-text` | not-allowed |
```tsx
// Button — Filled Primary Pill — production example
import { ButtonHTMLAttributes } from 'react';
interface PrimaryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
isLoading?: boolean;
}
export const PrimaryButton = ({ children, disabled, isLoading, ...props }: PrimaryButtonProps) => {
const isInactive = disabled || isLoading;
return (
<button
disabled={isInactive}
{...props}
style={{
// Typography
fontFamily: 'var(--whatsapp-font)',
fontSize: '16px',
fontWeight: 500,
lineHeight: '19.2px',
letterSpacing: 'normal',
// Layout
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
gap: '8px',
padding: '16px 28px',
// Shape — ALWAYS pill
borderRadius: 'var(--whatsapp-radius-md)', // 50px
border: 'none',
// Colour
backgroundColor: isInactive
? 'var(--whatsapp-disabled-bg)'
: 'var(--whatsapp-accent)',
color: isInactive
? 'var(--whatsapp-disabled-text)'
: 'var(--whatsapp-text-primary)',
// Interaction
cursor: isInactive ? 'not-allowed' : 'pointer',
opacity: isLoading ? 0.7 : 1,
transition: `background-color var(--whatsapp-duration-fast) var(--whatsapp-ease-default),
border-color var(--whatsapp-duration-base) ease-out`,
}}
onMouseEnter={e => {
if (!isInactive)
(e.target as HTMLButtonElement).style.backgroundColor = 'rgb(67, 205, 102)';
}}
onMouseLeave={e => {
if (!isInactive)
(e.target as HTMLButtonElement).style.backgroundColor = 'var(--whatsapp-accent)';
}}
>
{isLoading ? <span aria-label="Loading…">⏳</span> : children}
</button>
);
};
```
---
### 6.2 Button — Outlined (Dark Background Variant)
**Anatomy:** `<button>` with transparent/dark bg and white border — used on dark hero sections.
| State | Background | Border | Text |
|---|---|---|---|
| Default | `rgb(17,27,33)` | `2px solid rgb(255,255,255)` | `rgb(255,255,255)` |
| Hover | `rgb(37,211,102)` | `1px solid rgb(37,211,102)` | `rgb(17,27,33)` |
| Disabled | `inherit` | `rgb(205,208,213)` | `rgb(205,208,213)` |
```tsx
export const OutlineButton = ({ children, disabled, ...props }) => (
<button
disabled={disabled}
style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '16px',
fontWeight: 700, // Outline/dropdown variant uses 700
lineHeight: 'normal',
padding: '16px 28px',
borderRadius: 'var(--whatsapp-radius-md)',
backgroundColor: disabled ? 'inherit' : 'rgb(17, 27, 33)',
border: disabled
? '2px solid var(--whatsapp-disabled-border)'
: '2px solid rgb(255, 255, 255)',
color: disabled
? 'var(--whatsapp-text-disabled)'
: 'var(--whatsapp-text-on-dark)',
cursor: disabled ? 'not-allowed' : 'pointer',
transition: `all var(--whatsapp-duration-fast) var(--whatsapp-ease-default)`,
}}
{...props}
>
{children}
</button>
);
```
---
### 6.3 Navigation Item
**Anatomy:** `<nav>` (`display:flex`, `flex-direction:column` on mobile) → `<a>` or `<button>` nav items, with animated indicator underline on hover.
| State | Colour | Decoration |
|---|---|---|
| Default | `rgb(28, 30, 33)` | none |
| Hover | `rgb(28, 30, 33)` | underline |
| Active / Selected | bg: `rgb(28,30,33)`, text: `rgb(255,255,255)` | none |
| Hover (dark nav) | `rgb(37, 211, 102)` | underline colour `rgb(67,205,102)`, 2px thick, 5px offset |
```tsx
export const NavItem = ({ href, children, isActive, isDark = false }) => (
<a
href={href}
style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '16px',
fontWeight: 400,
lineHeight: '19.2px',
color: isActive
? 'var(--whatsapp-text-on-dark)'
: isDark ? 'var(--whatsapp-text-on-dark)' : 'var(--whatsapp-text-body)',
backgroundColor: isActive ? 'var(--whatsapp-text-primary)' : 'transparent',
textDecoration: 'none',
padding: '8px 12px',
borderRadius: isActive ? 'var(--whatsapp-radius-md)' : '0px',
display: 'block',
transition: `color var(--whatsapp-duration-fast) var(--whatsapp-ease-default)`,
}}
>
{children}
</a>
);
```
---
### 6.4 Card / Feature Item
**Anatomy:** `<li>` (`display:list-item`) → `[icon or image]` + `<h3>` + `<p>`
**Note:** Cards have **no border, no shadow, no background fill** — they are flat content blocks on the page surface.
| State | Background | Shadow | Border |
|---|---|---|---|
| Default | transparent (inherits page bg) | none | none |
| Hover | transparent | none | none |
| Focus | system focus outline | — | — |
```tsx
export const FeatureCard = ({ icon, heading, body }: {
icon?: React.ReactNode;
heading: string;
body: string;
}) => (
<li style={{
listStyle: 'none',
display: 'block',
padding: '0px',
margin: '0px 0px 18px 0px',
background: 'transparent',
boxShadow: 'none', // NEVER add shadow
border: 'none', // NEVER add border
borderRadius: '0px', // NEVER add rounded corners to cards
}}>
{icon && <div style={{ marginBottom: 'var(--whatsapp-space-xs)' }}>{icon}</div>}
<h3 style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '32px',
fontWeight: 400,
lineHeight: 'normal',
color: 'var(--whatsapp-text-primary)',
margin: '0 0 var(--whatsapp-space-xs) 0',
}}>
{heading}
</h3>
<p style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '18px',
fontWeight: 400,
lineHeight: '25px',
color: 'var(--whatsapp-text-body)',
margin: '0px',
}}>
{body}
</p>
</li>
);
```
---
### 6.5 Badge
**Anatomy:** `<span>` inline, centred text, white text on transparent or coloured bg.
| State | Background | Text | Border-radius |
|---|---|---|---|
| Default | transparent (set by parent) | `rgb(255,255,255)` | `0px` (no radius on badge itself) |
| On green button (role_button) | `rgb(37,211,102)` | `rgb(28,30,33)` | `50%` (circle) |
```tsx
export const Badge = ({ label, variant = 'default' }: { label: string; variant?: 'default' | 'indicator' }) => (
<span style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '12px',
fontWeight: 400,
lineHeight: '16.08px',
textAlign: 'center',
display: 'block',
color: variant === 'indicator'
? 'var(--whatsapp-text-body)'
: 'var(--whatsapp-text-on-dark)',
backgroundColor: variant === 'indicator' ? 'var(--whatsapp-accent)' : 'transparent',
borderRadius: variant === 'indicator' ? 'var(--whatsapp-radius-sm)' : '0px',
border: variant === 'indicator' ? '1px solid var(--whatsapp-text-body)' : 'none',
padding: variant === 'indicator' ? '2px 6px' : '0px',
}}>
{label}
</span>
);
```
---
### 6.6 Input / Language Selector
**Anatomy:** `<select>` with pill styling — `border-radius: 50px`, dark background, white border (from `dropdown` computed styles).
| State | Background | Border | Text |
|---|---|---|---|
| Default | `rgb(17,27,33)` | `2px solid rgb(255,255,255)` | `rgb(255,255,255)` |
| Focus | `rgb(255,255,255)` | auto | `rgb(28,30,33)` |
| Disabled | `rgb(240,244,249)` | — | `rgb(205,208,213)` |
```tsx
export const LanguageSelect = ({ options, disabled }: { options: string[]; disabled?: boolean }) => (
<select
disabled={disabled}
style={{
fontFamily: 'var(--whatsapp-font)',
fontSize: '16px',
fontWeight: 700,
lineHeight: 'normal',
padding: '16px 28px',
borderRadius: 'var(--whatsapp-radius-md)', // 50px — pill
backgroundColor: disabled ? 'var(--whatsapp-disabled-bg-input)' : 'var(--whatsapp-bg-dark)',
border: disabled
? '2px solid var(--whatsapp-disabled-border)'
: '2px solid var(--whatsapp-text-on-dark)',
color: disabled ? 'var(--whatsapp-text-disabled)' : 'var(--whatsapp-text-on-dark)',
cursor: disabled ? 'not-allowed' : 'pointer',
transition: `all var(--whatsapp-duration-fast) var(--whatsapp-ease-default)`,
}}
>
{options.map(opt => <option key={opt} value={opt}>{opt}</option>)}
</select>
);
```
---
## 7. Elevation & Depth
WhatsApp.com uses a **completely flat visual system**. No shadows, no elevation, no blur effects were detected across any element in the extraction.
```css
:root {
/* Shadow scale — WhatsApp uses NONE of these. Defined for completeness / override protection */
--whatsapp-shadow-none: none; /* All elements: cards, buttons, nav, modals */
--whatsapp-shadow-sm: none; /* Not used — do NOT add card shadows */
--whatsapp-shadow-md: none; /* Not used */
--whatsapp-shadow-lg: none; /* Not used */
/* Borders */
--whatsapp-border-button-dark: 2px solid rgb(255, 255, 255); /* Outline button on dark bg */
--whatsapp-border-button-accent: 1px solid rgb(37, 211, 102); /* Button hover state border */
--whatsapp-border-nav: 0px none; /* No nav borders */
--whatsapp-border-card: 0px none; /* No card borders */
/* Z-index scale */
--z-base: 0;
--z-content: 1;
--z-nav: 100; /* Sticky navigation */
--z-dropdown: 200; /* Language selector / mobile nav drawer */
--z-skip-link: 10000; /* Accessibility skip link on :focus (extracted) */
}
```
**Depth is communicated through:**
- Background colour contrast (dark hero vs cream page vs mint app preview)
- Section stacking via full-bleed bg colour changes
- Typography scale (80px → 18px hierarchy), never shadow
---
## 8. Motion
```css
:root {
/* ── Duration ── */
--whatsapp-duration-fast: 0.33s; /* Colour/background transitions: button hover, indicator */
--whatsapp-duration-base: 0.5s; /* Border-colour transitions, nav reveal */
--whatsapp-duration-nav: 0.3s; /* Mobile nav drawer slide (extracted: right 0.3s ease-in-out) */
/* ── Easing ── */
--whatsapp-ease-default: ease; /* Most transitions */
--whatsapp-ease-nav: ease-in-out; /* Mobile nav drawer */
--whatsapp-ease-border-out: ease-out; /* Border-colour transitions */
--whatsapp-ease-linear: linear; /* Colour transitions with delay (role_button) */
/* ── Compound motion tokens ── */
--whatsapp-transition-color: color var(--whatsapp-duration-fast) var(--whatsapp-ease-linear) var(--whatsapp-duration-base);
/* Matches role_button: color 0.33s linear 0.5s delay */
--whatsapp-transition-border: border-color var(--whatsapp-duration-base) var(--whatsapp-ease-border-out);
--whatsapp-transition-bg: background-color var(--whatsapp-duration-fast) var(--whatsapp-ease-linear);
--whatsapp-transition-nav: right var(--whatsapp-duration-nav) var(--whatsapp-ease-nav);
--whatsapp-transition-hover: opacity 0.25s ease-in-out; /* Used for overlay/image hover */
}
```
### Motion Rules
- **Animate only:** `color`, `background-color`, `border-color`, `opacity`, `transform` (scale on indicators), `right` (nav drawer)
- **NEVER animate:** `font-size`, `border-radius`, `width`/`height` layout properties, `display`
- **Fast interactions** (button hover) → `0.33s` (`--whatsapp-duration-fast`)
- **Structural transitions** (nav open/close) → `0.3s ease-in-out`
- **Nav indicator scale animation:** `transform: scale(1.47) translateY(0px)` on hover — extracted from `._allj:hover ._9u4j::after`
- **Hover opacity fade** → `0.25s ease-in-out` (`._aupu ._9vcv:hover`)
- **No animation for purely decorative motion** — functional state changes only
---
## 9. Anti-Patterns & Constraints
1. **Hardcoded colour values → AI defaults to nearest named colour or arbitrary hex → use semantic tokens.**
Rule: Never write `color: #25D366` or `backgroundColor: 'rgb(37,211,102)'` directly in component code.
Why it fails: AI agents regenerating the component will invent slightly different greens (`#22C55E` from Tailwind, `#25D366` from hex guessing) because there's no single source of truth. State variants (hover, disabled) then become inconsistent.
Instead: Always use `var(--whatsapp-accent)` and define hover/disabled as `var(--btn-primary-bg-hover)` from the semantic tier.
2. **Arbitrary spacing values → AI picks "round" numbers (20px, 24px, 40px) → use only `--whatsapp-space-*` tokens.**
Rule: Never write `padding: 24px` or `gap: 20px`.
Why it fails: The spacing scale (16, 32, 56, 70, 88) is intentionally irregular — an AI not given the scale will default to a generic 4px/8px grid and produce layouts that look subtly but definitely wrong at large scale.
Instead: Map all spacing to `var(--whatsapp-space-xs/sm/md/lg/xl)`.
3. **Using Inter, Roboto, or system-ui as the primary font → breaks brand identity.**
Rule: `font-family` MUST always begin with `"WhatsApp Sans Var"`.
Why it fails: AI agents trained on generic design systems default to Inter or system-ui when no font is specified. WhatsApp Sans Var is a variable font with specific weight rendering characteristics — substituting it changes perceived weight even when `font-weight: 400` is correct.
Instead: Set `--whatsapp-font: "WhatsApp Sans Var", system-ui, sans-serif` as a CSS custom property and reference it everywhere.
4. **Adding border-radius values in the 4–16px range → AI rounds corners "helpfully" → use only `0px`, `50%`, or `50px`.**
Rule: `border-radius` MUST be `0px`, `var(--whatsapp-radius-sm)` (50%), or `var(--whatsapp-radius-md)` (50px).
Why it fails: AI code generators assume a "modern" design system uses 8px or 12px rounded corners. Applying these to WhatsApp components produces Material Design aesthetics, completely misrepresenting the brand's sharp-or-pill-only system.
Instead: Enforce the three-value radius constraint. Cards and headings get `0px`. Buttons and selects get `50px`. Avatar/icon circles get `50%`.
5. **Using font-weight 700 for headings → breaks the brand's "confident but quiet" tone.**
Rule: NEVER use `font-weight: 700` on any `<h1>`, `<h2>`, or `<h3>` element.
Why it fails: AI models associate large text with bold weight (it's the default in most design systems). WhatsApp headings are weight 400 at 48–80px. Applying 700 creates an aggressive, corporate look the brand explicitly avoids.
Instead: Headings are always `font-weight: 400`. Only dropdown labels use `700`. CTA button labels use `500`.
6. **Adding drop shadows or card borders to feature items → destroys flat aesthetic.**
Rule: `box-shadow: none` and `border: none` on ALL cards (`<li>` feature items). Never add elevation.
Why it fails: AI models trained on Material Design or Bootstrap patterns will add `box-shadow: 0 2px 8px rgba(0,0,0,0.1)` to cards as a "sensible default." On WhatsApp.com this breaks the clean, flat layout where depth is communicated purely through background colour zones.
Instead: Use background colour switching between sections (`--whatsapp-bg-surface`, `--whatsapp-bg-app`, `--whatsapp-bg-dark`) to create perceived depth. No shadows ever.
7. **Constructing dynamic Tailwind class names with template literals → classes are purged.**
Rule: Never write `` `bg-[${color}]` `` or `` `text-${size}` `` in JSX.
Why it fails: Tailwind's JIT purger requires static class strings at build time. Dynamically constructed class names are removed from the final CSS bundle, producing invisible or unstyled components in production.
Instead: Use `style={{ backgroundColor: 'var(--whatsapp-accent)' }}` for dynamic values, or define explicit class variants like `bg-[var(--whatsapp-accent)]` as static strings.
8. **Missing interactive states on buttons → AI only implements default state.**
Rule: Every interactive element MUST implement: default, hover, focus, active, disabled.
Why it fails: AI code completions stop at the happy path. Missing `:disabled` cursor (`not-allowed`), missing hover colour change, and missing focus ring all create accessibility failures and confuse users about interaction affordance.
Instead: Reference the state table in Section 6 for every button variant. Confirm `cursor: not-allowed` and `opacity`/colour change for disabled, and visible focus ring for keyboard users.
9. **Using warm accent colours (orange, yellow, red) for CTAs → contradicts brand.**
Rule: The ONLY valid CTA colour is `var(--whatsapp-accent)` = `rgb(37, 211, 102)`.
Why it fails: AI hallucinating a "download" button may apply a generic blue or orange CTA colour. The entire WhatsApp brand identity rests on a single distinctive green — any other colour on a CTA is wrong by definition.
Instead: If you need a secondary/ghost CTA, use the outlined variant (dark bg + white border), not a different fill colour.
10. **Inline styles for layout structure → makes responsive overrides impossible.**
Rule: Never use inline `style` for structural layout properties (`display`, `flex-direction`, `grid-template-columns`, `width` percentages).
Why it fails: Inline styles have the highest CSS specificity and cannot be overridden by media queries. AI agents writing all styles inline produce components that cannot adapt to the 15 detected breakpoints.
Instead: Use CSS classes or CSS Modules for layout structure. Reserve inline styles (or CSS variables) for dynamic token-driven values (colours, transitions).
---
## 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 (56) */
--brand-primary-cta: rgb(37, 211, 102); /* Primary CTA background, dominant on 2 buttons — e.g. "a" /* mined from computed styles */ */
--brand-surface-1: rgb(252, 245, 235); /* Brand surface, dominant on 10 elements — e.g. "Página inicialAppsRecursosLiga" /* mined from computed styles */ */
--brand-surface-2: rgb(17, 27, 33); /* Brand surface, dominant on 4 elements — e.g. "Conversecom liberdadeA criptog" /* mined from computed styles */ */
--brand-surface-3: rgb(230, 255, 218); /* Brand surface, dominant on 1 element — e.g. "section" /* mined from computed styles */ */
--whatsapp-accent: rgb(37, 211, 102);
--whatsapp-bg-surface: rgb(252, 245, 235);
--whatsapp-bg-app: rgb(230, 255, 218);
--whatsapp-text-primary: rgb(17, 27, 33);
--whatsapp-text-dark: rgb(28, 30, 33);
--whatsapp-text-on-dark: rgb(255, 255, 255);
--whatsapp-disabled-bg: rgb(205, 208, 213);
--whatsapp-disabled-text: rgb(94, 94, 94);
--primitive-green-400: rgb(37, 211, 102);
--primitive-green-500: rgb(67, 205, 102);
--primitive-green-700: rgb(0, 128, 62);
--primitive-green-900: rgb(16, 57, 40);
--primitive-mint-100: rgb(230, 255, 218);
--primitive-cream-100: rgb(252, 245, 235);
--primitive-navy-900: rgb(17, 27, 33);
--primitive-charcoal: rgb(28, 30, 33);
--primitive-dark-mid: rgb(34, 34, 34);
--primitive-white: rgb(255, 255, 255);
--primitive-grey-200: rgb(240, 244, 249);
--primitive-grey-300: rgb(205, 208, 213);
--primitive-grey-600: rgb(94, 94, 94);
--whatsapp-bg-nav: rgb(255, 255, 255);
--whatsapp-bg-dark: rgb(17, 27, 33);
--whatsapp-text-body: rgb(28, 30, 33);
--whatsapp-text-on-accent: rgb(17, 27, 33);
--whatsapp-text-link-hover: rgb(0, 128, 62);
--whatsapp-text-disabled: rgb(205, 208, 213);
--whatsapp-disabled-border: rgb(205, 208, 213);
--whatsapp-disabled-bg-input: rgb(240, 244, 249);
--btn-primary-bg: var(--whatsapp-accent);
--btn-primary-bg-hover: var(--whatsapp-accent-hover);
--btn-primary-bg-disabled: var(--whatsapp-disabled-bg);
--btn-outline-bg: var(--whatsapp-bg-dark);
--btn-outline-border: rgb(255, 255, 255);
--btn-outline-text: rgb(255, 255, 255);
--btn-outline-bg-hover: var(--whatsapp-accent);
--btn-outline-border-hover: var(--whatsapp-accent);
--btn-outline-bg-disabled: inherit;
--btn-outline-border-disabled: var(--whatsapp-disabled-border);
--nav-bg: rgb(255, 255, 255);
--nav-active-bg: rgb(17, 27, 33);
--nav-active-text: rgb(255, 255, 255);
--whatsapp-border-button-dark: 2px solid rgb(255, 255, 255);
--whatsapp-border-button-accent: 1px solid rgb(37, 211, 102);
--whatsapp-border-nav: 0px none;
--whatsapp-border-card: 0px none;
--whatsapp-ease-border-out: ease-out;
--whatsapp-transition-color: color var(--whatsapp-duration-fast) var(--whatsapp-ease-linear) var(--whatsapp-duration-base);
--whatsapp-transition-border: border-color var(--whatsapp-duration-base) var(--whatsapp-ease-border-out);
--whatsapp-transition-bg: background-color var(--whatsapp-duration-fast) var(--whatsapp-ease-linear);
--whatsapp-accent-hover: rgb(67, 205, 102);
--whatsapp-accent-dark-hover: rgb(16, 57, 40);
/* Typography (27) */
--font-size-xs: 12px; /* 9 elements — e.g. h4 "O que fazemos", h4 "Quem somos", h4 "Use o WhatsApp" /* mined from computed styles */ */
--font-size-sm: 16px; /* 25 elements — e.g. span "Pular para o conteúd", span "Baixar", span "Recursos" /* mined from computed styles */ */
--font-size-md: 18px; /* 21 elements — e.g. p "Mensagens e ligações", p "Seja para colocar o ", p "Use o WhatsApp para " /* mined from computed styles */ */
--font-size-lg: 32px; /* 13 elements — e.g. h3 "Recursos", span "Página inicial", span "Apps" /* mined from computed styles */ */
--font-size-xl: 48px; /* 1 element — e.g. h2 "Com mensagens e liga" /* mined from computed styles */ */
--font-size-2xl: 60px; /* 6 elements — e.g. h2 "Nunca perca um momen", h2 "Converse e faça liga", h2 "Conversecom liberdad" /* mined from computed styles */ */
--font-size-3xl: 80px; /* 1 element — e.g. h1 "Envie mensagens com " /* mined from computed styles */ */
--font-weight-regular: 400; /* 75 elements — e.g. h1 "Envie mensagens com ", h2 "Com mensagens e liga", h2 "Nunca perca um momen" /* mined from computed styles */ */
--font-weight-medium: 500; /* 1 element — e.g. a "Baixar" /* mined from computed styles */ */
--line-height-normal: 25px; /* 21 elements — e.g. p "Mensagens e ligações", p "Seja para colocar o ", p "Use o WhatsApp para " /* mined from computed styles */ */
--whatsapp-font: "WhatsApp Sans Var", system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
--btn-primary-text: var(--whatsapp-text-on-accent);
--btn-primary-text-disabled: var(--whatsapp-disabled-text);
--btn-outline-text-disabled: var(--whatsapp-text-disabled);
--nav-text: var(--whatsapp-text-body);
--nav-text-hover: var(--primitive-charcoal);
--whatsapp-font-size-xs: 12px;
--whatsapp-font-size-sm: 16px;
--whatsapp-font-size-md: 18px;
--whatsapp-font-size-lg: 32px;
--whatsapp-font-size-xl: 48px;
--whatsapp-font-size-2xl: 60px;
--whatsapp-font-size-3xl: 80px;
--whatsapp-font-weight-regular: 400;
--whatsapp-font-weight-medium: 500;
--whatsapp-font-weight-bold: 700;
--whatsapp-line-height-normal: 25px;
/* Spacing (12) */
--space-xs: 16px; /* 16 elements — e.g. div ._9tar, div ._9tar, div ._9tar /* mined from computed styles */ */
--space-sm: 32px; /* 9 elements — e.g. article ._9ta2, article ._9ta2, article ._9ta2 /* mined from computed styles */ */
--space-md: 56px; /* 3 elements — e.g. article ._9ta2, article ._9ta2, article ._9ta2 /* mined from computed styles */ */
--space-lg: 70px; /* 1 element — e.g. nav ._9t0g /* mined from computed styles */ */
--space-xl: 88px; /* 1 element — e.g. article ._9ta2 /* mined from computed styles */ */
--whatsapp-space-xs: 16px;
--whatsapp-space-sm: 32px;
--whatsapp-space-md: 56px;
--whatsapp-space-lg: 70px;
--whatsapp-space-xl: 88px;
--whatsapp-container-max: 1200px;
--whatsapp-grid-gap: var(--whatsapp-space-sm);
/* Radius (4) */
--radius-sm: 50%; /* 6 elements — e.g. a ._afwh, a ._afwh, a ._afwh /* mined from computed styles */ */
--radius-md: 50px; /* 5 elements — e.g. a ._aeo8 "Baixar", select ._9tg0 "AzərbaycanAfrikaansB", select ._9tg0 "azərbaycanAfrikaansB" /* mined from computed styles */ */
--whatsapp-radius-sm: 50%;
--whatsapp-radius-md: 50px;
/* Effects (4) */
--whatsapp-shadow-none: none;
--whatsapp-shadow-sm: none;
--whatsapp-shadow-md: none;
--whatsapp-shadow-lg: none;
/* Motion (3) */
--duration-fast: 0.33s; /* 12 elements — e.g. a, a, a /* mined from computed styles */ */
--duration-base: 0.5s; /* 6 elements — e.g. a, a, a /* mined from computed styles */ */
--ease-default: ease; /* 84 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```yaml
tokenSource: reconstructed-from-computed
extractedFrom: whatsapp.com (live site computed styles)
nativeCSSVars: 0 found
curatedTokensUsed: 24 (provided by extraction pipeline with kit prefix "whatsapp")
confidenceOverall: low-to-medium
confidenceByCategory:
colours: medium # 4 brand surface tokens extracted; hover/disabled states reconstructed from interactive CSS rules
typography: high # Font sizes, weights, and line-heights directly confirmed from computed styles and font declarations
spacing: high # All 5 spacing tokens directly extracted from computed styles
radius: high # 2 radius values confirmed: 50% (6 elements) and 50px (5 elements)
motion: high # Duration and easing values directly extracted from transition properties
layout: medium # Inferred from display/flex properties in computed styles; no screenshots confirmed
clusteringMethod: |
Colours: grouped by hue family (greens, neutrals, whites, greys).
Spacing: extracted as-is from curated tokens — not forced onto a 4px/8px grid because
the site uses an irregular scale (16, 32, 56, 70, 88). The 70px off-grid value
is preserved from extraction rather than rounded, per the auto-detected anti-pattern note.
Radius: binary system confirmed — sharp (0px) or pill (50px) for UI, circle (50%) for avatars.
No intermediate radii detected in the element census.
Typography: composite groups assembled from font declarations + computed styles.
WhatsApp Sans Var is a variable font served from Meta CDN (/rsrc.php/...).
syntheticTokensAdded:
- Primitive colour layer (--primitive-*): synthesised from clustering computed colours
- Hover/active/disabled state colours: reconstructed from interactive CSS rule extraction
- Z-index scale: --z-skip-link (10000) extracted; others (100, 200) reconstructed from nav/dropdown context
- --whatsapp-duration-nav (0.3s): extracted from role_navigation transition rule
- --whatsapp-font-weight-bold (700): extracted from dropdown computed style
fontNotes: |
WhatsApp Sans Var is a proprietary Meta/WhatsApp variable font. It is NOT available via
Google Fonts or npm. The woff2 source URL (/rsrc.php/yN/r/fQtw5exLIdT.woff2) is served
from Meta's CDN and may not be hostable externally. For development/prototyping, use the
system-ui fallback. For production, obtain a licensed copy or use the self-hosted CDN URL
only if whatsapp.com infrastructure is available.
tokenAuthority: |
These tokens are REVERSE-ENGINEERED from computed browser styles, not from an authoritative
Figma design file or published design system. Treat as high-fidelity approximations.
The curated --whatsapp-* tokens from the extraction pipeline are treated as primary;
primitive and component tiers are synthesised by this layout.md document.
```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