---
version: alpha
name: Lululemon
website: "https://shop.lululemon.com"
description: >-
  A near-monochrome athletic-apparel storefront anchored on pure white canvas (#ffffff) and warm off-black ink (#140f0f, text count 131, border count 191) — with the signature Lululemon red (#c8102e) demoted to a scoped accent token (`--lll-color-border-accent`, total page count 2) that appears almost nowhere in chrome and lives mainly as a semantic error voltage. Type runs Saans across every tier on a variable axis at weights 380 (book) and 570 (medium), with the hero h2 reaching 100px at letter-spacing `-4px` and the primary CTA holding a 48px-radius pill at height 54px with weight 570. Two color systems coexist: the structural greyscale chrome (black, off-black, bone `#efeeec`, white) and a secondary editorial palette (sequoia `#73273d`, wilderness `#142a0e`, espresso `#2b1f1e`, daydream `#c0ddff`, mossy `#524a43`, rosewood `#dc6d85`) reserved for campaign tiles.

seo:
  title: "Lululemon Design System for React — Saans variable, ink #140f0f, 24 components"
  metaDescription: "Lululemon's design system as a DESIGN.md file. Saans variable, ink #140f0f, brand red #c8102e, 21 colors, 24 components. For React, Next.js, and AI tools."
  highlights:
    - "Variable-axis Saans at weights 380 and 570 — the brand never reaches weight 600+; confidence by typographic moderation"
    - "Brand red as scoped voltage — `#c8102e` (`--lll-color-border-accent`) carries only 2 occurrences across the chrome, reserved for error states and accent borders"
    - "Off-black ink, never pure — `#140f0f` runs as text and borders 322 times while `#000000` lives mainly in default button fills (text 545, border 544)"
    - "Pill CTA at 48px radius — primary button measures 54px tall with 24px horizontal padding and weight 570 caps; the only other radius is 50% for icon swatches and circular avatars"
    - "Two coexisting palettes — a load-bearing greyscale chrome plus a six-token secondary editorial palette (`sequoia`, `wilderness`, `espresso`, `daydream`, `mossy`, `rosewood`) reserved for campaign tiles, never for buttons"
  tags:
    - "E-commerce & Retail"
  lastUpdated: "2026-05-13"
  author:
    name: "Dov Azencot"
    url: "https://x.com/dovazencot"
  opening: |
    Lululemon's storefront reads like a printed yoga catalog rendered for the browser, with the chrome holding back while the photography carries every chromatic moment. The canvas is pure `#ffffff`, and the workhorse text colour is a warm off-black `#140f0f` rather than the pharmaceutical pure black you'd expect from an athletic brand — the warmer ink holds against skin tones in product imagery without going clinical. Where Nike screams in 96px Futura uppercase and Everlane whispers in 12px Maison Neue caps, Lululemon settles between them at 100px Saans on a single variable-weight axis (380 and 570), confident enough to skip bold weights entirely. The signature Lululemon red (`#c8102e`) is mapped in CSS variables under `--lll-color-border-accent` and `--lll-color-text-error`, but the extracted page renders it only twice — the brand uses it as a semantic accent voltage, not a chrome colour.

    This page packages the storefront into a DESIGN.md file written to the Google Labs open specification. Inside: 21 colour tokens grouped into ink, surface, hairline, semantic, and a six-entry secondary palette (sequoia, wilderness, espresso, daydream, mossy, rosewood) reserved for editorial tiles; 11 Saans typography roles ranging from a 100px hero through a 12px utility caption; a 5-step radius vocabulary anchored on 48px pills and 50% circles with a 6px input outlier; an 8-step spacing scale extracted from the `--zest-spacing-*` CSS variable cascade running 2px through 96px; and 24 component entries covering the announcement bar, the primary nav, the welcome modal, the hero overlay, the editorial 2-up, the colour swatch strip, the newsletter capture, the product tile, and the campaign tile. The site exposes 351 `:root` custom properties under twin `--lll-*` and `--zest-*` token cascades, which is how the chrome stays mechanical while the editorial palette stays expressive.

    Feed the file to Claude, Cursor, or GitHub Copilot and the agent reproduces Lululemon's specific restraint — the 48px-radius pill CTA at 54px height with weight 570, the warm `#140f0f` ink, the bone-toned `#efeeec` disabled-surface, the Saans-only typographic ladder — rather than a generic activewear template with heavy 700+ display weights and saturated brand fills. Reference tokens directly when you want one specific value: `{colors.ink}` resolves to `#140f0f`, `{rounded.pill}` to 48px, `{typography.display-xl}` to Saans 100px at weight 380, and `{colors.accent-red}` to `#c8102e`. The reason this system rewards study is that most athletic-apparel sites equate brand voltage with chromatic loudness — Lululemon proves the opposite, holding its signature red almost entirely off the chrome and letting weight 380 Saans carry the brand's whole personality.
  related:
    - href: "/design"
      title: "Browse all design systems"
      description: "The full directory of DESIGN.md files on shadcn.io, with live mockups for each."
    - href: "https://shop.lululemon.com"
      title: "Lululemon — official site"
      description: "The Lululemon storefront this DESIGN.md was extracted from on 2026-05-13."
    - href: "https://github.com/google-labs-code/design.md"
      title: "The DESIGN.md specification"
      description: "Google Labs' open spec for machine-readable design system files — the format this page is built on."
  questions:
    - id: "primary-color"
      title: "What is Lululemon's primary brand color?"
      answer: "Lululemon's chrome runs on warm off-black `#140f0f` and pure white `#ffffff`, with `#000000` carrying default interactive fills (text 545, border 544) and bone `#efeeec` carrying disabled and subdued surfaces. The signature Lululemon red (`#c8102e`) is declared across 13 CSS variables including `--lll-color-border-accent`, `--lll-color-text-error`, and `--lll-color-icon-accent`, but the extracted homepage renders it only twice — the brand treats red as a scoped semantic voltage for error and accent states, not as a primary chrome colour. The secondary editorial palette (sequoia `#73273d`, wilderness `#142a0e`, espresso `#2b1f1e`, daydream `#c0ddff`, mossy `#524a43`, rosewood `#dc6d85`) exists only as campaign-tile background swatches."
    - id: "typography"
      title: "What typography does Lululemon use, and what should I substitute?"
      answer: "Lululemon runs a single variable typeface — Saans by Displaay Type Foundry — across every tier, with weights restricted to 380 (book) for displays and body and 570 (medium) for buttons and capitalized links. The hero h2 sits at 100px with letter-spacing `-4px` and line-height 110px, the secondary display reaches 64px at `-2.56px` tracking, and body runs 14–18px at weight 380. The brand never reaches weight 600+, which is unusual for an athletic category. If Saans is unavailable, Inter Variable or Söhne at weights 400 and 500 are the closest substitutes — preserve the negative letter-spacing exactly (`-4px` at 100px, `-2.56px` at 64px, `-0.56px` at 28px), because the optical tightness is how the system reads as confident rather than corporate."
    - id: "pill-geometry"
      title: "Why is the primary CTA a 48px-radius pill at 54px tall?"
      answer: "The radius vocabulary is split across three thresholds: 50% for icon swatches and circular colour dots (172 occurrences), 100px and 48px for pill CTAs and stadium-shaped buttons (17 + 2 occurrences), and 4–6px for text inputs and form fields. The primary CTA is extracted at `borderRadius: 48px`, `height: 54px`, `padding: 0px 24px`, with Saans weight 570 at 16px and letter-spacing 0 — a deep pill rather than a full stadium because the inner padding is generous enough that 999px and 48px collapse to the same visual shape at this size. The 50% circles handle every category swatch, every colour-picker dot in the Shop By Colour strip, and every avatar — circles for selection, pills for action."
    - id: "secondary-palette"
      title: "When should I use the secondary editorial palette (sequoia, wilderness, espresso, daydream, mossy, rosewood)?"
      answer: "The six secondary palette tokens (`#73273d`, `#142a0e`, `#2b1f1e`, `#c0ddff`, `#524a43`, `#dc6d85`) are declared under `--zest-color-secondary-palette-*` and `--lll-color-background-*` and exist exclusively as campaign-tile background swatches behind editorial copy and product photography — never as button fills, never as text colours, never as borders. The chrome itself stays on `#140f0f` ink and `#ffffff` canvas. Use these tokens the way Lululemon does: as full-bleed atmosphere behind a single editorial sentence (`Match light with airy`) plus a pair of pill CTAs in inverse white. Do not promote any of them to a primary brand colour; doing so collapses the system's two-palette discipline."
    - id: "use-in-project"
      title: "Can I use this DESIGN.md to build my own React activewear storefront?"
      answer: "Yes — drop the file into Claude, Cursor, or any AI tool that reads structured design tokens and the agent reproduces Lululemon's specific restraint (48px-radius pill CTAs at 54px height, warm `#140f0f` ink instead of pure black, weight-380 Saans displays at 100px with `-4px` tracking, bone `#efeeec` disabled surfaces, scoped red voltage at `#c8102e`) rather than a generic activewear theme with heavy weights and saturated fills. Reference tokens directly when you want one specific value: `{colors.ink}` resolves to `#140f0f`, `{rounded.pill}` to 48px, `{typography.display-xl}` to Saans 100px at weight 380, `{colors.accent-red}` to `#c8102e`, and `{components.button-primary}` inherits the full pill geometry. Every hex, font, radius, and spacing entry is a quoted literal you can paste into Tailwind config or a CSS-variable manifest."
    - id: "known-gaps"
      title: "What's missing from this DESIGN.md spec?"
      answer: "Several surfaces aren't captured: the PDP (product detail page) typography hierarchy beyond the homepage tile, the size-and-fit selector on individual items, the slide-in bag drawer and the full checkout flow, the member area and the Lululemon Studio (mirror) subsystem, hover-state colours per Lululemon's no-hover documentation convention, the full Saans weight ramp (the homepage uses only 380 and 570 — additional axis stops exist in the variable file but aren't deployed), the mobile breakpoints (the spec is built from a 1440-pixel desktop capture), and the international currency picker. The extracted palette runs at 12 raw hexes clustered into 21 tokens — the chrome is genuinely near-monochrome, not under-extracted."

colors:
  ink: "#140f0f"
  ink-pure: "#000000"
  ink-subdued: "#53565a"
  ink-muted: "#757575"
  ink-disabled: "#8d9196"
  canvas: "#ffffff"
  surface-bone: "#efeeec"
  hairline: "#d6d6d6"
  hairline-soft: "#c8c8c8"
  link-default: "#0000ee"
  focus: "#005fcc"
  accent-red: "#c8102e"
  accent-red-deep: "#a00d25"
  status-info: "#2966b0"
  status-success: "#0f752f"
  status-success-surface: "#ddfbe7"
  status-warning: "#8a6c00"
  status-warning-surface: "#fff7da"
  status-error-surface: "#ffe1e4"
  hot-heat: "#de212f"
  palette-sequoia: "#73273d"
  palette-wilderness: "#142a0e"
  palette-espresso: "#2b1f1e"
  palette-daydream: "#c0ddff"
  palette-mossy: "#524a43"
  palette-rosewood: "#dc6d85"
  palette-lemonade: "#f4ff8e"

typography:
  display-xl:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 100px
    fontWeight: 380
    lineHeight: 1.1
    letterSpacing: "-4px"
  display-lg:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 64px
    fontWeight: 380
    lineHeight: 1.1
    letterSpacing: "-2.56px"
  display-md:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 40px
    fontWeight: 380
    lineHeight: 1.2
    letterSpacing: "-0.8px"
  heading-lg:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 28px
    fontWeight: 380
    lineHeight: 1.3
    letterSpacing: "-0.56px"
  heading-md:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 20px
    fontWeight: 380
    lineHeight: 1.4
    letterSpacing: "0.2px"
  body-lg:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 18px
    fontWeight: 380
    lineHeight: 1.4
    letterSpacing: "0.18px"
  body-md:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 14px
    fontWeight: 380
    lineHeight: 1.4
    letterSpacing: 0
  body-sm:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 12px
    fontWeight: 380
    lineHeight: 1.4
    letterSpacing: 0
  button-md:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 16px
    fontWeight: 570
    lineHeight: 1.4
    letterSpacing: 0
  link-capitalized:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 18px
    fontWeight: 570
    lineHeight: 1.4
    letterSpacing: "0.18px"
    textTransform: capitalize
  caption-utility:
    fontFamily: "Saans, Helvetica, Helvetica Neue, Roboto, sans-serif"
    fontSize: 14px
    fontWeight: 570
    lineHeight: 1.15
    letterSpacing: "1.2px"

rounded:
  none: "0px"
  input: "6px"
  card: "32px"
  pill: "48px"
  stadium: "100px"
  full: "9999px"
  circle: "50%"

spacing:
  xxs: "2px"
  xs: "8px"
  sm: "10px"
  md: "16px"
  base: "24px"
  lg: "40px"
  xl: "48px"
  xxl: "96px"

components:
  announcement-bar:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink-pure}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
    padding: "0px 32px"
    height: "17px"
  top-nav:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body-lg}"
    rounded: "{rounded.none}"
    padding: "8px 16px"
    height: "56px"
  nav-link:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body-lg}"
    rounded: "{rounded.none}"
    padding: "8px 16px"
  button-primary:
    backgroundColor: "{colors.ink-pure}"
    textColor: "{colors.canvas}"
    borderColor: "{colors.ink-pure}"
    typography: "{typography.button-md}"
    rounded: "{rounded.pill}"
    padding: "0px 24px"
    height: "54px"
  button-primary-hover:
    backgroundColor: "{colors.ink-subdued}"
    textColor: "{colors.canvas}"
    borderColor: "{colors.ink-subdued}"
  button-primary-disabled:
    backgroundColor: "{colors.ink-disabled}"
    textColor: "{colors.canvas}"
    borderColor: "{colors.ink-disabled}"
  button-secondary:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    borderColor: "{colors.ink}"
    typography: "{typography.button-md}"
    rounded: "{rounded.pill}"
    padding: "0px 24px"
    height: "54px"
  button-tertiary:
    backgroundColor: "{colors.surface-bone}"
    textColor: "{colors.ink}"
    borderColor: "{colors.ink}"
    typography: "{typography.button-md}"
    rounded: "{rounded.pill}"
    padding: "0px 24px"
    height: "54px"
  button-on-image:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.button-md}"
    rounded: "{rounded.pill}"
    padding: "0px 24px"
    height: "48px"
  text-input:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink-pure}"
    borderColor: "{colors.ink}"
    typography: "{typography.button-md}"
    rounded: "{rounded.input}"
    padding: "12px 50px 12px 16px"
    height: "40px"
  text-input-focus:
    backgroundColor: "{colors.canvas}"
    borderColor: "{colors.focus}"
    rounded: "{rounded.input}"
  welcome-modal:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.display-lg}"
    rounded: "{rounded.none}"
    padding: "40px"
  hero-overlay:
    backgroundColor: "{colors.palette-wilderness}"
    textColor: "{colors.canvas}"
    typography: "{typography.display-xl}"
    rounded: "{rounded.none}"
    padding: "96px 40px 48px"
  editorial-tile:
    backgroundColor: "{colors.palette-sequoia}"
    textColor: "{colors.canvas}"
    typography: "{typography.display-md}"
    rounded: "{rounded.none}"
    padding: "96px 40px 48px"
  product-card:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body-lg}"
    rounded: "{rounded.none}"
    padding: "0px"
  product-card-image:
    backgroundColor: "{colors.surface-bone}"
    rounded: "{rounded.none}"
  color-swatch:
    backgroundColor: "{colors.surface-bone}"
    borderColor: "{colors.ink}"
    rounded: "{rounded.circle}"
    height: "40px"
  color-swatch-label:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
    padding: "8px 0px 0px"
  category-tile:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.heading-md}"
    rounded: "{rounded.none}"
    padding: "20px 12px 0px"
  newsletter-capture:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body-md}"
    rounded: "{rounded.none}"
    padding: "24px 40px 12px"
  link-utility:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.link-default}"
    typography: "{typography.body-md}"
    rounded: "{rounded.none}"
    padding: "0"
  badge-accent:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.accent-red}"
    borderColor: "{colors.accent-red}"
    typography: "{typography.caption-utility}"
    rounded: "{rounded.pill}"
    padding: "2px 10px"
  status-error-row:
    backgroundColor: "{colors.status-error-surface}"
    textColor: "{colors.accent-red}"
    borderColor: "{colors.accent-red}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.input}"
    padding: "12px 16px"
  campaign-tile-inverse:
    backgroundColor: "{colors.ink}"
    textColor: "{colors.canvas}"
    typography: "{typography.display-md}"
    rounded: "{rounded.none}"
    padding: "96px 40px 48px"
  footer:
    backgroundColor: "{colors.canvas}"
    textColor: "{colors.ink}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.none}"
    padding: "48px 24px"
---

## Overview

Lululemon's storefront is built on a contradiction the brand never resolves out loud: it is an athletic-apparel chrome that withholds nearly every saturated colour, and the signature red `#c8102e` that the brand is known for in retail signage appears on the homepage only twice. **Demoted red**: where most activewear systems treat their brand voltage as the primary CTA fill, Lululemon files its red under `--lll-color-border-accent` and `--lll-color-text-error`, then uses it almost exclusively for semantic error states. The chrome itself runs on warm off-black ink (`#140f0f`, text 131 and border 191), pure black for default interactive fills (`#000000`, text 545 and border 544), pure white canvas (`#ffffff`), and bone (`#efeeec`) for disabled and subdued surfaces. The signature is in the *absence* of brand colour, not its presence.

The typography reinforces the same restraint. Where most athletic and fitness brands lean on weight 700+ display lockups to project intensity, Lululemon holds every tier of Saans on two variable-axis stops only — 380 (book) for displays and body, 570 (medium) for buttons and capitalized links. The hero h2 reaches 100px with letter-spacing `-4px` at weight 380; the secondary display sits at 64px with `-2.56px` tracking, also at 380. **Weight 380 as confidence signal**: Lululemon trusts the negative tracking and the size to do the work that bold weights do in louder systems. The result is a page that reads as quiet and self-assured rather than punchy.

Two palettes coexist deliberately. The structural chrome stays inside its greyscale envelope; the editorial layer carries a six-token secondary palette — sequoia `#73273d`, wilderness `#142a0e`, espresso `#2b1f1e`, daydream `#c0ddff`, mossy `#524a43`, rosewood `#dc6d85` — reserved for full-bleed campaign tiles behind a single editorial sentence and a pair of inverse-white pill CTAs. **Two-palette discipline**: chrome does not borrow from editorial, editorial does not infiltrate chrome. Across the homepage hero, the welcome modal, the editorial 2-up, the Shop By Colour strip, the four-up category grid, and the campaign tile, the same chrome appears in identical proportions — only the photography and the campaign palette swap.

## Colors

The palette below comes directly from the extraction's clustered top-30 list, with frequency counts and usage breakdowns drawn from the raw JSON.

- **Off-black ink (`#140f0f`)** — frequency 347. Used as text (131), border (191), background (13), gradient (12). The workhorse ink, mapped to `--lll-color-text-off-black` and twelve related opacity tokens. Warmer than `#000000`, holds against skin-tone product photography without going pharmaceutical.
- **Pure black (`#000000`)** — frequency 1093. Used as text (545), border (544), background (3), shadow (1). The default interactive fill — primary CTA backgrounds, strong borders, surface-inverse. Mapped to `--lll-color-interactive-filled-default` and `--lll-color-border-strong`.
- **Pure white (`#ffffff`)** — frequency 546. Used as text (262), border (259), background (25). The canvas, the inverse text token, the outlined-default button fill. Clustered with two warmer near-whites as alternative surface tokens.
- **Bone surface (`#efeeec`)** — frequency 25. Used as background (25). The disabled and subdued surface — `--zest-color-interactive-primary-disabled`, `--lll-color-background-gray-bone`, `--lll-color-surface-subdued`. Sits one degree warmer than white to signal cotton over screen.
- **Brand red (`#c8102e`)** — frequency 2. Used as text (1), border (1). The signature Lululemon voltage, mapped across 13 CSS variables including `--zest-color-border-accent`, `--lll-color-text-error`, and `--lll-color-icon-accent`. Reserved for error states and accent borders — almost entirely absent from chrome.
- **Brand red deep (`#a00d25`)** — frequency 0 on-page; declared in `--lll-color-interactive-priority-hover` for the priority-CTA hover state.
- **Hot-heat secondary (`#de212f`)** — frequency 12. Used as gradient (12). A warm orange-red mapped to `--lll-color-background-hot-heat-secondary` for heat-tech gradient overlays.
- **Subdued ink (`#53565a`)** — frequency 12. Used as text (6), border (6). The hover-state ink for filled buttons and the border for messages.
- **Disabled ink (`#8d9196`)** — frequency 8. Used as text (4), border (4). The disabled state for interactive-filled and outlined buttons.
- **Default link blue (`#0000ee`)** — frequency 646. Used as text (351), border (295). The unstyled-anchor browser-default that surfaces on a footer-class link cluster; not part of the chrome ladder but extracted in volume.
- **Focus blue (`#005fcc`)** — frequency 0 on-page; declared in `--lll-color-border-focus` for input focus rings.
- **Sequoia (`#73273d`)** — secondary palette, `--zest-color-secondary-palette-sequoia`. Editorial-tile background.
- **Wilderness (`#142a0e`)** — secondary palette, `--zest-color-secondary-palette-wilderness`. Deep forest editorial-tile background.
- **Espresso (`#2b1f1e`)** — secondary palette, `--zest-color-secondary-palette-espresso`. Warm dark-brown editorial-tile background.
- **Daydream (`#c0ddff`)** — secondary palette, `--zest-color-secondary-palette-daydream`. Pale-blue editorial-tile background.
- **Mossy (`#524a43`)** — secondary palette, `--zest-color-secondary-palette-mossy`. Warm-grey editorial-tile background.
- **Rosewood (`#dc6d85`)** — secondary palette, `--zest-color-secondary-palette-rosewood`. Soft-pink editorial-tile background.
- **Lemonade (`#f4ff8e`)** — secondary palette, `--zest-color-secondary-palette-lemonade`. Yellow-green editorial swipe background.

## Typography

The system runs Saans by Displaay Type Foundry across every tier on a single variable axis. Two stops are deployed on the homepage: weight 380 (book) for displays and body, weight 570 (medium) for buttons and capitalized links. The hero h2 reaches 100px at letter-spacing `-4px` with line-height 1.1, the secondary display sits at 64px with `-2.56px` tracking, and the 40px display holds `-0.8px`. Where most athletic brands command attention with weight 700+ display lockups, Lululemon never crosses weight 570 — confidence by typographic moderation rather than typographic muscle. Body copy runs Saans 14–18px at weight 380 with letter-spacing near zero, and button labels carry weight 570 at 16px with line-height 22.4px. The single non-Saans cameo is the nav link, which extracts as Calibre 16px weight 400 on the legacy `lululemon athletica` corporate anchor — kept here as a documented exception rather than promoted to a token.

## Layout

The page locks to a 24–40px outer padding with section blocks at 96px top / 48px bottom (`96px 40px 48px` repeats as the most common multi-value padding). Cards stack on an 8px / 16px / 24px / 48px rhythm extracted from `--zest-spacing-*` (the 2/8/12/16/20/24/40/48/96 ladder). Hero blocks span full-bleed at 1440px; editorial 2-up panels split 50/50 with 12px gutter; the Shop By Colour strip and the What's New 4-up both use 12px horizontal gutter between cards. The grid is generous but never sparse — Lululemon trusts photography to fill the frame, so the chrome holds at 24px outer padding rather than pushing to 48 or 64.

## Elevation & Depth

Lululemon has effectively zero shadow vocabulary in chrome. The extracted JSON shows one `shadow: 1` count across the entire colour ladder (on `#000000`). Depth comes from three devices instead: the bone-toned surface (`#efeeec`) sitting one degree below white for disabled and subdued zones, full-bleed campaign tiles in the secondary editorial palette stacking against the white chrome to create vertical depth, and 1px hairlines (`#d6d6d6` / `#c8c8c8`) separating sections. The welcome modal is the one place a `box-shadow` is implied (via overlay tokens like `--zest-color-surface-overlay-50`), but no decorative drop-shadow surface is documented anywhere in the homepage chrome.

## Shapes

Three radius thresholds carry the entire shape vocabulary. **Pill geometry**: `48px` on every primary CTA, `100px` on stadium-shaped utility buttons, `999px` on chip-shaped accent badges — these three values collapse visually to the same shape at typical button heights but are declared separately in the source. **Circle geometry**: `50%` (172 occurrences — the most-used radius on the page) carries every colour-swatch dot in Shop By Colour, every category avatar, every icon-button hit target. **Right-angle geometry**: `0px` on every card, every tile, every product image, every hero overlay. The only outliers are the 6px text-input radius and a single 32px card on the welcome-modal frame.

## Components

Every component below references the tokens declared above — chrome inherits from the greyscale palette, editorial tiles pull from the secondary palette, the welcome modal sits on canvas with 64px display type.

- **announcement-bar** — top-of-page utility row at body-sm on `{colors.canvas}` with `{colors.ink-pure}` text, 32px left padding, `0px` radius.
- **top-nav** — primary navigation row at 56px height, body-lg type, `{colors.canvas}` background, `{colors.ink}` text.
- **nav-link** — individual nav anchor; same chrome as top-nav with 8px 16px padding.
- **button-primary** — the pill CTA. 48px radius, 54px height, weight 570 at 16px, `{colors.ink-pure}` fill with `{colors.canvas}` text, 24px horizontal padding.
- **button-primary-hover / disabled** — inherit the base pill geometry; only the fill changes to `{colors.ink-subdued}` or `{colors.ink-disabled}`.
- **button-secondary** — same 48px pill geometry, inverted to `{colors.canvas}` fill with `{colors.ink}` text and a 1px `{colors.ink}` border.
- **button-tertiary** — bone-surface variant (`{colors.surface-bone}` fill) with the same pill geometry; used on subdued sections.
- **button-on-image** — slightly shorter (48px) pill in pure white, designed to overlay photography in the editorial tiles.
- **text-input** — 40px height, 6px radius, 12px / 50px / 12px / 16px padding (right padding holds the inline submit icon), `{colors.ink}` border at rest.
- **text-input-focus** — same geometry, border swaps to `{colors.focus}` (`#005fcc`).
- **welcome-modal** — the 15% Off promo capture; canvas-backed, display-lg type at 64px, 40px outer padding.
- **hero-overlay** — full-bleed editorial frame with secondary-palette fill, display-xl 100px Saans 380 white text, 96/40/48 padding.
- **editorial-tile** — campaign tile in any of the six secondary palette tokens with white display-md type at 40px.
- **product-card** — 0px-radius photograph-first tile; bone-tinted image background, white card surround, body-lg label.
- **color-swatch** — the 50% circular dot in the Shop By Colour strip; 40px diameter, `{colors.surface-bone}` fill, `{colors.ink}` 1px border.
- **category-tile** — 4-up grid card; canvas-backed, heading-md type at 20px, 20/12/0 padding.
- **newsletter-capture** — capture row at 24/40/12 padding with body-md type.
- **link-utility** — the `#0000ee` underlined-anchor browser default that appears on legacy corporate links and footer items.
- **badge-accent** — pill-shaped accent badge with `{colors.accent-red}` text on `{colors.canvas}` and a 1px red border; the rare on-chrome appearance of the brand red.
- **status-error-row** — error-state row with `{colors.status-error-surface}` fill, `{colors.accent-red}` text and border, 6px radius.
- **campaign-tile-inverse** — `{colors.ink}` full-bleed campaign tile with white display-md type; the inverse of the editorial-tile component for product-focused campaigns.
- **footer** — canvas-backed, body-sm type, 48/24 padding; cluster of utility links and locale picker.

## Do's and Don'ts

- **Don't reach for `#c8102e` as a primary CTA fill** — it lives at frequency 2 on the homepage and is mapped to `--lll-color-text-error`. Use `{colors.ink-pure}` (`#000000`) or `{colors.ink}` (`#140f0f`) for primary buttons instead, and reserve the accent red for error states and badge moments under 12px.
- **Don't promote any secondary-palette colour to chrome** — sequoia, wilderness, espresso, daydream, mossy, and rosewood are full-bleed editorial swatches. Using one of them as a card background or a button fill collapses the two-palette discipline that lets the secondary palette feel atmospheric.
- **Don't raise Saans above weight 570** — the homepage uses only weights 380 and 570 across every tier. Pushing the hero to weight 700 or 800 produces a louder activewear template, not Lululemon.
- **Don't soften the `48px` pill to `8px` or `12px`** — the radius vocabulary is binary at the interactive layer: 48px / 100px / 999px pills for actions, 50% circles for selection. A 4px or 8px corner radius reads as generic SaaS and breaks the catalog vocabulary.
- **Don't substitute pure black (`#000000`) for the text ink** — body text and headlines run on warm off-black `#140f0f`. Pure black is reserved for the interactive-filled-default token (button fills and strong borders). Mixing them collapses a deliberate two-ink ladder.
- **Don't add a drop shadow to the product card or the welcome modal** — the homepage has zero decorative shadow tokens. Depth comes from the bone surface and the editorial-tile background, not from elevation.

## Known Gaps

- **PDP and size-selector** typography and chrome are not captured — the spec is built from the homepage at `shop.lululemon.com`.
- **Slide-in bag drawer and checkout flow** are absent — the spec ends at the newsletter capture and footer.
- **Mobile breakpoints** are not extracted — capture was taken at 1440px desktop; the responsive ladder declared in `--lll-type-heading-gde-mobile-*` is not deployed here.
- **Hover states** are documented for the primary button only (`button-primary-hover`); full hover ladder for outlined, tertiary, and on-image variants is not in the spec.
- **Saans variable axis stops** beyond 380 and 570 — the file is declared as variable-weight but the homepage uses only those two values; additional stops exist in the typeface but aren't extracted here.
- **Lululemon Studio (mirror) subsystem and member area** are separate surfaces with their own chrome — not captured.
