Airtable
MIT
Clean, professional SaaS design system built on a structured token foundation with Neue Haas Grotesk typography, subtle shadows and a blue-dominant colour palette suited to productivity and enterprise tools
Colour (81)
color.themetext#333840
color.themeborder#040e20b0
color.focusringbluergba(7, 104, 248, 0.5) 0px 0px 0px 3px
color.focusringdarkrgba(0, 0, 0, 0.5) 0px 0px 0px 3px
color.themeinfotext#254fad
color.themetextweak#040e20b0
color.focusringwhitergba(255, 255, 255, 0.5) 0px 0px 0px 3px
color.primitivewhite#ffffff
color.brandprimaryctargba(1, 20, 53, 0.12)
color.gradientbadgebglinear-gradient(91.6deg, rgb(245, 98, 12) -3.95%, rgb(252, 71, 119) 14.34%, rgb(232, 72, 192) 28.2%, rgb(155, 103, 240) 52.43%, rgb(69, 143, 255) 68.27%, rgb(10, 178, 250) 86.46%, rgb(13, 189, 180) 101.9%)
color.themebackground#fff
color.themeborderweak#0114351f
color.themeinfoborder#458fff
color.themetextstrong#181d26
color.themeupselltext#181d26
color.primitiveblue500#458fff
color.primitiveblue600#254fad
color.primitiveblue700#1b61c9
color.primitivegray100#e0e2e6
color.primitivegray300#9297a0
color.primitivegray600#41454d
color.primitivegray800#333840
color.primitivegray900#181d26
color.primitiveinkweakrgba(4, 14, 32, 0.69)
color.primitivenavy900#1a3866
color.themesuccesstext#006400
color.primitivegreen400#39bf45
color.primitivegreen700#006400
color.primitiveinkghost#0114351f
color.themeupsellborder#9297a0
color.primitivenearwhite#f8fafc
color.themebackgroundz20#fff
color.themesuccessborder#39bf45
color.themebackgroundweak#fff
color.themeupselltextweak#41454d
color.themebackgroundmedium#f8fafc
color.themebackgroundstrong#e0e2e6
color.themeupselltextstrong#333840
color.themeanchorlinkprimary#1b61c9
color.themebuttontextprimary#fff
color.themebuttontextsecondary#181d26
color.themebuttontextspotlight#f9fcfff7
color.themespotlightbackgroundradial-gradient(100% 107.48% at 0% 50%,#fcab7966 0%,#fc9ab44d 17.27%,#fa91e040 38.25%,#c6a9f533 50.79%,#95befc1f 68.23%,#79cef20d 85.42%,#76d6d100 100%),linear-gradient(0deg,#fff,#fff)
color.themespotlighttextstrong#fff
color.themeanchorlinkprimaryfocus#1b61c9
color.themeanchorlinkprimaryhover#1b61c9cc
color.themebuttontextprimaryfocus#fff
color.themebuttontextprimaryhover#fff
Spacing (10)
spacing.spacexs8px
spacing.spacesm12px
spacing.spacemd16px
spacing.spacelg32px
spacing.spacexl40px
spacing.space2xl48px
spacing.mainnavheight79px
spacing.motionbaymaxmodule82ptnwspacey@keyframes baymax-module__82pTNW__spacey {
0% { transform: translate(0px)
spacing.space3xl120.98px
spacing.mainnavwidth702px
Radius (6)
radiussm2.5px
radiusfocus6px
radiusmd10px
radiusbutton12px
radiuslg16px
radiusfull50%
Shadow (25)
effect.navshadowrgba(15, 48, 106, 0.05) 0px 0px 20px 0px
effect.themebuttonthemelight
effect.themebuttonshadowprimary0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #2d7ff947, /* Blue-tinted lift */
inset 0px 0px 0px .5px #0000000f
effect.themebuttonshadowsecondary0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #0114351f
effect.themebuttonshadowspotlight0px 0px 1px 0px #00000052,
0px 0px 2px 0px #00000014,
0px 1px 3px 0px #2d7ff947
effect.themebuttonfilterprimaryhovernone
effect.themebuttonshadowprimaryfocus0px 0px 0px 2px #0768f880, /* Blue focus ring */
0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #2d7ff947,
inset 0px 0px 0px .5px #0000000f,
inset 0 0 0 1px #fff
effect.themebuttonshadowprimaryhover0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a, /* Stronger blue lift on hover */
inset 0px 0px 0px .5px #0000001f
effect.themebuttonshadowprimaryactive0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a,
inset 0px 0px 0px .5px #0000001f
effect.themebuttonfiltersecondaryhoverblur(6px)
effect.themebuttonshadowprimaryloading0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a,
inset 0px 0px 0px .5px #0000001f
effect.themebuttonshadowsecondaryfocus0px 0px 0px 2px #0768f880,
0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #0000001f,
inset 0 0 0 1px #020d206e
effect.themebuttonshadowsecondaryhover0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #458fff
effect.themebuttonshadowspotlighthover0px 0px 1px 0px #00000052,0px 0px 2px 0px #00000014,0px 1px 3px 0px #2d7ff947
effect.themebuttonshadowprimarydisabledinset 0 0 0 1px #9297a0
effect.themebuttonshadowsecondaryactive0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #0000001f,
inset 0 0 0 1px #000e263b
effect.themebuttonshadowsecondaryloading0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #0114351f
effect.themebuttonshadowsecondarydisabledinset 0 0 0 1px #9297a0
effect.themebuttonshadowspotlightdisabledinset 0px 0px 0px .5px #0000000f,
0px 0px 1px 0px #00000052,
0px 0px 2px 0px #00000014,
0px 1px 3px 0px #2d7ff947
effect.motionbaymaxmodule82ptnwopacitypulse@keyframes baymax-module__82pTNW__opacityPulse {
0% { opacity: 1
effect.motionbaymaxmodule82ptnwopacityfadein@keyframes baymax-module__82pTNW__opacityFadeIn {
0% { opacity: 0
effect.motionbaymaxmodule82ptnwopacityfadeout@keyframes baymax-module__82pTNW__opacityFadeOut {
0% { opacity: 1
effect.motionindexmodulescssmodulelyoopgopacityfadein@keyframes index-module-scss-module__LYoopG__opacityFadeIn {
0% { transform: translateY(100%)
effect.motionindexmodulescssmodulelyoopgopacityfadeout@keyframes index-module-scss-module__LYoopG__opacityFadeOut {
0% { transform: translateY(0px)
effect.motionbkaddtocalendarlinkmodulescssmodulewgr3ewtoopacity@keyframes BkAddToCalendarLink-module-scss-module__wgr3EW__ToOpacity {
0% { opacity: 0
# layout.md — Airtable Design System
---
## 0. Quick Reference
**Stack:** Next.js · CSS Modules · Custom CSS vars · Token source: `extracted-css-vars` (104 properties, high confidence)
**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 ── */
:root {
/* Backgrounds */
--theme_background: #fff;
--theme_background-medium: #f8fafc; /* App-level page background */
--theme_background-strong: #e0e2e6; /* Disabled state surfaces */
/* Text */
--theme_text: #333840; /* Default body text */
--theme_text-strong: #181d26; /* Headings, high-emphasis text */
--theme_text-weak: #040e20b0; /* Secondary / muted text */
/* Primary Button */
--theme_button-background-primary: #1b61c9;
--theme_button-text-primary: #fff;
--theme_button-shadow-primary: 0px 0px 1px #00000052, 0px 0px 2px #00000014, 0px 1px 3px #2d7ff947, inset 0px 0px 0px .5px #0000000f;
/* Borders & Focus */
--theme_upsell-border: #9297a0;
--theme_border-weak: #0114351f;
--theme_button-background-primary-focus: #254fad;
/* Spacing */
--space-xs: 8px; --space-sm: 12px; --space-md: 16px;
--space-lg: 32px; --space-xl: 40px; --space-2xl: 48px;
/* Radius */
--radius-sm: 2.5px; --radius-md: 10px; --radius-lg: 16px; --radius-full: 50%;
/* Motion */
--duration-fast: 0.15s; --duration-base: 0.2s; --ease-default: ease;
/* Typography */
--font-size-xs: 14px; --font-size-sm: 16px; --font-size-md: 18px;
--font-size-lg: 20px; --font-size-xl: 24px; --font-size-2xl: 32px; --font-size-3xl: 40px;
--font-weight-regular: 400; --font-weight-medium: 500; --font-weight-semibold: 900;
}
```
```tsx
// Primary Button — all states
<button
className="btn-primary"
style={{
background: 'var(--theme_button-background-primary)',
color: 'var(--theme_button-text-primary)',
boxShadow: 'var(--theme_button-shadow-primary)',
borderRadius: 'var(--radius-md)',
padding: '16px 24px',
fontSize: 'var(--font-size-sm)',
fontWeight: 'var(--font-weight-medium)',
transition: `background var(--duration-base) var(--ease-default)`,
}}
>
Get started
</button>
```
**NEVER rules:**
- NEVER use a font other than `Haas` (Neue Haas Grotesk) or `Haas Groot Disp`; never default to Inter, Roboto, or Arial in primary UI
- NEVER hardcode hex values — always reference `var(--theme_*)` tokens
- NEVER use spacing values not on the 8px grid (`--space-xs` through `--space-2xl`)
- NEVER apply `border-radius` > `--radius-lg` (16px) on content cards — pill shape (50%) is reserved for avatar/icon circles
- NEVER render a button without all six states: default, hover, focus, active, disabled, loading
- NEVER omit `backdrop-filter: blur(6px)` on secondary and spotlight button backgrounds
**Full design system → see layout.md**
---
<!-- Quick Reference truncated to fit the 75-line cap. See later sections for the full design system. -->
## 1. Design Direction & Philosophy
**Character:** Clean, professional, and quietly confident. Airtable's marketing site communicates enterprise-grade capability while remaining approachable — structured but not rigid, expressive but never loud.
**Mood:** Calm authority. The palette is predominantly white and near-white with a single strong blue action colour (`#1b61c9`). Personality arrives through the "spotlight" rainbow gradient system (used sparingly on badges and CTA variants), not through loud colour blocking.
**Typographic personality:** Neue Haas Grotesk (family alias `Haas`) is the single typeface. Its rounded, humanist grotesque forms soften the enterprise positioning. `Haas Groot Disp` (the display cut) appears at modal/hero scale. Weight contrast — mostly `400` with selective `500` for UI labels — creates hierarchy without needing size extremes.
**What this design explicitly rejects:**
- Warm or vibrant background colours — surfaces stay `#fff` or `#f8fafc`
- Heavy drop shadows or deep elevation — shadows are subtle, inset-weighted
- Rounded "bubbly" card corners beyond `16px` — corners are purposefully restrained
- Solid fills on secondary buttons — they use frosted-glass `rgba` backgrounds with `backdrop-filter: blur(6px)`
- Generic system fonts appearing anywhere in primary UI
- Dense information layouts — whitespace rhythm is generous, sections breathe
**Gradient system:** The "spotlight" gradient (`linear-gradient(91.6deg, #f5620c → #fc4777 → #e848c0 → #9b67f0 → #458fff → #0ab2fa → #0dbdb4)`) signals premium/AI features. It appears on badges, the spotlight button variant, and section accent backgrounds. Use it only for deliberate feature-highlight moments.
---
## 2. Colour System
### Tier 1 — Primitives
```css
/* ── Primitive Colour Values ── */
:root {
--primitive-white: #ffffff; /* Pure white */
--primitive-near-white: #f8fafc; /* Off-white, page background */
--primitive-gray-100: #e0e2e6; /* Light gray, disabled surfaces */
--primitive-gray-300: #9297a0; /* Mid gray, borders and muted UI */
--primitive-gray-600: #41454d; /* Medium dark, disabled text */
--primitive-gray-800: #333840; /* Default body text */
--primitive-gray-900: #181d26; /* Strong text, near-black */
--primitive-navy-900: #1a3866; /* Active/pressed primary */
--primitive-blue-600: #254fad; /* Focus ring, info text */
--primitive-blue-700: #1b61c9; /* Primary action blue */
--primitive-blue-500: #458fff; /* Info border, secondary hover border */
--primitive-green-700: #006400; /* Success text */
--primitive-green-400: #39bf45; /* Success border */
--primitive-ink-weak: rgba(4, 14, 32, 0.69); /* Muted overlaid text */
--primitive-ink-ghost: #0114351f; /* Ghost borders */
}
```
### Tier 2 — Semantic Aliases
```css
/* ── Semantic Colour Tokens ── */
:root {
/* Surfaces */
--theme_background: #fff; /* Primary page surface */
--theme_background-weak: #fff; /* Weak page surface (same as base) */
--theme_background-medium: #f8fafc; /* App shell, alternate rows */
--theme_background-strong: #e0e2e6; /* Disabled states, strong dividers */
--theme_background-z20: #fff; /* Elevated surface (modal, nav) */
/* Text */
--theme_text: #333840; /* Default body text */
--theme_text-strong: #181d26; /* High-emphasis: headings, labels */
--theme_text-weak: #040e20b0; /* Secondary text, captions */
--theme_upsell-text: #181d26; /* Upsell component headline text */
--theme_upsell-text-weak: #41454d; /* Upsell component secondary text */
--theme_upsell-text-strong: #333840; /* Upsell component body text */
--theme_spotlight-text-strong: #fff; /* Text on spotlight/gradient backgrounds */
/* Borders */
--theme_border: #040e20b0; /* Default border on light bg */
--theme_border-weak: #0114351f; /* Subtle borders, dividers */
--theme_upsell-border: #9297a0; /* Upsell card borders */
--theme_info-border: #458fff; /* Info state border, secondary hover */
--theme_success-border: #39bf45; /* Success state border */
/* Status */
--theme_success-text: #006400; /* Success message text */
--theme_info-text: #254fad; /* Info message text */
/* Links */
--theme_anchor-link-primary: #1b61c9; /* Default link colour */
--theme_anchor-link-primary-hover: #1b61c9cc; /* Link hover (80% opacity) */
--theme_anchor-link-primary-active: #1a3866; /* Link active/pressed */
--theme_anchor-link-primary-focus: #1b61c9; /* Link focus (same as default) */
--theme_anchor-link-primary-disabled: #000e263b; /* Disabled link */
/* Spotlight / Gradient Backgrounds */
--theme_spotlight-background: radial-gradient(100% 107.48% at 0% 50%, #fcab7966 0%, #fc9ab44d 17.27%, #fa91e040 38.25%, #c6a9f533 50.79%, #95befc1f 68.23%, #79cef20d 85.42%, #76d6d100 100%), linear-gradient(0deg, #fff, #fff); /* Hero left-aligned spotlight bg */
--theme_spotlight-background-weak: radial-gradient(50% 28.4% at 50% 0%, #fcab7966 0%, #fc9ab44d 17.27%, #fa91e040 38.25%, #c6a9f533 50.79%, #95befc1f 68.23%, #79cef20d 85.42%, #76d6d100 100%), linear-gradient(0deg, #fff, #fff); /* Centered weak spotlight bg */
--theme_spotlight-background-medium: radial-gradient(49.66% 53.37% at 50.34% 50%, #76d6d100 0%, #79cef21a 18.75%, #95befc33 36.46%, #c6a9f540 55.21%, #fa91e040 73.44%, #fc9ab44d 88.02%, #fcab7966 100%), linear-gradient(0deg, #fff, #fff); /* Centered medium spotlight bg */
--theme_spotlight-background-strong: linear-gradient(91.6deg, #f5620c -3.95%, #fc4777 14.34%, #e848c0 28.2%, #9b67f0 52.43%, #458fff 68.27%, #0ab2fa 86.46%, #0dbdb4 101.9%); /* Full rainbow gradient — badges, spotlight buttons, premium accents */
}
```
### Tier 3 — Component Tokens
```css
/* ── Primary Button Colours ── */
:root {
--theme_button-background-primary: #1b61c9;
--theme_button-background-primary-hover: linear-gradient(0deg, #00000040, #00000040), #254fad;
--theme_button-background-primary-active: #1a3866;
--theme_button-background-primary-focus: #254fad;
--theme_button-background-primary-loading: #1a3866;
--theme_button-background-primary-disabled: #e0e2e6;
--theme_button-text-primary: #fff;
--theme_button-text-primary-hover: #fff;
--theme_button-text-primary-active: #fff;
--theme_button-text-primary-focus: #fff;
--theme_button-text-primary-loading: #fff;
--theme_button-text-primary-disabled: #41454d;
/* ── Secondary Button Colours ── */
--theme_button-background-secondary: #ffffff3d; /* Frosted glass — pair with blur(6px) */
--theme_button-background-secondary-hover: #0d52ac14;
--theme_button-background-secondary-active: #ffffffa6;
--theme_button-background-secondary-focus: #ffffffa6;
--theme_button-background-secondary-loading: #ffffffa6;
--theme_button-background-secondary-disabled: #e0e2e6;
--theme_button-text-secondary: #181d26;
--theme_button-text-secondary-hover: #254fad;
--theme_button-text-secondary-active: #070c14d1;
--theme_button-text-secondary-focus: #040e20b0;
--theme_button-text-secondary-loading: #040e20b0;
--theme_button-text-secondary-disabled: #040e20b0;
/* ── Spotlight Button Colours ── */
--theme_button-background-spotlight: linear-gradient(81deg, #ff00a8 0%, #7c37ef 100%), #1b61c9;
--theme_button-background-spotlight-hover: linear-gradient(80deg, #ff00a8 0%, #7c37ef 52.45%), #1b61c9;
--theme_button-background-spotlight-active: linear-gradient(81deg, #ff00a8 0%, #7c37ef 100%), #1b61c9;
--theme_button-background-spotlight-focus: linear-gradient(81deg, #ff00a8 0%, #7c37ef 100%), #1b61c9;
--theme_button-background-spotlight-loading: linear-gradient(81deg, #ff00a8 0%, #7c37ef 100%), #1b61c9;
--theme_button-background-spotlight-disabled: #1b61c9;
--theme_button-text-spotlight: #f9fcfff7;
--theme_button-text-spotlight-hover: #fff;
--theme_button-text-spotlight-active: #fff;
--theme_button-text-spotlight-focus: #fff;
--theme_button-text-spotlight-loading: #fff;
--theme_button-text-spotlight-disabled: #fff;
}
```
### Colour Role Summary
| Role | Token | Value |
|---|---|---|
| **Page background** | `--theme_background-medium` | `#f8fafc` |
| **Surface** | `--theme_background` | `#ffffff` |
| **Primary action** | `--theme_button-background-primary` | `#1b61c9` |
| **Body text** | `--theme_text` | `#333840` |
| **Heading text** | `--theme_text-strong` | `#181d26` |
| **Muted text** | `--theme_text-weak` | `#040e20b0` |
| **Default border** | `--theme_border-weak` | `#0114351f` |
| **Focus ring blue** | `--theme_button-background-primary-focus` | `#254fad` |
| **Success** | `--theme_success-text` | `#006400` |
| **Info** | `--theme_info-text` | `#254fad` |
| **Premium gradient** | `--theme_spotlight-background-strong` | `linear-gradient(91.6deg, …)` |
---
## 3. Typography System
**Primary typeface:** `Haas` (Neue Haas Grotesk Text Round) — served from `static.airtable.com`
**Display typeface:** `Haas Groot Disp` (Neue Haas Grotesk Display) — used at modal and hero scale
**Fallback stack:** `-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif`
**System fallback declared:** `haasGrot Fallback` → `local("Arial")` (for CLS management only — never use Arial directly)
```css
/* ── Font Stack Declarations ── */
:root {
--font-family-text: 'Haas', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
--font-family-display: 'Haas Groot Disp', 'Haas', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
}
/* ── Weight Scale ── */
:root {
--font-weight-regular: 400; /* Body, headings (Airtable uses 400 for h1–h3) */
--font-weight-medium: 500; /* UI labels, button text, toggles */
--font-weight-semibold: 900; /* Black/display weight — single use on display callouts */
}
/* ── Size Scale (extracted) ── */
:root {
--font-size-xs: 14px; /* Body text, captions, h2 in context (note: h2 is small on this site) */
--font-size-sm: 16px; /* Button labels, body paragraphs, modal text */
--font-size-md: 18px; /* Resource card body copy */
--font-size-lg: 20px; /* Default card text, nav items, toggles — most common size (181 elements) */
--font-size-xl: 24px; /* Sub-section headings (h3), feature callouts */
--font-size-2xl: 32px; /* Section headings */
--font-size-3xl: 40px; /* Hero h1, hero body pull-quotes */
}
/* ── Line Height Scale ── */
:root {
--line-height-tight: 18.9px; /* 14px text at ~135% — captions, compact labels */
--line-height-normal: 25px; /* 20px text at 125% — nav, cards, body */
--line-height-loose: 26px; /* 16px text at ~163% — most common, spans and links */
}
```
### Composite Typography Groups
```css
/* ── Composite: Hero H1 ── */
/* font: 400 40px/48px Haas; letter-spacing: normal; color: var(--theme_text-strong); margin-bottom: 32px; text-align: center */
/* ── Composite: Section Heading (H2 on this site is semantically small) ── */
/* font: 400 14px/18.9px Haas; letter-spacing: 0.16px; color: rgba(4,14,32,1); text-align: center */
/* NOTE: h2 is used for eyebrow/label text at 14px. Section display headings use h2 at 24px–32px in practice. */
/* ── Composite: Feature Heading (H3) ── */
/* font: 400 24px/32.4px Haas; letter-spacing: 0.12px; color: var(--theme_spotlight-text-strong) [white on dark bg] */
/* ── Composite: Body / Default ── */
/* font: 400 14px/17.5px Haas; letter-spacing: normal; color: rgba(7,12,20,0.82) */
/* ── Composite: Card Body ── */
/* font: 400 20px/25px Haas; letter-spacing: normal; color: rgba(7,12,20,0.82) */
/* ── Composite: Button Label ── */
/* font: 500 16px/21.6px Haas; letter-spacing: 0.08px; display: flex; align-items: center; justify-content: center */
/* ── Composite: Badge / Eyebrow ── */
/* font: 600 14px/21px Haas; letter-spacing: 0.28px; text-transform: none; padding: 4px 12px */
/* ── Composite: Toggle / Accordion ── */
/* font: 500 20px/18px Haas; letter-spacing: 0.2px; text-align: left */
/* ── Composite: Display (Modal / Alert context using Haas Groot Disp) ── */
/* font: 400 20px/30px 'Haas Groot Disp', Haas; letter-spacing: normal */
```
### Typography Table
| Role | Family | Size | Weight | Line-height | Letter-spacing |
|---|---|---|---|---|---|
| **Hero H1** | Haas | 40px | 400 | 48px | normal |
| **Eyebrow label (H2)** | Haas | 14px | 400 | 18.9px | 0.16px |
| **Feature heading (H3)** | Haas | 24px | 400 | 32.4px | 0.12px |
| **Section heading** | Haas | 32px | 400 | — | — |
| **Body default** | Haas | 14px | 400 | 17.5px | normal |
| **Card body** | Haas | 20px | 400 | 25px | normal |
| **Button label** | Haas | 16px | 500 | 21.6px | 0.08px |
| **Badge/chip** | Haas | 14px | 600 | 21px | 0.28px |
| **Toggle** | Haas | 20px | 500 | 18px | 0.2px |
| **Modal / Display** | Haas Groot Disp | 16–20px | 400 | normal–30px | normal |
**Pairing rule:** Use `Haas Groot Disp` only for display moments (modals, hero callouts). Never mix display and text cuts within the same text block.
---
## 4. Spacing & Layout
```css
/* ── Spacing Scale ── */
:root {
--space-xs: 8px; /* Tight internal padding, icon gaps */
--space-sm: 12px; /* Input padding, compact list items */
--space-md: 16px; /* Standard internal padding, section sub-gaps */
--space-lg: 32px; /* Card gaps, section-internal margins (e.g. h1 margin-bottom) */
--space-xl: 40px; /* Between-section spacing, generous card padding */
--space-2xl: 48px; /* Major section breaks */
--space-3xl: 120.98px; /* Hero/section outer vertical rhythm (NOTE: off-grid — use only where extracted exactly) */
}
/* ── Base Grid Unit ── */
/* Base unit: 8px. All spacing MUST be a multiple of 8px except --space-xs (which IS 8px). */
/* --space-3xl (120.98px) is extracted verbatim — do not round in place of it; it is used for a specific section height. */
/* ── Navigation Layout ── */
:root {
--mainNavWidth: 702px; /* Max-width of main nav link group */
--mainNavHeight: 79px; /* Fixed nav bar height */
}
/* ── Border Radius Scale ── */
:root {
--radius-sm: 2.5px; /* Cookie banner / micro UI elements */
--radius-md: 10px; /* Promo cards, CTAs (e.g. .PromoCard links) */
--radius-lg: 16px; /* Content cards, section grids, resource cards */
--radius-full: 50%; /* Avatar circles, close/drawer buttons — NEVER on rectangular content */
/* Note: button_primary computed shows borderRadius: 12px — use closest token --radius-md (10px) or adopt 12px as --radius-button */
--radius-button: 12px; /* Extracted from button_primary computed style — button-specific token */
--radius-focus: 6px; /* Skip link, brand wrap, BkLink focus — internal focus-visible radius */
}
```
### Breakpoint Scale
| Breakpoint | px | Notes |
|---|---|---|
| xs | 400px | Smallest mobile |
| sm | 530px | Mid mobile |
| md | 768px | Standard tablet |
| lg | 1024px | Desktop starts |
| xl | 1184px | Wide desktop |
| 2xl | 1344px | Large desktop |
| 3xl | 1440px | Full-width / cinema |
| max | 1664px | Largest tracked |
*The full extracted set (400, 425, 426, 530, 550, 600, 642, 720, 768, 832, 834, 896, 904, 1024, 1080, 1100, 1184, 1344, 1350, 1408, 1440, 1600, 1664) reflects granular component-level breakpoints, not a uniform scale. Use the table above for structural layout decisions.*
### Grid & Flex Decision Rules
- **Navigation:** `display: grid` — use for the top nav shell that must align brand, links, and CTAs in defined columns
- **Buttons:** `display: flex; flex-direction: row; justify-content: center; align-items: center` — always for button internals
- **Cards (content grids):** `display: grid; gap: var(--space-lg)` — extracted gap of `32px` from `cls_card`
- **Card body:** `display: block` — cards are block-level containers, not flex
- **Modal / Alert:** `display: block` — these are document-flow elements, not flex containers
---
## 5. Page Structure & Layout Patterns
*No page screenshots provided. All section ordering and layout values are inferred from the Layout Digest, component inventory, and computed styles. Rows marked "(inferred)" are not visually confirmed.*
### 5.1 Section Map
| # | Section | Layout Type | Approx Height | Key Elements |
|---|---|---|---|---|
| 1 | **Navigation** | `display: grid` | 79px (`--mainNavHeight`) | Brand logo, nav links (702px wide), CTA buttons (primary + secondary), mobile drawer toggle |
| 2 | **Hero** | Block, full-width | ~480–600px (inferred) | H1 at 40px/400, spotlight radial gradient background, primary CTA button, optional secondary CTA |
| 3 | **Social proof / Logo bar** | Flex row, contained | ~120px (inferred) | H2 eyebrow "Trusted by 500,000+" at 14px, animated logo columns |
| 4 | **Feature / Card grid** | `display: grid; gap: 32px` | ~600–800px (inferred) | 2–3 column card grid, card `border-radius: 16px`, card bg `#f0f6ff` |
| 5 | **AI / Spotlight feature section** | Block, full-width spotlight bg | ~480px (inferred) | Spotlight gradient bg, H3 headings (24px, white), feature list |
| 6 | **Resource cards (editorial)** | Grid, `border-radius: 16px` | ~400px (inferred) | Resource card with `border-radius: 16px`, 18px body, image + title + CTA |
| 7 | **Pricing / CTA section** | Block, contained | ~320px (inferred) | Primary CTA button, section heading at 32px |
| 8 | **Footer** | Grid, full-width | ~280px (inferred) | Nav links, legal, social icons |
### 5.2 Layout Patterns
**Navigation:**
- `display: grid` shell with `padding: 0`
- Navigation width cap: `--mainNavWidth: 702px` for the link group
- Fixed height: `--mainNavHeight: 79px`
- Box shadow: `rgba(15, 48, 106, 0.05) 0px 0px 20px 0px` — extremely subtle lift
- Drawer toggle for mobile; nested `DrawerNested` panels for sub-menus
- Hover/focus bg on nav items: `rgba(15, 48, 106, 0.05)` (the brand "hover wash")
**Hero:**
- Full-width background using `--theme_spotlight-background` (radial gradient from left at 0%)
- H1 centred, `text-align: center`, `margin-bottom: var(--space-lg)` (32px)
- CTA row: `display: flex; gap: var(--space-sm)` (inferred) — primary blue + secondary frosted-glass
- Primary CTA: `--theme_button-background-primary: #1b61c9`, `border-radius: 12px`, `padding: 16px 24px`
**Card grid:**
- `display: grid; gap: var(--space-lg)` (32px — extracted from `cls_card`)
- Cards: `border-radius: var(--radius-lg)` (16px), `background: #f0f6ff` (card computed bg)
- Card text: 20px / `--font-weight-regular`, `text-align: start`
**Resource cards:**
- `border-radius: var(--radius-lg)` (16px)
- Body text: 18px (`--font-size-md`)
- Promo link CTAs use `border-radius: var(--radius-md)` (10px)
- Hover state: `opacity: 0.75` on promo links
### 5.3 Visual Hierarchy
**Primary CTA:** `--theme_button-background-primary: #1b61c9` — the single highest-contrast interactive element on any white surface. Always the first CTA in hero and section endings.
**Secondary CTA:** Frosted glass (`#ffffff3d` + `backdrop-filter: blur(6px)`) — visually subordinate to primary; relies on the border shadow `inset 0 0 0 1px #0114351f` for definition.
**Spotlight / Badge CTA:** Rainbow gradient `--theme_spotlight-background-strong` — reserved for AI / premium moments. Never used for generic actions.
**Image positions:** Cards carry visual assets (inferred from 119 card instances); images are within card containers at `border-radius: 16px`.
**Whitespace rhythm:** `--space-lg` (32px) is the dominant inter-element gap. Section breaks use `--space-2xl` (48px) to `--space-3xl` (120.98px).
### 5.4 Content Patterns
**Eyebrow → Heading → Body → CTA:** The canonical content block. Eyebrow label at 14px/0.16px letter-spacing (H2 used as label), feature heading at 24–32px, body at 16–20px, CTA button.
**Chip/badge system:** Gradient badges (`border-radius: 999px`, `padding: 4px 12px`) appear before headings to flag new features ("NEW", "AI", "BETA"). Always `margin-right: 8px` when inline.
**Feature toggle (accordion):** Heading at 20px/500 weight, `text-align: left`, background `rgba(1, 20, 53, 0.12)` when active. Used to expand product feature details without navigation.
**Logo column animation:** Logos enter with `translateY(50%) → translateY(0)` fade-in, staggered per column.
---
## 6. Component Patterns
### 6.1 Primary Button
**Anatomy:** `<button>` or `<a>` → optional loading icon + text label
**Token-to-property mapping:**
| State | Background | Text | Box-shadow | Filter |
|---|---|---|---|---|
| default | `--theme_button-background-primary` (#1b61c9) | `--theme_button-text-primary` (#fff) | `--theme_button-shadow-primary` | `none` |
| hover | `--theme_button-background-primary-hover` (gradient+#254fad) | `#fff` | `--theme_button-shadow-primary-hover` | `none` |
| focus | `--theme_button-background-primary-focus` (#254fad) | `#fff` | `--theme_button-shadow-primary-focus` | `none` |
| active | `--theme_button-background-primary-active` (#1a3866) | `#fff` | `--theme_button-shadow-primary-active` | `none` |
| disabled | `--theme_button-background-primary-disabled` (#e0e2e6) | `--theme_button-text-primary-disabled` (#41454d) | `--theme_button-shadow-primary-disabled` (inset 1px #9297a0) | `none` |
| loading | `--theme_button-background-primary-loading` (#1a3866) | `#fff` | `--theme_button-shadow-primary-loading` | `none` |
```tsx
import React from 'react';
type ButtonVariant = 'primary' | 'secondary' | 'spotlight';
type ButtonState = 'default' | 'loading' | 'disabled';
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: ButtonVariant;
isLoading?: boolean;
children: React.ReactNode;
}
const buttonStyles: Record<ButtonVariant, React.CSSProperties> = {
primary: {
background: 'var(--theme_button-background-primary)',
color: 'var(--theme_button-text-primary)',
boxShadow: 'var(--theme_button-shadow-primary)',
backdropFilter: 'none',
},
secondary: {
background: 'var(--theme_button-background-secondary)',
color: 'var(--theme_button-text-secondary)',
boxShadow: 'var(--theme_button-shadow-secondary)',
backdropFilter: 'blur(6px)',
},
spotlight: {
background: 'var(--theme_button-background-spotlight)',
color: 'var(--theme_button-text-spotlight)',
boxShadow: 'var(--theme_button-shadow-spotlight)',
backdropFilter: 'blur(6px)',
},
};
export function Button({
variant = 'primary',
isLoading = false,
disabled = false,
children,
...props
}: ButtonProps) {
const isDisabled = disabled || isLoading;
const baseStyle: React.CSSProperties = {
display: 'flex',
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
gap: 'var(--space-xs)', /* 8px icon-label gap */
padding: '16px 24px',
borderRadius: 'var(--radius-button)', /* 12px */
border: '1px solid transparent',
fontSize: 'var(--font-size-sm)', /* 16px */
fontWeight: 'var(--font-weight-medium)', /* 500 */
lineHeight: '21.6px',
letterSpacing: '0.08px',
fontFamily: 'var(--font-family-text)',
cursor: isDisabled ? 'not-allowed' : 'pointer',
transition: `background var(--duration-base) var(--ease-default), box-shadow var(--duration-base) var(--ease-default)`,
// Disabled overrides
...(isDisabled && variant === 'primary' && {
background: 'var(--theme_button-background-primary-disabled)',
color: 'var(--theme_button-text-primary-disabled)',
boxShadow: 'var(--theme_button-shadow-primary-disabled)',
}),
...(isDisabled && variant === 'secondary' && {
background: 'var(--theme_button-background-secondary-disabled)',
color: 'var(--theme_button-text-secondary-disabled)',
boxShadow: 'var(--theme_button-shadow-secondary-disabled)',
backdropFilter: 'none',
}),
...(!isDisabled && buttonStyles[variant]),
};
return (
<button
{...props}
disabled={isDisabled}
aria-busy={isLoading}
style={baseStyle}
// CSS hover/focus/active states MUST be handled via a stylesheet
// using --theme_button-background-primary-hover etc.
// Inline styles cannot express :hover — use a .btn-primary CSS class
>
{isLoading ? (
<>
<LoadingDots />
<span style={{ opacity: 0.7 }}>{children}</span>
</>
) : children}
</button>
);
}
// Minimal loading indicator matching Airtable's blink animation
function LoadingDots() {
return (
<span
aria-hidden="true"
style={{
display: 'inline-flex',
gap: '3px',
alignItems: 'center',
}}
>
{[0, 1, 2].map((i) => (
<span
key={i}
style={{
width: 4,
height: 4,
borderRadius: 'var(--radius-full)',
background: 'currentColor',
opacity: 0.2,
animation: `blink 1.4s var(--ease-default) ${i * 0.2}s infinite`,
}}
/>
))}
</span>
);
}
```
```css
/* Required companion stylesheet for :hover/:focus/:active states */
.btn-primary {
background: var(--theme_button-background-primary);
color: var(--theme_button-text-primary);
box-shadow: var(--theme_button-shadow-primary);
transition: background var(--duration-base) var(--ease-default),
box-shadow var(--duration-base) var(--ease-default);
}
.btn-primary:hover {
background: var(--theme_button-background-primary-hover);
box-shadow: var(--theme_button-shadow-primary-hover);
}
.btn-primary:focus {
background: var(--theme_button-background-primary-focus);
box-shadow: var(--theme_button-shadow-primary-focus);
outline: none;
}
.btn-primary:active {
background: var(--theme_button-background-primary-active);
box-shadow: var(--theme_button-shadow-primary-active);
}
.btn-primary:disabled,
.btn-primary[data-disabled="true"] {
background: var(--theme_button-background-primary-disabled);
color: var(--theme_button-text-primary-disabled);
box-shadow: var(--theme_button-shadow-primary-disabled);
cursor: not-allowed;
}
```
---
### 6.2 Secondary Button
**Anatomy:** `<button>` → text label. Background is frosted glass; `backdrop-filter: blur(6px)` is **required** — it is a CSS filter applied from `--theme_button-filter-secondary: blur(6px)`.
| State | Background | Text | Box-shadow | Backdrop-filter |
|---|---|---|---|---|
| default | `#ffffff3d` | `#181d26` | `--theme_button-shadow-secondary` | `blur(6px)` |
| hover | `#0d52ac14` | `#254fad` | `--theme_button-shadow-secondary-hover` (inset border → `#458fff`) | `blur(6px)` |
| focus | `#ffffffa6` | `#040e20b0` | `--theme_button-shadow-secondary-focus` | `none` |
| active | `#ffffffa6` | `#070c14d1` | `--theme_button-shadow-secondary-active` | `none` |
| disabled | `#e0e2e6` | `#040e20b0` | `inset 0 0 0 1px #9297a0` | `none` |
| loading | `#ffffffa6` | `#040e20b0` | `--theme_button-shadow-secondary-loading` | `none` |
---
### 6.3 Spotlight Button
**Anatomy:** `<button>` → text label. Rainbow gradient background; reserved for AI/premium feature CTAs.
| State | Background |
|---|---|
| default | `linear-gradient(81deg, #ff00a8 0%, #7c37ef 100%), #1b61c9` |
| hover | `linear-gradient(80deg, #ff00a8 0%, #7c37ef 52.45%), #1b61c9` |
| active/focus | Same as default |
| disabled | `#1b61c9` (gradient removed, flat blue) |
---
### 6.4 Navigation
**Anatomy:** `<nav role="navigation">` → brand logo + `<ul>` link group (702px) + CTA button group → mobile: drawer toggle button
```css
[role="navigation"] {
display: grid;
background: var(--theme_background); /* #fff */
box-shadow: rgba(15, 48, 106, 0.05) 0px 0px 20px 0px;
height: var(--mainNavHeight); /* 79px */
transition: var(--duration-fast) var(--ease-default); /* 0.15s ease */
}
.nav-link {
font-size: var(--font-size-lg); /* 20px */
font-weight: var(--font-weight-regular);
line-height: var(--line-height-normal); /* 25px */
color: var(--theme_text-strong);
padding: var(--space-xs) var(--space-md); /* 8px 16px — from link computed */
transition: var(--duration-fast) var(--ease-default);
}
.nav-link:hover,
.nav-link:focus {
background-color: rgba(15, 48, 106, 0.05); /* Brand hover wash */
}
.nav-link:focus-visible {
outline: 2px solid rgba(4, 14, 32, 0.69);
outline-offset: 2px;
}
.dropdown-item:hover,
.dropdown-item:focus {
color: rgb(7, 104, 248); /* Vivid blue on nav dropdown items */
}
```
---
### 6.5 Card
**Anatomy:** `<div>` → optional image → heading (h3, 24px) → body text (20px) → optional CTA link
```css
.card {
display: block;
background-color: #f0f6ff; /* Computed card background — light blue tint */
border-radius: var(--radius-lg); /* 16px */
font-size: var(--font-size-lg); /* 20px */
font-weight: var(--font-weight-regular);
line-height: var(--line-height-normal); /* 25px */
color: rgba(7, 12, 20, 0.82);
transition: all var(--duration-fast) var(--ease-default);
}
/* Card grid container */
.card-grid {
display: grid;
gap: var(--space-lg); /* 32px — extracted from cls_card */
}
```
| State | Treatment |
|---|---|
| default | `background: #f0f6ff`, `border-radius: 16px` |
| hover | No extracted override — infer subtle lift (add `box-shadow` at component level if needed) |
| focus | Not applicable to card container — apply to interactive children |
| disabled | Not applicable |
---
### 6.6 Badge / Eyebrow Chip
**Anatomy:** `<span>` or `<div>` → text label
```tsx
function Badge({ children }: { children: React.ReactNode }) {
return (
<span
style={{
display: 'inline-block',
backgroundImage: 'var(--theme_spotlight-background-strong)',
/* linear-gradient(91.6deg, #f5620c -3.95%, #fc4777 14.34%, ...) */
color: '#ffffff',
fontSize: 'var(--font-size-xs)', /* 14px */
fontWeight: 600,
lineHeight: '21px',
letterSpacing: '0.28px',
borderRadius: '999px', /* pill shape */
padding: '4px 12px', /* space-xs / space-sm */
marginRight: 'var(--space-xs)', /* 8px — extracted margin */
fontFamily: 'var(--font-family-text)',
}}
>
{children}
</span>
);
}
```
| State | Treatment |
|---|---|
| default | Rainbow gradient background, white text, `border-radius: 999px` |
| hover | Not interactive — no hover state |
| `.chip` active | `background: var(--theme_background-strong)`, `color: var(--theme_text-strong)` |
| `.chip` hover/focus | `background: var(--theme_background-medium)` (`#f8fafc`) |
---
### 6.7 Link (BkLink)
**Anatomy:** `<a>` → text
| State | Color | Decoration | Other |
|---|---|---|---|
| default | `var(--theme_text-strong)` (#181d26) | underline | — |
| hover / active | underline | — | — |
| hover (`.blue`) | `rgb(6, 95, 229)` | — | — |
| active (`.blue`) | `rgb(5, 80, 190)` | — | — |
| focus | `box-shadow: rgba(0,0,0,0.5) 0 0 0 3px`, `border-radius: 6px`, `outline: none` | — | — |
| focus (`.blue`) | `color: rgb(6,95,229)`, `box-shadow: rgba(7,104,248,0.5) 0 0 0 3px` | — | — |
| focus (`.white`) | `box-shadow: rgba(255,255,255,0.5) 0 0 0 3px` | — | — |
| disabled | `color: #000e263b` | none | `cursor: not-allowed` |
---
## 7. Elevation & Depth
```css
/* ── Shadow Tokens ── */
:root {
/* Primary Button Shadows — layered inset + drop */
--theme_button-shadow-primary: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #2d7ff947, /* Blue-tinted lift */
inset 0px 0px 0px .5px #0000000f; /* Subtle inner border */
--theme_button-shadow-primary-hover: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a, /* Stronger blue lift on hover */
inset 0px 0px 0px .5px #0000001f;
--theme_button-shadow-primary-active: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a,
inset 0px 0px 0px .5px #0000001f; /* Same as hover */
--theme_button-shadow-primary-focus: 0px 0px 0px 2px #0768f880, /* Blue focus ring */
0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #2d7ff947,
inset 0px 0px 0px .5px #0000000f,
inset 0 0 0 1px #fff; /* White inner ring for contrast */
--theme_button-shadow-primary-loading: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a,
inset 0px 0px 0px .5px #0000001f;
--theme_button-shadow-primary-disabled: inset 0 0 0 1px #9297a0; /* Gray inset border only */
/* Secondary Button Shadows — border-simulating inset shadow system */
--theme_button-shadow-secondary: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #0114351f; /* Ghost border */
--theme_button-shadow-secondary-hover: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #458fff; /* Blue border on hover */
--theme_button-shadow-secondary-active: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #0000001f,
inset 0 0 0 1px #000e263b;
--theme_button-shadow-secondary-focus: 0px 0px 0px 2px #0768f880,
0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #0000001f,
inset 0 0 0 1px #020d206e;
--theme_button-shadow-secondary-loading: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #0114351f;
--theme_button-shadow-secondary-disabled: inset 0 0 0 1px #9297a0;
/* Spotlight Button Shadows */
--theme_button-shadow-spotlight: 0px 0px 1px 0px #00000052,
0px 0px 2px 0px #00000014,
0px 1px 3px 0px #2d7ff947;
--theme_button-shadow-spotlight-disabled: inset 0px 0px 0px .5px #0000000f,
0px 0px 1px 0px #00000052,
0px 0px 2px 0px #00000014,
0px 1px 3px 0px #2d7ff947;
/* Navigation */
--nav-shadow: rgba(15, 48, 106, 0.05) 0px 0px 20px 0px; /* Very soft nav lift */
/* Focus ring (links, skip links) */
--focus-ring-dark: rgba(0, 0, 0, 0.5) 0px 0px 0px 3px;
--focus-ring-blue: rgba(7, 104, 248, 0.5) 0px 0px 0px 3px;
--focus-ring-white: rgba(255, 255, 255, 0.5) 0px 0px 0px 3px;
}
```
### Z-Index Scale (inferred — no explicit z-index tokens extracted)
| Layer | Value | Usage |
|---|---|---|
| Base content | 0 | Page body, cards |
| Sticky nav | 100 | `[role="navigation"]` |
| Drawers / Dropdowns | 200 | Nav drawers |
| Modals | 300 | Modal overlays |
| Skip link | 9999 | Accessibility skip nav |
### Elevation Principles
- **Airtable uses inset box-shadows as borders** — not CSS `border` properties. The secondary button's border is `inset 0 0 0 1px #0114351f`. This is intentional to avoid layout reflow on state changes.
- **Blue-tinted lift:** The `#2d7ff947` value in primary button shadows adds a subtle blue warmth to the drop shadow, reinforcing the brand blue.
- **No hard drop shadows** — all elevation values are soft, multi-layer, with low opacity. Never use a single `0px 4px 8px rgba(0,0,0,0.2)` shadow.
---
## 8. Motion
```css
/* ── Motion Tokens ── */
:root {
--duration-fast: 0.15s; /* Navigation transitions, role_button, nav items */
--duration-base: 0.2s; /* Button transitions */
--duration-heading: 0.25s; /* H1, H2, H3 transitions (extracted from computed) */
--ease-default: ease; /* Default easing — used on 191 elements */
}
/* ── Named Keyframes in Use ── */
/* Fade in/out — general purpose */
@keyframes opacityFadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes opacityFadeOut {
0% { opacity: 1; }
100% { opacity: 0; }
}
/* Fade up — dropdowns, tooltips entering from below */
@keyframes fadeUpIn {
0% { opacity: 0; transform: translateY(-4px); }
100% { opacity: 1; transform: translate(0px); }
}
/* Bounce in — app-internal UI confirmations */
@keyframes bounceIn {
0% { opacity: 0.9; transform: scale3d(0.98, 0.98, 0.98); animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1); }
70% { opacity: 1; transform: scale3d(1.03, 1.03, 1.03); }
100% { transform: scale(1); }
}
/* Logo column entrance */
@keyframes comingIn {
0% { opacity: 0; transform: translateY(50%); }
100% { opacity: 1; transform: translateY(0px); }
}
/* Loading blink — dots loading indicator */
@keyframes blink {
0% { opacity: 0.2; }
20% { opacity: 1; }
100% { opacity: 0.2; }
}
/* Animated button background slide (spotlight/CTA hover) */
@keyframes animatedBackground {
0% { background-position-x: -100px; }
100% { background-position-x: 0px; }
}
/* Aura button rotation — gradient angle animation */
@keyframes auraButtonRotation {
0% { --gradient-angle: 0deg; }
100% { --gradient-angle: 360deg; }
}
/* Progress bar */
@keyframes progress {
0% { width: 0%; }
100% { width: 100%; }
}
/* Spin/scale for loading icon */
@keyframes spinScale {
0% { transform: rotate(0deg) scale(1); }
50% { transform: rotate(360deg) scale(0.9); }
100% { transform: rotate(720deg) scale(1); }
}
/* Fade in/out crossfade (roofline banner cycling) */
@keyframes fadeInOut {
0% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 0; }
}
```
### Motion Rules
- **Transitions:** Use `var(--duration-fast) var(--ease-default)` (0.15s ease) for navigation items and interactive UI. Use `var(--duration-base) var(--ease-default)` (0.2s ease) for button state changes.
- **Heading transitions:** H1/H2/H3 elements have `transition: 0.25s ease-in` — use `ease-in` specifically for text that fades into view.
- **Entrance animations:** Prefer `opacityFadeIn` (simple) or `fadeUpIn` (with 4px Y offset) for UI entering the viewport.
- **Loading state:** Use `blink` keyframes on 3 dots at `1.4s` duration with `0.2s` per-dot stagger.
- **NEVER animate layout properties** (width, height, margin, padding) — animate `transform` and `opacity` only for performance.
- **Reduced motion:** All animations must respect `@media (prefers-reduced-motion: reduce)` — wrap keyframe animations in a `not (prefers-reduced-motion: reduce)` query.
---
## 9. Anti-Patterns & Constraints
1. **NEVER hardcode hex colours in component code.**
→ **Why it fails:** AI agents default to writing `color: #1b61c9` directly in JSX styles or Tailwind classes when they see a primary blue in the context. This creates orphaned values that don't update when the theme changes and defeats the entire CSS variable system.
→ **What to do instead:** Always write `color: 'var(--theme_button-background-primary)'` or `bg-[var(--theme_button-background-primary)]`. The only exception is gradient values that are themselves assigned to a `--theme_*` variable.
2. **NEVER use a font family other than `Haas` or `Haas Groot Disp` in primary UI.**
→ **Why it fails:** When Airtable's font files fail to load or aren't referenced, AI agents fill in `Inter`, `Roboto`, or `Arial` as the primary font rather than using the declared fallback stack. The fallback `haasGrot Fallback → local("Arial")` exists specifically for CLS management — it must not be surfaced as a design choice.
→ **What to do instead:** Always use `font-family: var(--font-family-text)` or `var(--font-family-display)`. The full fallback stack is baked into those variables.
3. **NEVER construct Tailwind classes dynamically from variables.**
→ **Why it fails:** `className={\`text-[var(--font-size-${size})\`}` generates a class string Tailwind cannot purge and cannot match at compile time. The JIT engine sees an unresolvable template and produces nothing.
→ **What to do instead:** Use CSS-in-JS `style={{ fontSize: 'var(--font-size-lg)' }}` or pre-define static class variants (`.text-lg { font-size: var(--font-size-lg) }`).
4. **NEVER omit `backdrop-filter: blur(6px)` on secondary and spotlight buttons.**
→ **Why it fails:** The secondary button background is `#ffffff3d` (24% opacity white). Without the blur filter, it renders as an almost-invisible near-transparent rectangle with no legible boundary, especially over dark or gradient section backgrounds. The AI sees the hex value and outputs the background but misses the filter entirely because it's in a separate `--theme_button-filter-secondary` token.
→ **What to do instead:** Always pair `background: var(--theme_button-background-secondary)` with `backdrop-filter: var(--theme_button-filter-secondary)` (blur(6px)). Remove the filter in active/focus/loading states as the extracted rules do.
5. **NEVER use `border-radius` > `--radius-lg` (16px) on content cards.**
→ **Why it fails:** AI agents associate "modern SaaS" with large 24px–32px border radii and default to them when not explicitly constrained. Airtable's extracted radius scale tops out at 16px for cards and 12px for buttons. `--radius-full: 50%` is strictly for circular elements (avatar containers, close buttons).
→ **What to do instead:** Use `var(--radius-lg)` (16px) for cards, `var(--radius-button)` (12px) for buttons, `var(--radius-md)` (10px) for promo link elements.
6. **NEVER render interactive states using only inline styles.**
→ **Why it fails:** React inline styles cannot express `:hover`, `:focus`, `:active`, or `:disabled` pseudo-classes. An AI agent writing all button styles as `style={{}}` will produce a button that looks correct at rest but has zero visual feedback on interaction — a critical accessibility failure.
→ **What to do instead:** Define a CSS class (`.btn-primary`) with all pseudo-class states. Use inline styles only for dynamic values that change at runtime (e.g., computed widths). All state-based visual changes live in CSS.
7. **NEVER use arbitrary spacing values outside the `--space-*` scale.**
→ **Why it fails:** Airtable's extraction flagged 3 off-grid values (79px, 120.98px, 702px) — these are structural constants (`--mainNavHeight`, `--space-3xl`, `--mainNavWidth`), not general-purpose spacing values. An AI agent seeing these in the token list may interpret them as usable spacing and apply `padding: 79px` to a card.
→ **What to do instead:** Use only `--space-xs` through `--space-2xl` for general spacing. Use `--mainNavHeight`, `--mainNavWidth`, and `--space-3xl` only in their specific structural contexts.
8. **NEVER mix `Haas` (text cut) and `Haas Groot Disp` (display cut) within the same text block.**
→ **Why it fails:** The display cut has different optical sizing and spacing characteristics than the text cut. AI agents may concatenate font stacks or apply `Haas Groot Disp` to body paragraphs because it appears earlier in the `@font-face` declarations.
→ **What to do instead:** `Haas Groot Disp` is for headings at modal/hero scale only (extracted from `modal` and `alert` element computed styles). All body text, UI labels, nav items, and buttons use `Haas`.
9. **NEVER simulate borders with CSS `border` on buttons — use `box-shadow: inset`.**
→ **Why it fails:** Airtable's entire button border system uses `inset 0 0 0 1px [color]` inside `box-shadow` rather than `border`. If an agent adds `border: 1px solid var(--theme_border-weak)`, it changes the box model, shifts layout by 1–2px per side, and creates a separate paint layer that conflicts with the shadow system.
→ **What to do instead:** Replicate the border effect using the inset shadow pattern: `box-shadow: ..., inset 0 0 0 1px var(--theme_border-weak)`. Match the exact extracted shadow token for each state.
10. **NEVER apply the spotlight/rainbow gradient to non-premium UI elements.**
→ **Why it fails:** The `--theme_spotlight-background-strong` gradient is Airtable's visual signal for AI and premium features. Agents trained on "colourful = engaging" heuristics may apply it to generic CTA buttons, cards, or section backgrounds. Overuse dilutes the premium signal entirely.
→ **What to do instead:** Use `--theme_spotlight-background-
## 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 (81) */
--theme_button-text-primary-hover: #fff;
--theme_background-medium: #f8fafc;
--theme_button-background-primary-disabled: #e0e2e6;
--theme_success-text: #006400;
--theme_button-background-primary-focus: #254fad;
--theme_upsell-text-strong: #333840;
--theme_button-text-secondary-focus: #040e20b0;
--theme_button-text-secondary: #181d26;
--theme_button-text-primary-disabled: #41454d;
--theme_info-border: #458fff;
--theme_success-border: #39bf45;
--theme_upsell-border: #9297a0;
--theme_border-weak: #0114351f;
--theme_spotlight-background: radial-gradient(100% 107.48% at 0% 50%,#fcab7966 0%,#fc9ab44d 17.27%,#fa91e040 38.25%,#c6a9f533 50.79%,#95befc1f 68.23%,#79cef20d 85.42%,#76d6d100 100%),linear-gradient(0deg,#fff,#fff);
--theme_spotlight-background-weak: radial-gradient(50% 28.4% at 50% 0%,#fcab7966 0%,#fc9ab44d 17.27%,#fa91e040 38.25%,#c6a9f533 50.79%,#95befc1f 68.23%,#79cef20d 85.42%,#76d6d100 100%),linear-gradient(0deg,#fff,#fff);
--theme_spotlight-background-medium: radial-gradient(49.66% 53.37% at 50.34% 50%,#76d6d100 0%,#79cef21a 18.75%,#95befc33 36.46%,#c6a9f540 55.21%,#fa91e040 73.44%,#fc9ab44d 88.02%,#fcab7966 100%),linear-gradient(0deg,#fff,#fff);
--theme_spotlight-background-strong: linear-gradient(91.6deg,#f5620c -3.95%,#fc4777 14.34%,#e848c0 28.2%,#9b67f0 52.43%,#458fff 68.27%,#0ab2fa 86.46%,#0dbdb4 101.9%);
--theme_button-background-primary: #1b61c9;
--theme_button-background-primary-hover: linear-gradient(0deg,#00000040,#00000040),#254fad;
--theme_button-background-primary-active: #1a3866;
--theme_button-background-secondary: #ffffff3d;
--theme_button-background-secondary-hover: #0d52ac14;
--theme_button-background-secondary-active: #ffffffa6;
--theme_button-text-secondary-active: #070c14d1;
--theme_button-background-spotlight-active: linear-gradient(81deg,#ff00a8 0%,#7c37ef 100%),#1b61c9;
--theme_button-background-spotlight-hover: linear-gradient(80deg,#ff00a8 0%,#7c37ef 52.45%),#1b61c9;
--theme_button-text-spotlight: #f9fcfff7;
--theme_anchor-link-primary-hover: #1b61c9cc;
--theme_anchor-link-primary-disabled: #000e263b;
----gradient-badge-bg: linear-gradient(91.6deg, rgb(245, 98, 12) -3.95%, rgb(252, 71, 119) 14.34%, rgb(… <0.2KB elided>; /* Gradient from badge background /* reconstructed */ */
--brand-primary-cta: rgba(1, 20, 53, 0.12); /* Primary CTA background, dominant on 1 button — e.g. "span" /* mined from computed styles */ */
--theme_background: #fff;
--theme_background-strong: #e0e2e6;
--theme_text: #333840;
--theme_text-strong: #181d26;
--theme_text-weak: #040e20b0;
--theme_button-text-primary: #fff;
--primitive-white: #ffffff;
--primitive-near-white: #f8fafc;
--primitive-gray-100: #e0e2e6;
--primitive-gray-300: #9297a0;
--primitive-gray-600: #41454d;
--primitive-gray-800: #333840;
--primitive-gray-900: #181d26;
--primitive-navy-900: #1a3866;
--primitive-blue-600: #254fad;
--primitive-blue-700: #1b61c9;
--primitive-blue-500: #458fff;
--primitive-green-700: #006400;
--primitive-green-400: #39bf45;
--primitive-ink-weak: rgba(4, 14, 32, 0.69);
--primitive-ink-ghost: #0114351f;
--theme_background-weak: #fff;
--theme_background-z20: #fff;
--theme_upsell-text: #181d26;
--theme_upsell-text-weak: #41454d;
--theme_spotlight-text-strong: #fff;
--theme_border: #040e20b0;
--theme_info-text: #254fad;
--theme_anchor-link-primary: #1b61c9;
--theme_anchor-link-primary-active: #1a3866;
--theme_anchor-link-primary-focus: #1b61c9;
--theme_button-background-primary-loading: #1a3866;
--theme_button-text-primary-active: #fff;
--theme_button-text-primary-focus: #fff;
--theme_button-text-primary-loading: #fff;
--theme_button-background-secondary-focus: #ffffffa6;
--theme_button-background-secondary-loading: #ffffffa6;
--theme_button-background-secondary-disabled: #e0e2e6;
--theme_button-text-secondary-hover: #254fad;
--theme_button-text-secondary-loading: #040e20b0;
--theme_button-text-secondary-disabled: #040e20b0;
--theme_button-background-spotlight-disabled: #1b61c9;
--theme_button-text-spotlight-hover: #fff;
--theme_button-text-spotlight-active: #fff;
--theme_button-text-spotlight-focus: #fff;
--theme_button-text-spotlight-loading: #fff;
--theme_button-text-spotlight-disabled: #fff;
--focus-ring-dark: rgba(0, 0, 0, 0.5) 0px 0px 0px 3px;
--focus-ring-blue: rgba(7, 104, 248, 0.5) 0px 0px 0px 3px;
--focus-ring-white: rgba(255, 255, 255, 0.5) 0px 0px 0px 3px;
/* Typography (37) */
--theme_button-shadow-primary: 0px 0px 1px #00000052,0px 0px 2px #00000014,0px 1px 3px #2d7ff947,inset 0px 0px 0px .5px #0000000f;
--theme_button-shadow-primary-hover: 0px 0px 1px #00000052,0px 0px 3px #0000001c,0px 1px 4px #2d7ff97a,inset 0px 0px 0px .5px #0000001f;
--theme_button-shadow-primary-focus: 0px 0px 0px 2px #0768f880,0px 0px 1px #00000052,0px 0px 2px #00000014,0px 1px 3px #2d7ff947,inset 0px 0px 0px .5px #0000000f,inset 0 0 0 1px #fff;
--theme_button-shadow-secondary: 0px 0px 1px #00000052,0px 0px 2px #00000014,0px 1px 3px #00000014,inset 0 0 0 1px #0114351f;
--theme_button-shadow-secondary-hover: 0px 0px 1px #00000052,0px 0px 2px #00000014,0px 1px 3px #00000014,inset 0 0 0 1px #458fff;
--theme_button-shadow-secondary-active: 0px 0px 1px #00000052,0px 0px 3px #0000001c,0px 1px 4px #0000001f,inset 0 0 0 1px #000e263b;
--theme_button-shadow-secondary-focus: 0px 0px 0px 2px #0768f880,0px 0px 1px #00000052,0px 0px 3px #0000001c,0px 1px 4px #0000001f,inset 0 0 0 1px #020d206e;
--theme_button-shadow-spotlight-hover: 0px 0px 1px 0px #00000052,0px 0px 2px 0px #00000014,0px 1px 3px 0px #2d7ff947;
--theme_button-shadow-spotlight-disabled: 0px 0px 0px .5px #0000000f inset,0px 0px 1px 0px #00000052,0px 0px 2px 0px #00000014,0px 1px 3px 0px #2d7ff947;
--font-size-xs: 14px; /* 37 elements — e.g. h2 "Trusted by 500,000 l", p "Bring your Airtable ", p "HyperDB with record " /* mined from computed styles */ */
--font-size-sm: 16px; /* 31 elements — e.g. p "Build AI-powered wor", p "Streamline your team", p "Embed intelligence i" /* mined from computed styles */ */
--font-size-md: 18px; /* 3 elements — e.g. p "Builders & Breakthro", p "The 2026 AI guide fo", p "In action: Airtable " /* mined from computed styles */ */
--font-size-lg: 20px; /* 181 elements — e.g. p "Scalable infrastruct", p "Flexible administrat", p "Security and complia" /* mined from computed styles */ */
--font-size-xl: 24px; /* 7 elements — e.g. h2 "Don’t just ask AI. D", h2 "Say hello to Omni", h2 "The power of AI with" /* mined from computed styles */ */
--font-size-2xl: 32px; /* 8 elements — e.g. h2 "Sophisticated workfl", h2 "The path to 10x ever", h2 "Start building with " /* mined from computed styles */ */
--font-size-3xl: 40px; /* 3 elements — e.g. h1 "All your teams, all ", p "All your teams, all ", p "“Airtable makes it e" /* mined from computed styles */ */
--font-weight-regular: 400; /* 114 elements — e.g. h1 "All your teams, all ", h2 "Trusted by 500,000 l", h2 "Sophisticated workfl" /* mined from computed styles */ */
--font-weight-medium: 500; /* 158 elements — e.g. p "Read this brief and ", p "Gather intel on all ", p "What are customers s" /* mined from computed styles */ */
--font-weight-semibold: 900; /* 1 element — e.g. div "Sophisticated workfl" /* mined from computed styles */ */
--line-height-tight: 18.9px; /* 31 elements — e.g. h2 "Trusted by 500,000 l", p "HyperDB with record ", p "Scale workflows to t" /* mined from computed styles */ */
--line-height-normal: 25px; /* 52 elements — e.g. a "Airtable home or vie", li "Platform & ProductsA", li "Airtable PlatformUnl" /* mined from computed styles */ */
--line-height-loose: 26px; /* 110 elements — e.g. span ".salesforce_svg__st1", a "Airtable PlatformUnl", a "AI App BuildingNEWEn" /* mined from computed styles */ */
--font-size-xs: 14px;
--font-size-sm: 16px;
--font-size-md: 18px;
--font-size-lg: 20px;
--font-size-xl: 24px;
--font-size-2xl: 32px;
--font-size-3xl: 40px;
--font-weight-regular: 400;
--font-weight-medium: 500;
--font-weight-semibold: 900;
--font-family-text: 'Haas', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
--font-family-display: 'Haas Groot Disp', 'Haas', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
--line-height-tight: 18.9px;
--line-height-normal: 25px;
--line-height-loose: 26px;
/* Spacing (16) */
--mainNavWidth: 702px;
--mainNavHeight: 79px;
--space-xs: 8px; /* 27 elements — e.g. button .DrawerGoBack-module_backArrow__1SuVU, button .DrawerGoBack-module_backArrow__1SuVU, button .DrawerGoBack-module_backArrow__1SuVU /* mined from computed styles */ */
--space-sm: 12px; /* 24 elements — e.g. button .DrawerGoBack-module_backArrow__1SuVU, button .DrawerGoBack-module_backArrow__1SuVU, div .BkEyebrow-module_bkEyebrow__PSCUD /* mined from computed styles */ */
--space-md: 16px; /* 78 elements — e.g. nav .CategoryGroup-module_wrapper__3SbDq, nav .CategoryGroup-module_wrapper__3SbDq, nav .CategoryGroup-module_wrapper__3SbDq /* mined from computed styles */ */
--space-lg: 32px; /* 13 elements — e.g. section .VideoPane-module-scss-module__wIJCfq__vi, section .VideoPane-module-scss-module__wIJCfq__vi, div .CoreHeadingCtaLeft-module-scss-module__F /* mined from computed styles */ */
--space-xl: 40px; /* 13 elements — e.g. section .logobar-module-scss-module__Qnpilq__logo, div .ResourceCard-module-scss-module__gbPA3G_, div .ResourceCard-module-scss-module__gbPA3G_ /* mined from computed styles */ */
--space-2xl: 48px; /* 71 elements — e.g. section .index-module-scss-module__iCjpvq__animat, section .index-module-scss-module__iCjpvq__animat, section .index-module-scss-module__wWuT5q__textMe /* mined from computed styles */ */
--space-3xl: 120.98px; /* 9 elements — e.g. nav .Drawer-module_navDrawerMenu__2EJwm, nav .DrawerNested-module_drawerNested__2dap7, nav .DrawerNested-module_drawerNested__2dap7 /* mined from computed styles */ */
--space-xs: 8px;
--space-sm: 12px;
--space-md: 16px;
--space-lg: 32px;
--space-xl: 40px;
--space-2xl: 48px;
--space-3xl: 120.98px;
/* Radius (10) */
--radius-sm: 2.5px; /* 1 element — e.g. div .otFloatingRoundedCorner "This website uses co" /* mined from computed styles */ */
--radius-md: 10px; /* 2 elements — e.g. a .PromoCard-module_promoLink__3MoH1 "Try it now", a .PromoCard-module_promoLink__3MoH1 "Try it now" /* mined from computed styles */ */
--radius-lg: 16px; /* 4 elements — e.g. div .SectionGrid-module-scss-module__vBeZ1q__sectionGrid "Start building with ", div .ResourceCard-module-scss-module__gbPA3G__card "Builders & Breakthro", div .ResourceCard-module-scss-module__gbPA3G__card "The 2026 AI guide fo" /* mined from computed styles */ */
--radius-full: 50%; /* 4 elements — e.g. button .DrawerClose-module_closeDrawerButtonWrap__2ePcL, button .DrawerClose-module_closeDrawerButtonWrap__2ePcL, button .DrawerClose-module_closeDrawerButtonWrap__2ePcL /* mined from computed styles */ */
--radius-sm: 2.5px;
--radius-md: 10px;
--radius-lg: 16px;
--radius-full: 50%;
--radius-button: 12px;
--radius-focus: 6px;
/* Effects (18) */
--theme_button-theme: light;
--theme_button-shadow-primary-disabled: inset 0 0 0 1px #9297a0;
--theme_button-filter-primary-hover: none;
--theme_button-filter-secondary-hover: blur(6px);
--theme_button-shadow-primary: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #2d7ff947, /* Blue-tinted lift */
inset 0px 0px 0px .5px #0000000f;
--theme_button-shadow-primary-hover: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a, /* Stronger blue lift on hover */
inset 0px 0px 0px .5px #0000001f;
--theme_button-shadow-primary-active: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a,
inset 0px 0px 0px .5px #0000001f;
--theme_button-shadow-primary-focus: 0px 0px 0px 2px #0768f880, /* Blue focus ring */
0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #2d7ff947,
inset 0px 0px 0px .5px #0000000f,
inset 0 0 0 1px #fff;
--theme_button-shadow-primary-loading: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #2d7ff97a,
inset 0px 0px 0px .5px #0000001f;
--theme_button-shadow-secondary: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #0114351f;
--theme_button-shadow-secondary-hover: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #458fff;
--theme_button-shadow-secondary-active: 0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #0000001f,
inset 0 0 0 1px #000e263b;
--theme_button-shadow-secondary-focus: 0px 0px 0px 2px #0768f880,
0px 0px 1px #00000052,
0px 0px 3px #0000001c,
0px 1px 4px #0000001f,
inset 0 0 0 1px #020d206e;
--theme_button-shadow-secondary-loading: 0px 0px 1px #00000052,
0px 0px 2px #00000014,
0px 1px 3px #00000014,
inset 0 0 0 1px #0114351f;
--theme_button-shadow-secondary-disabled: inset 0 0 0 1px #9297a0;
--theme_button-shadow-spotlight: 0px 0px 1px 0px #00000052,
0px 0px 2px 0px #00000014,
0px 1px 3px 0px #2d7ff947;
--theme_button-shadow-spotlight-disabled: inset 0px 0px 0px .5px #0000000f,
0px 0px 1px 0px #00000052,
0px 0px 2px 0px #00000014,
0px 1px 3px 0px #2d7ff947;
--nav-shadow: rgba(15, 48, 106, 0.05) 0px 0px 20px 0px;
/* Motion (45) */
----motion-BkButton-module-scss-module__dZ-VXq__animatedBackground: @keyframes BkButton-module-scss-module__dZ-VXq__animatedBackground {
0% { background-position-x: -100px; }
100% { background-position-x: 0px; }
}; /* @keyframes BkButton-module-scss-module__dZ-VXq__animatedBackground */
----motion-BkButton-module-scss-module__dZ-VXq__counterAnimatedBackground: @keyframes BkButton-module-scss-module__dZ-VXq__counterAnimatedBackground {
0% { background-position-x: 0px; }
100% { background-position-x: -100px; }
}; /* @keyframes BkButton-module-scss-module__dZ-VXq__counterAnimatedBackground */
----motion-BkLoadingAnimation-module-scss-module__gtyXKW__loader: @keyframes BkLoadingAnimation-module-scss-module__gtyXKW__loader {
100% { opacity: 0.33; background: var(--theme_upsell-text-weak); }
}; /* @keyframes BkLoadingAnimation-module-scss-module__gtyXKW__loader */
----motion-index-module-scss-module__KcLkaG__fadeInOut: @keyframes index-module-scss-module__KcLkaG__fadeInOut {
0% { opacity: 0; }
50% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes index-module-scss-module__KcLkaG__fadeInOut */
----motion-MarketoSubmitButton-module-scss-module__xCPVEa__blink: @keyframes MarketoSubmitButton-module-scss-module__xCPVEa__blink {
0% { opacity: 0.2; }
20% { opacity: 1; }
100% { opacity: 0.2; }
}; /* @keyframes MarketoSubmitButton-module-scss-module__xCPVEa__blink */
----motion-baymax-module__82pTNW__progress: @keyframes baymax-module__82pTNW__progress {
0% { width: 0%; }
100% { width: 100%; }
}; /* @keyframes baymax-module__82pTNW__progress */
----motion-baymax-module__82pTNW__spinScale: @keyframes baymax-module__82pTNW__spinScale {
0% { transform: rotate(0deg) scale(1); }
50% { transform: rotate(360deg) scale(0.9); }
100% { transform: rotate(720deg) scale(1); }
}; /* @keyframes baymax-module__82pTNW__spinScale */
----motion-baymax-module__82pTNW__swayHorizontal: @keyframes baymax-module__82pTNW__swayHorizontal {
0% { transform: translate(-3%); }
60% { transform: translate(3%); }
100% { transform: translate(-3%); }
}; /* @keyframes baymax-module__82pTNW__swayHorizontal */
----motion-baymax-module__82pTNW__spin: @keyframes baymax-module__82pTNW__spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}; /* @keyframes baymax-module__82pTNW__spin */
----motion-baymax-module__82pTNW__spinReverse: @keyframes baymax-module__82pTNW__spinReverse {
0% { transform: rotate(0deg); }
100% { transform: rotate(-360deg); }
}; /* @keyframes baymax-module__82pTNW__spinReverse */
----motion-baymax-module__82pTNW__highlight: @keyframes baymax-module__82pTNW__highlight {
0% { background-color: rgb(208,… <0.3KB elided>; /* @keyframes baymax-module__82pTNW__highlight */
----motion-baymax-module__82pTNW__highlightYellow: @keyframes baymax-module__82pTNW__highlightYellow {
0% { background-color: rgb(255, 234, 182); }
100% { background-color: rgba(255, 255, 255, 0); }
}; /* @keyframes baymax-module__82pTNW__highlightYellow */
----motion-baymax-module__82pTNW__spacey: @keyframes baymax-module__82pTNW__spacey {
0% { transform: translate(0px); }
100% { transform: translate(-2560px); }
}; /* @keyframes baymax-module__82pTNW__spacey */
----motion-baymax-module__82pTNW__bounceIn: @keyframes baymax-module__82pTNW__bounceIn {
0%, 50%, 100% { animation-timing… <0.3KB elided>; /* @keyframes baymax-module__82pTNW__bounceIn */
----motion-baymax-module__82pTNW__opacityFadeIn: @keyframes baymax-module__82pTNW__opacityFadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes baymax-module__82pTNW__opacityFadeIn */
----motion-baymax-module__82pTNW__opacityFadeOut: @keyframes baymax-module__82pTNW__opacityFadeOut {
0% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes baymax-module__82pTNW__opacityFadeOut */
----motion-baymax-module__82pTNW__fadeUpIn: @keyframes baymax-module__82pTNW__fadeUpIn {
0% { opacity: 0; transform: translateY(-4px); }
100% { opacity: 1; transform: translate(0px); }
}; /* @keyframes baymax-module__82pTNW__fadeUpIn */
----motion-baymax-module__82pTNW__opacityPulse: @keyframes baymax-module__82pTNW__opacityPulse {
0% { opacity: 1; }
100% { opacity: 0.25; }
}; /* @keyframes baymax-module__82pTNW__opacityPulse */
----motion-baymax-module__82pTNW__pulseBlue: @keyframes baymax-module__82pTNW__pulseBlue {
0% { box-shadow: rgb(45, 127, 2… <0.2KB elided>; /* @keyframes baymax-module__82pTNW__pulseBlue */
----motion-baymax-module__82pTNW__pulseYellow: @keyframes baymax-module__82pTNW__pulseYellow {
0% { box-shadow: rgb(252, 180… <0.2KB elided>; /* @keyframes baymax-module__82pTNW__pulseYellow */
----motion-baymax-module__82pTNW__pulseWhite: @keyframes baymax-module__82pTNW__pulseWhite {
0% { box-shadow: rgba(255, 255… <0.2KB elided>; /* @keyframes baymax-module__82pTNW__pulseWhite */
----motion-baymax-module__82pTNW__pulseDark: @keyframes baymax-module__82pTNW__pulseDark {
0% { box-shadow: rgba(0, 0, 0,… <0.2KB elided>; /* @keyframes baymax-module__82pTNW__pulseDark */
----motion-baymax-module__82pTNW__shakeHorizontal: @keyframes baymax-module__82pTNW__shakeHorizontal {
10%, 90% { transform: tra… <0.2KB elided>; /* @keyframes baymax-module__82pTNW__shakeHorizontal */
----motion-BkArticleTopics-module-scss-module__18G1va__fadeIn: @keyframes BkArticleTopics-module-scss-module__18G1va__fadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes BkArticleTopics-module-scss-module__18G1va__fadeIn */
----motion-LoadingIcon-module-scss-module__CZAfta__blink: @keyframes LoadingIcon-module-scss-module__CZAfta__blink {
0% { opacity: 0.2; }
20% { opacity: 1; }
100% { opacity: 0.2; }
}; /* @keyframes LoadingIcon-module-scss-module__CZAfta__blink */
----motion-BkInlineBanner-module-scss-module__PnG2rW__animatedBackground: @keyframes BkInlineBanner-module-scss-module__PnG2rW__animatedBackground {
0% { background-position-x: -100px; }
100% { background-position-x: 0px; }
}; /* @keyframes BkInlineBanner-module-scss-module__PnG2rW__animatedBackground */
----motion-BkInlineBanner-module-scss-module__PnG2rW__counterAnimatedBackground: @keyframes BkInlineBanner-module-scss-module__PnG2rW__counterAnimatedBackground {
0% { background-position-x: 0px; }
100% { background-position-x: -100px; }
}; /* @keyframes BkInlineBanner-module-scss-module__PnG2rW__counterAnimatedBackground */
----motion-BkAddToCalendarLink-module-scss-module__wgr3EW__ToOpacity: @keyframes BkAddToCalendarLink-module-scss-module__wgr3EW__ToOpacity {
0% { opacity: 0; visibility: hidden; }
100% { opacity: 1; visibility: visible; }
}; /* @keyframes BkAddToCalendarLink-module-scss-module__wgr3EW__ToOpacity */
----motion-DotAnimation-module-scss-module__FGLqoq__ripple: @keyframes DotAnimation-module-scss-module__FGLqoq__ripple {
0% { opacity: 0.… <0.5KB elided>; /* @keyframes DotAnimation-module-scss-module__FGLqoq__ripple */
----motion-DotAnimation-module-scss-module__FGLqoq__rippleDeflate: @keyframes DotAnimation-module-scss-module__FGLqoq__rippleDeflate {
0% { opac… <0.5KB elided>; /* @keyframes DotAnimation-module-scss-module__FGLqoq__rippleDeflate */
----motion-DotAnimation-module-scss-module__FGLqoq__wipe: @keyframes DotAnimation-module-scss-module__FGLqoq__wipe {
0% { opacity: 0.15… <0.2KB elided>; /* @keyframes DotAnimation-module-scss-module__FGLqoq__wipe */
----motion-DotAnimation-module-scss-module__FGLqoq__wipeReappearDisappear: @keyframes DotAnimation-module-scss-module__FGLqoq__wipeReappearDisappear {
0… <0.5KB elided>; /* @keyframes DotAnimation-module-scss-module__FGLqoq__wipeReappearDisappear */
----motion-LogosColumn-module-scss-module__QL6jNq__coming-in: @keyframes LogosColumn-module-scss-module__QL6jNq__coming-in {
0% { opacity: 0; transform: translateY(50%); }
100% { opacity: 1; transform: translateY(0px); }
}; /* @keyframes LogosColumn-module-scss-module__QL6jNq__coming-in */
----motion-index-module-scss-module__LYoopG__opacityFadeIn: @keyframes index-module-scss-module__LYoopG__opacityFadeIn {
0% { transform: translateY(100%); }
100% { transform: translateY(0px); }
}; /* @keyframes index-module-scss-module__LYoopG__opacityFadeIn */
----motion-index-module-scss-module__LYoopG__opacityFadeOut: @keyframes index-module-scss-module__LYoopG__opacityFadeOut {
0% { transform: translateY(0px); }
100% { transform: translateY(100%); }
}; /* @keyframes index-module-scss-module__LYoopG__opacityFadeOut */
----motion-AurasStatic-module-scss-module__pGD15G__vertical: @keyframes AurasStatic-module-scss-module__pGD15G__vertical {
0% { transform: translateY(-50px); }
100% { transform: translateY(50px); }
}; /* @keyframes AurasStatic-module-scss-module__pGD15G__vertical */
----motion-AurasStatic-module-scss-module__pGD15G__horizontal: @keyframes AurasStatic-module-scss-module__pGD15G__horizontal {
0% { transform: translate(-75px); }
100% { transform: translate(75px); }
}; /* @keyframes AurasStatic-module-scss-module__pGD15G__horizontal */
----motion-AurasStatic-module-scss-module__pGD15G__rotate: @keyframes AurasStatic-module-scss-module__pGD15G__rotate {
0% { transform: rotate(0deg) scale(1); }
50% { transform: rotate(180deg) scale(1.3); }
100% { transform: rotate(360deg) scale(1); }
}; /* @keyframes AurasStatic-module-scss-module__pGD15G__rotate */
----motion-auraButton-module-scss-module__wbteMG__auraButtonRotation: @keyframes auraButton-module-scss-module__wbteMG__auraButtonRotation {
0% { --gradient-angle: 0deg; }
100% { --gradient-angle: 360deg; }
}; /* @keyframes auraButton-module-scss-module__wbteMG__auraButtonRotation */
----motion-auraButton-module-scss-module__wbteMG__auraPulse: @keyframes auraButton-module-scss-module__wbteMG__auraPulse {
0% { transform:… <0.3KB elided>; /* @keyframes auraButton-module-scss-module__wbteMG__auraPulse */
----motion-ResourceHeroAssetCarouselCentered-module-scss-module__nqPniq__autoplaySpeed: @keyframes ResourceHeroAssetCarouselCentered-module-scss-module__nqPniq__autoplaySpeed {
0% { transform: translate(-100%); }
100% { transform: translate(0%); }
}; /* @keyframes ResourceHeroAssetCarouselCentered-module-scss-module__nqPniq__autoplaySpeed */
----motion-slide-down-custom: @-webkit-keyframes slide-down-custom {
0% { }
100% { bottom: 1em; }
}; /* @keyframes slide-down-custom */
--duration-fast: 0.15s; /* 60 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-base: 0.2s; /* 1 element — e.g. button /* mined from computed styles */ */
--ease-default: ease; /* 191 elements — e.g. button, button, button /* mined from computed styles */ */
```
More from the gallery
Browse all kits →You may also like

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

Sentry
MITDark, minimal design system for developer tools with a sophisticated purple palette and refined typography, tailored for error monitoring and performance platforms
00
darkminimaldeveloper-toolsaas

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