Zendesk
MIT
Modern SaaS design system with dark green and lime accents, built for customer support platforms and enterprise applications
Layout StudioImport this kit into a Studio project and start editing.
CLI installRun it in any project. No account needed.
npx @layoutdesign/context install zendesk# layout.md — Zendesk Design System
---
## 0. Quick Reference
**Stack:** Next.js · CSS custom properties · Styled Components · Bootstrap grid
**Token source:** extracted-css-vars (19 CSS vars) + curated zendesk-* aliases (medium confidence)
**How to apply:** Use as `var(--zendesk-accent)` in CSS, `style={{ background: 'var(--zendesk-accent)' }}` in JSX, or `bg-[var(--zendesk-accent)]` in Tailwind.
```css
:root {
/* Colour */
--zendesk-bg-surface: rgb(32, 53, 36); /* dark green hero/section bg */
--zendesk-accent: rgb(209, 244, 112); /* ONLY CTA bg — lime green */
--zendesk-text-primary: rgb(17, 17, 13); /* near-black body/heading text */
--zendesk-text-inverse: rgb(245, 245, 242); /* off-white text on dark bg */
--zendesk-surface-card: rgb(245, 245, 242); /* card background */
/* Typography */
--zendesk-font-family: "Vanilla Sans", Arial, sans-serif;
--zendesk-font-size-xs: 14px;
--zendesk-font-size-sm: 15px;
--zendesk-font-size-md: 16px;
--zendesk-font-size-lg: 18px;
--zendesk-font-size-xl: 26px;
--zendesk-font-size-2xl: 42px;
--zendesk-font-size-3xl: 68px;
--zendesk-font-weight-regular: 400;
--zendesk-font-weight-medium: 500;
--zendesk-font-weight-semibold: 600;
--zendesk-font-weight-bold: 700;
/* Spacing */
--space-textMarginSm: 8px;
--space-textMarginMd: 16px;
--space-textMarginLg: 24px;
--space-globalPadding: 40px;
--space-sectionPadding: 104px;
--space-contentMarginSm: 24px;
--space-contentMarginMd: 56px;
--space-contentMarginLg: 72px;
--space-buttonMargin: 32px;
--contentWidth: 1600px;
/* Radius */
--zendesk-radius-sm: 2px;
--zendesk-radius-md: 4px;
--zendesk-radius-lg: 8px;
--zendesk-radius-full: 12px; /* inputs; NOTE: --radius: 40px on page root */
/* Motion */
--zendesk-duration-fast: 0.1s;
--zendesk-duration-base: 0.25s;
--zendesk-duration-slow: 0.6s;
--zendesk-ease-default: ease;
}
```
```tsx
// Primary CTA Button — production-ready
<a
href="/trial"
style={{
display: 'inline-block',
backgroundColor: 'var(--zendesk-accent)', /* rgb(209,244,112) */
color: 'var(--zendesk-text-primary)',
fontFamily: 'var(--zendesk-font-family)',
fontSize: 'var(--zendesk-font-size-lg)', /* 18px */
fontWeight: 'var(--zendesk-font-weight-semibold)',
borderRadius: 'var(--zendesk-radius-lg)', /* 8px */
padding: '14px 28px',
transition: `all var(--zendesk-duration-slow) cubic-bezier(0.7, 0, 0.3, 1)`,
textDecoration: 'none',
}}
>
Kostenlos testen
</a>
```
<!-- Quick Reference truncated to fit the 75-line cap. See later sections for the full design system. -->
## 1. Design Direction & Philosophy
### Character & Mood
Zendesk's marketing homepage projects **confident enterprise minimalism with a natural edge**. The palette — dark forest green (`rgb(32, 53, 36)`) hero against near-black body text and a sharp acid-lime CTA (`rgb(209, 244, 112)`) — reads as premium, modern, and slightly editorial. The custom typeface "Vanilla Sans" is a geometric humanist sans that feels neither sterile nor casual; it bridges corporate credibility with approachability.
### What this design does
- Uses **high contrast light/dark section alternation**: dark green hero sections against light off-white (`rgb(245, 245, 242)`) card/body sections.
- Employs **large, commanding typographic scale** (68px h1, 42px h2) with medium weight (500) — bold without heaviness.
- Uses **restraint in colour**: exactly two brand colours (dark green surface + lime accent), everything else is neutral near-black/near-white.
- Applies **slow, cubic-bezier transitions** (`0.6s cubic-bezier(0.7, 0, 0.3, 1)`) for premium tactility.
### What this design explicitly rejects
- **Rounded pill buttons** — despite `--radius: 40px` existing on the root, CTA buttons use `4px–8px` radius (sharp, considered)
- **Warm colour palettes** — the green is cool and natural, not yellow-warm
- **Drop shadows as primary depth signal** — depth is achieved through surface colour contrast, not heavy shadows
- **Serif or display typefaces** — Vanilla Sans exclusively
- **Generic system fonts** — never render with Inter, Roboto, or the system-ui stack
---
## 2. Colour System
### Tier 1 — Primitives
```css
/* Raw values — do not use directly in components */
:root {
--primitive-green-900: rgb(32, 53, 36); /* darkest brand green */
--primitive-lime-300: rgb(209, 244, 112); /* acid lime accent */
--primitive-neutral-950: rgb(17, 17, 13); /* near-black */
--primitive-neutral-50: rgb(245, 245, 242); /* off-white */
--primitive-white: rgb(255, 255, 255); /* pure white (tooltips, link bg) */
--primitive-neutral-700: rgb(75, 75, 57); /* disabled state bg */
--primitive-neutral-600: rgb(89, 89, 68); /* disabled button bg variant */
--primitive-neutral-400: rgb(144, 145, 140); /* muted/placeholder borders */
}
```
### Tier 2 — Semantic Aliases
```css
:root {
/* Surfaces */
--zendesk-bg-surface: var(--primitive-green-900); /* hero, dark sections; original: --brand-surface-1 */
--zendesk-surface-card: var(--primitive-neutral-50); /* card backgrounds */
--zendesk-surface-input: rgba(17, 17, 13, 0.05); /* input field fill */
--zendesk-surface-white: var(--primitive-white); /* tooltip, dropdown bg */
/* Text */
--zendesk-text-primary: var(--primitive-neutral-950); /* all body + heading text on light */
--zendesk-text-inverse: var(--primitive-neutral-50); /* text on dark green bg */
--zendesk-text-disabled: rgb(46, 46, 35); /* disabled text */
--zendesk-text-muted: var(--primitive-neutral-400); /* secondary/placeholder text */
/* Actions */
--zendesk-accent: var(--primitive-lime-300); /* PRIMARY CTA bg only; original: --brand-primary-cta */
--zendesk-border-default: rgba(17, 17, 13, 0.47); /* input inset border */
--zendesk-border-subtle: rgba(17, 17, 13, 0.18); /* tooltip border */
--zendesk-border-focus: var(--primitive-neutral-950); /* focus outline colour */
/* States */
--zendesk-disabled-bg: var(--primitive-neutral-700); /* rgb(75,75,57) */
--zendesk-hover-overlay: rgba(17, 17, 13, 0.08); /* radio/checkbox hover */
--zendesk-active-overlay: rgba(17, 17, 13, 0.20); /* radio/checkbox active */
}
```
### Tier 3 — Component Tokens
```css
:root {
/* Button */
--btn-primary-bg: var(--zendesk-accent);
--btn-primary-text: var(--zendesk-text-primary);
--btn-primary-radius: var(--zendesk-radius-lg); /* 8px */
--btn-disabled-bg: var(--zendesk-disabled-bg);
/* Card */
--card-bg: var(--zendesk-surface-card);
--card-radius: 16px; /* extracted from computed styles */
--card-border: 1px solid rgba(0, 0, 0, 0);
/* Input */
--input-bg: var(--zendesk-surface-input);
--input-radius: var(--zendesk-radius-full); /* 12px */
--input-border: var(--zendesk-border-default);
/* Tooltip */
--tooltip-bg: var(--zendesk-surface-white);
--tooltip-border: var(--zendesk-border-subtle);
--tooltip-radius: var(--zendesk-radius-lg); /* 8px */
}
```
### Colour Usage Table
| Token | Value | Usage |
|---|---|---|
| `--zendesk-bg-surface` | `rgb(32, 53, 36)` | Dark hero/feature section backgrounds |
| `--zendesk-accent` | `rgb(209, 244, 112)` | **Primary CTA button background only** |
| `--zendesk-text-primary` | `rgb(17, 17, 13)` | All body copy, headings on light bg |
| `--zendesk-text-inverse` | `rgb(245, 245, 242)` | Headings/text on dark green bg |
| `--zendesk-surface-card` | `rgb(245, 245, 242)` | Card, tag, badge backgrounds |
| `--zendesk-disabled-bg` | `rgb(75, 75, 57)` | Disabled button/input backgrounds |
---
## 3. Typography System
**Primary typeface:** `"Vanilla Sans"` — Zendesk's proprietary geometric humanist sans-serif. Self-hosted at `web-assets.zendesk.com`. Available weights: 100, 200, 300, 400, 500, 600, 700, 900 (normal + italic).
**CJK fallback:** `"Noto Sans JP"` for Japanese markets.
```css
/* Font stack */
--zendesk-font-family: "Vanilla Sans", Arial, sans-serif;
--zendesk-font-family-cjk: "Noto Sans JP", "Vanilla Sans", Arial, sans-serif;
```
### Composite Typography Tokens
```css
/* ── Display / Hero ── */
.type-display {
/* h1 — hero headline */
font-family: var(--zendesk-font-family);
font-size: 68px; /* --zendesk-font-size-3xl */
font-weight: 500; /* --zendesk-font-weight-medium */
line-height: 71.4px; /* 1.05 ratio */
letter-spacing: normal;
}
/* ── Heading XL ── */
.type-heading-xl {
/* h2 large — section titles (Von Branchenführern, etc.) */
font-family: var(--zendesk-font-family);
font-size: 42px; /* --zendesk-font-size-2xl */
font-weight: 500; /* --zendesk-font-weight-medium */
line-height: 48.3px; /* --line-height-loose */
letter-spacing: normal;
}
/* ── Heading LG ── */
.type-heading-lg {
/* h3 — feature section subtitles, testimonial headers */
font-family: var(--zendesk-font-family);
font-size: 26px; /* --zendesk-font-size-xl */
font-weight: 500; /* --zendesk-font-weight-medium */
line-height: 32.5px; /* 1.25 ratio */
letter-spacing: normal;
}
/* ── Heading SM ── */
.type-heading-sm {
/* h2 small — card titles, feature labels */
font-family: var(--zendesk-font-family);
font-size: 18px; /* --zendesk-font-size-lg */
font-weight: 600; /* --zendesk-font-weight-semibold */
line-height: 26.1px; /* 1.45 ratio */
letter-spacing: normal;
}
/* ── Body MD ── */
.type-body-md {
/* Standard body copy, nav links */
font-family: var(--zendesk-font-family);
font-size: 16px; /* --zendesk-font-size-md */
font-weight: 400; /* --zendesk-font-weight-regular */
line-height: 23.2px; /* --line-height-normal */
letter-spacing: normal;
}
/* ── Body SM ── */
.type-body-sm {
/* Caption, small labels, metadata */
font-family: var(--zendesk-font-family);
font-size: 14px; /* --zendesk-font-size-xs */
font-weight: 400; /* --zendesk-font-weight-regular */
line-height: 18.2px; /* --line-height-tight */
letter-spacing: normal;
}
/* ── Button / CTA ── */
.type-button {
font-family: var(--zendesk-font-family);
font-size: 18px; /* --zendesk-font-size-lg — primary CTA */
font-weight: 600; /* --zendesk-font-weight-semibold */
line-height: 23px;
letter-spacing: normal;
}
/* ── Input ── */
.type-input {
font-family: var(--zendesk-font-family);
font-size: 15px; /* --zendesk-font-size-sm */
font-weight: 400; /* --zendesk-font-weight-regular */
line-height: 21px; /* 1.4 ratio */
letter-spacing: normal;
}
```
### Weight Usage Guide
| Weight | Token | Usage |
|---|---|---|
| 400 | `--zendesk-font-weight-regular` | Body copy, labels, input text |
| 500 | `--zendesk-font-weight-medium` | h1, h2 large, h3, nav links |
| 600 | `--zendesk-font-weight-semibold` | h2 small, card titles, CTA buttons |
| 700 | `--zendesk-font-weight-bold` | Stat callouts, event dates, emphasis |
---
## 4. Spacing & Layout
```css
:root {
/* ── Extracted raw spacing tokens (preserve exact names) ── */
--space-textMarginSm: 8px; /* between label and sub-element */
--space-textMarginMd: 16px; /* paragraph margin, link margin sm */
--space-textMarginLg: 24px; /* heading bottom margin, content margin sm */
--space-tabletExtraPadding: 0px; /* tablet extra padding (currently unused) */
--space-space: 32px; /* general block spacing unit */
--space-globalPadding: 40px; /* page-level horizontal padding */
--space-sectionPadding: 104px; /* alias for sectionPaddingVertical */
--space-sectionPaddingHorizontal: 40px; /* section left/right padding */
--space-sectionPaddingVertical: 104px; /* section top/bottom padding */
--space-scrollPadding: 88px; /* scroll-margin-top for anchors (normalised from 90px) */
--space-contentMarginSm: 24px; /* small content block gap */
--space-contentMarginMd: 56px; /* medium content block gap */
--space-contentMarginLg: 72px; /* large content block gap */
--space-buttonMargin: 32px; /* margin below CTA button groups */
--space-linkMarginSm: 16px; /* spacing between inline links (sm) */
--space-linkMarginMd: 24px; /* spacing between inline links (md) */
--space-modalPaddingHorizontal: 56px; /* modal horizontal padding */
/* ── Curated semantic spacing aliases ── */
--zendesk-space-xs: 4px; /* micro spacing, icon gaps */
--zendesk-space-sm: 12px; /* tight component internal spacing */
--zendesk-space-md: 88px; /* large section spacing (normalised from --space-3xl) */
--zendesk-space-lg: 20px; /* standard component spacing */
--zendesk-space-xl: 40px; /* global horizontal padding */
--zendesk-space-2xl: 48px; /* generous block gap */
--zendesk-space-3xl: 72px; /* content margin large */
/* ── Layout geometry ── */
--contentWidth: 1600px; /* max page content width */
--radius: 40px; /* page-root border-radius token (NOT for buttons) */
/* ── Radius scale ── */
--zendesk-radius-sm: 2px; /* subtle — cookie banner elements */
--zendesk-radius-md: 4px; /* secondary buttons */
--zendesk-radius-lg: 8px; /* primary CTA buttons, tooltips, most UI elements */
--zendesk-radius-full: 12px; /* input fields */
/* Card uses 16px — see component tokens. Not on the extracted radius scale. */
}
```
### Grid System
| Breakpoint | Width | Behaviour |
|---|---|---|
| `0–767px` | 100% | Single column, stacked layout |
| `768px–969px` | 100% | Tablet — minor layout shifts |
| `970px–1149px` | 100% | Desktop entry — multi-column grids activate |
| `1150px–1599px` | 100% | Wide desktop |
| `≥ 1600px` | `1600px` | Fixed max — `--contentWidth` constraint |
- **Column gutter:** `--space-globalPadding` (40px) horizontal padding on sections
- **Section vertical rhythm:** `--space-sectionPaddingVertical` (104px) top + bottom
- **Card grids:** `display: flex; flex-direction: column` per card; grids are likely 3-column at 970px+ (inferred)
---
## 5. Page Structure & Layout Patterns
*No screenshots supplied. Section map derived from LAYOUT DIGEST: component inventory, probable-sections signal, computed structural styles, and button/colour census.*
### 5.1 Section Map
| # | Section | Layout Type | Key Elements | Source |
|---|---|---|---|---|
| 1 | **Navigation / Header** | `display: block` full-width | Logo, nav links (69 instances), primary CTA button | extracted |
| 2 | **Hero** | Full-width, centred column | h1 (68px/500), subhead p, 2 CTAs (lime accent + ghost), possibly video embed | inferred |
| 3 | **Social proof / Trust bar** | Horizontal flex row | "100,000+ Unternehmen" stat callout, logo strip | inferred |
| 4 | **Feature / Product overview** | 3-column card grid | 8 cards — `display: flex; flex-direction: column`, h3 titles (16px/600), body copy | extracted |
| 5 | **Dark feature section** | Full-width, dark bg (`--zendesk-bg-surface`) | h2 (42px), body text in `--zendesk-text-inverse`, possible illustration | inferred |
| 6 | **Testimonials / Social proof** | Flex row or carousel | h3 (26px), quote text, attribution (14px/bold), star ratings | inferred |
| 7 | **Pricing / CTA section** | Centred single column | h2 (42px), CTA button (lime), supporting text | inferred |
| 8 | **Footer** | Multi-column grid | Nav links (69 total inventory), legal text (14px) | inferred |
### 5.2 Layout Patterns
**Navigation:**
```
display: block → contains flex row
padding: 0px (edge-to-edge container)
horizontal padding via --space-globalPadding (40px)
```
**Hero Section (inferred):**
```
Full viewport width, dark bg: var(--zendesk-bg-surface)
Content centred, max-width: var(--contentWidth) = 1600px
Vertical padding: var(--space-sectionPaddingVertical) = 104px top/bottom
h1 text-align: center
CTA row: display inline-block buttons, gap: --space-buttonMargin (32px)
Primary CTA: background var(--zendesk-accent), radius 8px
```
**Card Grid:**
```
Each card: display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start
Card bg: rgb(245, 245, 242); border-radius: 16px
Grid gap: inferred ~24px (--space-contentMarginSm)
Columns: 3 at ≥970px, 2 at 768–969px, 1 below 768px (inferred)
```
**Dark Feature Section:**
```
background: var(--zendesk-bg-surface) = rgb(32, 53, 36)
text colour: var(--zendesk-text-inverse) = rgb(245, 245, 242)
padding: var(--space-sectionPadding) = 104px vertical
```
### 5.3 Visual Hierarchy
- **Dominant CTA colour:** `rgb(209, 244, 112)` — lime green. Appears on the two primary CTAs ("Kostenlos testen", "Kostenlos registrieren"). Highly visible against both dark green and near-white backgrounds.
- **Primary typographic anchor:** 68px / 500 weight h1, centred, near-black or inverse white depending on section bg.
- **Section separation:** Colour-field alternation (dark green ↔ off-white) rather than borders or shadows.
- **CTA placement:** Top of hero (2 buttons), repeated at bottom of major feature sections (1 button), in nav (1 persistent).
- **Whitespace rhythm:** 104px section padding creates generous breathing room; 24–56px content block gaps.
### 5.4 Content Patterns
**Feature Card (repeating pattern — 8 instances):**
```
[Icon or image — top]
[h3 — 16–18px, semibold]
[Body copy — 14–16px, regular]
[Optional CTA link — 16px/500, underlined]
Card bg: rgb(245,245,242); radius: 16px; transition: 0.3s cubic-bezier(0.7,0,0.3,1)
```
**Stat/Callout (repeating pattern):**
```
[Large number — 42px/700]
[Descriptor — 14–16px/400]
Arranged in horizontal flex row with equal column widths
```
**CTA Block (hero + section bottoms):**
```
Primary button: bg var(--zendesk-accent), text --zendesk-text-primary, radius 8px, 18px semibold
Secondary button: ghost/outline variant, same radius (inferred)
Buttons inline-block, gap: --space-buttonMargin (32px)
```
---
## 6. Component Patterns
### 6.1 Primary CTA Button
**Anatomy:** `[optional icon] [label text]`
- `display: inline-block`
- `font: 18px/600 "Vanilla Sans"`
- `border-radius: var(--zendesk-radius-lg)` (8px)
- `background: var(--zendesk-accent)`
- `transition: all 0.6s cubic-bezier(0.7, 0, 0.3, 1)`
**State table:**
| State | background | color | outline | cursor |
|---|---|---|---|---|
| default | `rgb(209,244,112)` | `rgb(17,17,13)` | none | pointer |
| hover | slightly darker (inferred `rgb(190,226,100)`) | `rgb(3,3,2)` | none | pointer |
| focus-visible | `rgb(209,244,112)` | `rgb(17,17,13)` | `2px solid rgb(17,17,13)`, offset 1px | pointer |
| active | `rgb(209,244,112)` | `rgb(0,0,0)` | none | pointer |
| disabled | `rgb(89,89,68)` | `rgb(46,46,35)` | none | default |
| loading | `rgb(209,244,112)` | `rgb(17,17,13)` | none | wait (inferred) |
```tsx
// PrimaryButton.tsx — production-ready with full state coverage
import React, { ButtonHTMLAttributes } from 'react';
interface PrimaryButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
loading?: boolean;
children: React.ReactNode;
}
export function PrimaryButton({ loading, disabled, children, ...props }: PrimaryButtonProps) {
const isDisabled = disabled || loading;
return (
<button
{...props}
disabled={isDisabled}
style={{
display: 'inline-block',
backgroundColor: isDisabled
? 'rgb(89, 89, 68)'
: 'var(--zendesk-accent)', /* rgb(209,244,112) */
color: isDisabled
? 'rgb(46, 46, 35)'
: 'var(--zendesk-text-primary)', /* rgb(17,17,13) */
fontFamily: 'var(--zendesk-font-family)',
fontSize: 'var(--zendesk-font-size-lg)', /* 18px */
fontWeight: 'var(--zendesk-font-weight-semibold)', /* 600 */
lineHeight: '23px',
borderRadius: 'var(--zendesk-radius-lg)', /* 8px */
padding: '14px 28px',
border: 'none',
cursor: isDisabled ? 'default' : 'pointer',
transition: `all var(--zendesk-duration-slow) cubic-bezier(0.7, 0, 0.3, 1)`,
textDecoration: 'none',
opacity: loading ? 0.7 : 1,
}}
// Focus outline via CSS — must be in global stylesheet:
// button:focus { outline: none }
// button:focus-visible { outline: 2px solid var(--zendesk-text-primary); outline-offset: 1px }
>
{loading ? 'Wird geladen…' : children}
</button>
);
}
```
---
### 6.2 Card
**Anatomy:** `[media/image top] [content area: title + body + optional link]`
- `display: flex; flex-direction: column; justify-content: flex-start; align-items: flex-start`
- `background: var(--surface-card)` = `rgb(245,245,242)`
- `border-radius: 16px`
- `border: 1px solid rgba(0,0,0,0)` (transparent — can animate to visible on hover)
- `transition: 0.3s cubic-bezier(0.7, 0, 0.3, 1)`
| State | background | border | transform |
|---|---|---|---|
| default | `rgb(245,245,242)` | transparent | none |
| hover | `rgb(245,245,242)` | `rgba(0,0,0,0.1)` (inferred) | `translateY(-2px)` (inferred) |
| focus-visible | `rgb(245,245,242)` | `2px solid rgb(17,17,13)` | none |
| disabled | n/a (cards are not typically disabled) | — | — |
```tsx
export function FeatureCard({ title, body, href }: { title: string; body: string; href?: string }) {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'flex-start',
backgroundColor: 'var(--zendesk-surface-card)', /* rgb(245,245,242) */
borderRadius: '16px',
border: '1px solid rgba(0, 0, 0, 0)',
transition: '0.3s cubic-bezier(0.7, 0, 0.3, 1)',
overflow: 'hidden',
}}
>
<div style={{ padding: '24px' }}>
<h3 style={{
fontFamily: 'var(--zendesk-font-family)',
fontSize: 'var(--zendesk-font-size-md)', /* 16px */
fontWeight: 'var(--zendesk-font-weight-semibold)', /* 600 */
lineHeight: '23.2px',
color: 'var(--zendesk-text-primary)',
margin: `0 0 var(--space-textMarginSm)`, /* 0 0 8px */
}}>{title}</h3>
<p style={{
fontFamily: 'var(--zendesk-font-family)',
fontSize: 'var(--zendesk-font-size-xs)', /* 14px */
fontWeight: 'var(--zendesk-font-weight-regular)', /* 400 */
lineHeight: '18.2px',
color: 'var(--zendesk-text-primary)',
margin: 0,
}}>{body}</p>
</div>
</div>
);
}
```
---
### 6.3 Input Field
**Anatomy:** `[label above] [text input]`
- `border-radius: 12px` (`--zendesk-radius-full`)
- `background: rgba(17,17,13,0.05)`
- `box-shadow: rgba(17,17,13,0.47) 0px 0px 0px 1px inset` (border via inset shadow)
- `padding: 12px`
- `transition: border-color 0.25s ease, box-shadow 0.1s ease, background-color 0.25s ease, color 0.25s ease`
| State | box-shadow | background | outline |
|---|---|---|---|
| default | `rgba(17,17,13,0.47) 0 0 0 1px inset` | `rgba(17,17,13,0.05)` | none |
| hover | `rgba(17,17,13,0.8) 0 0 0 1px inset` (inferred) | `rgba(17,17,13,0.05)` | none |
| focus-visible | `rgb(255,255,255) 0 2px 4px, rgb(17,17,13) 0 4px 12px` | `rgba(17,17,13,0.05)` | `2px solid transparent` (offset) |
| disabled | `rgba(17,17,13,0.2) 0 0 0 1px inset` (inferred) | `rgba(17,17,13,0.03)` | none |
| error | `rgba(200,0,0,0.6) 0 0 0 1px inset` (inferred) | `rgba(17,17,13,0.05)` | none |
```tsx
export function TextInput({ label, id, error, ...props }: {
label: string; id: string; error?: string;
} & React.InputHTMLAttributes<HTMLInputElement>) {
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '4px' }}>
<label htmlFor={id} style={{
fontFamily: 'var(--zendesk-font-family)',
fontSize: 'var(--zendesk-font-size-sm)', /* 15px */
fontWeight: 'var(--zendesk-font-weight-regular)',
color: 'var(--zendesk-text-primary)',
display: 'block',
}}>
{label}
</label>
<input
id={id}
style={{
fontFamily: 'var(--zendesk-font-family)',
fontSize: 'var(--zendesk-font-size-sm)', /* 15px */
fontWeight: 'var(--zendesk-font-weight-regular)',
lineHeight: '21px',
color: 'var(--zendesk-text-primary)',
backgroundColor: 'var(--zendesk-surface-input)', /* rgba(17,17,13,0.05) */
borderRadius: 'var(--zendesk-radius-full)', /* 12px */
padding: 'var(--space-textMarginMd)', /* 12px — closest token */
border: 'none',
boxShadow: error
? 'rgba(200,0,0,0.6) 0px 0px 0px 1px inset'
: 'rgba(17, 17, 13, 0.47) 0px 0px 0px 1px inset',
transition: `border-color var(--zendesk-duration-base) var(--zendesk-ease-default),
box-shadow var(--zendesk-duration-fast) var(--zendesk-ease-default),
background-color var(--zendesk-duration-base) var(--zendesk-ease-default)`,
width: '100%',
outline: 'none', // rely on :focus-visible in CSS
}}
{...props}
/>
{error && (
<span style={{
fontSize: 'var(--zendesk-font-size-xs)',
color: 'rgb(200, 0, 0)',
}}>{error}</span>
)}
</div>
);
}
```
---
### 6.4 Navigation Item
**Anatomy:** `[text label]` (optionally with dropdown trigger)
- `font: 16px/400 "Vanilla Sans"`
- `color: rgb(17,17,13)` default / `rgb(0,0,0)` on dark contexts
- `transition: all`
| State | color | decoration | outline |
|---|---|---|---|
| default | `rgb(17,17,13)` | none | none |
| hover | `rgb(3,3,2)` | none | none |
| focus-visible | `rgb(17,17,13)` | none | `2px solid rgb(17,17,13)`, offset 1px |
| active | `rgb(0,0,0)` | none | none |
| disabled | n/a | none | cursor: default |
---
### 6.5 Tooltip
**Anatomy:** `[text content]` floating box
- `background: rgb(255,255,255)`
- `border: 1px solid rgba(17,17,13,0.18)`
- `border-radius: 8px`
- `padding: 16px`
- `box-shadow: rgba(0,0,0,0.08) 0px 16px 28px 0px`
- `margin: 12px` (from trigger)
```css
.tooltip {
font-family: var(--zendesk-font-family);
font-size: var(--zendesk-font-size-xs); /* 14px */
font-weight: var(--zendesk-font-weight-regular);
line-height: 17.5px;
color: var(--zendesk-text-primary);
background: var(--zendesk-surface-white);
border: 1px solid var(--zendesk-border-subtle);
border-radius: var(--zendesk-radius-lg); /* 8px */
padding: var(--space-textMarginMd); /* 16px */
box-shadow: rgba(0, 0, 0, 0.08) 0px 16px 28px 0px;
margin: var(--space-textMarginSm); /* 12px from trigger — closest */
display: inline-block;
}
```
---
### 6.6 Badge / Tag
**Anatomy:** `[short label]`
- 11 instances detected
- `background: var(--zendesk-surface-card)` = `rgb(245,245,242)` (inferred from card surface)
- `font: 14px/400`
- `border-radius: var(--zendesk-radius-lg)` — 8px (inferred)
```css
.badge {
font-family: var(--zendesk-font-family);
font-size: var(--zendesk-font-size-xs); /* 14px */
font-weight: var(--zendesk-font-weight-regular);
line-height: var(--zendesk-line-height-tight); /* 18.2px */
background: var(--zendesk-surface-card);
color: var(--zendesk-text-primary);
border-radius: var(--zendesk-radius-lg); /* 8px */
padding: 4px 12px; /* --zendesk-space-xs --zendesk-space-sm */
display: inline-block;
}
```
---
## 7. Elevation & Depth
Zendesk uses colour-field contrast as the primary depth signal. Shadows are restrained and only appear on floating elements (tooltips, dropdowns, link-style cards).
```css
:root {
/* Shadow scale */
--shadow-sm: rgba(0, 0, 0, 0.08) 0px 8px 24px 0px; /* link cards, nav dropdowns */
--shadow-md: rgba(0, 0, 0, 0.08) 0px 16px 28px 0px; /* tooltips */
--shadow-focus: rgb(255, 255, 255) 0px 2px 4px,
rgb(17, 17, 13) 0px 4px 12px; /* focus ring on inputs */
--shadow-inset-default: rgba(17, 17, 13, 0.47) 0px 0px 0px 1px inset; /* input border */
/* Border scale */
--border-subtle: 1px solid rgba(17, 17, 13, 0.18); /* tooltips */
--border-card: 1px solid rgba(0, 0, 0, 0); /* card (transparent — animatable) */
/* Z-index scale */
--z-base: 0;
--z-raised: 1; /* hover/focus button in group */
--z-dropdown: 100; /* nav dropdowns (inferred) */
--z-modal: 200; /* modals */
--z-tooltip: 300; /* tooltips */
--z-buried: -1; /* disabled items in button groups */
}
```
**Layering principles:**
- Surface colour (`rgb(32,53,36)` dark vs `rgb(245,245,242)` light) creates the primary visual layer stack — no shadow needed between same-level siblings
- Shadows only used when an element **physically floats** above the document (tooltip, dropdown, video modal)
- Focus state uses a **compound shadow** (white + dark) to ensure visibility on both light and dark surfaces
---
## 8. Motion
```css
:root {
/* Duration tokens */
--zendesk-duration-fast: 0.1s; /* micro: hover color flips, inset-shadow switch */
--zendesk-duration-base: 0.25s; /* standard: input bg, border, colour transitions */
--zendesk-duration-slow: 0.6s; /* expressive: button hover, card hover, reveal anims */
/* Easing tokens */
--zendesk-ease-default: ease; /* general purpose */
--zendesk-ease-expressive: cubic-bezier(0.7, 0, 0.3, 1); /* buttons, cards — feels weighted */
/* Named transition compositions */
--transition-button: all var(--zendesk-duration-slow) var(--zendesk-ease-expressive);
--transition-card: all 0.3s var(--zendesk-ease-expressive);
--transition-input: border-color var(--zendesk-duration-base) var(--zendesk-ease-default),
box-shadow var(--zendesk-duration-fast) var(--zendesk-ease-default),
background-color var(--zendesk-duration-base) var(--zendesk-ease-default),
color var(--zendesk-duration-base) var(--zendesk-ease-default);
--transition-link: color var(--zendesk-duration-fast) var(--zendesk-ease-default);
}
/* Named keyframe animations */
@keyframes slideUp {
0% { opacity: 0.01; transform: translateY(5%); }
100% { opacity: 1; transform: translateY(0px); }
}
@keyframes slideUpBlur {
0% { opacity: 0.01; transform: translateY(10%); }
100% { backdrop-filter: blur(25px); opacity: 1; transform: translateY(0px); }
}
@keyframes progressBar {
0% { opacity: 1; width: 0%; }
100% { opacity: 1; width: 100%; }
}
```
### When to animate
| Trigger | Animation | Duration |
|---|---|---|
| Button hover/active | `background-color`, `color` crossfade | `0.6s ease-expressive` |
| Card hover | `transform: translateY(-2px)`, border reveal | `0.3s ease-expressive` |
| Input focus/blur | `box-shadow`, `background-color` | `0.1s–0.25s ease` |
| Section entrance (scroll) | `slideUp` keyframe | `0.6s` |
| Modal/dropdown open | `slideUp` or `blippity` fade | `0.25–0.6s` |
| Nav link hover | `color` shift | `0.1s` |
### When NOT to animate
- NEVER animate `width`, `height`, or `margin` for layout shifts — this causes reflow jank
- NEVER use `transition: all` on elements with many computed properties (use specific property lists)
- NEVER animate at `>0.6s` for interactive state changes — only use `0.6s` for expressive entrance animations
- Respect `prefers-reduced-motion`: wrap entrance animations in a media query check
---
## 9. Anti-Patterns & Constraints
1. **Hardcoded colour values → Why it fails → What to do instead.**
AI agents default to writing `color: #11110D` or `background: #d1f470` directly in component styles. When the brand colour changes (e.g., dark mode, campaign variants), every hardcoded instance breaks and there is no single source of truth. **Always** use `var(--zendesk-text-primary)` and `var(--zendesk-accent)` — the token is the contract, not the hex value.
2. **Using `font-family: Inter, sans-serif` → Why it fails → What to do instead.**
AI models are heavily trained on codebases using Inter as the default. Without explicit context, they substitute it silently. The result looks obviously wrong against the Vanilla Sans brand. **Always** declare `font-family: "Vanilla Sans", Arial, sans-serif` as `var(--zendesk-font-family)`. The Arial fallback must appear second, never first.
3. **Setting border-radius to 50px or 9999px for buttons → Why it fails → What to do instead.**
Zendesk's root stylesheet defines `--radius: 40px`, which AI agents interpret as the button radius. The brand actually uses `4–8px` for buttons (sharp, considered). Pill-shaped buttons are wrong for this brand. **Always** use `var(--zendesk-radius-md)` (4px) or `var(--zendesk-radius-lg)` (8px) for buttons; reserve `--radius: 40px` for the page-root context only.
4. **Arbitrary spacing values → Why it fails → What to do instead.**
With 16 unique spacing values extracted, AI agents invent ad-hoc values like `margin: 20px` or `padding: 35px`. These break the visual rhythm and create inconsistent layouts. **Always** choose from the defined `--space-*` tokens. If a value isn't on the scale, map to the nearest token — never invent a new value.
5. **Omitting `focus-visible` states → Why it fails → What to do instead.**
AI agents regularly generate components without focus ring styles, failing WCAG 2.4.7. Zendesk uses a specific focus pattern: `outline: 2px solid rgb(17,17,13); outline-offset: 1px` — not a browser default blue ring. Omitting this produces both an accessibility failure and an off-brand visual. **Always** add `:focus { outline: none }` + `:focus-visible { outline: 2px solid var(--zendesk-border-focus); outline-offset: 1px }`.
6. **Using `color: rgb(209,244,112)` (the accent) for text → Why it fails → What to do instead.**
The lime green `--zendesk-accent` fails WCAG contrast when placed on white or light surfaces (contrast ratio < 3:1). AI agents sometimes use the accent as a text highlight colour. **Never** use `--zendesk-accent` as a text colour — it is exclusively a background fill value.
7. **Applying `transition: all` to every element → Why it fails → What to do instead.**
Zendesk uses `transition: all` on several elements in its stylesheet, but this is a performance smell — it transitions every CSS property including `width`, `height`, `display`, and `opacity` on every change, causing unexpected layout jank on complex components. **Use specific property transitions** as defined in `--transition-button`, `--transition-input`, `--transition-card`.
8. **Generating `!important` overrides for spacing → Why it fails → What to do instead.**
When Bootstrap's grid system (detected on this site) conflicts with component styles, AI agents apply `!important` to force padding/margin values. This permanently breaks overridability and creates a cascade nightmare. **Use component-level CSS classes** with specific selectors instead, or apply spacing tokens via inline styles where Bootstrap doesn't apply.
9. **Dynamic Tailwind class construction → Why it fails → What to do instead.**
Patterns like `` `bg-[var(--${colorToken})]` `` cause Tailwind's PurgeCSS to strip the class at build time because the full class string is never statically present. The component renders with no background. **Always** write the complete class string: `bg-[var(--zendesk-accent)]` or use `style={{ backgroundColor: 'var(--zendesk-accent)' }}` for token-driven dynamic styles.
10. **Treating the h2 styles as the only heading variant → Why it fails → What to do instead.**
The typographic hierarchy has two h2 sizes: 42px/500 (section-level) and 18px/600 (card-level). AI agents default to a single h2 style and produce either oversized or undersized headings in card contexts. **Always** check context: section-level h2s use `--zendesk-font-size-2xl` (42px / weight 500); card-level h2s use `--zendesk-font-size-lg` (18px / weight 600).
11. **Ignoring the disabled state background → Why it fails → What to do instead.**
AI agents either omit disabled states or use `opacity: 0.5` on the accent button, resulting in a washed lime-green that reads as "glitchy" rather than intentionally disabled. Zendesk's actual disabled background is `rgb(89,89,68)` (warm dark olive) with `color: rgb(46,46,35)`. **Use `--zendesk-disabled-bg` and `--zendesk-text-disabled` explicitly** when `disabled` or `aria-disabled="true"` is present.
---
## 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 (35) */
--brand-primary-cta: rgb(209, 244, 112); /* Primary CTA background, dominant on 2 buttons — e.g. "Kostenlos testen" /* mined from computed styles */ */
--brand-surface-1: rgb(32, 53, 36); /* Brand surface, dominant on 4 elements — e.g. "Tauchen Sie ein in die Zukunft" /* mined from computed styles */ */
--zendesk-bg-surface: rgb(32, 53, 36);
--zendesk-accent: rgb(209, 244, 112);
--zendesk-text-primary: rgb(17, 17, 13);
--zendesk-text-inverse: rgb(245, 245, 242);
--zendesk-surface-card: rgb(245, 245, 242);
--primitive-green-900: rgb(32, 53, 36);
--primitive-lime-300: rgb(209, 244, 112);
--primitive-neutral-950: rgb(17, 17, 13);
--primitive-neutral-50: rgb(245, 245, 242);
--primitive-white: rgb(255, 255, 255);
--primitive-neutral-700: rgb(75, 75, 57);
--primitive-neutral-600: rgb(89, 89, 68);
--primitive-neutral-400: rgb(144, 145, 140);
--zendesk-surface-input: rgba(17, 17, 13, 0.05);
--zendesk-text-disabled: rgb(46, 46, 35);
--zendesk-text-muted: rgb(144, 145, 140);
--zendesk-border-default: rgba(17, 17, 13, 0.47);
--zendesk-border-subtle: rgba(17, 17, 13, 0.18);
--zendesk-border-focus: rgb(17, 17, 13);
--zendesk-disabled-bg: rgb(75, 75, 57);
--zendesk-hover-overlay: rgba(17, 17, 13, 0.08);
--zendesk-active-overlay: rgba(17, 17, 13, 0.20);
--btn-primary-bg: var(--zendesk-accent);
--btn-disabled-bg: var(--zendesk-disabled-bg);
--card-bg: var(--zendesk-surface-card);
--card-border: 1px solid rgba(0, 0, 0, 0);
--input-bg: var(--zendesk-surface-input);
--input-border: var(--zendesk-border-default);
--tooltip-bg: var(--zendesk-surface-white);
--tooltip-border: var(--zendesk-border-subtle);
--border-subtle: 1px solid rgba(17, 17, 13, 0.18);
--border-card: 1px solid rgba(0, 0, 0, 0);
--zendesk-surface-white: rgb(255, 255, 255);
/* Typography (31) */
--font-size-xs: 14px; /* 20 elements — e.g. h2 "100.000+ Unternehmen", p "Erleben Sie die Zuku", p "14 Tage kostenlos te" /* mined from computed styles */ */
--font-size-sm: 15px; /* 1 element — e.g. label "Bitte aktivieren Sie" /* mined from computed styles */ */
--font-size-md: 16px; /* 22 elements — e.g. h3 "Verbessern Sie die A", h3 "Reduzieren Sie den A", h3 "Halten Sie die Koste" /* mined from computed styles */ */
--font-size-lg: 18px; /* 2 elements — e.g. button "Kostenlos testen", button "Video ansehen" /* mined from computed styles */ */
--font-size-xl: 26px; /* 4 elements — e.g. h2 "Übertreffen Sie alle", h3 "Sichern Sie sich Ihr", h3 "Ali Wong" /* mined from computed styles */ */
--font-size-2xl: 42px; /* 8 elements — e.g. h2 "Von Branchenführern ", h2 "Ihre All-in-One-Lösu", h2 "Machen Sie den Emplo" /* mined from computed styles */ */
--font-size-3xl: 68px; /* 1 element — e.g. h1 "Liefern Sie erstklas" /* mined from computed styles */ */
--font-weight-regular: 400; /* 14 elements — e.g. p "Erleben Sie die Zuku", p "Wir stärken über 20.", p "14 Tage kostenlos te" /* mined from computed styles */ */
--font-weight-medium: 500; /* 13 elements — e.g. h1 "Liefern Sie erstklas", h2 "Von Branchenführern ", h2 "Ihre All-in-One-Lösu" /* mined from computed styles */ */
--font-weight-semibold: 600; /* 16 elements — e.g. h3 "Verbessern Sie die A", h3 "Reduzieren Sie den A", h3 "Halten Sie die Koste" /* mined from computed styles */ */
--font-weight-bold: 700; /* 15 elements — e.g. h2 "100.000+ Unternehmen", p "Seien Sie live dabei", p "18.–20. Mai 2026" /* mined from computed styles */ */
--line-height-tight: 18.2px; /* 14 elements — e.g. h2 "100.000+ Unternehmen", p "Seien Sie live dabei", p "18.–20. Mai 2026" /* mined from computed styles */ */
--line-height-normal: 23.2px; /* 19 elements — e.g. h3 "Verbessern Sie die A", h3 "Reduzieren Sie den A", h3 "Halten Sie die Koste" /* mined from computed styles */ */
--line-height-loose: 48.3px; /* 8 elements — e.g. h2 "Von Branchenführern ", h2 "Ihre All-in-One-Lösu", h2 "Machen Sie den Emplo" /* mined from computed styles */ */
--zendesk-font-family: "Vanilla Sans", Arial, sans-serif;
--zendesk-font-size-xs: 14px;
--zendesk-font-size-sm: 15px;
--zendesk-font-size-md: 16px;
--zendesk-font-size-lg: 18px;
--zendesk-font-size-xl: 26px;
--zendesk-font-size-2xl: 42px;
--zendesk-font-size-3xl: 68px;
--zendesk-font-weight-regular: 400;
--zendesk-font-weight-medium: 500;
--zendesk-font-weight-semibold: 600;
--zendesk-font-weight-bold: 700;
--btn-primary-text: var(--zendesk-text-primary);
--zendesk-font-family-cjk: "Noto Sans JP", "Vanilla Sans", Arial, sans-serif;
--zendesk-line-height-tight: 18.2px;
--zendesk-line-height-normal: 23.2px;
--zendesk-line-height-loose: 48.3px;
/* Spacing (30) */
--space-space: 32px;
--space-globalPadding: 40px;
--space-sectionPadding: 104px;
--space-scrollPadding: 88px;
--space-textMarginSm: 8px;
--space-textMarginMd: 16px;
--space-textMarginLg: 24px;
--space-contentMarginMd: 56px;
--space-contentMarginLg: 72px;
--space-tabletExtraPadding: 0px;
--contentWidth: 1600px;
--space-xs: 4px; /* 3 elements — e.g. nav .sc-612b179e-5, nav .sc-612b179e-5, nav .sc-612b179e-5 /* mined from computed styles */ */
--space-sm: 12px; /* 3 elements — e.g. nav .sc-512deb61-2, nav .sc-512deb61-2, nav .sc-512deb61-2 /* mined from computed styles */ */
--space-lg: 20px; /* 1 element — e.g. section .StyledPanel-sc-1piryze-0 /* mined from computed styles */ */
--space-2xl: 48px; /* 1 element — e.g. section .StyledPanel-sc-1piryze-0 /* mined from computed styles */ */
--space-3xl: 88px; /* 20 elements — e.g. section .sc-3cb30ae3-10, section .sc-3cb30ae3-10, section .sc-3cb30ae3-10 /* mined from computed styles */ */
--space-contentMarginSm: 24px;
--space-buttonMargin: 32px;
--space-sectionPaddingHorizontal: 40px;
--space-sectionPaddingVertical: 104px;
--space-linkMarginSm: 16px;
--space-linkMarginMd: 24px;
--space-modalPaddingHorizontal: 56px;
--zendesk-space-xs: 4px;
--zendesk-space-sm: 12px;
--zendesk-space-md: 88px;
--zendesk-space-lg: 20px;
--zendesk-space-xl: 40px;
--zendesk-space-2xl: 48px;
--zendesk-space-3xl: 72px;
/* Radius (13) */
--radius: 40px;
--radius-sm: 2px; /* 6 elements — e.g. button .ot-link-btn "Angaben zum Anbieter", button .ot-link-btn "Angaben zum Anbieter", button .ot-link-btn "Angaben zum Anbieter" /* mined from computed styles */ */
--radius-md: 4px; /* 2 elements — e.g. a .StyledButton-sc-qe3ace-0 "Kostenlos registrier", a .StyledButton-sc-qe3ace-0 /* mined from computed styles */ */
--radius-lg: 8px; /* 16 elements — e.g. a .StyledButton-sc-qe3ace-0 "Zendesk Resolution P", a .StyledButton-sc-qe3ace-0 "Zendesk-KIOptimieren", a .StyledButton-sc-qe3ace-0 "Berichte und Analyse" /* mined from computed styles */ */
--radius-full: 12px; /* 2 elements — e.g. input .StyledTextInput-sc-k12n8x-0, input .StyledTextInput-sc-k12n8x-0 /* mined from computed styles */ */
--zendesk-radius-sm: 2px;
--zendesk-radius-md: 4px;
--zendesk-radius-lg: 8px;
--zendesk-radius-full: 12px;
--btn-primary-radius: var(--zendesk-radius-lg);
--card-radius: 16px;
--input-radius: var(--zendesk-radius-full);
--tooltip-radius: var(--zendesk-radius-lg);
/* Effects (4) */
--shadow-sm: rgba(0,0,0,0.08) 0px 8px 24px 0px;
--shadow-md: rgba(0,0,0,0.08) 0px 16px 28px 0px;
--shadow-focus: rgb(255,255,255) 0 2px 4px, rgb(17,17,13) 0 4px 12px;
--shadow-inset-default: rgba(17,17,13,0.47) 0 0 0 1px inset;
/* Motion (23) */
----motion-progressBar: @keyframes progressBar {
0% { opacity: 1; width: 0%; }
100% { opacity: 1; width: 100%; }
}; /* @keyframes progressBar */
----motion-blippity: @keyframes blippity {
0% { opacity: 0; width: 100%; }
100% { opacity: 1; width: 100%; }
}; /* @keyframes blippity */
----motion-slideUp: @keyframes slideUp {
0% { opacity: 0.01; transform: translateY(5%); }
100% { opacity: 1; transform: translateY(0px); }
}; /* @keyframes slideUp */
----motion-slideUpBlur: @keyframes slideUpBlur {
0% { opacity: 0.01; transform: translateY(10%); }
100% { backdrop-filter: blur(25px); opacity: 1; transform: translateY(0px); }
}; /* @keyframes slideUpBlur */
----motion-slideOut-left-sm: @keyframes slideOut-left-sm {
0% { opacity: 0.01; transform: translateY(-50%); }
100% { opacity: 1; transform: translate(-100%, -50%); }
}; /* @keyframes slideOut-left-sm */
----motion-slideOut-left-lg: @keyframes slideOut-left-lg {
0% { opacity: 0.01; transform: translateY(-50%); }
100% { opacity: 1; transform: translate(-44%, -50%); }
}; /* @keyframes slideOut-left-lg */
----motion-slideOut-right-lg: @keyframes slideOut-right-lg {
0% { opacity: 0.01; transform: translateY(-50%); }
100% { opacity: 1; transform: translate(44%, -50%); }
}; /* @keyframes slideOut-right-lg */
----motion-slideOut-right-sm: @keyframes slideOut-right-sm {
0% { opacity: 0.01; transform: translateY(-50%); }
100% { opacity: 1; transform: translate(100%, -50%); }
}; /* @keyframes slideOut-right-sm */
----motion-gJZWFA: @keyframes gJZWFA {
0% { position: static; display: none; opacity: 0; }
1% { display: block; }
100% { display: block; opacity: 1; }
}; /* @keyframes gJZWFA */
----motion-cwqaCA: @keyframes cwqaCA {
0% { position: absolute; opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes cwqaCA */
----motion-hxqKPd: @keyframes hxqKPd {
0% { opacity: 1; display: block; }
99% { opacity: 0; display: block; }
100% { display: none; }
}; /* @keyframes hxqKPd */
----motion-gUmuQi: @keyframes gUmuQi {
0% { left: 0px; opacity: 1; }
100% { left: 10px; opacity: 0; }
}; /* @keyframes gUmuQi */
----motion-kezRlp: @keyframes kezRlp {
0% { display: block; background: white; position: absolut… <0.3KB elided>; /* @keyframes kezRlp */
----motion-jAYiMU: @keyframes jAYiMU {
0% { position: static; opacity: 0.01; transform: translateX(5%); }
100% { position: static; opacity: 1; transform: translateX(0px); }
}; /* @keyframes jAYiMU */
----motion-eEAsaf: @keyframes eEAsaf {
0% { top: 5px; }
100% { top: 0px; }
}; /* @keyframes eEAsaf */
----motion-fVoCkF: @keyframes fVoCkF {
0% { transform: translateX(0px); }
100% { transform: translateX(calc(-100% - 24px)); }
}; /* @keyframes fVoCkF */
----motion-fOEIGv: @keyframes fOEIGv {
0% { transform: translateX(0px); }
100% { transform: translateX(calc(-100% - 24px)); }
}; /* @keyframes fOEIGv */
----motion-VOLUME_SMALL_WAVE_FLASH: @keyframes VOLUME_SMALL_WAVE_FLASH {
0% { opacity: 0; }
33% { opacity: 1; }
66% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes VOLUME_SMALL_WAVE_FLASH */
----motion-VOLUME_LARGE_WAVE_FLASH: @keyframes VOLUME_LARGE_WAVE_FLASH {
0% { opacity: 0; }
33% { opacity: 1; }
66% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes VOLUME_LARGE_WAVE_FLASH */
--duration-fast: 0.1s; /* 17 elements — e.g. button, button, button /* mined from computed styles */ */
--duration-base: 0.25s; /* 8 elements — e.g. input, input, input /* mined from computed styles */ */
--duration-slow: 0.6s; /* 12 elements — e.g. button, button, button /* mined from computed styles */ */
--ease-default: ease; /* 108 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```yaml
tokenSource: extracted-css-vars
site: zendesk.com
extractionDate: "[TBD — extract date manually]"
confidence: medium
cssVarsFound: 19
curatedAliases: 31 (--zendesk-* prefix)
notes:
- Primary CSS variables are --space-* naming with exact values preserved verbatim
- --brand-primary-cta and --brand-surface-1 are the only extracted colour vars;
all other colours derived from computed styles (medium confidence)
- --zendesk-* tokens are synthesised semantic aliases mapping to original vars
- border-radius: extracted radius scale shows 2/4/8/12px in UI; 40px (--radius)
exists on page root but does NOT apply to buttons (confirmed: buttons use 4–8px)
- Card border-radius (16px) confirmed from computed styles; no CSS var found
- Spacing: 16 unique values extracted; normalised to 7-token scale + preserved
exact --space-* names. 90px (--space-scrollPadding) rounded to 88px for 4px grid
- Font: "Vanilla Sans" is a Zendesk proprietary typeface, self-hosted at
web-assets.zendesk.com. All 8 weights (100–900) available.
- WistiaPlayer* fonts are third-party video player fonts — exclude from brand system
- Interactive states: extracted from CSS rules referencing Styled Components hashed
class names (cbIMud, gmtpxB, btcjit, etc.) — these are reliable but may change
on recompile
- Detected libraries: Next.js (framework), Bootstrap (grid), Styled Components (CSS-in-JS)
clusteringMethod: N/A — token source is extracted-css-vars, not reconstructed-from-computed.
Computed styles used only to supplement missing colour tokens and confirm radius values.
```More from the gallery
Browse all kits →You may also like

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

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

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