Webflow
MIT
Clean, professional design system for a SaaS marketing platform with Webflow's signature blue accent and neutral palette, built on CSS custom properties for seamless integration
Colour (39)
color.colorstext#080808
color.bordererror1px solid var(--webflow-error)
color.borderfocus1px solid rgb(56, 152, 236)
color.webflowinfo#146ef5
color.colorblue300#006acc
color.colorsborder#d8d8d8
color.webflowerror#ee1d36
color.borderdefault1px solid var(--colors--border)
color.webflowsuccess#00d722
color.webflowwarning#ff6b00
color.brandprimaryctargb(20, 110, 245)
color.colorsbackgroundwhite
color.colorneutralblack#080808
color.colorneutralwhitewhite
color.colorsecondaryred#ee1d36
color.webflowaccentcool#7a3dff
color.webflowaccentwarm#ed52cb
color.colorsecondarypink#ed52cb
color.colorneutralgray100#f0f0f0
color.colorneutralgray200#d8d8d8
color.colorneutralgray300#ababab
color.colorneutralgray400#898989
color.colorneutralgray500#757575
color.colorneutralgray600#5a5a5a
color.colorneutralgray700#363636
color.colorneutralgray800#222222
color.colorneutralgray900#171717
color.colorprimaryblue400#3b89ff
color.colorprimaryblue600#0055d4
color.colorsecondarygreen#00d722
color.colorsprimaryaccent#146ef5
color.colorstextsecondary#5a5a5a
color.colorsecondaryorange#ff6b00
color.colorsecondarypurple#7a3dff
color.colorsecondaryyellow#ffae13
color.colorprimarywebflowblue#146ef5
color.colorsprimaryaccenttextcolor-mix(...)
color.colorssecondarybackground#f0f0f0
color.colorsprimaryaccentbackgroundcolor-mix(...)
Spacing (35)
spacing.layoutgridgaplgvar(--_layout---spacing--margin-xl)
spacing.layoutgridgapmdvar(--_layout---spacing--margin-md)
spacing.layoutgridgapsmvar(--_layout---spacing--margin-sm)
spacing.layoutgridgapxsvar(--_layout---spacing--margin-xs)
spacing.layoutgridgapmainvar(--_layout---spacing--margin-lg)
spacing.componentsinputbottommarginvar(--_layout---grid--gap-md)
spacing.typographycaptionbottommarginvar(--_layout---spacing--margin-sm)
spacing.layoutspacingmarginxsclamp(0.375rem, fluid, 0.5rem)
spacing.layoutspacingmarginsmclamp(0.625rem, fluid, 1rem)
spacing.componentscardpaddingclamp(1rem, fluid, 1.5rem)
spacing.componentsbuttonverticalpadding1em
spacing.layoutspacingmarginmdclamp(1.25rem, fluid, 1.5rem)
spacing.componentsbuttonhorizontalpadding1.5em
spacing.layoutspacingmarginlgclamp(1.75rem, fluid, 2rem)
spacing.layoutspacingmarginxlclamp(2.25rem, fluid, 3rem)
spacing.layoutgridgapxlclamp(2.5rem, fluid, 5rem)
spacing.layoutsectionspacinglargeclamp(3rem, fluid, 15rem)
spacing.layoutsectionspacingsmallclamp(3rem, fluid, 5rem)
spacing.layoutsectionspacingmediumclamp(3rem, fluid, 9rem)
spacing.spacexs4px
spacing.webflowspacexs4px
spacing.componentsnavheight4.25rem
spacing.spacesm8px
spacing.webflowspacesm8px
spacing.layoutsectionspacingextralargeclamp(10rem, fluid, 28rem)
spacing.spacemd12px
spacing.webflowspacemd12px
spacing.spacelg16px
spacing.webflowspacelg16px
spacing.spacexl24px
spacing.webflowspacexl24px
spacing.space2xl32px
spacing.webflowspace2xl32px
spacing.space3xl80px
spacing.webflowspace3xl80px
Radius (11)
radiussm0px 2px 2px 0px
webflowradiussm0px 2px 2px 0px
componentsinputborderradius0.25rem
componentsbuttonborderradius0.25rem
componentscardborderradius0.5rem
radiusmd4px
webflowradiusmd4px
radiuslg6px
webflowradiuslg6px
radiusfull8px
webflowradiusfull8px
Shadow (11)
effect.shadowavatarrgba(0, 0, 0, 0) 0px 105px 30px 0px,
rgba(0, 0, 0, 0.02) 0px 67px 27px 0px,
rgba(0, 0, 0, 0.06) 0px 38px 23px 0px,
rgba(0, 0, 0, 0.1) 0px 17px 17px 0px,
rgba(0, 0, 0, 0.12) 0px 4px 9px 0px
effect.layoutfluidmax90
effect.layoutfluidmin20
effect.animationdelayd00s
effect.animationdelayd10.3s
effect.animationdelayd20.45s
effect.animationdelayd30.75s
effect.animationdelayd41.2s
effect.animationdelayd51.95s
effect.transitionduration10ms
effect.layoutcontainermaxwidthcalc(var(--_layout---fluid--max)*1rem)
# layout.md — Webflow Design System
---
## 0. Quick Reference
**Stack:** Webflow marketing site · CSS custom properties (217 vars extracted, high confidence) · No Tailwind/utility-class authoring — use `var()` references directly.
**How to apply:** Use as `var(--token-name)` in CSS, `style={{ prop: 'var(--token-name)' }}` in JSX, or `bg-[var(--token-name)]` in Tailwind.
```css
/* ── Core Tokens ── */
/* Colours */
--colors--background: var(--_color---neutral--white); /* page background: white */
--colors--text: var(--_color---neutral--black); /* primary text: #080808 */
--colors--text-secondary: var(--_color---neutral--gray-600); /* secondary text: #5a5a5a */
--colors--primary-accent: var(--_color---primary--webflow-blue); /* CTA / links: #146ef5 */
--colors--border: var(--_color---neutral--gray-200); /* borders: #d8d8d8 */
--colors--secondary-background: var(--_color---neutral--gray-100); /* subtle bg: #f0f0f0 */
--_color---primary--webflow-blue: #146ef5; /* Webflow brand blue */
--_color---neutral--black: #080808;
--_color---neutral--white: white;
--_color---neutral--gray-200: #d8d8d8;
/* Typography */
--_typography---fonts--primary-font: "WF Visual Sans Variable", Arial, sans-serif;
/* Spacing */
--webflow-space-xs: 4px; --webflow-space-sm: 8px;
--webflow-space-md: 12px; --webflow-space-lg: 16px;
--webflow-space-xl: 24px; --webflow-space-2xl: 32px;
--webflow-space-3xl: 80px;
/* Radius */
--_components---button--border-radius: .25rem; /* 4px — buttons */
--_components---card--border-radius: .5rem; /* 8px — cards */
--_components---input--border-radius: .25rem; /* 4px — inputs */
/* Motion */
--animation-duration-1: 0.3s;
--animation-duration-2: 0.45s;
--transition-timing-inoutquad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
```
```tsx
// Primary CTA button — correct token usage
<button
className="btn-primary"
style={{
background: 'var(--colors--primary-accent)',
color: 'var(--_color---neutral--white)',
borderRadius: 'var(--_components---button--border-radius)',
fontFamily: 'var(--_typography---fonts--primary-font)',
fontWeight: 500,
fontSize: '1rem',
padding: '1em 1.5em',
transition: `background-color var(--animation-duration-1) var(--transition-timing-inoutquad)`,
}}
>
Get started free
</button>
```
**NEVER rules:**
- NEVER hardcode `#146ef5` — always use `var(--colors--primary-accent)`
- NEVER use Inter, Roboto, or system-ui as body font — always `var(--_typography---fonts--primary-font)`
- NEVER use arbitrary spacing values — always use `--webflow-space-*` tokens
- NEVER define border-radius > 8px on brand UI elements (pill shapes are reserved for pill-badge component only)
- NEVER skip focus-visible states — use `outline: 2px solid var(--colors--primary-accent); outline-offset: 2px`
- NEVER use `!important` to override token values
- NEVER construct Tailwind class names dynamically (e.g. `` `bg-${color}` ``)
**Full design system → see layout.md**
---
## 1. Design Direction & Philosophy
### Character & Mood
Webflow's marketing site projects **technical confidence with creative accessibility** — it is the design tool for builders who care about craft. The aesthetic is clean, spacious, and modern without being cold. Typography carries significant weight: fluid type scales communicate ambition and precision simultaneously.
The colour palette is restrained at the surface level — near-black text on white backgrounds, blue as the singular accent — but explodes into vibrant secondary colours (#ed52cb pink, #7a3dff purple, #ffae13 yellow, #00d722 green) in illustration tiles, decorative feature cards, and brand accents. These vivid secondaries are **never used as interactive controls or backgrounds for large surface areas**.
### What This Design Explicitly Rejects
- **No warm beige or off-white backgrounds.** The surface is always `white` or `#f0f0f0` — never cream or warm-tinted.
- **No decorative serifs.** Every typographic element uses `"WF Visual Sans Variable"` — a single variable font family.
- **No pill-shaped primary action buttons.** The `cls_badge` component is pill-shaped (border-radius: 1440px), but action buttons use `border-radius: 0.25rem` (4px).
- **No aggressive drop shadows on cards.** Cards use background-colour transitions on hover — not elevation lift.
- **No static type sizes.** Headlines use fluid `clamp()` typography — never fixed px sizes at the heading level.
- **No warm colours in interactive feedback.** Hover/focus states use the Webflow blue or neutral greys, never orange or yellow.
- **No rounded corners above 8px** on primary brand UI components (navs, buttons, inputs, cards).
### Aesthetic Principles
1. **Fluid spacing over fixed breakpoint jumps** — layout breathes using clamp() fluid values across a 20rem–90rem viewport range.
2. **Typography as layout** — h0–h1 headings are large enough to define section rhythm without supporting imagery.
3. **Blue is singular** — `#146ef5` is the only interactive colour. All secondary brand colours are decorative.
---
## 2. Colour System
### Tier 1: Primitive Values
```css
/* ── Neutral Primitives ── */
--_color---neutral--white: white; /* #ffffff — absolute white */
--_color---neutral--black: #080808; /* near-black, not pure #000 */
--_color---neutral--gray-100: #f0f0f0; /* lightest grey surface */
--_color---neutral--gray-200: #d8d8d8; /* border / divider grey */
--_color---neutral--gray-300: #ababab; /* placeholder / disabled text */
--_color---neutral--gray-400: #898989; /* muted icon / secondary UI */
--_color---neutral--gray-500: #757575; /* medium grey text */
--_color---neutral--gray-600: #5a5a5a; /* secondary body text */
--_color---neutral--gray-700: #363636; /* dark secondary text */
--_color---neutral--gray-800: #222222; /* near-black alternative */
--_color---neutral--gray-900: #171717; /* darkest surface/text */
/* ── Blue Primitives ── */
--_color---primary--webflow-blue: #146ef5; /* Webflow brand blue — primary action */
--_color---primary--blue-400: #3b89ff; /* lighter blue hover tint */
--_color---primary--blue-600: #0055d4; /* darker blue pressed state */
--_color---blue-300: #006acc; /* mid-blue utility */
/* ── Secondary Brand Primitives (decorative only) ── */
--_color---secondary--purple: #7a3dff; /* decorative — never interactive */
--_color---secondary--pink: #ed52cb; /* decorative — never interactive */
--_color---secondary--yellow: #ffae13; /* decorative — never interactive */
--_color---secondary--orange: #ff6b00; /* warning status only */
--_color---secondary--green: #00d722; /* success status only */
--_color---secondary--red: #ee1d36; /* error status only */
```
### Tier 2: Semantic Aliases
```css
/* ── Semantic Colour Tokens ── */
--colors--background: var(--_color---neutral--white);
/* Page and section background — always white */
--colors--secondary-background: var(--_color---neutral--gray-100);
/* Subtle section tinting, hover fills on secondary buttons: #f0f0f0 */
--colors--text: var(--_color---neutral--black);
/* All primary body and heading text: #080808 */
--colors--text-secondary: var(--_color---neutral--gray-600);
/* Captions, metadata, secondary labels: #5a5a5a */
--colors--border: var(--_color---neutral--gray-200);
/* All borders and dividers: #d8d8d8 */
--colors--primary-accent: var(--_color---primary--webflow-blue);
/* Primary interactive colour — CTAs, links, focus outlines: #146ef5 */
--colors--primary-accent-text: color-mix(in hsl, var(--colors--primary-accent) 92%, var(--colors--text) 8%);
/* Slightly darkened accent for text-on-white legibility */
--colors--primary-accent-background: color-mix(in hsl, var(--colors--primary-accent) 10%, transparent 90%);
/* 10% blue tint for pill hover states and light accent fills */
```
### Tier 3: Component-Level Applications
```css
/* ── Status Tokens ── */
--webflow-success: #00d722; /* Success state: form confirm, positive badge */
--webflow-warning: #ff6b00; /* Warning state: degraded service indicators */
--webflow-error: #ee1d36; /* Error state: form validation, destructive alerts */
--webflow-info: #146ef5; /* Info state: aliases primary-accent */
/* ── Accent / Brand Decorative (never for interactive controls) ── */
--webflow-accent: var(--_color---primary--webflow-blue); /* #146ef5 */
--webflow-accent-warm: #ed52cb; /* Pink — illustration tiles, decorative only */
--webflow-accent-cool: #7a3dff; /* Purple — illustration tiles, decorative only */
--_color---secondary--yellow: #ffae13; /* Yellow — decorative brand tile only */
```
### Colour Usage Table
| Token | Value | Usage |
|---|---|---|
| `--colors--background` | `white` | Page background |
| `--colors--secondary-background` | `#f0f0f0` | Button hover, subtle section fill |
| `--colors--text` | `#080808` | All headings and body text |
| `--colors--text-secondary` | `#5a5a5a` | Captions, meta, secondary labels |
| `--colors--border` | `#d8d8d8` | All borders, input strokes, dividers |
| `--colors--primary-accent` | `#146ef5` | CTAs, links, focus rings |
| `--_color---primary--blue-600` | `#0055d4` | Button pressed / active state |
| `--webflow-accent-warm` | `#ed52cb` | Decorative only — pink brand tiles |
| `--webflow-accent-cool` | `#7a3dff` | Decorative only — purple brand tiles |
| `--webflow-error` | `#ee1d36` | Error feedback |
| `--webflow-success` | `#00d722` | Success feedback |
---
## 3. Typography System
**Primary font:** `"WF Visual Sans Variable"` — a variable font (weight axis: 100–900, optical size axis). All headings, body, buttons, and labels use this single family. Fallback: `Arial, sans-serif`.
**Mono font:** `WFVisualSans-Mono` — used exclusively for `label` elements and `tab` components.
```css
/* ── Font Stack Declaration ── */
--_typography---fonts--primary-font: "WF Visual Sans Variable", Arial, sans-serif;
/* Variable font — supports weight 100–900 and optical size axes */
/* ── Fluid Scale Foundation ── */
--_layout---fluid--min: 20; /* 20rem = 320px viewport minimum */
--_layout---fluid--max: 90; /* 90rem = 1440px viewport maximum */
```
### Composite Typography Groups
```css
/* ── Display / Hero (h0) ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(3rem, fluid, 7rem) [--_typography---h0--font-size]
font-weight: 600 [--_typography---h0--font-weight]
line-height: 1.04 [--_typography---h0--line-height]
letter-spacing: 0em [--_typography---h0--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-md) */
/* ── Heading 1 ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(2.75rem, fluid, 5rem) [--_typography---h1--font-size]
font-weight: 600 [--_typography---h1--font-weight]
line-height: 1.04 [--_typography---h1--line-height]
letter-spacing: -0.01em [--_typography---h1--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-md) */
/* ── Heading 2 ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(2rem, fluid, 3.5rem) [--_typography---h2--font-size]
font-weight: 600 [--_typography---h2--font-weight]
line-height: 1.04 [--_typography---h2--line-height]
letter-spacing: 0em [--_typography---h2--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-md) */
/* ── Heading 3 ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1.75rem, fluid, 2.5rem) [--_typography---h3--font-size]
font-weight: 600 [--_typography---h3--font-weight]
line-height: 1.2 [--_typography---h3--line-height]
letter-spacing: 0em [--_typography---h3--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-sm) */
/* ── Heading 4 ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1.375rem, fluid, 2rem) [--_typography---h4--font-size]
font-weight: 600 [--_typography---h4--font-weight]
line-height: 1.2 [--_typography---h4--line-height]
letter-spacing: 0em [--_typography---h4--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-xs) */
/* ── Heading 5 ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1.25rem, fluid, 1.5rem) [--_typography---h5--font-size]
font-weight: 600 [--_typography---h5--font-weight]
line-height: 1.3 [--_typography---h5--line-height]
letter-spacing: 0em [--_typography---h5--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-sm) */
/* ── Heading 6 ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1.125rem, fluid, 1.25rem) [--_typography---h6--font-size]
font-weight: 600 [--_typography---h6--font-weight]
line-height: 1.4 [--_typography---h6--line-height]
letter-spacing: 0em [--_typography---h6--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-xs) */
/* ── Body (paragraph-body) ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: 1rem [--_typography---paragraph-body--font-size]
font-weight: 400 [--_typography---paragraph-body--font-weight]
line-height: 1.6 [--_typography---paragraph-body--line-height]
letter-spacing: 0em [--_typography---paragraph-body--letter-spacing]
bottom-margin: var(--_layout---spacing--margin-sm) */
/* ── Paragraph Large ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1.1rem, fluid, 1.25rem) [--_typography---paragraph-lg--font-size]
font-weight: 400 [--_typography---paragraph-lg--font-weight]
line-height: 1.5 [--_typography---paragraph-lg--line-height]
letter-spacing: 0em [--_typography---paragraph-lg--letter-spacing] */
/* ── Paragraph XL ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1.5rem, fluid, 2rem) [--_typography---paragraph-xl--font-size]
font-weight: 400 [--_typography---paragraph-xl--font-weight]
line-height: 1.4 [--_typography---paragraph-xl--line-height]
letter-spacing: 0em [--_typography---paragraph-xl--letter-spacing] */
/* ── Paragraph XXL ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(2rem, fluid, 3.5rem) [--_typography---paragraph-xxl--font-size]
font-weight: 400 [--_typography---paragraph-xxl--font-weight]
line-height: 1.2 [--_typography---paragraph-xxl--line-height]
letter-spacing: 0em [--_typography---paragraph-xxl--letter-spacing] */
/* ── Paragraph Small ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: 0.875rem [--_typography---paragraph-sm--font-size]
font-weight: 400 [--_typography---paragraph-sm--font-weight]
line-height: 1.6 [--_typography---paragraph-sm--line-height]
letter-spacing: 0em [--_typography---paragraph-sm--letter-spacing] */
/* ── Paragraph XS ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: 0.75rem [--_typography---paragraph-xs--font-size]
font-weight: 400 [--_typography---paragraph-xs--font-weight]
line-height: 1.6 [--_typography---paragraph-xs--line-height]
letter-spacing: 0em [--_typography---paragraph-xs--letter-spacing] */
/* ── Eyebrow ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: clamp(1rem, fluid, 1.25rem) [--_typography---eyebrow--font-size]
font-weight: 500 [--_typography---eyebrow--font-weight]
line-height: 1.4 [--_typography---eyebrow--line-height]
letter-spacing: 0em [--_typography---eyebrow--letter-spacing] */
/* ── Caption ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: 0.8rem [--_typography---caption--font-size]
font-weight: 550 [--_typography---caption--font-weight] (semibold via variable axis)
line-height: 1.2 [--_typography---caption--line-height]
letter-spacing: 0em [--_typography---caption--letter-spacing] */
/* ── Button ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: 1rem [--_components---button--font-size]
font-weight: 500 [--_components---button--font-weight]
line-height: 1.2em [--_components---button--line-height]
letter-spacing: -0.01em [--_components---button--letter-spacing] */
/* ── Input ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: 1rem [--_components---input--font-size]
font-weight: 400 [--_components---input--font-weight]
line-height: 1.5em [--_components---input--line-height]
letter-spacing: 0em [--_components---input--letter-spacing] */
/* ── Input Label ── */
/* font-family: WFVisualSans-Mono, sans-serif (mono variant for labels)
font-size: 0.9rem [--_components---input-label--font-size]
font-weight: 500 [--_components---input-label--font-weight]
line-height: 1.4em [--_components---input-label--line-height]
letter-spacing: 0em [--_components---input-label--letter-spacing] */
/* ── Subheading (h6-equivalent) ── */
/* font-family: var(--_typography---fonts--primary-font)
font-size: var(--_typography---h6--font-size)
font-weight: 500 [--_typography---subheading--font-weight]
line-height: 1.4 [--_typography---subheading--line-height]
letter-spacing: 0px [--_typography---subheading--letter-spacing] */
```
### Font Weight Reference
| Weight | Usage |
|---|---|
| 400 | Body text, paragraph variants, inputs |
| 500 | Buttons, eyebrow, subheadings, input labels |
| 550 | Captions (variable font axis value) |
| 600 | All headings h0–h6 |
---
## 4. Spacing & Layout
```css
/* ── Base Spacing Scale ── */
--webflow-space-xs: 4px; /* Tight inline gap, icon-to-text spacing */
--webflow-space-sm: 8px; /* Card internal gap, input padding vertical */
--webflow-space-md: 12px; /* Input padding, small component padding */
--webflow-space-lg: 16px; /* Default content padding, nav item padding */
--webflow-space-xl: 24px; /* Section inner padding, card gap */
--webflow-space-2xl: 32px; /* Between content groups */
--webflow-space-3xl: 80px; /* Major section separators */
/* ── Fluid Margin Scale (clamp-based, 320px–1440px range) ── */
--_layout---spacing--margin-xs: clamp(0.375rem, fluid, 0.5rem); /* ~6–8px */
--_layout---spacing--margin-sm: clamp(0.625rem, fluid, 1rem); /* ~10–16px */
--_layout---spacing--margin-md: clamp(1.25rem, fluid, 1.5rem); /* ~20–24px */
--_layout---spacing--margin-lg: clamp(1.75rem, fluid, 2rem); /* ~28–32px */
--_layout---spacing--margin-xl: clamp(2.25rem, fluid, 3rem); /* ~36–48px */
/* ── Fluid Section Spacing ── */
--_layout---section-spacing--small: clamp(3rem, fluid, 5rem); /* ~48–80px */
--_layout---section-spacing--medium: clamp(3rem, fluid, 9rem); /* ~48–144px */
--_layout---section-spacing--large: clamp(3rem, fluid, 15rem); /* ~48–240px */
--_layout---section-spacing--extra-large: clamp(10rem, fluid, 28rem);/* ~160–448px */
/* ── Grid Gap Scale ── */
--_layout---grid--gap-xs: var(--_layout---spacing--margin-xs);
--_layout---grid--gap-sm: var(--_layout---spacing--margin-sm);
--_layout---grid--gap-md: var(--_layout---spacing--margin-md);
--_layout---grid--gap-main: var(--_layout---spacing--margin-lg);
--_layout---grid--gap-lg: var(--_layout---spacing--margin-xl);
--_layout---grid--gap-xl: clamp(2.5rem, fluid, 5rem);
/* ── Container ── */
--_layout---container--max-width: calc(var(--_layout---fluid--max) * 1rem);
/* = 90rem = 1440px — max content width */
--_layout---fluid--min: 20; /* 20rem = 320px */
--_layout---fluid--max: 90; /* 90rem = 1440px */
/* ── Component Dimensions ── */
--_components---nav--height: 4.25rem; /* 68px navigation bar height */
--_components---card--padding: clamp(1rem, fluid, 1.5rem); /* 16–24px card internal padding */
--_components---button--vertical-padding: 1em; /* relative to button font-size */
--_components---button--horizontal-padding: 1.5em;
/* ── Border Radius ── */
--_components---button--border-radius: 0.25rem; /* 4px — action buttons */
--_components---card--border-radius: 0.5rem; /* 8px — cards and surfaces */
--_components---input--border-radius: 0.25rem; /* 4px — text inputs */
/* Note: cls_badge uses border-radius: 1440px (pill) — this is badge-specific, NOT a global radius token */
```
### Grid System
| Breakpoint | Viewport | Behaviour |
|---|---|---|
| Default (mobile) | < 479px | Single column, full-width stack |
| Small mobile | 479px | Minor layout adjustments |
| Tablet portrait | 767–768px | Two-column grid transitions begin |
| Tablet landscape | 991–992px | Three-column grids enabled |
| Desktop | ≥ 992px | Full multi-column layouts active |
| Max container | 1440px (90rem) | Content constrained, outer margin auto |
**Flex vs Grid decision:**
- `display: flex` for nav bars, button groups, inline badge rows, and card internal layouts (flex-column)
- CSS Grid for feature card grids, pricing columns, and multi-column content sections
- Cards: `display: flex; flex-direction: column; justify-content: flex-start`
- Nav: `display: block` at the nav role level; inner elements use flex
---
## 5. Page Structure & Layout Patterns
> No screenshots provided. Section derived from Layout Digest, component inventory, and computed styles. Rows marked "(inferred)" are not visually confirmed.
### 5.1 Section Map
| Order | Section | Layout Type | Approx. Height | Key Elements |
|---|---|---|---|---|
| 1 | Navigation / Header | Sticky flex row, full-width | 4.25rem (68px fixed) | Logo, nav links (173 instances), CTA button, persona dropdown |
| 2 | Hero | Full-width, centred flex column | Large — `section-spacing--extra-large` | h1 (80px fluid), eyebrow badge, paragraph-xl body, 2× CTA buttons |
| 3 | Social Proof / Logo Bar (inferred) | Flex row, centred, full-width | Small — ~80–120px | Brand logos, marquee animation |
| 4 | Feature / Card Grid | Multi-column CSS grid | Medium — `section-spacing--medium` | 135 card instances, flex-column cards, blue background cards (#146ef5) |
| 5 | AI / Product Feature (inferred) | Alternating 2-col text+media | Large | paragraph-xxl text, product screenshots, autoplay tabs |
| 6 | Testimonials / Quote section (inferred) | 1–3 col grid | Medium | Avatar elements, card components |
| 7 | Pricing / Plans (inferred) | 3-col grid | Large | toggle (billing switch), cards, CTA buttons |
| 8 | CTA Banner (inferred) | Full-width, centred | Medium — `section-spacing--small` | h2 fluid heading, primary CTA button (#146ef5 bg) |
| 9 | Footer | Multi-column grid | Auto | Logo, nav-link columns, paragraph-xs text, secondary links |
### 5.2 Layout Patterns
**Navigation:**
- `display: block` at nav role level; internal flex row at `height: 4.25rem`
- Left: logo; centre: nav links with dropdown triggers; right: persona selector + CTA
- Nav CTA: `background: var(--colors--primary-accent)` (#146ef5), `border-radius: 0.25rem`
**Hero Section (inferred from h1 computed styles):**
- `display: flex; flex-direction: column; align-items: center; text-align: center`
- h1 at `clamp(2.75rem, fluid, 5rem)`, weight 600, letter-spacing -0.01em
- Body copy at `paragraph-xl` size: `clamp(1.5rem, fluid, 2rem)`
- Two CTA buttons: primary (blue #146ef5) + secondary (transparent/border variant), gap `var(--webflow-space-md)`
**Feature Card Grid:**
- Cards: `display: flex; flex-direction: column; justify-content: flex-start`
- Card background: computed `rgb(20, 110, 245)` (#146ef5) for featured cards, white for standard
- Card `border-radius: var(--_components---card--border-radius)` (8px)
- Card `transition: background-color 0.3s cubic-bezier(0.455, 0.03, 0.515, 0.955)` on hover
- Hover state: `background-color: var(--colors--border)` (#d8d8d8) on hoverable cards
**Footer:**
- Multi-column grid; link text at `paragraph-xs` (0.75rem / lh 1.6)
- Hover on brand logo: `color: #898989` (`--_color---neutral--gray-400`)
- Focus-visible on footer links: `outline: 2px solid var(--colors--primary-accent); outline-offset: 2px; color: var(--colors--text)`
### 5.3 Visual Hierarchy
1. **h1 / h0 headlines** dominate each section — fluid 44px–80px range at desktop
2. **Primary CTA** (#146ef5 background, white text) appears in hero, feature sections, and sticky nav
3. **Eyebrow badges** (pill-shaped, `border-radius: 1440px`, `border: 1px solid #d8d8d8`) precede major headings
4. **Whitespace rhythm:** sections breathe using `section-spacing--medium` to `section-spacing--large`; component groups use `margin-md` and `margin-sm`
5. **Decorative colour blocks** (pink, purple, yellow) appear only inside card tiles — never as section backgrounds
### 5.4 Content Patterns
**Feature card pattern:**
```
[Eyebrow badge — pill shape]
[H3 heading — 600 weight, fluid]
[Paragraph body — 400 weight, 1.6 lh]
[Optional: CTA link or button]
```
**Section header pattern (centred):**
```
[Eyebrow — uppercase, 500 weight, blue colour]
[H2 — fluid 2rem–3.5rem, 600 weight, centred]
[Paragraph-lg body — fluid 1.1rem–1.25rem, centred, max-width constrained]
```
**CTA button pair pattern:**
```
[Primary btn — #146ef5 bg, white text, 4px radius]
[Secondary btn — transparent bg, border var(--colors--border), #080808 text]
```
---
## 6. Component Patterns
### 6.1 Button
**Anatomy:** `[optional icon] [label text]`
**8 variants detected:** primary, secondary, text/ghost, copy-prompt, and icon-only variants.
**Token-to-property mappings:**
| State | Background | Text | Border | Shadow | Outline |
|---|---|---|---|---|---|
| Default (primary) | `var(--colors--primary-accent)` #146ef5 | `white` | none | none | none |
| Default (secondary) | `transparent` | `var(--colors--text)` | `1px solid var(--colors--border)` | none | none |
| Hover (primary) | `var(--_color---primary--blue-600)` #0055d4 | `white` | none | none | none |
| Hover (secondary) | `var(--colors--secondary-background)` #f0f0f0 | `var(--colors--text)` | unchanged | none | none |
| Focus-visible | unchanged | unchanged | unchanged | none | `2px solid var(--colors--primary-accent); offset: 2px` |
| Active | unchanged bg | unchanged | unchanged | none | none |
| Disabled | `var(--_color---neutral--gray-200)` | `var(--_color---neutral--gray-400)` | none | none | none |
```tsx
// ── Production-ready Button component ──
import React from 'react';
type ButtonVariant = 'primary' | 'secondary' | 'text';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant;
loading?: boolean;
children: React.ReactNode;
}
const buttonStyles: Record<ButtonVariant, React.CSSProperties> = {
primary: {
backgroundColor: 'var(--colors--primary-accent)',
color: 'var(--_color---neutral--white)',
border: 'none',
},
secondary: {
backgroundColor: 'transparent',
color: 'var(--colors--text)',
border: '1px solid var(--colors--border)',
},
text: {
backgroundColor: 'transparent',
color: 'var(--colors--primary-accent)',
border: 'none',
},
};
export const Button: React.FC<ButtonProps> = ({
variant = 'primary',
loading = false,
disabled,
children,
...props
}) => {
const isDisabled = disabled || loading;
return (
<button
{...props}
disabled={isDisabled}
data-variant={variant}
style={{
/* Typography */
fontFamily: 'var(--_typography---fonts--primary-font)',
fontSize: 'var(--_components---button--font-size)', /* 1rem */
fontWeight: 500, /* --_components---button--font-weight */
lineHeight: 'var(--_components---button--line-height)', /* 1.2em */
letterSpacing: 'var(--_components---button--letter-spacing)', /* -0.01em */
/* Layout */
display: 'inline-flex',
alignItems: 'center',
gap: 'var(--webflow-space-sm)', /* 8px icon gap */
padding: 'var(--_components---button--vertical-padding) var(--_components---button--horizontal-padding)',
/* Shape */
borderRadius: 'var(--_components---button--border-radius)', /* 0.25rem = 4px */
/* Motion */
transition: `background-color var(--animation-duration-1) var(--transition-timing-inoutquad),
color var(--animation-duration-1) var(--transition-timing-inoutquad),
border-color var(--animation-duration-1) var(--transition-timing-inoutquad)`,
cursor: isDisabled ? 'not-allowed' : 'pointer',
/* Disabled override */
...(isDisabled ? {
backgroundColor: 'var(--_color---neutral--gray-200)',
color: 'var(--_color---neutral--gray-400)',
border: 'none',
opacity: 0.7,
} : buttonStyles[variant]),
}}
>
{loading ? <span aria-hidden>…</span> : null}
{children}
</button>
);
};
```
```css
/* Hover and focus states (CSS required — cannot be inlined) */
[data-variant="primary"]:hover:not(:disabled) {
background-color: var(--_color---primary--blue-600); /* #0055d4 */
}
[data-variant="secondary"]:hover:not(:disabled) {
background-color: var(--colors--secondary-background); /* #f0f0f0 */
}
[data-variant="text"]:hover:not(:disabled) {
background-color: transparent;
box-shadow: none;
}
.btn:focus-visible,
button:focus-visible {
outline: 2px solid var(--colors--primary-accent);
outline-offset: 2px;
}
```
---
### 6.2 Card
**Anatomy:** `[optional media/image] [card body: eyebrow + heading + body text + optional CTA]`
**Token-to-property mappings:**
| State | Background | Border | Shadow |
|---|---|---|---|
| Default (standard) | `var(--colors--background)` white | `1px solid var(--colors--border)` | none |
| Default (featured) | `var(--colors--primary-accent)` #146ef5 | none | none |
| Hover (hoverable) | `var(--colors--secondary-background)` #f0f0f0 | unchanged | none |
| Hover (featured hoverable) | `var(--colors--border)` #d8d8d8 | unchanged | none |
| Focus-visible | unchanged | unchanged | `outline: 2px solid var(--colors--primary-accent)` |
| Disabled | opacity: 0.5 | unchanged | none |
```tsx
// ── Production-ready Card component ──
interface CardProps {
featured?: boolean;
hoverable?: boolean;
children: React.ReactNode;
className?: string;
}
export const Card: React.FC<CardProps> = ({
featured = false,
hoverable = false,
children,
className,
}) => (
<div
data-featured={featured}
data-hoverable={hoverable}
className={['card', hoverable ? 'cc-hoverable' : '', className].filter(Boolean).join(' ')}
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
borderRadius: 'var(--_components---card--border-radius)', /* 0.5rem = 8px */
padding: 'var(--_components---card--padding)', /* clamp(1rem, fluid, 1.5rem) */
backgroundColor: featured
? 'var(--colors--primary-accent)' /* #146ef5 */
: 'var(--colors--background)', /* white */
color: featured
? 'var(--_color---neutral--white)'
: 'var(--colors--text)',
border: featured ? 'none' : '1px solid var(--colors--border)',
transition: `background-color var(--animation-duration-1) var(--transition-timing-inoutquad)`,
fontFamily: 'var(--_typography---fonts--primary-font)',
fontSize: '1rem',
lineHeight: 1.6,
}}
>
{children}
</div>
);
```
```css
.card.cc-hoverable:hover {
background-color: var(--colors--secondary-background); /* #f0f0f0 */
}
.card[data-featured="true"].cc-hoverable:hover {
background-color: var(--colors--border); /* #d8d8d8 */
}
```
---
### 6.3 Input
**Anatomy:** `[label] [input field] [optional helper/error text]`
| State | Border | Background | Outline |
|---|---|---|---|
| Default | `1px solid var(--colors--border)` #d8d8d8 | `white` | none |
| Hover | `1px solid var(--_color---neutral--gray-400)` | `white` | none |
| Focus | `1px solid rgb(56, 152, 236)` | `white` | none (suppressed by `.w-input:focus` rule) |
| Error | `1px solid var(--webflow-error)` #ee1d36 | `white` | none |
| Disabled | `1px solid var(--colors--border)` | `var(--colors--secondary-background)` | none |
```tsx
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
label: string;
error?: string;
}
export const Input: React.FC<InputProps> = ({ label, error, disabled, id, ...props }) => (
<div style={{ display: 'flex', flexDirection: 'column', gap: 'var(--webflow-space-xs)' }}>
<label
htmlFor={id}
style={{
fontFamily: 'WFVisualSans-Mono, sans-serif',
fontSize: 'var(--_components---input-label--font-size)', /* 0.9rem */
fontWeight: 500,
lineHeight: 'var(--_components---input-label--line-height)',
color: 'var(--colors--text)',
}}
>
{label}
</label>
<input
id={id}
disabled={disabled}
className="w-input"
{...props}
style={{
fontFamily: 'var(--_typography---fonts--primary-font)',
fontSize: 'var(--_components---input--font-size)', /* 1rem */
fontWeight: 400,
lineHeight: 'var(--_components---input--line-height)',
padding: 'var(--webflow-space-sm) var(--webflow-space-md)', /* 8px 12px */
borderRadius: 'var(--_components---input--border-radius)', /* 0.25rem = 4px */
border: error
? '1px solid var(--webflow-error)'
: '1px solid var(--colors--border)',
backgroundColor: disabled
? 'var(--colors--secondary-background)'
: 'var(--_color---neutral--white)',
color: 'var(--colors--text)',
outline: 'none', /* Focus handled by .w-input:focus class */
transition: `border-color var(--animation-duration-1) var(--transition-timing-inoutquad)`,
width: '100%',
}}
/>
{error && (
<span style={{
fontSize: 'var(--_typography---paragraph-xs--font-size)', /* 0.75rem */
color: 'var(--webflow-error)',
lineHeight: 1.4,
}}>
{error}
</span>
)}
</div>
);
```
---
### 6.4 Badge / Pill
**Anatomy:** `[optional dot/icon] [label text]`
Two badge types:
1. **`cls_badge`** — pill shape, `border-radius: 1440px`, used for eyebrow/tag labels
2. **`badge`** (semantic element) — flat, uppercase, 10px, 600 weight, letter-spacing 1px, blue text
| State | Background | Border | Text |
|---|---|---|---|
| Default | `var(--_color---neutral--white)` | `1px solid var(--colors--border)` | `var(--colors--text)` |
| Hover | `var(--colors--secondary-background)` #f0f0f0 | unchanged | unchanged |
| Active/selected | `var(--colors--primary-accent-background)` | `var(--colors--primary-accent)` | `var(--colors--primary-accent)` |
```tsx
interface BadgeProps {
children: React.ReactNode;
variant?: 'pill' | 'label';
}
export const Badge: React.FC<BadgeProps> = ({ children, variant = 'pill' }) => {
if (variant === 'label') {
return (
<span style={{
fontFamily: 'var(--_typography---fonts--primary-font)',
fontSize: '10px',
fontWeight: 600,
lineHeight: '13px',
letterSpacing: '1px',
textTransform: 'uppercase',
color: 'var(--colors--primary-accent)',
display: 'block',
}}>
{children}
</span>
);
}
return (
<div
className="cls_badge"
style={{
display: 'inline-flex',
flexDirection: 'row',
alignItems: 'center',
gap: 'var(--webflow-space-xs)', /* 4px */
padding: '6px 10px 6px 6px',
borderRadius: '1440px', /* pill — badge-specific only */
border: '1px solid var(--colors--border)',
backgroundColor: 'var(--_color---neutral--white)',
color: 'var(--colors--text)',
fontFamily: 'var(--_typography---fonts--primary-font)',
fontSize: 'var(--webflow-font-size-sm)', /* 14px */
fontWeight: 500,
lineHeight: '19.6px',
transition: `background-color var(--animation-duration-1) var(--transition-timing-inoutquad),
color var(--animation-duration-1) var(--transition-timing-inoutquad),
box-shadow var(--animation-duration-1) var(--transition-timing-inoutquad),
border var(--animation-duration-1) var(--transition-timing-inoutquad)`,
cursor: 'default',
}}
>
{children}
</div>
);
};
```
---
### 6.5 Nav Item
**Anatomy:** `[nav link text] [optional dropdown chevron]`
| State | Colour | Outline |
|---|---|---|
| Default | `var(--colors--text)` #080808 | none |
| Hover | unchanged (parent dropdown shows) | none |
| Focus-visible (link) | `var(--colors--primary-accent)` #146ef5 | `2px solid var(--colors--primary-accent); offset: 2px` |
| Focus-visible (dropdown btn) | unchanged | `2px solid var(--_color---primary--webflow-blue); offset: 2px` |
| Active | `var(--colors--primary-accent)` | none |
```css
.nav-link {
font-family: var(--_typography---fonts--primary-font);
font-size: 1rem;
font-weight: 400;
line-height: 1.6;
color: var(--colors--text);
text-decoration: none;
transition: color var(--animation-duration-1) var(--transition-timing-inoutquad);
}
.nav-link:focus-visible,
.nav-link[data-wf-focus-visible] {
color: var(--colors--primary-accent);
outline: 2px solid var(--colors--primary-accent);
outline-offset: 2px;
}
.nav-link.cc-dropdown-btn:focus-visible {
outline: 2px solid var(--_color---primary--webflow-blue);
outline-offset: 2px;
}
```
---
## 7. Elevation & Depth
Webflow's design system uses **minimal elevation** — components are differentiated by colour and border, not shadows. The one notable exception is the avatar/floating image element which uses a layered shadow stack to simulate photo lifting off the surface.
```css
/* ── Shadow Tokens ── */
/* No shadow — default for cards, buttons, inputs */
/* box-shadow: none; */
/* Avatar / floating image lift — extracted from computed styles */
--shadow-avatar:
rgba(0, 0, 0, 0) 0px 105px 30px 0px,
rgba(0, 0, 0, 0.02) 0px 67px 27px 0px,
rgba(0, 0, 0, 0.06) 0px 38px 23px 0px,
rgba(0, 0, 0, 0.1) 0px 17px 17px 0px,
rgba(0, 0, 0, 0.12) 0px 4px 9px 0px;
/* Used on: floating avatar/image elements, not standard cards */
/* Nav banner overlay hover — inset shadow used to darken banner image */
/* box-shadow: rgba(0, 0, 0, 0.15) 0px 0px 0px 100px inset; — .nav-banner:hover */
/* Slider dot focus */
/* box-shadow: rgb(255, 255, 255) 0px 0px 0px 2px; — .w-slider-dot:focus */
```
```css
/* ── Border Tokens ── */
--border-default: 1px solid var(--colors--border); /* #d8d8d8 — standard card/input border */
--border-focus: 1px solid rgb(56, 152, 236); /* .w-input:focus border */
--border-error: 1px solid var(--webflow-error); /* #ee1d36 — validation error */
/* ── Z-Index Scale (inferred) ── */
--z-base: 0; /* Default document flow */
--z-dropdown: 10; /* Dropdown menus */
--z-nav: 100; /* Sticky navigation */
--z-modal: 1000; /* Modal overlays (display:flex, justify:center, align:center) */
--z-toast: 1100; /* Toast / alert overlays above modal */
```
**Layering principles:**
- Cards do NOT lift on hover — they transition `background-color` only
- Navigation is sticky at `z-index` above content, below modals
- Modals: `display: none` default → `display: flex; justify-content: center; align-items: center` when open
- NEVER add `box-shadow` to standard cards or buttons — this breaks the flat design language
---
## 8. Motion
```css
/* ── Duration Tokens ── */
--animation-duration-1: 0.3s; /* Fast micro-interactions: hover colour, opacity toggle */
--animation-duration-2: 0.45s; /* Standard transitions: card bg, nav drawer */
--animation-duration-3: 0.75s; /* Medium: section reveals, image entrance */
--animation-duration-4: 1.2s; /* Slow: hero animations, complex orchestration */
/* ── Delay Tokens ── */
--animation-delay-d0: 0s;
--animation-delay-d1: 0.3s;
--animation-delay-d2: 0.45s;
--animation-delay-d3: 0.75s;
--animation-delay-d4: 1.2s;
--animation-delay-d5: 1.95s;
/* ── Easing Tokens ── */
--transition-timing-inoutquad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
/* Standard ease-in-out — used on buttons, cards, most UI transitions */
--transition-timing-inoutcubic: cubic-bezier(0.645, 0.045, 0.355, 1);
/* Stronger ease — panel slides, drawers */
--transition-timing-inoutquart: cubic-bezier(0.77, 0, 0.175, 1);
/* Sharpest ease — hero entrances, dramatic reveals */
--ease-default: ease;
/* Fallback for generic transitions */
/* ── Keyframe Animations ── */
/* Fade in from opacity 0 */
@keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}
/* Scale + fade entrance (hero elements) */
@keyframes scale {
0% { opacity: 0; transform: scale(1.015) translateZ(0); }
100% { opacity: 1; transform: scale(1) translateZ(0); }
}
/* Marquee — continuous leftward scroll for logo bars */
@keyframes marquee_1_timeline {
0% { transform: translateX(0%); }
100% { transform: translateX(-50%); }
}
/* Gradient animation (decorative hero bg) */
@keyframes moveGradientRight {
0% { background-position: 0% 20%; }
50% { background-position: 15% 0%; }
100% { background-position: 0% 20%; }
}
/* Noise texture animation (decorative) */
@keyframes noise-animation {
0% { transform: translate(0, 0); }
10% { transform: translate(-2%, -3%); }
/* ... continues 100% { transform: translate(1%, 0); } */
}
/* Rotation utility */
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
```
**When to animate:**
- **Always animate:** button hover bg (`duration-1`), card hover bg (`duration-1`), focus-visible outlines, nav dropdown open/close (`duration-2`)
- **Animate on scroll:** section reveals using `scale` or `fade` keyframes with `duration-3`/`duration-4`
- **Marquee:** logo bars, partner strips — continuous `marquee_1_timeline` on repeat
- **NEVER animate:** layout shifts, font changes, or text-content transitions
- **Reduce motion:** wrap scroll-triggered and decorative animations in `@media (prefers-reduced-motion: reduce) { animation: none; transition: none; }`
> **Note:** The extracted CSS contains `--transition-duration-1` through `--transition-duration-7` all set to `0ms`. These are Webflow editor transition-duration overrides — do NOT use them as motion tokens. Use `--animation-duration-*` instead.
---
## 9. Anti-Patterns & Constraints
1. **NEVER hardcode colour hex values → Why it fails: AI agents default to inline `#146ef5` or `#080808` when no token context is provided, creating values that cannot be updated via the design token system. A single brand colour change then requires grep-and-replace across hundreds of files. → Do instead:** Always reference `var(--colors--primary-accent)` or the primitive `var(--_color---primary--webflow-blue)`. Every colour must trace back to a token.
2. **NEVER use Inter, Roboto, Arial, or system-ui as the primary font family → Why it fails: AI agents trained on generic UI patterns default to Inter or system fonts when the brand font name is unfamiliar. This produces text that renders in a fallback font, breaking visual consistency the moment WF Visual Sans loads. → Do instead:** Always declare `font-family: var(--_typography---fonts--primary-font)` which resolves to `"WF Visual Sans Variable", Arial, sans-serif`. The Arial fallback is intentional and correct.
3. **NEVER use arbitrary spacing values not in the token scale → Why it fails: AI agents fill gaps with round numbers like `20px`, `40px`, or `60px` that appear visually similar but break the fluid rhythm system. Sections built with fixed px margins collapse improperly on smaller viewports. → Do instead:** Use `var(--webflow-space-*)` for component-level spacing and `var(--_layout---spacing--margin-*)` or `var(--_layout---section-spacing--*)` for layout-level spacing. These are clamp()-based and fluid.
4. **NEVER apply border-radius > 8px to interactive button or input components → Why it fails: AI agents see the `cls_badge` pill radius (`1440px`) and incorrectly infer that Webflow uses pill-shaped CTAs. This produces rounded buttons that contradict the sharp, geometric brand language of the actual site. → Do instead:** Buttons use `var(--_components---button--border-radius)` (0.25rem = 4px). Cards use `var(--_components---card--border-radius)` (0.5rem = 8px). Only `cls_badge` eyebrow pills use `border-radius: 1440px`.
5. **NEVER omit focus-visible states → Why it fails: AI agents generate visually complete components but skip `:focus-visible` styles because they are invisible in static previews. This creates inaccessible components that fail WCAG 2.1 AA keyboard navigation requirements — particularly critical since Webflow suppresses default browser outlines via `outline: 0` on `.w-input:focus`. → Do instead:** Every interactive element must include `outline: 2px solid var(--colors--primary-accent); outline-offset: 2px` on `:focus-visible`. Use `[data-wf-focus-visible]` as a JS-polyfilled equivalent.
6. **NEVER use `--transition-duration-1` through `--transition-duration-7` for motion → Why it fails: These CSS variables are all set to `0ms` in the extracted stylesheet — they are Webflow editor internal overrides, not animation timing tokens. Using them produces instant, unanimated transitions that appear broken. → Do instead:** Use `var(--animation-duration-1)` (0.3s) for fast transitions and `var(--animation-duration-2)` (0.45s) for standard transitions.
7. **NEVER use secondary brand colours (pink #ed52cb, purple #7a3dff, yellow #ffae13) on interactive elements → Why it fails: AI agents see vivid brand colours in the palette and apply them to buttons, links, and focus states, creating interactions that look urgent or broken. These colours exist only as decorative tile backgrounds and illustration accents. → Do instead:** `var(--colors--primary-accent)` (#146ef5) is the only colour permitted on interactive controls. Secondary colours are assigned exclusively to decorative `background-color` within illustrative card tiles.
8. **NEVER construct Tailwind class names dynamically → Why it fails: Dynamic class construction like `` `bg-${colorToken}` `` prevents Tailwind's static analysis from detecting the class, so it is purged from the production bundle. The element renders with no background. → Do instead:** Use `bg-[var(--colors--primary-accent)]` with the full `var()` expression as an arbitrary value, or use inline `style={{ backgroundColor: 'var(--colors--primary-accent)' }}`.
9. **NEVER use `!important` to override design tokens → Why it fails: AI agents reach for `!important` when specificity conflicts arise, particularly with Webflow's `.w-*` base classes. This breaks the token cascade: a design token update no longer propagates because the `!important` declaration wins regardless of token value. → Do instead:** Resolve specificity by scoping to a component class (e.g. `.btn.primary { background-color: var(--colors--primary-accent) }`) or using a data attribute selector.
10. **NEVER use absolute positioning to establish primary layout structure → Why it fails: AI agents sometimes use `position: absolute` for card grids or hero layouts when flex/grid direction is ambiguous. This breaks at responsive breakpoints since absolute elements do not participate in document flow and cannot reflow when the viewport changes. → Do instead:** Use `display: flex; flex-direction: column` for card internals, CSS Grid for multi-column feature sections, and flex-row for nav elements. Reference computed display values from the layout digest.
11. **NEVER consolidate near-duplicate colour tokens into a single value without checking usage context → Why it fails: The extraction found 10 pairs of near-duplicate colours. Merging `#d8d8d8` (border) and `#d8d8d8` (bg-surface) appears safe, but one is used for interactive border transitions and the other for hover backgrounds — merging them makes it impossible to independently update one role. → Do instead:** Keep `--colors--border` and `--webflow-bg-surface` as separate tokens even if their current values are identical. Role is the differentiator, not the hex value.
---
## 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 (39) */
--colors--background: white;
--_color---neutral--black: #080808;
--colors--primary-accent: #146ef5;
--colors--text: #080808;
--colors--border: #d8d8d8;
--_color---secondary--purple: #7a3dff;
--_color---secondary--pink: #ed52cb;
--_color---neutral--white: white;
--_color---primary--webflow-blue: #146ef5;
--colors--secondary-background: #f0f0f0;
--_color---neutral--gray-700: #363636;
--_color---neutral--gray-400: #898989;
--colors--text-secondary: #5a5a5a;
--_color---neutral--gray-100: #f0f0f0;
--colors--primary-accent-text: color-mix(...);
--colors--primary-accent-background: color-mix(...);
--_color---neutral--gray-600: #5a5a5a;
--_color---neutral--gray-800: #222222;
--_color---neutral--gray-900: #171717;
--_color---neutral--gray-500: #757575;
--_color---neutral--gray-300: #ababab;
--_color---neutral--gray-200: #d8d8d8;
--_color---secondary--orange: #ff6b00;
--_color---secondary--green: #00d722;
--_color---primary--blue-600: #0055d4;
--_color---secondary--red: #ee1d36;
--_color---primary--blue-400: #3b89ff;
--_color---secondary--yellow: #ffae13;
--_color---blue-300: #006acc;
--brand-primary-cta: rgb(20, 110, 245); /* Primary CTA background, dominant on 12 buttons — e.g. "Auto (OS)" /* mined from computed styles */ */
--webflow-success: #00d722;
--webflow-warning: #ff6b00;
--webflow-error: #ee1d36;
--webflow-info: #146ef5;
--webflow-accent-warm: #ed52cb;
--webflow-accent-cool: #7a3dff;
--border-default: 1px solid var(--colors--border);
--border-focus: 1px solid rgb(56, 152, 236);
--border-error: 1px solid var(--webflow-error);
/* Typography (81) */
--_components---button--font: var(--_typography---fonts--primary-font);
--_components---button--font-size: 1rem;
--_typography---paragraph-body--line-height: 1.6;
--_components---input--font-weight: 400;
--_typography---caption--letter-spacing: 0em;
--_typography---h1--font-size: clamp(2.75rem, fluid, 5rem);
--_typography---h1--line-height: 1.04;
--_typography---h1--font-weight: 600;
--_components---button--letter-spacing: -0.01em;
--_typography---h2--font-size: clamp(2rem, fluid, 3.5rem);
--_typography---h3--font-size: clamp(1.75rem, fluid, 2.5rem);
--_typography---caption--line-height: 1.2;
--_typography---h4--font-size: clamp(1.375rem, fluid, 2rem);
--_typography---h5--font-size: clamp(1.25rem, fluid, 1.5rem);
--_typography---h5--line-height: 1.3;
--_typography---h6--font-size: clamp(1.125rem, fluid, 1.25rem);
--_typography---h6--line-height: 1.4;
--_components---button--line-height: 1.2em;
--_components---button--font-weight: 500;
--_size---0-5rem<deleted|variable-70a8c3ac-c656-f79e-479c-716ec38165c2>: .5rem;
--_components---input--line-height: 1.5em;
--_components---input-label--font-size: 0.9rem;
--_components---input-label--line-height: 1.4em;
--_typography---eyebrow--font-size: clamp(1rem, fluid, 1.25rem);
--_typography---paragraph-sm--font-size: 0.875rem;
--_typography---paragraph-lg--font-size: clamp(1.1rem, fluid, 1.25rem);
--_typography---paragraph-lg--line-height: 1.5;
--_typography---paragraph-xl--font-size: clamp(1.5rem, fluid, 2rem);
--_typography---type-paragraph-lg--font-size-md<deleted|variable-cdbe9950-9272-2284-ccf6-60cab96acd5f>: 1.25rem;
--_typography---type-paragraph-lg--font-size-sm<deleted|variable-841c9cf1-74b8-7850-db1d-b82cdc8d3013>: 1.1rem;
--_typography---subheading-xl--font-size: var(--_typography---h4--font-size);
--_size---0-25rem<deleted|variable-2d47388d-3251-c56b-03c9-35dfc0a59c39>: .25rem;
--_typography---paragraph-xs--font-size: 0.75rem;
--_size---5rem<deleted|variable-ff14b77f-fe78-09a6-d1f0-e9e7c84aae7c>: 5rem;
--_typography---caption--font-size: 0.8rem;
--_typography---caption--font-weight: 550;
--_typography---h0--font-size: clamp(3rem, fluid, 7rem);
--_typography---subheading-xxl--font-size: var(--_typography---h3--font-size);
--_typography---subheading-lg--font-size: var(--_typography---h5--font-size);
--_typography---subheading--font-size: var(--_typography---h6--font-size);
--_typography---subheading--letter-spacing: 0px;
--_components---image--float-size: max(-2vw,-3.5rem);
--_typography---fonts--primary-font: "WF Visual Sans Variable", Arial, sans-serif;
--transition-timing-inoutquad: cubic-bezier(0.455, 0.03, 0.515, 0.955);
--transition-timing-inoutcubic: cubic-bezier(0.645, 0.045, 0.355, 1);
--transition-timing-inoutquart: cubic-bezier(0.77, 0, 0.175, 1);
--font-size-xs: 12px; /* 115 elements — e.g. p "“@type”: “WebPageEle", p "“@type”: “ItemList”,", p "“@type”: “ListItem” " /* mined from computed styles */ */
--font-size-sm: 14px; /* 3 elements — e.g. p "Advanced collaborati", p "Own your site’s visi", p "Schedule a demo with" /* mined from computed styles */ */
--font-size-md: 16px; /* 49 elements — e.g. p "Bring team members a", p "Create and manage co", p "Turn every page into" /* mined from computed styles */ */
--font-size-lg: 20px; /* 14 elements — e.g. h2 "Product", h2 "Solutions", h2 "Resources" /* mined from computed styles */ */
--font-size-xl: 24px; /* 3 elements — e.g. h3 "Build", h3 "Manage", h3 "Optimize" /* mined from computed styles */ */
--font-size-2xl: 32px; /* 3 elements — e.g. p "AI has raised the st", div "AI has raised the st", div "AI has raised the st" /* mined from computed styles */ */
--font-size-3xl: 56px; /* 4 elements — e.g. h2 "Webflow is the agent", h2 "300,000+ brands move", h2 "From idea to impact," /* mined from computed styles */ */
--line-height-tight: 18px; /* 114 elements — e.g. p "“@type”: “WebPageEle", p "“@type”: “ItemList”,", p "“@type”: “ListItem” " /* mined from computed styles */ */
--line-height-normal: 25.6px; /* 47 elements — e.g. p "Bring team members a", p "Create and manage co", p "Turn every page into" /* mined from computed styles */ */
--line-height-loose: 28px; /* 13 elements — e.g. h2 "Product", h2 "Solutions", h2 "Resources" /* mined from computed styles */ */
--_typography---h0--line-height: 1.04;
--_typography---h0--font-weight: 600;
--_typography---h1--letter-spacing: -0.01em;
--_typography---h2--line-height: 1.04;
--_typography---h2--font-weight: 600;
--_typography---h3--line-height: 1.2;
--_typography---h3--font-weight: 600;
--_typography---h4--line-height: 1.2;
--_typography---h4--font-weight: 600;
--_typography---h5--font-weight: 600;
--_typography---h6--font-weight: 600;
--_typography---paragraph-body--font-size: 1rem;
--_typography---paragraph-body--font-weight: 400;
--_typography---paragraph-body--letter-spacing: 0em;
--_typography---paragraph-xl--line-height: 1.4;
--_typography---paragraph-xxl--font-size: clamp(2rem, fluid, 3.5rem);
--_typography---paragraph-xxl--line-height: 1.2;
--_typography---paragraph-sm--line-height: 1.6;
--_typography---paragraph-xs--line-height: 1.6;
--_typography---eyebrow--line-height: 1.4;
--_typography---eyebrow--font-weight: 500;
--_typography---subheading--line-height: 1.4;
--_typography---subheading--font-weight: 500;
--_components---input--font-size: 1rem;
--_components---input-label--font-weight: 500;
/* Spacing (35) */
--_layout---grid--gap-md: var(--_layout---spacing--margin-md);
--_typography---caption--bottom-margin: var(--_layout---spacing--margin-sm);
--_layout---grid--gap-xs: var(--_layout---spacing--margin-xs);
--_layout---section-spacing--small: clamp(3rem, fluid, 5rem);
--_layout---spacing--margin-xl: clamp(2.25rem, fluid, 3rem);
--_layout---spacing--margin-md: clamp(1.25rem, fluid, 1.5rem);
--_layout---section-spacing--medium: clamp(3rem, fluid, 9rem);
--_components---nav--height: 4.25rem;
--_layout---spacing--margin-sm: clamp(0.625rem, fluid, 1rem);
--_layout---section-spacing--extra-large: clamp(10rem, fluid, 28rem);
--_layout---grid--gap-main: var(--_layout---spacing--margin-lg);
--_layout---grid--gap-lg: var(--_layout---spacing--margin-xl);
--_layout---grid--gap-xl: clamp(2.5rem, fluid, 5rem);
--_components---button--vertical-padding: 1em;
--_components---button--horizontal-padding: 1.5em;
--_layout---spacing--margin-lg: clamp(1.75rem, fluid, 2rem);
--_components---card--padding: clamp(1rem, fluid, 1.5rem);
--_components---input--bottom-margin: var(--_layout---grid--gap-md);
--_layout---spacing--margin-xs: clamp(0.375rem, fluid, 0.5rem);
--_layout---section-spacing--large: clamp(3rem, fluid, 15rem);
--space-xs: 4px; /* 2 elements — e.g. nav .nav-dropdown_content, nav .nav-dropdown_content /* mined from computed styles */ */
--space-sm: 8px; /* 62 elements — e.g. nav .nav-setting_dropdown-content, nav .nav-setting_dropdown-content, nav .nav-setting_dropdown-content /* mined from computed styles */ */
--space-md: 12px; /* 8 elements — e.g. div .col, div .col, div .col /* mined from computed styles */ */
--space-lg: 16px; /* 87 elements — e.g. div .container, div .container, div .container /* mined from computed styles */ */
--space-xl: 24px; /* 20 elements — e.g. div .card-body, div .card-body, div .card-body /* mined from computed styles */ */
--space-2xl: 32px; /* 29 elements — e.g. footer .section, div .logo_grid-logos, div .logo_grid-logos /* mined from computed styles */ */
--space-3xl: 80px; /* 25 elements — e.g. section .section, section .section, section .section /* mined from computed styles */ */
--webflow-space-xs: 4px;
--webflow-space-sm: 8px;
--webflow-space-md: 12px;
--webflow-space-lg: 16px;
--webflow-space-xl: 24px;
--webflow-space-2xl: 32px;
--webflow-space-3xl: 80px;
--_layout---grid--gap-sm: var(--_layout---spacing--margin-sm);
/* Radius (11) */
--_components---button--border-radius: 0.25rem;
--_components---card--border-radius: 0.5rem;
--radius-sm: 0px 2px 2px 0px; /* 1 element — e.g. div .mm-button /* mined from computed styles */ */
--radius-md: 4px; /* 15 elements — e.g. div .nav-setting_dropdown-btn "Marketer", div .nav-setting_dropdown-btn "Marketer", div .nav-setting_dropdown-btn "Marketer" /* mined from computed styles */ */
--radius-lg: 6px; /* 1 element — e.g. input .one-tap-input /* mined from computed styles */ */
--radius-full: 8px; /* 7 elements — e.g. a .nav-skip-link "Skip to Main Content", div .card "Platform OverviewExp", div .card "Webflow AIElevate we" /* mined from computed styles */ */
--_components---input--border-radius: 0.25rem;
--webflow-radius-sm: 0px 2px 2px 0px;
--webflow-radius-md: 4px;
--webflow-radius-lg: 6px;
--webflow-radius-full: 8px;
/* Effects (11) */
--_layout---container--max-width: calc(var(--_layout---fluid--max)*1rem);
--_layout---fluid--max: 90;
--_layout---fluid--min: 20;
--transition-duration-1: 0ms;
--animation-delay-d1: 0.3s;
--animation-delay-d2: 0.45s;
--animation-delay-d3: 0.75s;
--animation-delay-d4: 1.2s;
--animation-delay-d0: 0s;
--animation-delay-d5: 1.95s;
--shadow-avatar: rgba(0, 0, 0, 0) 0px 105px 30px 0px,
rgba(0, 0, 0, 0.02) 0px 67px 27px 0px,
rgba(0, 0, 0, 0.06) 0px 38px 23px 0px,
rgba(0, 0, 0, 0.1) 0px 17px 17px 0px,
rgba(0, 0, 0, 0.12) 0px 4px 9px 0px;
/* Motion (11) */
----motion-spin: @keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}; /* @keyframes spin */
----motion-fadein: @keyframes fadein {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes fadein */
----motion-marquee_1_timeline: @keyframes marquee_1_timeline {
0% { transform: translateX(0%); }
100% { transform: translateX(-50%); }
}; /* @keyframes marquee_1_timeline */
----motion-moveGradientRight: @keyframes moveGradientRight {
0% { background-position: 0% 20%; }
50% { background-position: 15% 0%; }
100% { background-position: 0% 20%; }
}; /* @keyframes moveGradientRight */
----motion-moveGradientLeft: @keyframes moveGradientLeft {
0% { background-position: 0% 20%; }
50% { background-position: 15% 0%; }
100% { background-position: 0% 20%; }
}; /* @keyframes moveGradientLeft */
----motion-scale: @keyframes scale {
0% { opacity: 0; transform: scale(1.015) translateZ(0px); }
100% { opacity: 1; transform: scale(1) translateZ(0px); }
}; /* @keyframes scale */
----motion-fade: @keyframes fade {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes fade */
----motion-noise-animation: @keyframes noise-animation {
0% { transform: translate(0px, 0px); }
10% { t… <0.5KB elided>; /* @keyframes noise-animation */
--duration-fast: 0.3s; /* 94 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-base: 0.45s; /* 6 elements — e.g. div, div, div /* mined from computed styles */ */
--ease-default: ease; /* 234 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```
tokenSource: extracted-css-vars
confidence: high
cssVarsFound: 217
curatedTokens: 38 (mapped to standard roles with --webflow-* prefix aliases)
extractionSite: webflow.com
```
**Source type:** CSS custom properties extracted directly from the live webflow.com site. These are **authoritative production values**, not design tool exports or reverse-engineered computed styles. Token names are preserved exactly as defined in the site's CSS.
**Naming convention:** Webflow uses a double-dash triple-segment naming pattern for primitives (`--_color---neutral--gray-200`) and a double-dash double-segment pattern for semantic aliases (`--colors--background`). Component tokens use the `--_components---[component]--[property]` pattern.
**Curated alias layer:** The `--webflow-*` prefixed tokens are synthesised aliases created for this layout.md to provide human-readable semantic names. In production code, prefer the original CSS variable names (`--colors--primary-accent`, `--_typography---fonts--primary-font`, etc.) for 1:1 fidelity with the Webflow stylesheet.
**Fluid type system:** Typography and spacing use a fluid clamp() system scoped between `--_layout---fluid--min: 20` (20rem / 320px) and `--_layout---fluid--max: 90` (90rem / 1440px). All heading and section spacing values interpolate linearly between these breakpoints — no hard breakpoint jumps.
**Near-duplicate colours flagged:** 10 pairs of near-identical colour values detected in extraction. These have been preserved as separate tokens per their semantic role (e.g. `--colors--border` and `--webflow-bg-surface` both resolve to `#d8d8d8` but serve different component roles).
**Deleted/internal variables:** Several tokens with `<deleted|variable-*>` suffixes appear in the extraction — these are Webflow Editor internal variables that have been deprecated. They are documented in Appendix A for completeness but should not be used in new code.
**Libraries detected:** Tailwind and Bootstrap class names appear in the HTML class attribute strings, but the site's primary styling is token-based CSS custom properties. Do not assume Tailwind utility classes are the canonical styling method — use `var()` token references.More from the gallery
Browse all kits →You may also like

Xero
MITClean, modern SaaS design system built on navy and mint green with sharp corners and purposeful typography for accounting and business software
00
saasfintechlightminimal

Netflix
MITDark, bold streaming platform design system with signature red accent and cinematic motion, built for large-scale video content discovery and subscription flows
00
darkboldecommlanding-page

Klarna
MITClean, modern fintech interface with Klarna's signature pink accents and dark eggplant typography, designed for seamless payment and shopping experiences
00
lightboldfintechecomm