Netflix
MIT
Dark, bold streaming platform design system with signature red accent and cinematic motion, built for large-scale video content discovery and subscription flows
Layout StudioImport this kit into a Studio project and start editing.
CLI installRun it in any project. No account needed.
npx @layoutdesign/context install netflix# layout.md — Netflix Design System
---
## 0. Quick Reference
**Stack:** React/CSS-in-JS (Emotion), custom CSS properties, Bootstrap utility layer. Token source: `extracted-css-vars` (262 properties, high confidence). Use as `var(--token-name)` in CSS, `style={{ prop: 'var(--token-name)' }}` in JSX, or `bg-[var(--token-name)]` in Tailwind.
```css
:root {
/* Brand */
--netflix-accent: rgb(229, 9, 20); /* Primary CTA background — "Get Started", "Sign In" buttons */
--netflix-accent-warm: rgb(193, 17, 25); /* Button hover state surface */
--netflix-accent-pressed: rgb(153, 22, 29); /* Button active/pressed surface */
--netflix-accent-disabled: rgba(229, 9, 20, 0.4); /* Button disabled surface */
/* Surfaces */
--netflix-bg-surface: rgba(22, 22, 22, 0.7); /* Form inputs, select, overlaid containers */
--netflix-accordion-surface: rgb(45, 45, 45); /* Accordion headline background */
--netflix-accordion-surface-hover: rgb(65, 65, 65); /* Accordion headline hover */
/* Text */
--netflix-text-white: rgb(255, 255, 255); /* Primary text on dark surfaces */
--netflix-text-muted: rgba(255, 255, 255, 0.7); /* Labels, descriptions */
--netflix-text-disabled: rgba(255, 255, 255, 0.4);/* Disabled state text */
/* Status */
--netflix-success: rgb(43, 184, 113);
--netflix-warning: rgb(216, 157, 49);
--netflix-error: rgb(235, 57, 66);
/* Border */
--netflix-border: rgba(128, 128, 128, 0.7);
--netflix-border-focus: rgb(255, 255, 255);
/* Radius */
--netflix-radius-sm: 2px; /* badge, tile corners */
--netflix-radius-md: 4px; /* buttons, inputs */
--netflix-radius-lg: 8px; /* content cards */
/* Motion */
--netflix-duration-base: 0.25s;
--netflix-ease-out: cubic-bezier(0.32, 0.94, 0.6, 1);
--netflix-ease-in: cubic-bezier(0.4, 0, 0.68, 0.06);
}
```
```tsx
// Primary CTA button — production-ready
<button
style={{
backgroundColor: 'var(--netflix-accent)',
color: 'var(--netflix-text-white)',
borderRadius: 'var(--netflix-radius-md)',
padding: '12px 24px',
fontSize: '24px',
fontWeight: 500,
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
transition: `background-color var(--netflix-duration-base) var(--netflix-ease-in)`,
border: 'none',
cursor: 'pointer',
}}
onMouseOver={e => e.currentTarget.style.backgroundColor = 'var(--netflix-accent-warm)'}
onMouseOut={e => e.currentTarget.style.backgroundColor = 'var(--netflix-accent)'}
>
Get Started
</button>
```
**NEVER rules:**
- NEVER use `Inter`, `Roboto`, or `Arial` as the primary font — use `"Netflix Sans"` with its full fallback stack
- NEVER hardcode `#e50914` — use `var(--netflix-accent)`
- NEVER use `border-radius > 8px` on primary buttons — Netflix buttons use `4px` (`--netflix-radius-md`)
- NEVER omit hover and active states on buttons — surface color must change on hover (`rgb(193,17,25)`) and active (`rgb(153,22,29)`)
- NEVER use warm or light backgrounds — the entire UI is dark (`rgb(0,0,0)` to `rgb(45,45,45)` range)
- NEVER skip focus ring — all interactive elements must show `outline: 0.125rem solid rgb(255,255,255)` on `:focus-visible`
**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
Netflix's design is **cinematic, authoritative, and immersive**. The visual language prioritises content (show artwork, thumbnails) above all else. The UI is a dark stage that recedes to let media take center focus. The red accent (`rgb(229,9,20)`) signals action and brand identity — it appears only on CTAs, never as decoration.
### Aesthetic Intent
- **Dark-first**: Every surface is dark. Background ranges from pure black to `rgba(22,22,22,0.7)`. There is no light mode.
- **High contrast**: White text (`rgb(255,255,255)`) on near-black backgrounds achieves maximum legibility for TV/monitor viewing distances.
- **Typographic scale is dramatic**: `h1` at `56px / 900` weight is deliberately billboard-scale. The jump from body (`20px`) to hero heading (`56px`) is intentional and must not be compressed.
- **Minimal chrome**: Borders are semi-transparent (`rgba(128,128,128,0.7)`), not solid. Shadows are used sparingly. The UI does not compete with content.
- **Sharp-ish geometry**: Buttons are `4px` radius — not pill, not square. Cards are `8px`. Accordions are `0px`. Each shape is deliberate.
### What This Design Explicitly Rejects
- **Light backgrounds**: NEVER use white or light-grey surfaces for content sections.
- **Decorative colour**: Red is reserved for primary actions only. It is NEVER used for text, dividers, or decorative elements.
- **Rounded pill buttons**: Despite having a `--netflix-radius-full: 50px` token (used on one `input` element), primary CTA buttons are `4px` radius.
- **Font substitution**: The proprietary `Netflix Sans` font is critical to brand identity. System font fallbacks exist but should never be used as a deliberate choice.
- **Generic spacing**: Netflix uses precise, non-standard spacing values (e.g. `0.375rem` for field gaps). Do not substitute an 8px grid system.
---
## 2. Colour System
### Tier 1 — Primitive Values
```css
/* Raw colour values — reference only, use semantic tokens in components */
:root {
/* Red scale */
--color-red-500: rgb(229, 9, 20); /* #e50914 — brand primary */
--color-red-600: rgb(193, 17, 25); /* #c11119 — hover */
--color-red-700: rgb(153, 22, 29); /* #99161d — pressed */
/* Dark scale */
--color-dark-900: rgb(0, 0, 0); /* Pure black — page background */
--color-dark-800: rgb(22, 22, 22); /* #161616 — form surfaces */
--color-dark-700: rgb(35, 35, 35); /* #232323 — loading skeleton base */
--color-dark-600: rgb(45, 45, 45); /* #2d2d2d — accordion surface */
--color-dark-500: rgb(65, 65, 65); /* #414141 — accordion hover, skeleton shimmer */
/* White scale */
--color-white-100: rgb(255, 255, 255); /* Full white */
--color-white-70: rgba(255, 255, 255, 0.7); /* Muted text */
--color-white-40: rgba(255, 255, 255, 0.4); /* Disabled text */
/* Grey scale */
--color-grey-50: rgba(128, 128, 128, 0.7); /* Border default */
--color-grey-30: rgba(128, 128, 128, 0.4); /* Border disabled */
--color-grey-focus: #a9a9a9; /* Focus ring default (non-keyboard) */
/* Status */
--color-green-400: rgb(43, 184, 113); /* success */
--color-yellow-400: rgb(216, 157, 49); /* warning */
--color-red-error: rgb(235, 57, 66); /* error — distinct from brand red */
}
```
### Tier 2 — Semantic Aliases (Primary Reference Layer)
```css
:root {
/* Action / Brand */
--netflix-accent: rgb(229, 9, 20); /* extracted: high confidence — primary CTA bg */
--netflix-accent-warm: rgb(193, 17, 25); /* extracted: high confidence — button hover */
--netflix-accent-pressed: rgb(153, 22, 29); /* extracted: high confidence — button active */
--netflix-accent-disabled: rgba(229, 9, 20, 0.4); /* extracted: high confidence — button disabled */
/* Surfaces */
--netflix-bg-app: rgb(0, 0, 0); /* reconstructed: high confidence — page background */
--netflix-bg-surface: rgba(22, 22, 22, 0.7); /* extracted: high confidence — form surface */
--netflix-bg-surface-disabled: rgba(22, 22, 22, 0.2); /* extracted: high confidence */
--netflix-bg-skeleton-base: rgb(35, 35, 35); /* extracted: high confidence — loading animation base */
--netflix-bg-skeleton-shimmer: rgb(65, 65, 65); /* extracted: high confidence — loading animation peak */
/* Text */
--netflix-text-white: rgb(255, 255, 255); /* extracted: high confidence — primary foreground */
--netflix-text-muted: rgba(255, 255, 255, 0.7); /* extracted: high confidence — labels, helper text */
--netflix-text-disabled: rgba(255, 255, 255, 0.4);/* extracted: high confidence — disabled state */
--netflix-text-pressed: rgba(255, 255, 255, 0.7); /* extracted: high confidence — button text when active */
/* Borders */
--netflix-border: rgba(128, 128, 128, 0.7); /* extracted: high confidence — default border */
--netflix-border-disabled: rgba(128, 128, 128, 0.4); /* extracted: high confidence */
--netflix-border-focus: rgb(255, 255, 255); /* extracted: high confidence — keyboard focus ring */
--netflix-border-transparent: rgba(0, 0, 0, 0); /* extracted: high confidence — button border (no border) */
/* Status */
--netflix-success: rgb(43, 184, 113); /* extracted: high confidence */
--netflix-warning: rgb(216, 157, 49); /* extracted: high confidence */
--netflix-error: rgb(235, 57, 66); /* extracted: high confidence */
/* Accordion */
--netflix-accordion-surface: rgb(45, 45, 45); /* extracted: high confidence */
--netflix-accordion-surface-hover: rgb(65, 65, 65); /* extracted: high confidence */
--netflix-accordion-foreground: rgb(255, 255, 255); /* extracted: high confidence */
}
```
### Tier 3 — Component Tokens (Original CSS Variable Names)
```css
/* Button component tokens — PRESERVE these original names exactly */
:root {
--wct--local-design--Button-Surface: rgb(229, 9, 20); /* button bg: default */
--wct--local-design--Button-SurfaceHovered: rgb(193, 17, 25); /* button bg: hover */
--wct--local-design--Button-SurfaceDisabled: rgba(229, 9, 20, 0.4);/* button bg: disabled */
--wct--local-design--Button-SurfacePressed: rgb(153, 22, 29); /* button bg: active/pressed */
--wct--local-design--Button-Foreground: rgb(255, 255, 255); /* button text: default */
--wct--local-design--Button-ForegroundDisabled: rgba(255, 255, 255, 0.4); /* button text: disabled */
--wct--local-design--Button-ForegroundHovered: var(--wct--local-design--Button-Foreground);
--wct--local-design--Button-ForegroundPressed: rgba(255, 255, 255, 0.7); /* button text: active */
--wct--local-design--Button-Border: rgba(0, 0, 0, 0); /* button border: transparent */
--wct--local-design--Button-BorderDisabled: rgba(0, 0, 0, 0);
--wct--local-design--Button-BorderHovered: rgba(0, 0, 0, 0);
--wct--local-design--Button-BorderPressed: rgba(0, 0, 0, 0);
--wct--local-design--Button-BorderRadius: 0.25rem; /* 4px */
--wct--local-design--Button-BorderWidth: 0.0625rem; /* 1px */
/* Input / Select component tokens */
--wct--local-design--Select-Surface: rgba(22, 22, 22, 0.7);
--wct--local-design--Select-SurfaceDisabled: rgba(22, 22, 22, 0.02);
--wct--local-design--Select-Foreground: rgb(255, 255, 255);
--wct--local-design--Select-ForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Select-LabelForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Select-LabelForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Select-DescriptionForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Select-Border: rgba(128, 128, 128, 0.7);
--wct--local-design--Select-BorderDisabled: rgba(128, 128, 128, 0.4);
--wct--local-design--Select-BorderError: rgb(235, 57, 66);
--wct--local-design--Select-BorderSuccess: rgb(43, 184, 113);
--wct--local-design--Select-BorderWarning: rgb(216, 157, 49);
--wct--local-design--Select-BorderRadius: 0.25rem;
--wct--local-design--Select-BorderWidth: 0.0625rem;
--wct--local-design--Select-MessageForegroundError: rgb(235, 57, 66);
--wct--local-design--Select-MessageForegroundSuccess: rgb(43, 184, 113);
--wct--local-design--Select-MessageForegroundWarning: rgb(216, 157, 49);
/* Input tokens */
--wct--local-design--Input-Surface: rgba(22, 22, 22, 0.7);
--wct--local-design--Input-SurfaceDisabled: rgba(22, 22, 22, 0.2);
--wct--local-design--Input-Foreground: rgb(255, 255, 255);
--wct--local-design--Input-ForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Input-LabelForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Input-LabelForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Input-DescriptionForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Input-Border: rgba(128, 128, 128, 0.7);
--wct--local-design--Input-BorderDisabled: rgba(128, 128, 128, 0.4);
--wct--local-design--Input-BorderError: rgb(235, 57, 66);
--wct--local-design--Input-BorderSuccess: rgb(43, 184, 113);
--wct--local-design--Input-BorderWarning: rgb(216, 157, 49);
--wct--local-design--Input-BorderRadius: 0.25rem;
--wct--local-design--Input-BorderWidth: 0.0625rem;
--wct--local-design--Input-MessageForegroundError: rgb(235, 57, 66);
--wct--local-design--Input-MessageForegroundSuccess: rgb(43, 184, 113);
--wct--local-design--Input-MessageForegroundWarning: rgb(216, 157, 49);
/* Focus ring */
--wct--focus-ring--color: rgb(255, 255, 255);
--wct--focus-ring--color-default: #a9a9a9;
--wct--focus-ring--width: 0.125rem; /* 2px */
--wct--focus-ring--style: solid;
--wct--focus-ring--offset: 0.125rem; /* 2px */
}
```
### Accent / Brand Subgroup (additional detected)
```css
:root {
/* Decorative brand colours — tile backgrounds, illustration accents */
--wct--local-design--Button-SurfacePressed: rgb(153, 22, 29); /* deep red pressed state */
--brand-primary-cta: rgb(229, 9, 20); /* extracted: high confidence — maps to --netflix-accent */
}
```
---
## 3. Typography System
### Font Stack
```css
:root {
/* Primary typeface — Netflix proprietary variable font */
--font-family-primary: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
/* extracted: high confidence — used on h1, h2, h3, body, button, input, dropdown */
/* Script-specific overrides (do not use for Latin UI) */
--font-family-arabic: "NKufi", "Netflix Sans", sans-serif;
--font-family-thai: "GraphikTH", "Netflix Sans", sans-serif;
--font-family-ja: "Netflix Sans JA", "Netflix Sans", sans-serif;
}
```
### Composite Typography Tokens
```css
/* Each composite bundles family + size + weight + line-height + letter-spacing */
/* Hero Heading */
--type-hero: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 56px; /* --netflix-font-size-2xl */
font-weight: 900; /* --netflix-font-weight-semibold (Netflix's "Black" cut) */
line-height: 70px; /* --netflix-line-height-loose */
letter-spacing: normal;
color: rgb(255, 255, 255);
text-align: center;
}
/* Usage: h1 on hero/landing section only */
/* Section Heading */
--type-section-heading: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 24px; /* --netflix-font-size-xl */
font-weight: 500;
line-height: normal;
letter-spacing: normal;
color: rgb(255, 255, 255);
text-align: start;
}
/* Usage: h2 — "Trending Now", "More Reasons to Join", "Frequently Asked Questions" */
/* Body / Subheading */
--type-body-large: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 20px; /* --netflix-font-size-lg */
font-weight: 500;
line-height: normal;
letter-spacing: normal;
color: rgb(255, 255, 255);
text-align: center;
}
/* Usage: body — hero sub-copy, section intro text. margin-bottom: 32px */
/* Content Heading / UI Label Large */
--type-ui-heading: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 16px; /* --netflix-font-size-md */
font-weight: 400;
line-height: 24px;
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Usage: h3 — form field labels, feature sub-labels */
/* Button Text (large CTA) */
--type-button-large: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 24px; /* extracted from button_primary computed style */
font-weight: 500;
line-height: 24px;
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Usage: primary hero CTA — "Get Started" */
/* Button Text (small/nav) */
--type-button-small: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 14px; /* --netflix-font-size-sm */
font-weight: 500;
line-height: 14px; /* extracted from link computed style */
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Usage: nav "Sign In" button, secondary CTAs, footer links */
/* Accordion Headline */
--type-accordion-headline: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 24px; /* --wct--local-design--Accordion-HeadlineTextFontSize: 1.5rem */
font-weight: 400;
line-height: normal;
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Usage: FAQ accordion question headers */
/* Accordion Panel / Body */
--type-accordion-panel: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 24px; /* --wct--local-design--Accordion-PanelTextFontSize: 1.5rem */
font-weight: 400;
line-height: normal;
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Usage: FAQ accordion answer body text */
/* Input / Form Text */
--type-input-value: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 16px; /* --wct--local-design--Input-TextFontSize: 1rem */
font-weight: 400;
line-height: 24px; /* 1.5 relative → 24px computed */
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Input Label (filled state) */
--type-input-label-filled: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 12px; /* --wct--local-design--Input-LabelTextFontSize: 0.75rem */
font-weight: 400;
line-height: 18px; /* 1.5 relative */
letter-spacing: normal;
color: rgba(255, 255, 255, 0.7);
}
/* Input Label (empty/placeholder state) */
--type-input-label-empty: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 16px; /* --wct--local-design--Input-LabelTextEmptyFontSize: 1rem */
font-weight: 400;
line-height: 24px; /* 1.5 relative */
letter-spacing: normal;
color: rgba(255, 255, 255, 0.7);
}
/* Helper / Description / Message */
--type-field-helper: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 13px; /* --wct--local-design--Input-DescriptionFontSize: 0.8125rem */
font-weight: 400;
line-height: normal;
letter-spacing: normal;
color: rgba(255, 255, 255, 0.7);
}
/* Dropdown / Select */
--type-dropdown: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 16px;
font-weight: 400;
line-height: 20px;
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Footer / Nav small */
--type-footer: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 14px; /* --netflix-font-size-sm — 44 elements in footer */
font-weight: 500;
line-height: 21px; /* --netflix-line-height-tight */
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Large Numeric Display (category numbers, episode counts) */
--type-display-numeral: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
font-size: 100px; /* --netflix-font-size-3xl — 20 elements, span numerals */
font-weight: 900;
line-height: normal;
letter-spacing: normal;
color: rgb(255, 255, 255);
}
/* Usage: ranking numbers overlaid on content tiles (Top 10 rows) */
```
### Weight Scale
| Weight | Token value | Netflix Sans Cut | Usage |
|--------|-------------|-----------------|-------|
| 100 | `font-weight: 100` | Thin | Decorative only |
| 300 | `font-weight: 300` | Light | Secondary copy |
| 400 | `font-weight: 400` | Regular | Body, labels, accordion |
| 500 | `font-weight: 500` | Medium | **Buttons, nav, section heads** |
| 700 | `font-weight: 700` | Bold | Emphasis |
| **900** | `font-weight: 900` | Black | **Hero h1 — single use** |
---
## 4. Spacing & Layout
### Base Unit & Scale
```css
:root {
/* Component micro-spacing (from extracted CSS vars) */
--wct--local-design--Button-BorderWidth: 0.0625rem; /* 1px — border widths */
--wct--focus-ring--width: 0.125rem; /* 2px — focus ring, also offset */
--wct--focus-ring--offset: 0.125rem; /* 2px */
--wct--local-design--Select-SpaceVerticalEmpty: 0.375rem; /* 6px — field top gap when empty */
--wct--local-design--Select-SpaceBetweenFieldDescription: 0.375rem; /* 6px */
--wct--local-design--Select-SpaceBetweenFieldMessage: 0.375rem; /* 6px */
--wct--local-design--Select-MessageSpaceBetweenIconContent: 0.25rem;/* 4px */
--wct--local-design--Select-SpaceBetweenIconContent: 0.5rem; /* 8px */
--wct--local-design--Select-SpaceHorizontal: 0.625rem; /* 10px — field horizontal padding */
--wct--local-design--Button-SpaceVertical: 0.25rem; /* 4px */
--wct--local-design--Button-SpaceHorizontal: 1rem; /* 16px */
--wct--local-design--Button-SpaceBetweenIconText: 0.5rem;/* 8px */
--wct--local-design--Button-Height: 2rem; /* 32px — default button height */
--wct--local-design--Button-IconHeight: 1rem; /* 16px */
--wct--local-design--Button-IconWidth: 1rem; /* 16px */
--wct--local-design--Input-SpaceHorizontal: 1rem; /* 16px */
--wct--local-design--Input-SpaceVertical: 0.25rem; /* 4px */
--wct--local-design--Input-SpaceVerticalEmpty: 0.75rem; /* 12px */
--wct--local-design--Input-SpaceBetweenIconContent: 0.5rem; /* 8px */
--wct--local-design--Input-SpaceBetweenFieldDescription: 0.375rem; /* 6px */
--wct--local-design--Input-SpaceBetweenFieldMessage: 0.375rem; /* 6px */
--wct--local-design--Accordion-HeadlineSpace: 1.5rem; /* 24px — accordion header padding */
--wct--local-design--Accordion-HeadlineSpaceExpanded: var(--wct--local-design--Accordion-HeadlineSpace);
--wct--local-design--Accordion-PanelSpaceExpanded: 1.5rem; /* 24px — accordion body padding */
--wct--local-design--Accordion-SpaceBetween: 0.5rem; /* 8px — gap between accordion items */
--wct--local-design--Accordion-SpaceBetweenHeadlinePanel: 0.0625rem; /* 1px — separator */
--wct--local-design--Accordion-HeadlineSpaceBetweenIconText: 0.75rem; /* 12px */
/* Page-level spacing (computed from element styles) */
--space-hero-heading-bottom: 16px; /* reconstructed: high confidence — h1 margin-bottom */
--space-body-bottom: 32px; /* reconstructed: high confidence — body margin-bottom */
--ot-footer-space: 160px; /* extracted: high confidence — footer top spacing */
/* Semantic spacing aliases */
--netflix-space-xs: 0.0625rem; /* 1px — borders */
--netflix-space-sm: 0.125rem; /* 2px — focus ring */
--netflix-space-md: 0.25rem; /* 4px — tight padding */
--netflix-space-lg: 0.375rem; /* 6px — field spacing */
--netflix-space-xl: 0.5rem; /* 8px — icon-text gap */
--netflix-space-2xl: 0.625rem; /* 10px — horizontal field padding */
--netflix-space-3xl: 0.75rem; /* 12px — icon-text in accordion */
}
```
### Radius Scale
```css
:root {
--netflix-radius-sm: 2px; /* 28 elements — badges, small tiles, decorative */
--netflix-radius-md: 4px; /* 4 elements — PRIMARY BUTTONS, form inputs */
--netflix-radius-lg: 8px; /* 11 elements — content cards, thumbnail containers */
--netflix-radius-full: 50px; /* 1 element — specific input field only, NOT buttons */
/* Component-specific */
--wct--local-design--Button-BorderRadius: 0.25rem; /* 4px */
--wct--local-design--Input-BorderRadius: 0.25rem; /* 4px */
--wct--local-design--Select-BorderRadius: 0.25rem; /* 4px */
--wct--local-design--Accordion-HeadlineBorderRadius: 0rem; /* 0px — sharp */
--wct--local-design--Accordion-PanelBorderRadius: 0rem; /* 0px — sharp */
}
```
### Grid & Breakpoints
```css
/* Responsive breakpoints (from media query extraction) */
/* Key tiers for layout decisions: */
:root {
--bp-mobile-sm: 400px; /* small phones */
--bp-mobile: 530px; /* standard mobile */
--bp-tablet-sm: 640px; /* small tablet */
--bp-tablet: 768px; /* standard tablet */
--bp-tablet-lg: 960px; /* large tablet / small desktop */
--bp-desktop: 1024px; /* desktop */
--bp-desktop-lg: 1280px; /* large desktop */
--bp-desktop-xl: 1600px; /* XL desktop */
--bp-hd: 1920px; /* HD / full screen */
--bp-4k: 2560px; /* 4K displays */
}
/* Layout container pattern (layout-container vars are intentionally `initial` — */
/* populated per-breakpoint by the component system) */
--wct--layout-container--width: inherit;
/* Column spacing, row spacing, padding, maxWidth: set via --wct--layout-container--{prop}-{breakpoint} */
```
### Button Layout (computed)
```css
/* Primary hero button */
.btn-primary-hero {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 12px 24px; /* extracted from button_primary computed style */
height: auto; /* not fixed — grows with content */
gap: normal;
}
/* Small / nav button */
.btn-small {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
padding: 4px 16px; /* extracted from link computed style */
}
```
---
## 5. Page Structure & Layout Patterns
> **Note:** No screenshots provided. All section ordering and layout details are inferred from the LAYOUT DIGEST, component inventory, computed styles, and CTA census. Rows marked **(inferred)** are not visually confirmed.
### 5.1 Section Map
| # | Section | Layout Type | Approx. Height | Key Elements |
|---|---------|-------------|----------------|--------------|
| 1 | **Navigation / Header** | Flex row, space-between | ~70px | Netflix logo (left), language dropdown (right), Sign In button — red CTA `rgb(229,9,20)` |
| 2 | **Hero / Landing Banner** | Flex column, centered | ~600px | Full-bleed background gradient, h1 (56px/900), body subtext (20px/500), email input + CTA row |
| 3 | **Trending Now / Content Row** (inferred) | Horizontal scroll flex | ~300–400px | h2 section heading, thumbnail tiles (radius-lg: 8px), Top 10 numerals (100px/900) |
| 4 | **Feature Highlights** (inferred) | Alternating 2-column | ~300px each | h2 left/right, media image opposite, body copy at 20px |
| 5 | **More Reasons to Join** (inferred) | 2–4 column grid | ~300px | h2 heading, feature cards with icon + text |
| 6 | **FAQ / Accordion** | Single column, full-width | ~400px+ | h2 "Frequently Asked Questions", accordion items (0px radius, 1px separator) |
| 7 | **Footer CTA** (inferred) | Flex column, centered | ~150px | Repeated email input + "Get Started" button, disclaimer text (13px) |
| 8 | **Footer** | Multi-column grid | ~400px (`--ot-footer-space: 160px` + links) | 4-column link grid, language selector dropdown, legal text (14px) |
### 5.2 Layout Patterns
**Hero section:**
- `display: flex; flex-direction: column; align-items: center; text-align: center`
- h1 has `margin-bottom: 16px`; body paragraph has `margin-bottom: 32px`
- Email input + button inline: `display: flex; flex-direction: row; gap: 8px`
- Button: `display: flex; justify-content: center; align-items: center; padding: 12px 24px`
**Content tile rows (inferred from computed badge/thumbnail styles):**
- Horizontal scroll: `display: flex; flex-direction: row; overflow-x: auto`
- Tiles: `border-radius: 8px` (`--netflix-radius-lg`)
- Top 10 numerals: `font-size: 100px` overlapping left edge of tile
**FAQ Accordion:**
- Single column, full-width
- Headline: `background: rgb(45,45,45)`; hover: `rgb(65,65,65)`
- No border-radius on accordion items (`0rem`)
- `1px` gap between headline and panel: `--wct--local-design--Accordion-SpaceBetweenHeadlinePanel: 0.0625rem`
- `8px` gap between accordion items: `--wct--local-design--Accordion-SpaceBetween: 0.5rem`
- Internal padding: `24px` on all sides when expanded
**Footer:**
- Grid: 4 columns on desktop, stacks on mobile
- Footer top spacing: `160px` (`--ot-footer-space`)
- Link text: `14px / 500 / line-height: 21px`
### 5.3 Visual Hierarchy
- **Primary CTA** colour is **always** `rgb(229,9,20)` — confirmed by button census (3 "Get Started" buttons extracted)
- **Hero heading** (56px/900) is the dominant typographic element — nothing else approaches this scale on the landing page
- **Top 10 numerals** at 100px are a visual signature but appear on content rows, not the hero
- **Accordion** on FAQ section uses dark grey surfaces (`rgb(45,45,45)`) slightly lighter than page black — creates subtle separation
- CTA button appears at minimum twice: hero section + pre-footer repeat (confirmed by 3 button instances in computed styles)
- Images/thumbnails are right or left of text in alternating feature rows — Netflix's classic zig-zag pattern (inferred)
- Whitespace between sections is generous — `32px` body margin and `160px` footer space signal deliberate breathing room
### 5.4 Content Patterns
**Pattern A — Hero email-capture row:**
```
[h1: large headline centered]
[p: subtext centered, mb: 32px]
[input: email field] [button: Get Started — red]
```
**Pattern B — Feature zig-zag (inferred):**
```
[image/video — 50%] [text block — 50%] ← alternates left/right per row
h2: feature name (24px/500)
p: description (20px/500)
```
**Pattern C — Accordion FAQ:**
```
[h2: "Frequently Asked Questions" — 24px/500]
[Accordion item — dark grey bg]
[header: question — 24px/400, padding: 24px]
[panel: answer — 24px/400, padding: 24px]
[Accordion item]
...
```
**Pattern D — Content tile row:**
```
[h2: row title — 24px/500]
[scrollable row of tiles: border-radius: 8px]
Tile: thumbnail + optional Top 10 numeral (100px, overlapping)
```
---
## 6. Component Patterns
### 6.1 Primary Button
**Anatomy:** `<button>` → `[optional icon]` + `[label text]`
**Token-to-property mappings:**
| State | Background | Text color | Border | Transition |
|-------|-----------|-----------|--------|-----------|
| Default | `rgb(229,9,20)` | `rgb(255,255,255)` | none | — |
| Hover | `rgb(193,17,25)` | `rgb(255,255,255)` | none | `0.25s cubic-bezier(0.32,0.94,0.6,1)` |
| Focus | `rgb(229,9,20)` | `rgb(255,255,255)` | outline: `2px solid rgb(255,255,255)`, offset `2px` | — |
| Active/Pressed | `rgb(153,22,29)` | `rgba(255,255,255,0.7)` | none | `0s` (instant) |
| Disabled | `rgba(229,9,20,0.4)` | `rgba(255,255,255,0.4)` | none | `0.25s` |
```tsx
// Production-ready Netflix Primary Button
import { ButtonHTMLAttributes, FC } from 'react';
interface NetflixButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
size?: 'large' | 'small';
isLoading?: boolean;
}
const NetflixButton: FC<NetflixButtonProps> = ({
children,
size = 'large',
isLoading = false,
disabled,
style,
...props
}) => {
const isDisabled = disabled || isLoading;
const baseStyles: React.CSSProperties = {
// Layout
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
gap: 'var(--wct--local-design--Button-SpaceBetweenIconText)', // 8px
// Sizing
padding: size === 'large' ? '12px 24px' : '4px 16px',
height: 'auto',
width: 'var(--wct--local-design--Button-Width)', // auto
// Typography
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: size === 'large' ? '24px' : '14px',
fontWeight: 500,
lineHeight: size === 'large' ? '24px' : '14px',
letterSpacing: 'normal',
textDecoration: 'none',
whiteSpace: 'nowrap',
// Appearance
backgroundColor: isDisabled
? 'var(--wct--local-design--Button-SurfaceDisabled)'
: 'var(--wct--local-design--Button-Surface)',
color: isDisabled
? 'var(--wct--local-design--Button-ForegroundDisabled)'
: 'var(--wct--local-design--Button-Foreground)',
border: `var(--wct--local-design--Button-BorderWidth) solid var(--wct--local-design--Button-Border)`,
borderRadius: 'var(--wct--local-design--Button-BorderRadius)', // 4px
cursor: isDisabled ? 'not-allowed' : 'pointer',
opacity: 1,
// Motion
transition: `
background-color var(--wct--local-design--Button-Duration) var(--wct--local-design--Button-Easing),
border-color var(--wct--local-design--Button-Duration) var(--wct--local-design--Button-Easing),
color var(--wct--local-design--Button-Duration) var(--wct--local-design--Button-Easing)
`,
...style,
};
return (
<button
{...props}
disabled={isDisabled}
aria-disabled={isDisabled}
style={baseStyles}
onMouseEnter={(e) => {
if (!isDisabled) {
e.currentTarget.style.backgroundColor =
'var(--wct--local-design--Button-SurfaceHovered)';
e.currentTarget.style.transitionTimingFunction =
'var(--wct--local-design--Button-EasingHovered)';
}
props.onMouseEnter?.(e);
}}
onMouseLeave={(e) => {
if (!isDisabled) {
e.currentTarget.style.backgroundColor =
'var(--wct--local-design--Button-Surface)';
e.currentTarget.style.transitionTimingFunction =
'var(--wct--local-design--Button-Easing)';
}
props.onMouseLeave?.(e);
}}
onMouseDown={(e) => {
if (!isDisabled) {
e.currentTarget.style.backgroundColor =
'var(--wct--local-design--Button-SurfacePressed)';
e.currentTarget.style.color =
'var(--wct--local-design--Button-ForegroundPressed)';
e.currentTarget.style.transitionDuration = '0s';
}
props.onMouseDown?.(e);
}}
onMouseUp={(e) => {
if (!isDisabled) {
e.currentTarget.style.backgroundColor =
'var(--wct--local-design--Button-SurfaceHovered)';
e.currentTarget.style.color =
'var(--wct--local-design--Button-Foreground)';
e.currentTarget.style.transitionDuration =
'var(--wct--local-design--Button-Duration)';
}
props.onMouseUp?.(e);
}}
>
{isLoading ? (
<span aria-label="Loading" style={{ opacity: 0.7 }}>
{/* Replace with spinner SVG */}
···
</span>
) : (
children
)}
</button>
);
};
export default NetflixButton;
```
---
### 6.2 Form Input (Floating Label)
**Anatomy:** `<div wrapper>` → `<input>` + `<label>` (floating) + `[border chrome]` + `[helper/error message]`
**Token-to-property mappings:**
| State | Border color | Label | Background |
|-------|-------------|-------|-----------|
| Default/Empty | `rgba(128,128,128,0.7)` | `16px rgba(255,255,255,0.7)` | `rgba(22,22,22,0.7)` |
| Focused | outline `2px solid rgb(255,255,255)` | `12px rgba(255,255,255,0.7)` (floated) | `rgba(22,22,22,0.7)` |
| Filled | `rgba(128,128,128,0.7)` | `12px rgba(255,255,255,0.7)` (floated) | `rgba(22,22,22,0.7)` |
| Disabled | `rgba(128,128,128,0.4)` | `rgba(255,255,255,0.4)` | `rgba(22,22,22,0.2)` |
| Error | `rgb(235,57,66)` | `rgba(255,255,255,0.7)` | `rgba(22,22,22,0.7)` |
| Success | `rgb(43,184,113)` | `rgba(255,255,255,0.7)` | `rgba(22,22,22,0.7)` |
| Warning | `rgb(216,157,49)` | `rgba(255,255,255,0.7)` | `rgba(22,22,22,0.7)` |
```tsx
// Netflix floating-label input
interface NetflixInputProps {
id: string;
label: string;
value: string;
onChange: (v: string) => void;
type?: string;
disabled?: boolean;
error?: string;
success?: string;
helperText?: string;
}
const NetflixInput: FC<NetflixInputProps> = ({
id, label, value, onChange, type = 'text',
disabled = false, error, success, helperText,
}) => {
const hasValue = value.length > 0;
const validationState = error ? 'error' : success ? 'success' : 'default';
const borderColor =
validationState === 'error' ? 'var(--wct--local-design--Input-BorderError)' :
validationState === 'success' ? 'var(--wct--local-design--Input-BorderSuccess)' :
disabled ? 'var(--wct--local-design--Input-BorderDisabled)' :
'var(--wct--local-design--Input-Border)';
const messageColor =
validationState === 'error' ? 'var(--wct--local-design--Input-MessageForegroundError)' :
validationState === 'success' ? 'var(--wct--local-design--Input-MessageForegroundSuccess)' :
'var(--wct--local-design--Input-DescriptionForeground)';
return (
<div style={{ position: 'relative', width: '100%' }}>
{/* Chrome / border layer */}
<div
data-wct-form-control-chrome
style={{
position: 'absolute',
inset: 0,
borderRadius: 'var(--wct--local-design--Input-BorderRadius)',
border: `var(--wct--local-design--Input-BorderWidth) solid ${borderColor}`,
backgroundColor: disabled
? 'var(--wct--local-design--Input-SurfaceDisabled)'
: 'var(--wct--local-design--Input-Surface)',
pointerEvents: 'none',
}}
/>
{/* Floating label */}
<label
htmlFor={id}
style={{
position: 'absolute',
left: 'var(--wct--local-design--Input-SpaceHorizontal)',
top: hasValue ? '8px' : '50%',
transform: hasValue ? 'none' : 'translateY(-50%)',
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: hasValue
? 'var(--wct--local-design--Input-LabelTextFontSize)' /* 0.75rem / 12px */
: 'var(--wct--local-design--Input-LabelTextEmptyFontSize)', /* 1rem / 16px */
fontWeight: 'var(--wct--local-design--Input-LabelTextFontWeight)',
color: disabled
? 'var(--wct--local-design--Input-LabelForegroundDisabled)'
: 'var(--wct--local-design--Input-LabelForeground)',
transition: 'all var(--netflix-duration-base) var(--netflix-ease-in)',
pointerEvents: 'none',
zIndex: 1,
}}
>
{label}
</label>
{/* Actual input */}
<input
id={id}
type={type}
value={value}
disabled={disabled}
onChange={(e) => onChange(e.target.value)}
style={{
position: 'relative',
zIndex: 1,
display: 'block',
width: '100%',
padding: `24px var(--wct--local-design--Input-SpaceHorizontal) 8px`,
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: 'var(--wct--local-design--Input-TextFontSize)',
fontWeight: 'var(--wct--local-design--Input-TextFontWeight)',
lineHeight: 'var(--wct--local-design--Input-TextLineHeight)',
color: disabled
? 'var(--wct--local-design--Input-ForegroundDisabled)'
: 'var(--wct--local-design--Input-Foreground)',
background: 'transparent',
border: 'none',
outline: 'none',
borderRadius: 'var(--wct--local-design--Input-BorderRadius)',
boxSizing: 'border-box',
}}
/>
{/* Validation / helper message */}
{(error || success || helperText) && (
<p
data-wct-form-control-validation
style={{
marginTop: 'var(--wct--local-design--Input-SpaceBetweenFieldMessage)',
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: 'var(--wct--local-design--Input-MessageFontSize)',
fontWeight: 'var(--wct--local-design--Input-MessageFontWeight)',
color: messageColor,
lineHeight: 'normal',
margin: 0,
paddingTop: 'var(--wct--local-design--Input-SpaceBetweenFieldMessage)',
}}
>
{error || success || helperText}
</p>
)}
</div>
);
};
```
---
### 6.3 Accordion (FAQ)
**Anatomy:** `<div container>` → `[accordion item: header button + panel]`
**Token-to-property mappings:**
| State | Headline bg | Headline text | Transition |
|-------|------------|--------------|-----------|
| Collapsed | `rgb(45,45,45)` | `rgb(255,255,255)` | — |
| Hover | `rgb(65,65,65)` | `rgb(255,255,255)` | `250ms cubic-bezier(0.32,0.94,0.6,1)` |
| Expanded | `rgb(45,45,45)` | `rgb(255,255,255)` | `250ms cubic-bezier(0.4,0,0.68,0.06)` |
| Focus | outline `2px solid rgb(255,255,255)`, offset `2px` | — | — |
```tsx
// Netflix FAQ Accordion item
import { useState, FC } from 'react';
interface AccordionItemProps {
question: string;
answer: string;
}
const NetflixAccordionItem: FC<AccordionItemProps> = ({ question, answer }) => {
const [isOpen, setIsOpen] = useState(false);
return (
<div
style={{
marginBottom: 'var(--wct--local-design--Accordion-SpaceBetween)', /* 8px */
}}
>
{/* Headline / trigger */}
<button
onClick={() => setIsOpen(!isOpen)}
aria-expanded={isOpen}
style={{
display: 'flex',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
width: '100%',
padding: 'var(--wct--local-design--Accordion-HeadlineSpace)', /* 24px */
gap: 'var(--wct--local-design--Accordion-HeadlineSpaceBetweenIconText)', /* 12px */
backgroundColor: 'var(--wct--local-design--Accordion-HeadlineSurface)', /* rgb(45,45,45) */
color: 'var(--wct--local-design--Accordion-HeadlineForeground)',
border: 'none',
borderRadius: isOpen
? 'var(--wct--local-design--Accordion-HeadlineBorderRadiusExpanded)' /* top corners only: 0 */
: 'var(--wct--local-design--Accordion-HeadlineBorderRadius)', /* 0 */
cursor: 'pointer',
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: 'var(--wct--local-design--Accordion-HeadlineTextFontSize)', /* 1.5rem */
fontWeight: 'var(--wct--local-design--Accordion-HeadlineTextFontWeight)', /* 400 */
textAlign: 'left',
transition: `background-color var(--wct--local-design--Accordion-HeadlineDuration) var(--wct--local-design--Accordion-HeadlineEasing)`,
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLElement).style.backgroundColor =
'var(--wct--local-design--Accordion-HeadlineSurfaceHovered)';
(e.currentTarget as HTMLElement).style.transitionTimingFunction =
'var(--wct--local-design--Accordion-HeadlineEasingHovered)';
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLElement).style.backgroundColor =
'var(--wct--local-design--Accordion-HeadlineSurface)';
(e.currentTarget as HTMLElement).style.transitionTimingFunction =
'var(--wct--local-design--Accordion-HeadlineEasing)';
}}
>
<span>{question}</span>
{/* Icon rotates -45deg when closed → 0deg when open */}
<span
style={{
display: 'inline-block',
transform: isOpen ? 'rotate(0deg)' : 'rotate(-45deg)',
transition: `transform var(--wct--local-design--Accordion-HeadlineIconDuration) var(--wct--local-design--Accordion-HeadlineIconEasing)`,
fontSize: '2rem',
lineHeight: 1,
}}
aria-hidden
>
✕
</span>
</button>
{/* Panel */}
{isOpen && (
<div
style={{
backgroundColor: 'var(--wct--local-design--Accordion-PanelSurface)', /* rgb(45,45,45) */
color: 'var(--wct--local-design--Accordion-PanelForeground)',
padding: `var(--wct--local-design--Accordion-PanelSpaceExpanded)`, /* 24px */
borderRadius: 'var(--wct--local-design--Accordion-PanelBorderRadiusExpanded)',
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: 'var(--wct--local-design--Accordion-PanelTextFontSize)', /* 1.5rem */
fontWeight: 'var(--wct--local-design--Accordion-PanelTextFontWeight)', /* 400 */
borderTop: `var(--wct--local-design--Accordion-SpaceBetweenHeadlinePanel) solid rgba(128,128,128,0.3)`,
}}
>
{answer}
</div>
)}
</div>
);
};
```
---
### 6.4 Badge / Content Label
**Anatomy:** `<span>` with `box-shadow` for subtle elevation
**Token-to-property mappings:**
| State | Background | Shadow | Radius |
|-------|-----------|--------|--------|
| Default | contextual (tile bg) | `rgb(128,128,128) 0px 0px 5px 0px` | `2px` |
| Hover | — | unchanged | unchanged |
```tsx
const NetflixBadge: FC<{ children: React.ReactNode }> = ({ children }) => (
<span
style={{
display: 'inline-block',
borderRadius: 'var(--netflix-radius-sm)', /* 2px */
boxShadow: 'rgb(128, 128, 128) 0px 0px 5px 0px',
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: '13px',
fontWeight: 400,
color: 'var(--netflix-text-white)',
padding: '2px 6px',
}}
>
{children}
</span>
);
```
---
### 6.5 Language Dropdown (Select)
**Anatomy:** `<div wrapper>` → `<select>` + `[chrome border]` + `[label]`
| State | Border | Surface | Text |
|-------|--------|---------|------|
| Default | `rgba(128,128,128,0.7)` | `rgba(22,22,22,0.7)` | `rgb(255,255,255)` |
| Focus | outline `2px solid rgb(255,255,255)` on chrome | same | same |
| Disabled | `rgba(128,128,128,0.4)` | `rgba(22,22,22,0.02)` | `rgba(255,255,255,0.4)` |
| Error | `rgb(235,57,66)` | same | same |
```tsx
const NetflixSelect: FC<{ options: string[]; disabled?: boolean; error?: string }> = ({
options,
disabled = false,
error,
}) => (
<div
data-wct-form-control-chrome
style={{
position: 'relative',
display: 'inline-block',
border: `var(--wct--local-design--Select-BorderWidth) solid ${
error ? 'var(--wct--local-design--Select-BorderError)' :
disabled ? 'var(--wct--local-design--Select-BorderDisabled)' :
'var(--wct--local-design--Select-Border)'
}`,
borderRadius: 'var(--wct--local-design--Select-BorderRadius)',
backgroundColor: disabled
? 'var(--wct--local-design--Select-SurfaceDisabled)'
: 'var(--wct--local-design--Select-Surface)',
}}
>
<select
disabled={disabled}
style={{
appearance: 'none',
background: 'transparent',
border: 'none',
outline: 'none',
padding: `var(--wct--local-design--Select-SpaceVerticalEmpty) var(--wct--local-design--Select-SpaceHorizontal)`,
fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif',
fontSize: 'var(--wct--local-design--Select-TextFontSize)',
fontWeight: 'var(--wct--local-design--Select-TextFontWeight)',
lineHeight: 'var(--wct--local-design--Select-TextLineHeight)',
color: disabled
? 'var(--wct--local-design--Select-ForegroundDisabled)'
: 'var(--wct--local-design--Select-Foreground)',
paddingRight: '2rem', /* space for dropdown arrow */
width: 'var(--wct--local-design--Select-Width)',
cursor: disabled ? 'not-allowed' : 'pointer',
}}
>
{options.map((o) => <option key={o} value={o}>{o}</option>)}
</select>
</div>
);
```
---
## 7. Elevation & Depth
```css
:root {
/* Shadows — extracted from computed styles */
--shadow-badge: rgb(128, 128, 128) 0px 0px 5px 0px;
/* Usage: badge/label overlays on content tiles */
--shadow-none: none;
/* Usage: buttons, inputs, accordion panels — no shadow on interactive form elements */
/* Focus ring (elevation via outline, not shadow) */
--focus-ring: 0.125rem solid rgb(255, 255, 255);
/* equivalent to: outline: var(--wct--focus-ring--width) var(--wct--focus-ring--style) var(--wct--focus-ring--color) */
--focus-ring-offset: 0.125rem;
/* Usage: ALL keyboard-focusable elements */
/* Z-index scale (inferred from page structure) */
--z-content: 0; /* default page content */
--z-badge: 1; /* top-10 numerals and tile overlays */
--z-dropdown: 10; /* language selector open state */
--z-nav: 100; /* sticky navigation bar */
--z-modal: 1000; /* dialogs and overlays */
--z-toast: 2000; /* notification toasts */
}
```
**Layering principles:**
- Netflix UI is primarily **flat** — depth is achieved through colour contrast (dark bg → darker surface), not drop shadows
- Shadows appear **only** on tile badges and overlaid labels
- **No box-shadow** on buttons, inputs, or accordion — these use background colour to signal state
- Focus rings use `outline` (not `box-shadow`) to ensure they are visible over any background
---
## 8. Motion
```css
:root {
/* Duration tokens */
--netflix-duration-fast: 0.2s; /* extracted: high confidence — button hover micro-interactions */
--netflix-duration-base: 0.25s; /* extracted: high confidence — standard UI transitions (buttons, accordion) */
--netflix-duration-slow: 0.4s; /* extracted: high confidence — larger layout transitions */
/* Easing tokens */
--netflix-ease-default: ease; /* extracted: high confidence — 78 elements */
--netflix-ease-in: cubic-bezier(0.4, 0, 0.68, 0.06);
/* Usage: element leaving screen, button default state transition */
/* Corresponds to: --wct--local-design--Button-Easing, --wct--local-design--Accordion-HeadlineEasing */
--netflix-ease-out: cubic-bezier(0.32, 0.94, 0.6, 1);
/* Usage: element entering screen, hover state transition (fast in, satisfying deceleration) */
/* Corresponds to: --wct--local-design--Button-EasingHovered, --wct--local-design--Accordion-HeadlineIconEasing */
/* Component-specific motion */
--wct--local-design--Button-Duration: 250ms;
--wct--local-design--Button-DurationPressed: 0; /* INSTANT on press — intentional */
--wct--local-design--Button-Easing: cubic-bezier(0.4, 0, 0.68, 0.06);
--wct--local-design--Button-EasingHovered: cubic-bezier(0.32, 0.94, 0.6, 1);
--wct--local-design--Button-EasingPressed: cubic-bezier(0.4, 0, 0.68, 0.06);
--wct--local-design--Accordion-HeadlineDuration: 250ms;
--wct--local-design--Accordion-HeadlineEasing: cubic-bezier(0.4, 0, 0.68, 0.06);
--wct--local-design--Accordion-HeadlineIconDuration: 250ms;
--wct--local-design--Accordion-HeadlineIconEasing: cubic-bezier(0.32, 0.94, 0.6, 1);
--wct--local-design--Accordion-HeadlineDurationHovered: var(--wct--local-design--Accordion-HeadlineDuration);
--wct--local-design--Accordion-HeadlineEasingHovered: cubic-bezier(0.32, 0.94, 0.6, 1);
--wct--local-design--Accordion-PanelDuration: 250ms;
--wct--local-design--Accordion-PanelEasing: cubic-bezier(0.32, 0.94, 0.6, 1);
/* Loading skeleton animation */
/* @keyframes loading: 0% rgb(35,35,35) → 70% rgb(65,65,65) → 90% rgb(35,35,35) */
/* Applied to: skeleton/placeholder content tiles while data loads */
}
```
**When to animate:**
- Button background on hover/focus: `0.25s` with `ease-out` (`cubic-bezier(0.32,0.94,0.6,1)`)
- Button background on press/active: **instant** (`0s` transition-duration) — feels physically snappy
- Accordion headline background: `250ms ease-in`
- Accordion icon rotation: `250ms ease-out`
- Accordion panel expand: `250ms ease-out`
- Loading skeleton shimmer: continuous loop — `0% → 70% → 90%` background colour pulse
**When NOT to animate:**
- Do NOT animate layout shifts or width/height changes unless panel expand/collapse
- Do NOT add entrance animations to static text content
- Do NOT animate colour changes on disabled states — `transition-duration` set to `var(--netflix-duration-base)` but visually irrelevant since no interaction occurs
---
## 9. Anti-Patterns & Constraints
1. **NEVER use a generic font stack without Netflix Sans first → Why it fails → What to do instead.**
AI agents default to `Inter`, `system-ui`, or `Arial` when no font is specified. Netflix's typographic identity depends entirely on the proprietary `Netflix Sans` variable font. Without it, headings lose weight range (100–900), and the distinctive kerning vanishes. **Do this instead:** Always declare `fontFamily: '"Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif'` — the full stack with proper fallbacks.
2. **NEVER hardcode red hex values as `#e50914` or `#E50914` directly in component styles → Why it fails → What to do instead.**
Hardcoded values break when Netflix A/B tests button colours or adjusts brand colour globally. Additionally, hardcoded hex bypasses the three-state red system (default/hover/pressed). An AI agent seeing "red button" will pick one hex and stop there, missing the `rgb(193,17,25)` hover and `rgb(153,22,29)` pressed states. **Do this instead:** Use `var(--wct--local-design--Button-Surface)` for default, `var(--wct--local-design--Button-SurfaceHovered)` for hover, `var(--wct--local-design--Button-SurfacePressed)` for active.
3. **NEVER use `border-radius` values larger than `8px` on primary buttons → Why it fails → What to do instead.**
AI agents trained on generic design systems often produce pill buttons (`border-radius: 50px` or `9999px`) because they're visually common. Netflix buttons are strictly `4px` radius (`--wct--local-design--Button-BorderRadius: 0.25rem`). Pill-shaped buttons break the geometric language and look alien on the Netflix homepage. **Do this instead:** Use `var(--wct--local-design--Button-BorderRadius)` for every button. Reserve `--netflix-radius-full: 50px` for the one specific input field that uses it.
4. **NEVER omit the active/pressed state with `transition-duration: 0` → Why it fails → What to do instead.**
AI agents model hover and focus states but routinely skip the "pressed" (`:active`) state. Netflix's design system explicitly sets `--wct--local-design--Button-DurationPressed: 0` — the background colour change to `rgb(153,22,29)` is instantaneous. Omitting this makes buttons feel sluggish and wrong. **Do this instead:** Apply `onMouseDown` handler that sets `backgroundColor` to `var(--wct--local-design--Button-SurfacePressed)` and `transitionDuration` to `0s`.
5. **NEVER use a light or white background for any content section → Why it fails → What to do instead.**
AI agents filling in "blank" sections default to white or off-white backgrounds. Netflix is a pure dark-mode product — `rgb(0,0,0)` page background, `rgba(22,22,22,0.7)` form surfaces, `rgb(45,45,45)` accordion surfaces. Any light surface would destroy the cinematic immersive experience. **Do this instead:** Default every new section to `background-color: rgb(0,0,0)` unless a specific token (`--netflix-bg-surface`, `--netflix-accordion-surface`) is more appropriate.
6. **NEVER use `rgb(229,9,20)` for decorative elements, text colour, or dividers → Why it fails → What to do instead.**
Red in the Netflix system is exclusively reserved for primary call-to-action button backgrounds. AI agents, seeing the dominant brand colour, will apply it to borders, link text, hover underlines, or section dividers. This dilutes the CTA signal — red means "click this" and nothing else. **Do this instead:** Use `rgb(255,255,255)` for text, `rgba(128,128,128,0.7)` for borders, and `rgb(45,45,45)` for surface dividers.
7. **NEVER use arbitrary spacing values or substitute a standard 8px grid → Why it fails → What to do instead.**
Netflix uses precise, non-8px-aligned spacing values: `0.375rem` (6px) for field gaps, `0.625rem` (10px) for horizontal field padding, `0.0625rem` (1px) for the accordion separator. An AI agent normalising these to the nearest 8px multiple (`8px`, `8px`, `0px`) destroys the tight micro-spacing that makes form components feel refined. **Do this instead:** Always reference the exact extracted token. Never round to a "cleaner" value.
8. **NEVER remove or simplify the focus ring → Why it fails → What to do instead.**
AI agents often drop focus styles when they "look bad" or clash with the dark design. Netflix's focus ring is `2px solid rgb(255,255,255)` with `2px offset` — white on black, maximum visibility. The system uses `:focus-visible` to suppress it for mouse users and show it for keyboard users via `var(--wct--focus-ring--override-on/off)`. Removing this violates WCAG 2.4.11 and breaks keyboard navigation. **Do this instead:** Use `outline: var(--wct--focus-ring--width) var(--wct--focus-ring--style) var(--wct--focus-ring--color); outline-offset: var(--wct--focus-ring--offset)` on all interactive elements.
9. **NEVER construct dynamic Tailwind class names with string interpolation → Why it fails → What to do instead.**
Patterns like `` `bg-[${color}]` `` or `` `text-${size}` `` cause Tailwind's JIT scanner to miss the class, resulting in unstyled elements in production. **Do this instead:** For dynamic values, use inline CSS custom property references (`style={{ backgroundColor: 'var(--netflix-accent)' }}`) or use complete, static class names that can be statically analysed.
10. **NEVER use `!important` to override Netflix's component token cascade → Why it fails → What to do instead.**
The `--wct--local-design--*` token system uses CSS custom property inheritance for component-level overrides. Adding `!important` breaks the cascade in ways that are difficult to debug and will cause previously functional states (disabled, hover) to stop updating. **Do this instead:** Override tokens at the appropriate scope — set `--wct--local-design--Button-Surface: your-value` on the parent container to scope changes correctly.
11. **NEVER use `position: absolute` to achieve column layouts or section stacking → Why it fails → What to do instead.**
AI agents sometimes use absolute positioning for complex multi-column layouts. Netflix's layout system uses `display: flex` with `flexDirection: row/column` and responsive `--wct--layout-container` tokens. Absolute positioning breaks the responsive reflow at the numerous breakpoints (98px through 2560px). **Do this instead:** Use `display: flex` or `display: grid` with gap values from the spacing scale, and respond to breakpoints via media queries.
---
## 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 (95) */
--wct--layout-container--width: inherit;
--wct--local-design--Select-Border: rgba(128, 128, 128, 0.7);
--wct--local-design--Select-BorderDisabled: rgba(128, 128, 128, 0.4);
--wct--local-design--Select-BorderError: rgb(235, 57, 66);
--wct--local-design--Select-BorderSuccess: rgb(43, 184, 113);
--wct--local-design--Select-BorderWarning: rgb(216, 157, 49);
--wct--local-design--Button-ForegroundPressed: rgba(255, 255, 255, 0.7);
--wct--focus-ring--color: rgb(255, 255, 255);
--wct--local-design--Button-ForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Select-Surface: rgba(22, 22, 22, 0.7);
--wct--local-design--Select-SurfaceDisabled: rgba(22, 22, 22, 0.02);
--wct--focus-ring--color-default: #a9a9a9;
--wct--local-design--Button-BorderDisabled: rgba(0, 0, 0, 0);
--wct--local-design--Button-Surface: rgb(229, 9, 20);
--wct--local-design--Button-SurfaceDisabled: rgba(229, 9, 20, 0.4);
--wct--local-design--Button-SurfaceHovered: rgb(193, 17, 25);
--wct--local-design--Button-SurfacePressed: rgb(153, 22, 29);
--wct--local-design--Input-SurfaceDisabled: rgba(22, 22, 22, 0.2);
--wct--local-design--Accordion-HeadlineSurface: rgb(45,45,45);
--wct--local-design--Accordion-HeadlineSurfaceHovered: rgb(65,65,65);
--brand-primary-cta: rgb(229, 9, 20); /* Primary CTA background, dominant on 3 buttons — e.g. "Get Started" /* mined from computed styles */ */
--netflix-accent: rgb(229, 9, 20);
--netflix-accent-warm: rgb(193, 17, 25);
--netflix-accent-pressed: rgb(153, 22, 29);
--netflix-accent-disabled: rgba(229, 9, 20, 0.4);
--netflix-bg-surface: rgba(22, 22, 22, 0.7);
--netflix-accordion-surface: rgb(45, 45, 45);
--netflix-accordion-surface-hover: rgb(65, 65, 65);
--netflix-text-white: rgb(255, 255, 255);
--netflix-text-muted: rgba(255, 255, 255, 0.7);
--netflix-text-disabled: rgba(255, 255, 255, 0.4);
--netflix-success: rgb(43, 184, 113);
--netflix-warning: rgb(216, 157, 49);
--netflix-error: rgb(235, 57, 66);
--netflix-border: rgba(128, 128, 128, 0.7);
--netflix-border-focus: rgb(255, 255, 255);
--color-red-500: rgb(229, 9, 20);
--color-red-600: rgb(193, 17, 25);
--color-red-700: rgb(153, 22, 29);
--color-dark-900: rgb(0, 0, 0);
--color-dark-800: rgb(22, 22, 22);
--color-dark-700: rgb(35, 35, 35);
--color-dark-600: rgb(45, 45, 45);
--color-dark-500: rgb(65, 65, 65);
--color-white-100: rgb(255, 255, 255);
--color-white-70: rgba(255, 255, 255, 0.7);
--color-white-40: rgba(255, 255, 255, 0.4);
--color-grey-50: rgba(128, 128, 128, 0.7);
--color-grey-30: rgba(128, 128, 128, 0.4);
--color-grey-focus: #a9a9a9;
--color-green-400: rgb(43, 184, 113);
--color-yellow-400: rgb(216, 157, 49);
--color-red-error: rgb(235, 57, 66);
--netflix-bg-app: rgb(0, 0, 0);
--netflix-bg-surface-disabled: rgba(22, 22, 22, 0.2);
--netflix-bg-skeleton-base: rgb(35, 35, 35);
--netflix-bg-skeleton-shimmer: rgb(65, 65, 65);
--netflix-text-pressed: rgba(255, 255, 255, 0.7);
--netflix-border-disabled: rgba(128, 128, 128, 0.4);
--netflix-border-transparent: rgba(0, 0, 0, 0);
--netflix-accordion-foreground: rgb(255, 255, 255);
--wct--local-design--Button-Foreground: rgb(255, 255, 255);
--wct--local-design--Button-Border: rgba(0, 0, 0, 0);
--wct--local-design--Button-BorderHovered: rgba(0, 0, 0, 0);
--wct--local-design--Button-BorderPressed: rgba(0, 0, 0, 0);
--wct--local-design--Button-BorderWidth: 0.0625rem;
--wct--local-design--Select-Foreground: rgb(255, 255, 255);
--wct--local-design--Select-ForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Select-LabelForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Select-LabelForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Select-DescriptionForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Select-BorderWidth: 0.0625rem;
--wct--local-design--Select-MessageForegroundError: rgb(235, 57, 66);
--wct--local-design--Select-MessageForegroundSuccess: rgb(43, 184, 113);
--wct--local-design--Select-MessageForegroundWarning: rgb(216, 157, 49);
--wct--local-design--Input-Surface: rgba(22, 22, 22, 0.7);
--wct--local-design--Input-Foreground: rgb(255, 255, 255);
--wct--local-design--Input-ForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Input-LabelForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Input-LabelForegroundDisabled: rgba(255, 255, 255, 0.4);
--wct--local-design--Input-DescriptionForeground: rgba(255, 255, 255, 0.7);
--wct--local-design--Input-Border: rgba(128, 128, 128, 0.7);
--wct--local-design--Input-BorderDisabled: rgba(128, 128, 128, 0.4);
--wct--local-design--Input-BorderError: rgb(235, 57, 66);
--wct--local-design--Input-BorderSuccess: rgb(43, 184, 113);
--wct--local-design--Input-BorderWarning: rgb(216, 157, 49);
--wct--local-design--Input-BorderWidth: 0.0625rem;
--wct--local-design--Input-MessageForegroundError: rgb(235, 57, 66);
--wct--local-design--Input-MessageForegroundSuccess: rgb(43, 184, 113);
--wct--local-design--Input-MessageForegroundWarning: rgb(216, 157, 49);
--brand-primary-cta: rgb(229, 9, 20);
--type-input-label-filled: {
font-family: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
--wct--local-design--Accordion-PanelSurface: rgb(45, 45, 45);
--wct--local-design--Accordion-HeadlineForeground: rgb(255, 255, 255);
--wct--local-design--Accordion-PanelForeground: rgb(255, 255, 255);
/* Typography (42) */
--wct--local-design--Button-TextFontFamily: unset;
--wct--local-design--Select-DescriptionFontSize: 0.8125rem;
--wct--local-design--Accordion-HeadlineTextFontWeight: 400;
--wct--local-design--Select-LabelTextFontSize: 0.75rem;
--wct--local-design--Button-TextFontSize: 0.875rem;
--wct--local-design--Input-TextFontSize: 1rem */
font-weight: 400;
--wct--local-design--Accordion-HeadlineTextFontSize: 1.5rem */
font-weight: 400;
--wct--local-design--Select-TextLineHeight: 1.25rem;
--wct--local-design--Button-TextFontWeight: 500;
--wct--local-design--Button-Easing: cubic-bezier(0.4,0,0.68,0.06);
--wct--local-design--Button-EasingHovered: cubic-bezier(0.32,0.94,0.6,1);
--wct--local-design--Input-LabelTextLineHeight: 1.5;
--wct--input--date-text: var(--wct--local-design--Input-Foreground);
--wct--input--date-calendar-icon: url("data:image/svg+xml; <0.4KB elided>");
--font-size-xs: 13px; /* 1 element — e.g. p "This page is protect" /* mined from computed styles */ */
--font-size-sm: 14px; /* 44 elements — e.g. p "Netflix Germany", a "Sign In", a "FAQ" /* mined from computed styles */ */
--font-size-md: 16px; /* 40 elements — e.g. h3 "Ready to watch? Ente", h3 "Ready to watch? Ente", p "Get our most afforda" /* mined from computed styles */ */
--font-size-lg: 20px; /* 2 elements — e.g. h3 "The Netflix you love", p "Starts at €4.99. Can" /* mined from computed styles */ */
--font-size-xl: 24px; /* 28 elements — e.g. h2 "Trending Now", h2 "More Reasons to Join", h2 "Frequently Asked Que" /* mined from computed styles */ */
--font-size-2xl: 56px; /* 1 element — e.g. h1 "Unlimited movies, TV" /* mined from computed styles */ */
--font-size-3xl: 100px; /* 20 elements — e.g. span "11", span "11", span "22" /* mined from computed styles */ */
--font-weight-semibold: 900; /* 1 element — e.g. h1 "Unlimited movies, TV" /* mined from computed styles */ */
--line-height-tight: 21px; /* 42 elements — e.g. a "FAQ", a "Cancel Membership", a "Help Center" /* mined from computed styles */ */
--line-height-loose: 70px; /* 1 element — e.g. h1 "Unlimited movies, TV" /* mined from computed styles */ */
--font-family-primary: "Netflix Sans", "Helvetica Neue", "Segoe UI", Roboto, Ubuntu, sans-serif;
--font-family-arabic: "NKufi", "Netflix Sans", sans-serif;
--font-family-thai: "GraphikTH", "Netflix Sans", sans-serif;
--font-family-ja: "Netflix Sans JA", "Netflix Sans", sans-serif;
--wct--local-design--Accordion-PanelTextFontSize: 1.5rem */
font-weight: 400;
--wct--local-design--Input-LabelTextFontSize: 0.75rem */
font-weight: 400;
--wct--local-design--Input-LabelTextEmptyFontSize: 1rem */
font-weight: 400;
--wct--local-design--Input-DescriptionFontSize: 0.8125rem */
font-weight: 400;
--netflix-font-size-xs: 13px;
--netflix-font-size-sm: 14px;
--netflix-font-size-md: 16px;
--netflix-font-size-lg: 20px;
--netflix-font-size-xl: 24px;
--netflix-font-size-2xl: 56px;
--netflix-font-size-3xl: 100px;
--netflix-font-weight-semibold: 900;
--netflix-line-height-tight: 21px;
--netflix-line-height-loose: 70px;
/* Spacing (51) */
--wct--layout-item--padding: initial;
--wct--local-design--Button-BorderWidth: 0.0625rem;
--wct--local-design--Button-SpaceVertical: 0.25rem;
--wct--local-design--Button-SpaceBetweenIconText: 0.5rem;
--wct--local-design--Select-SpaceVerticalEmpty: 0.375rem;
--wct--local-design--Select-SpaceHorizontal: 0.625rem;
--wct--local-design--Select-SpaceVertical: 0rem;
--wct--focus-ring--width: 0.125rem;
--wct--local-design--Button-Height: 2rem;
--wct--local-design--Button-IconHeight: 1rem;
--wct--local-design--Accordion-HeadlineSpaceBetweenIconText: 0.75rem;
--wct--local-design--Accordion-HeadlineSpace: 1.5rem;
--wct--local-design--Accordion-HeadlineSpaceExpanded: var(--wct--local-design--Accordion-HeadlineSpace);
--wct--local-design--Accordion-PanelSpace: 0rem var(--wct--local-design--Accordion-PanelSpaceExpanded);
--ot-footer-space: 160px;
--wct--focus-ring--offset: 0.125rem;
--wct--local-design--Select-SpaceBetweenFieldDescription: 0.375rem;
--wct--local-design--Select-SpaceBetweenFieldMessage: 0.375rem;
--wct--local-design--Select-MessageSpaceBetweenIconContent: 0.25rem;
--wct--local-design--Select-SpaceBetweenIconContent: 0.5rem;
--wct--local-design--Button-SpaceHorizontal: 1rem;
--wct--local-design--Button-IconWidth: 1rem;
--wct--local-design--Input-SpaceHorizontal: 1rem;
--wct--local-design--Input-SpaceVertical: 0.25rem;
--wct--local-design--Input-SpaceVerticalEmpty: 0.75rem;
--wct--local-design--Input-SpaceBetweenIconContent: 0.5rem;
--wct--local-design--Input-SpaceBetweenFieldDescription: 0.375rem;
--wct--local-design--Input-SpaceBetweenFieldMessage: 0.375rem;
--wct--local-design--Accordion-PanelSpaceExpanded: 1.5rem;
--wct--local-design--Accordion-SpaceBetween: 0.5rem;
--wct--local-design--Accordion-SpaceBetweenHeadlinePanel: 0.0625rem;
--space-hero-heading-bottom: 16px;
--space-body-bottom: 32px;
--netflix-space-xs: 0.0625rem;
--netflix-space-sm: 0.125rem;
--netflix-space-md: 0.25rem;
--netflix-space-lg: 0.375rem;
--netflix-space-xl: 0.5rem;
--netflix-space-2xl: 0.625rem;
--netflix-space-3xl: 0.75rem;
--bp-mobile-sm: 400px;
--bp-mobile: 530px;
--bp-tablet-sm: 640px;
--bp-tablet: 768px;
--bp-tablet-lg: 960px;
--bp-desktop: 1024px;
--bp-desktop-lg: 1280px;
--bp-desktop-xl: 1600px;
--bp-hd: 1920px;
--bp-4k: 2560px;
--focus-ring-offset: 0.125rem;
/* Radius (15) */
--wct--local-design--Button-BorderRadius: 0.25rem;
--wct--local-design--Accordion-HeadlineBorderRadius: 0rem;
--wct--local-design--Accordion-HeadlineBorderRadiusExpanded: var(--wct--local-design--Accordion-HeadlineBorderRadius) var(--wct--local-design--Accordion-HeadlineBorderRadius) 0rem 0rem;
--wct--local-design--Accordion-PanelBorderRadiusExpanded: 0rem 0rem var(--wct--local-design--Accordion-PanelBorderRadius) var(--wct--local-design--Accordion-PanelBorderRadius);
--radius-sm: 2px; /* 28 elements — e.g. a "Check out some of ou", a "Questions? Contact u", a .default-ltr-iqcdef-cache-348dfw "FAQ" /* mined from computed styles */ */
--radius-md: 4px; /* 4 elements — e.g. button .e136yimv2 "Get Started", button .e136yimv2 "Learn More", button .e136yimv2 "Get Started" /* mined from computed styles */ */
--radius-lg: 8px; /* 11 elements — e.g. button .default-ltr-iqcdef-cache-1it3med "Berlin and the Lady ", button .default-ltr-iqcdef-cache-1it3med "Apex22", button .default-ltr-iqcdef-cache-1it3med "ONE PIECE33" /* mined from computed styles */ */
--radius-full: 50px; /* 1 element — e.g. input /* mined from computed styles */ */
--netflix-radius-sm: 2px;
--netflix-radius-md: 4px;
--netflix-radius-lg: 8px;
--wct--local-design--Select-BorderRadius: 0.25rem;
--wct--local-design--Input-BorderRadius: 0.25rem;
--netflix-radius-full: 50px;
--wct--local-design--Accordion-PanelBorderRadius: 0rem;
/* Effects (12) */
--wct--layout-container--flexDirection-xs: initial;
--wct--local-design--Button-Width: auto;
--wct--focus-ring--style: solid;
--wct--local-design--Button-ForegroundHovered: var(--wct--local-design--Button-Foreground);
--wct--local-design--Button-Duration: 250ms;
--wct--local-design--Button-DurationDisabled: var(--wct--local-design--Button-Duration);
--wct--local-design--Button-DurationPressed: 0;
--wct--local-design--Button-EasingDisabled: var(--wct--local-design--Button-Easing);
--wct--local-design--Accordion-HeadlineDurationHovered: var(--wct--local-design--Accordion-HeadlineDuration);
--wct--accordion--icon-rotation: -45deg;
--shadow-badge: rgb(128, 128, 128) 0px 0px 5px 0px;
--shadow-none: none;
/* Motion (7) */
----motion-animation-1o3pzgb-autofillStart: @keyframes animation-1o3pzgb-autofillStart {
}; /* @keyframes animation-1o3pzgb-autofillStart */
----motion-animation-und0r9-autofillEnd: @keyframes animation-und0r9-autofillEnd {
}; /* @keyframes animation-und0r9-autofillEnd */
----motion-loading: @keyframes loading {
0% { background-color: rgb(35, 35, 35); }
40% { backgr… <0.2KB elided>; /* @keyframes loading */
--duration-fast: 0.2s; /* 10 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-base: 0.25s; /* 4 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-slow: 0.4s; /* 2 elements — e.g. button, div /* mined from computed styles */ */
--ease-default: ease; /* 78 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```
tokenSource: extracted-css-vars
site: netflix.com
extractionDate: [see extraction run metadata]
confidence: high
totalCSSCustomProperties: 262
curatedTokensMapped: 38
fontSource: extracted-font-declarations
- Netflix Sans Variable (woff2, 100–900 variable axis) — PRIMARY
- Netflix Sans (woff2/woff, 6 weights: 100/300/400/500/700/900) — fallback static
- Netflix Sans JA (Japanese ellipsis override)
- NKufi (Arabic, weights 400/500)
- GraphikTH (Thai, weights 400/500)
- Netflix Sans Debug (development only)
originalVariableConvention: --wct--local-design--{Component}-{Property}
Prefix: wct (Web Component Toolkit — Netflix's internal design system)
Components documented: Button, Input, Select, Accordion, Text
Additional: --wct--focus-ring--*, --wct--layout-container--*, --wct--layout-item--*
syntheticTokensCreated:
- --netflix-accent, --netflix-accent-warm, --netflix-accent-pressed (clustered from 3 red values)
- --netflix-bg-app (inferred from page dark background, not directly extracted)
- --netflix-bg-skeleton-base / shimmer (from @keyframes loading animation)
- --space-hero-heading-bottom / --space-body-bottom (from h1/body computed margin)
- --font-family-primary (from computed fontFamily on h1/h2/button)
All synthetic tokens annotated with confidence level inline.
nearDuplicateWarning:
11 pairs of near-identical colours detected.
Resolution: canonical value selected per role, duplicates merged.
Example: --wct--local-design--Select-Border and --wct--local-design--Input-Border
both equal rgba(128,128,128,0.7) → merged to --netflix-border
layoutContainerTokens:
--wct--layout-container--{columnSpacing|rowSpacing|maxWidth|padding|width}-{breakpoint}: initial
These are intentionally `initial` at the :root level — the component system
populates them per-breakpoint. Do not override these with fixed values.
breakpointCount: 23 distinct media query values detected (98px–2560px)
Key layout breakpoints: 768px (tablet), 1024px (desktop), 1280px (large desktop)
libraryDetected: Bootstrap (utility layer only — Netflix's primary styling is bespoke CSS-in-JS via Emotion)
tokenAuthority: reverse-engineered from live production site CSS
These are NOT Figma-authoritative tokens. They represent the production implementation.
Treat as high-fidelity but not design-source-of-truth.
```More from the gallery
Browse all kits →You may also like

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

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

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