IBM
MIT
Enterprise-grade design system with IBM's iconic blue accent, sophisticated typography hierarchy, and fluid spacing built on Carbon principles—ideal for corporate products and SaaS platforms
Colour (47)
color.cdsfocus#0f62fe
color.ibmaccentrgb(15, 98, 254)
color.cdsbackground#fff
color.cdslayerhoverhsla(0, 0%, 55.3%, 0.12)
color.cdsicononcolor#fff
color.cdslinkprimaryrgb(15, 98, 254)
color.cdstextinverse#fff
color.cdstextoncolor#fff
color.primitivelabelrgb(51, 51, 51)
color.primitivered60rgb(218, 30, 40)
color.primitivered70rgb(184, 25, 33)
color.primitivered80rgb(117, 14, 19)
color.primitivewhitergb(255, 255, 255)
color.brandprimaryctargb(15, 98, 254)
color.cdstextdisabledrgba(22, 22, 22, 0.25)
color.primitiveblue40rgb(0, 67, 206)
color.primitiveblue60rgb(15, 98, 254)
color.primitiveblue70rgb(0, 80, 230)
color.primitiveblue80rgb(0, 45, 156)
color.primitivegray10rgb(244, 244, 244)
color.primitivegray30rgb(224, 224, 224)
color.primitivegray40rgb(141, 141, 141)
color.primitivegray60rgb(111, 111, 111)
color.primitivegray70rgb(82, 82, 82)
color.primitivegray80rgb(57, 57, 57)
color.cdslayeraccent01#e0e0e0
color.motionwrapborder@keyframes wrap-border {
0% { --percentage: 0%
color.primitiveblack100rgb(22, 22, 22)
color.cdsbackgroundhoverhsla(0, 0%, 55.3%, 0.12)
color.cdsbuttonseparator#e0e0e0
color.motioncdsstrokeend@keyframes cds--stroke-end {
0% { stroke-dashoffset: 52.5276
color.motionprefixstroke@keyframes prefix--stroke {
100% { stroke-dashoffset: 0
color.cdsbackgroundactivehsla(0, 0%, 55.3%, 0.5)
color.cdsbuttonfocuscolorvar(--cds-focus, #0f62fe)
color.cdslinkprimaryhover#0043ce
color.motioncdsinitstroke@keyframes cds--init-stroke {
0% { stroke-dashoffset: 276.461
color.cdsborderinteractive#0f62fe
color.cdsbuttondangerhover#b81921
color.cdsbuttondangeractive#750e13
color.cdsbuttonprimaryhover#0050e6
color.cdsbuttondangerprimary#da1e28
color.cdsbuttonprimaryactive#002d9c
color.cdsbuttontertiaryhover#0050e6
color.cdstextoncolordisabled#8d8d8d
color.cdsbuttonsecondaryhover#474747
color.cdsbuttontertiaryactive#002d9c
color.cdsbuttonsecondaryactive#6f6f6f
Spacing (26)
spacing.verticalspacingvar(--vertical-spacing-default)
spacing.cdslayoutsizeheightmin0px
spacing.cdslayoutdensitypaddinginlinemin0px
spacing.verticalspacingreducedcalc(var(--vertical-spacing-default) * 0.75)
spacing.spacexs1px
spacing.cdsgridmargin1.5rem
spacing.verticalspacingexpandedcalc(var(--vertical-spacing-default) * 1.5)
spacing.cdsgridgutter2rem
spacing.verticalspacingdefaultclamp(2rem, 0.9908rem + 3.6697cqi, 4rem)
spacing.cdslayoutdensitypaddinginlinecondensed8px
spacing.cdslayoutdensitypaddinginlinenormal16px
spacing.spacemd24px
spacing.ibmspacemd24px
spacing.cdslayoutsizeheightxs24px
spacing.spacelg32px
spacing.ibmspacelg32px
spacing.cdslayoutsizeheightsm32px
spacing.cdslayoutsizeheightmd40px
spacing.spacexl48px
spacing.ibmspacexl48px
spacing.cdslayoutsizeheightlg48px
spacing.cdslayoutsizeheightxl64px
spacing.space2xl72px
spacing.cdslayoutsizeheight2xl80px
spacing.cdslayoutsizeheightmax999999999px
spacing.cdslayoutdensitypaddinginlinemax999999999px
Radius (5)
radiussm0px 8px 0px 0px
radiusmd4px
ibmradiusmd4px
radiuslg8px 0px 0px
radiusfull28px
Shadow (5)
effect.cdsgridcolumns16
effect.ibmshadowfocusinset 0 0 0 1px #0f62fe, inset 0 0 0 2px #fff
effect.ibmshadowfocushalorgb(255, 255, 255) 0px 0px 0px 1px,
rgb(54, 153, 241) 0px 0px 0px 4px
effect.ibmshadowbtnseparator-0.0625rem 0 0 0 var(--cds-button-separator, #e0e0e0)
effect.ibmshadowbtnseparatorstacked0 -0.0625rem 0 0 var(--cds-button-separator, #e0e0e0)
# layout.md — IBM.com Design System
---
## 0. Quick Reference
**Stack:** IBM Carbon Design System · CSS custom properties (extracted-css-vars, medium confidence, 19 props found) · Vanilla CSS + Bootstrap detected · `--ibm-*` curated token prefix over original `--cds-*` vars.
**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
:root {
/* Colour */
--ibm-accent: rgb(15, 98, 254); /* IBM Blue — primary CTA, links, h3 text */
/* Typography */
--ibm-font-sans: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;
--ibm-font-mono: "IBM Plex Mono", "Courier New", monospace;
--ibm-font-size-xs: 13.3333px; /* Pagination labels */
--ibm-font-size-sm: 14px; /* Body small, labels, links */
--ibm-font-size-md: 16px; /* Body default, buttons, tabs */
--ibm-font-size-lg: 21.8824px; /* Lead paragraph */
--ibm-font-size-2xl: 42px; /* Stats / callout numbers */
--ibm-font-size-3xl: 53.6469px; /* H1 / H2 display */
--ibm-font-weight-regular: 300; /* Display headings */
--ibm-font-weight-medium: 400; /* Body, buttons, nav */
--ibm-font-weight-semibold: 600; /* Section labels, emphasis */
/* Spacing */
--ibm-space-md: 24px; /* Component internal padding */
--ibm-space-lg: 32px; /* Heading margin-bottom */
--ibm-space-xl: 48px; /* Section sub-gaps */
/* Layout */
--cds-grid-columns: 16; /* Carbon 16-column grid */
--cds-grid-gutter: 2rem; /* 32px column gutter */
--cds-grid-margin: 1.5rem; /* 24px page margin */
--vertical-spacing-default: clamp(2rem, 0.9908rem + 3.6697cqi, 4rem); /* Fluid section gap */
/* Motion */
--ibm-duration-fast: 0.07s; /* Micro-interactions */
--ibm-ease-default: ease; /* Default easing */
--ibm-ease-productive: cubic-bezier(0.2, 0, 0.38, 0.9); /* Carbon productive motion */
}
```
```tsx
// Primary CTA Button — IBM Carbon pattern
const PrimaryButton = ({ label, onClick, disabled }: ButtonProps) => (
<button
className="cds--btn cds--btn--primary"
onClick={onClick}
disabled={disabled}
style={{
backgroundColor: disabled ? 'transparent' : 'var(--ibm-accent)',
color: '#ffffff',
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-md)',
fontWeight: 'var(--ibm-font-weight-medium)',
padding: '0 var(--ibm-space-md)',
height: 'var(--cds-layout-size-height-lg)', /* 48px */
borderRadius: '0px',
border: 'none',
cursor: disabled ? 'not-allowed' : 'pointer',
transition: 'background-color var(--ibm-duration-fast) var(--ibm-ease-productive)',
}}
>
{label}
</button>
);
```
**NEVER rules:**
- **NEVER** use `border-radius` > 0 on Carbon buttons — IBM buttons are square (0px radius)
- **NEVER** use Inter, Roboto, or system-ui as the primary font — always `"IBM Plex Sans"` first
- **NEVER** hardcode `#0f62fe` — always use `var(--ibm-accent)` or `var(--cds-border-interactive, #0f62fe)`
- **NEVER** use spacing values off the 4px grid — no `1px` gaps or arbitrary margins
- **NEVER** use fewer than 16 grid columns — IBM Carbon uses a 16-column grid, not 12
- **NEVER** omit hover/focus/active/disabled states on interactive elements — Carbon enforces all four
- **NEVER** use `font-weight: 700` (bold) — IBM Plex Sans weight scale tops at `600` (semibold)
<!-- Quick Reference truncated to fit the 75-line cap. See later sections for the full design system. -->
## 1. Design Direction & Philosophy
### Character & Aesthetic Intent
IBM.com expresses **enterprise precision and technical authority**. The visual language is derived from the IBM Carbon Design System — a rigorously structured, accessibility-first system built for global scale.
**Mood:** Professional, intelligent, confident. Not warm. Not playful. Not decorative.
**Primary visual signals:**
- **Sharp geometry everywhere** — `border-radius: 0px` on all buttons, cards, inputs, modals. The only rounded element is the Watson chat launcher button (28px), which is a third-party widget anomaly.
- **Type-led hierarchy** — scale jumps from 14px body small to 53.6px display are dramatic and intentional. Headlines at `font-weight: 300` create an unexpected lightness against IBM Blue accents.
- **Monochromatic with one electric blue** — `rgb(15, 98, 254)` is the sole accent. It appears on CTAs, links, h3 text, and interactive states. All other UI is black (`#161616`), white, and neutral grays.
- **16-column grid discipline** — content is always contained in the Carbon grid. Sections never break out of the column structure.
### What This Design Explicitly Rejects
- **NEVER** rounded corners on interactive components (buttons, inputs, cards, tabs)
- **NEVER** drop shadows for card elevation — Carbon uses border or background-color to differentiate surfaces
- **NEVER** warm colour tones (orange, yellow, red except for semantic danger states)
- **NEVER** decorative typography (serif for display, mixed font stacks for personality)
- **NEVER** dense information layouts — generous whitespace between sections via `clamp(2rem, ..., 4rem)` vertical rhythm
- **NEVER** pill-shaped buttons on brand UI — the 28px radius on the chat launcher is a chat widget, not an IBM brand pattern
---
## 2. Colour System
### Tier 1 — Primitive Values
```css
:root {
/* Blues */
--primitive-blue-60: rgb(15, 98, 254); /* #0f62fe — IBM Blue 60 */
--primitive-blue-70: rgb(0, 80, 230); /* #0050e6 — Blue 70, hover */
--primitive-blue-80: rgb(0, 45, 156); /* #002d9c — Blue 80, active */
--primitive-blue-40: rgb(0, 67, 206); /* #0043ce — link hover */
/* Neutrals */
--primitive-black-100: rgb(22, 22, 22); /* #161616 — IBM Black */
--primitive-gray-80: rgb(57, 57, 57); /* #393939 — secondary button bg */
--primitive-gray-70: rgb(82, 82, 82); /* #525252 — button_primary text (nav context) */
--primitive-gray-60: rgb(111, 111, 111); /* #6f6f6f — secondary active bg */
--primitive-gray-40: rgb(141, 141, 141); /* #8d8d8d — disabled text */
--primitive-gray-30: rgb(224, 224, 224); /* #e0e0e0 — button separator */
--primitive-gray-10: rgb(244, 244, 244); /* #f4f4f4 — input bg, tab bg */
--primitive-white: rgb(255, 255, 255); /* #ffffff — text on dark, modal bg */
--primitive-label: rgb(51, 51, 51); /* #333333 — label/dropdown text */
/* Semantic feedback */
--primitive-red-60: rgb(218, 30, 40); /* #da1e28 — danger primary */
--primitive-red-70: rgb(184, 25, 33); /* #b81921 — danger hover */
--primitive-red-80: rgb(117, 14, 19); /* #750e13 — danger active */
}
```
### Tier 2 — Semantic Aliases (original `--cds-*` names preserved)
```css
:root {
/* Interactive */
--ibm-accent: rgb(15, 98, 254); /* = --brand-primary-cta; primary action, links, h3 */
--cds-border-interactive: #0f62fe; /* definition term hover/focus underline */
--cds-focus: #0f62fe; /* focus ring inset colour */
--cds-background: #fff; /* page/modal background for focus ring offset */
/* Button semantic tokens (Carbon originals) */
--cds-button-primary-hover: #0050e6; /* primary button :hover bg */
--cds-button-primary-active: #002d9c; /* primary button :active bg */
--cds-button-secondary-hover: #474747; /* secondary button :hover bg */
--cds-button-secondary-active: #6f6f6f; /* secondary button :active bg */
--cds-button-tertiary-hover: #0050e6; /* tertiary button :hover bg */
--cds-button-tertiary-active: #002d9c; /* tertiary button :active bg */
--cds-button-danger-primary: #da1e28; /* danger CTA fill */
--cds-button-danger-hover: #b81921; /* danger :hover */
--cds-button-danger-active: #750e13; /* danger :active */
--cds-button-focus-color: var(--cds-focus, #0f62fe); /* focus ring colour */
--cds-button-separator: #e0e0e0; /* button set divider */
/* Text */
--cds-text-on-color: #fff; /* text on coloured backgrounds */
--cds-text-on-color-disabled: #8d8d8d; /* disabled text on colour */
--cds-text-disabled: rgba(22, 22, 22, 0.25); /* disabled text on white */
--cds-text-inverse: #fff; /* text-inverse on dark surfaces */
--cds-link-primary: rgb(15, 98, 254); /* default link colour */
--cds-link-primary-hover: #0043ce; /* link :hover */
/* Surfaces */
--cds-layer-hover: hsla(0, 0%, 55.3%, 0.12); /* ghost button hover overlay */
--cds-background-hover: hsla(0, 0%, 55.3%, 0.12); /* ghost button hover bg */
--cds-background-active: hsla(0, 0%, 55.3%, 0.5); /* ghost button active bg */
--cds-layer-accent-01: #e0e0e0; /* skeleton shimmer base */
/* Feedback / danger */
--cds-icon-on-color: #fff; /* icon on coloured surfaces */
}
```
### Tier 3 — Component Tokens
| Component | Property | Token | Value |
|---|---|---|---|
| Primary button | background | `--cds-button-primary` | `var(--ibm-accent)` |
| Primary button hover | background | `--cds-button-primary-hover` | `#0050e6` |
| Primary button active | background | `--cds-button-primary-active` | `#002d9c` |
| Secondary button | background | `--cds-button-secondary` | `rgb(57, 57, 57)` |
| Input | background | — | `rgb(244, 244, 244)` |
| Tab (inactive) | background | — | `rgb(244, 244, 244)` |
| H3 / subsection heading | color | `--ibm-accent` | `rgb(15, 98, 254)` |
| Body text | color | `--primitive-black-100` | `rgb(22, 22, 22)` |
| Disabled text | color | `--cds-text-on-color-disabled` | `#8d8d8d` |
---
## 3. Typography System
### Font Stack
```css
:root {
--ibm-font-sans: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif; /* primary — all UI */
--ibm-font-mono: "IBM Plex Mono", "Courier New", monospace; /* code, data */
--ibm-font-serif: "IBM Plex Serif", Georgia, serif; /* long-form editorial (rare) */
/* Note: Helvetica and Source Sans Pro loaded via consent banner — NOT brand fonts */
}
```
### Composite Type Scales
```css
:root {
/* ── Display / H1 ── */
--type-display: {
font-family: var(--ibm-font-sans);
font-size: 53.6469px; /* --ibm-font-size-3xl */
font-weight: 300; /* --ibm-font-weight-regular — intentionally light */
line-height: 62.7669px; /* ~1.17 ratio */
letter-spacing: normal;
/* Used on: h1, primary h2 */
}
/* ── H2 / Section Title ── */
--type-heading-2: {
font-family: var(--ibm-font-sans);
font-size: 53.6469px;
font-weight: 300;
line-height: 62.7669px;
letter-spacing: normal;
/* margin-bottom: 32px (h2) or 64px (h1) */
}
/* ── H3 / Subsection ── */
--type-heading-3: {
font-family: var(--ibm-font-sans);
font-size: 32px;
font-weight: 400; /* --ibm-font-weight-medium */
line-height: 40px;
letter-spacing: normal;
color: var(--ibm-accent); /* IBM Blue — h3 rendered in brand blue */
/* margin-bottom: 32px */
}
/* ── Stats / Callout Number ── */
--type-stat: {
font-family: var(--ibm-font-sans);
font-size: 42px; /* --ibm-font-size-2xl */
font-weight: 400;
line-height: 52px; /* inferred ~1.24 */
letter-spacing: normal;
}
/* ── Lead Paragraph ── */
--type-lead: {
font-family: var(--ibm-font-sans);
font-size: 21.8824px; /* --ibm-font-size-lg */
font-weight: 400;
line-height: 28px;
letter-spacing: normal;
}
/* ── Body Default ── */
--type-body: {
font-family: var(--ibm-font-sans);
font-size: 20px; /* body computed style */
font-weight: 400;
line-height: 28px;
letter-spacing: normal;
}
/* ── Body / UI Default (Carbon body-01) ── */
--type-body-sm: {
font-family: var(--ibm-font-sans);
font-size: 16px; /* --ibm-font-size-md */
font-weight: 400;
line-height: 24px;
letter-spacing: normal;
}
/* ── Label / Helper / Link ── */
--type-label: {
font-family: var(--ibm-font-sans); /* Helvetica for consent forms only */
font-size: 14px; /* --ibm-font-size-sm */
font-weight: 400;
line-height: 18px; /* --ibm-line-height-tight */
letter-spacing: 0.16px;
/* Used on: labels, links, badges, button secondary, tooltips, dropdowns */
}
/* ── Caption / Micro ── */
--type-caption: {
font-family: var(--ibm-font-sans);
font-size: 13.3333px; /* --ibm-font-size-xs */
font-weight: 400;
line-height: 18px;
letter-spacing: 0.16px;
/* Used on: pagination, footnotes */
}
/* ── Section Eyebrow ── */
--type-eyebrow: {
font-family: var(--ibm-font-sans);
font-size: 16px;
font-weight: 600; /* --ibm-font-weight-semibold */
line-height: 22px; /* --ibm-line-height-normal */
letter-spacing: normal;
/* Used on: "Recommended for you" labels */
}
}
```
### Weight Scale
| Token | Value | Usage |
|---|---|---|
| `--ibm-font-weight-regular` | `300` | Display headings (h1, h2) |
| `--ibm-font-weight-medium` | `400` | Body, UI, buttons, nav |
| `--ibm-font-weight-semibold` | `600` | Section labels, emphasis |
**Note:** `300` is named "regular" in the IBM token system — this is not a typo. IBM Plex Sans Light (300) is the display weight.
---
## 4. Spacing & Layout
### Spacing Scale
```css
:root {
/* Component height scale (Carbon layout sizing) */
--cds-layout-size-height-xs: 24px; /* icon buttons, compact rows */
--cds-layout-size-height-sm: 32px; /* small inputs, compact buttons */
--cds-layout-size-height-md: 40px; /* default inputs */
--cds-layout-size-height-lg: 48px; /* large buttons, standard CTAs */
--cds-layout-size-height-xl: 64px; /* navigation bar height */
--cds-layout-size-height-2xl: 80px; /* hero CTAs, jumbo inputs */
/* Inline padding density (Carbon layout density) */
--cds-layout-density-padding-inline-condensed: 8px; /* tight mode */
--cds-layout-density-padding-inline-normal: 16px; /* default mode */
/* Curated spacing scale */
--ibm-space-md: 24px; /* component padding, label margin */
--ibm-space-lg: 32px; /* heading margin-bottom, section rhythm */
--ibm-space-xl: 48px; /* dropdown margin, card gaps */
/* Fluid vertical section spacing */
--vertical-spacing-default: clamp(2rem, 0.9908rem + 3.6697cqi, 4rem); /* 32px → 64px fluid */
--vertical-spacing-reduced: calc(var(--vertical-spacing-default) * 0.75);
--vertical-spacing-expanded: calc(var(--vertical-spacing-default) * 1.5);
--vertical-spacing: var(--vertical-spacing-default); /* apply this to section gaps */
/* DO NOT USE: --ibm-space-xs (1px) or --ibm-space-2xl (999999999px) — both are off-grid artifacts */
}
```
### Grid System
```css
:root {
--cds-grid-columns: 16; /* IBM Carbon 16-column grid — not 12 */
--cds-grid-gutter: 2rem; /* 32px between columns */
--cds-grid-margin: 1.5rem; /* 24px page edge margin */
}
/* Carbon grid applied */
.ibm-grid {
display: grid;
grid-template-columns: repeat(var(--cds-grid-columns), 1fr);
gap: var(--cds-grid-gutter);
margin-inline: var(--cds-grid-margin);
}
```
### Breakpoints
IBM Carbon uses these named breakpoints (inferred from media query census):
| Name | Width | Notes |
|---|---|---|
| `sm` | 320px | Mobile start |
| `md` | 672px | Tablet |
| `lg` | 1056px | Desktop |
| `xlg` | 1312px | Wide desktop |
| `max` | 1584px | Full-width cap |
Additional breakpoints at 768px, 1024px, 1200px detected (likely legacy or Bootstrap overlap).
---
## 5. Page Structure & Layout Patterns
> **Source:** Inferred from LAYOUT DIGEST component inventory, computed styles, and CTA census. No screenshots available. Rows marked `(inferred)` are not visually confirmed.
### 5.1 Section Map
| Order | Section | Layout Type | Approx. Height | Key Elements |
|---|---|---|---|---|
| 1 | Global Navigation | `display:block`, sticky | 64px (`--cds-layout-size-height-xl`) | Logo, nav links (16px/400), search, menu |
| 2 | Hero / Masthead | Full-width, 16-col grid | 480–720px (inferred) | H1 (53.6px/300), lead text, primary CTA (IBM Blue) |
| 3 | Feature Card Grid | Grid, 4-up or 3-up | ~400px (inferred) | 143 card instances detected; cards `display:block`, no shadow |
| 4 | Stats / Callout Band | Flex row, full-width | ~200px (inferred) | 42px stat numbers, `--ibm-font-size-2xl` |
| 5 | Content / Editorial | 2-col grid (text + image) | ~600px (inferred) | H3 in IBM Blue, body 20px/400, secondary CTAs |
| 6 | Tabbed Content Section | Role=tab pattern | ~500px (inferred) | `role_tab` with `background: rgb(244,244,244)`, 32px padding, `border-radius: 4px 0 0 4px` on active |
| 7 | Dropdown / Filter Section | Block, 16-col | ~120px (inferred) | Dropdown with `margin: 24px 0 48px`, 14px text |
| 8 | Newsletter / Subscribe | Block with input | ~300px (inferred) | Input (`bg: rgb(244,244,244)`), subscribe button |
| 9 | Modal / Dialog | Overlay | Full viewport | `role_dialog`, `display:inline`, IBM Blue focus ring |
| 10 | Footer | Block, 16-col, multi-row | ~400px (inferred) | Nav links 14px/400, legal text 13.3px |
### 5.2 Layout Patterns
**Navigation:**
- `display: block` container; internal items use `display: flex, flex-direction: row`
- Height locked to `--cds-layout-size-height-xl` (64px)
- No border-radius, no shadow — flat bar
**Hero:**
- 16-column grid; headline typically spans 8–12 cols at `lg` breakpoint (inferred)
- H1 at `53.6469px / 300 weight` — counterintuitively light for maximum scale impact
- Primary CTA: IBM Blue (`rgb(15, 98, 254)`), `height: 48px`, `border-radius: 0px`, `padding: 16px`
**Card Grid:**
- `display: block` per card; grid container wraps at 1–4 columns across breakpoints
- No `box-shadow` — surface differentiation via background color only
- Card icon/accent in IBM Blue (`rgb(15, 98, 254)`)
- Gap: `var(--cds-grid-gutter)` = 32px
**Tab Component:**
- Active tab: `background: rgb(244, 244, 244)`, `border-radius: 4px 0px 0px 4px`, `padding: 32px`
- Transition: `background 0.3s cubic-bezier(0.2, 0, 0.38, 0.9)` (Carbon productive easing)
- Inactive tabs: `filter: grayscale(1) opacity(0.8)`
**Content Columns:**
- 2-column at `lg`+: text (left, ~8 cols) + media (right, ~8 cols) (inferred)
- Column gap: `var(--cds-grid-gutter)` (32px)
### 5.3 Visual Hierarchy
1. **H1/H2 display text** at 53.6px/300 — largest element, low weight for elegant scale
2. **IBM Blue** (`#0f62fe`) as the single accent — all CTAs, links, and H3 rendered in this colour
3. **Primary CTA buttons** — IBM Blue fill, white text, 48px height, square corners; always visible above the fold
4. **Cards** are flat (no shadow) — hierarchy from whitespace and type scale, not elevation
5. **Section rhythm** driven by `clamp(2rem, ..., 4rem)` vertical-spacing — sections breathe
### 5.4 Content Patterns
**Card pattern (143 instances):**
- Icon or image (IBM Blue icon font `ibm_icons`)
- H3 or label (IBM Blue, 14–16px)
- Body text (black, 14–16px)
- Link or CTA (`display:flex, gap:4px, align:center` — icon+text inline)
**Link pattern:**
- `display: flex`, `flex-direction: row`, `align-items: center`, `gap: 4px`
- IBM Blue text + trailing arrow icon from `ibm_icons` font
- `margin-bottom: 16px` between stacked links
**CTA census result:**
- Primary button: IBM Blue (`rgb(15, 98, 254)`) — confirmed on 2+ detected instances
- Secondary button: Dark gray (`rgb(57, 57, 57)`) — `display:flex, justify-content:space-between` with trailing icon
- Ghost/tertiary: transparent background, IBM Blue text
---
## 6. Component Patterns
### 6.1 Button — Primary (`cds--btn--primary`)
**Anatomy:** Container → Label text → Optional trailing icon
**State table:**
| State | Background | Text | Border | Shadow |
|---|---|---|---|---|
| Default | `rgb(15, 98, 254)` | `#fff` | none | none |
| Hover | `var(--cds-button-primary-hover, #0050e6)` | `#fff` | none | none |
| Focus | `rgb(15, 98, 254)` | `#fff` | none | `inset 0 0 0 1px #0f62fe, inset 0 0 0 2px #fff` |
| Active | `var(--cds-button-primary-active, #002d9c)` | `#fff` | none | none |
| Disabled | transparent | `#8d8d8d` | none | none |
```tsx
import { useState } from 'react';
interface PrimaryButtonProps {
label: string;
onClick?: () => void;
disabled?: boolean;
loading?: boolean;
}
export const PrimaryButton = ({ label, onClick, disabled, loading }: PrimaryButtonProps) => {
const [isFocused, setIsFocused] = useState(false);
return (
<button
onClick={onClick}
disabled={disabled || loading}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
gap: '1rem',
height: 'var(--cds-layout-size-height-lg)', /* 48px */
paddingInline: 'var(--cds-layout-density-padding-inline-normal)', /* 16px */
backgroundColor: disabled || loading ? 'transparent' : 'var(--ibm-accent)',
color: disabled ? 'var(--cds-text-on-color-disabled, #8d8d8d)' : 'var(--cds-text-on-color, #fff)',
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-md)', /* 16px */
fontWeight: 'var(--ibm-font-weight-medium)', /* 400 */
lineHeight: 'var(--ibm-font-size-md)',
borderRadius: '0px', /* NEVER round IBM buttons */
border: 'none',
cursor: disabled ? 'not-allowed' : 'pointer',
boxShadow: isFocused
? 'inset 0 0 0 1px var(--cds-button-focus-color, #0f62fe), inset 0 0 0 2px var(--cds-background, #fff)'
: 'none',
transition: `background-color var(--ibm-duration-fast) var(--ibm-ease-productive),
box-shadow var(--ibm-duration-fast) var(--ibm-ease-productive)`,
}}
onMouseOver={(e) => {
if (!disabled && !loading) {
(e.currentTarget as HTMLButtonElement).style.backgroundColor =
'var(--cds-button-primary-hover, #0050e6)';
}
}}
onMouseOut={(e) => {
if (!disabled && !loading) {
(e.currentTarget as HTMLButtonElement).style.backgroundColor = 'var(--ibm-accent)';
}
}}
onMouseDown={(e) => {
if (!disabled && !loading) {
(e.currentTarget as HTMLButtonElement).style.backgroundColor =
'var(--cds-button-primary-active, #002d9c)';
}
}}
onMouseUp={(e) => {
if (!disabled && !loading) {
(e.currentTarget as HTMLButtonElement).style.backgroundColor = 'var(--ibm-accent)';
}
}}
>
{loading ? <span aria-label="Loading…" className="cds--loading" /> : label}
{!loading && <span aria-hidden="true" style={{ fontFamily: 'ibm_icons' }}>→</span>}
</button>
);
};
```
---
### 6.2 Button — Secondary (`cds--btn--secondary`)
**Anatomy:** Container (`flex, space-between`) → Label → Trailing icon
| State | Background | Text |
|---|---|---|
| Default | `rgb(57, 57, 57)` | `#fff` |
| Hover | `var(--cds-button-secondary-hover, #474747)` | `#fff` |
| Focus | `rgb(57, 57, 57)` + inset shadow | `#fff` |
| Active | `var(--cds-button-secondary-active, #6f6f6f)` | `#fff` |
| Disabled | transparent | `#8d8d8d` |
Extracted styles: `display:flex`, `justify-content:space-between`, `align-items:center`, `padding: 1px 0px 1px 16px`, `border-radius:0px`, `font-size:14px`, `letter-spacing:0.16px`.
---
### 6.3 Input
**Anatomy:** Label → Input field → Helper text / Error message
| State | Background | Border-bottom | Text |
|---|---|---|---|
| Default | `rgb(244, 244, 244)` | — | `rgb(22, 22, 22)` |
| Focus | `rgb(244, 244, 244)` | IBM Blue focus ring | `rgb(22, 22, 22)` |
| Disabled | [TBD — extract manually] | — | `rgba(22,22,22,0.25)` |
| Error | [TBD — extract manually] | `#da1e28` | `rgb(22, 22, 22)` |
Extracted styles: `padding: 0px 16px`, `border-radius: 0px`, `font-size: 14px`, `letter-spacing: 0.16px`, `line-height: 18px`.
Transition: `background-color 0.07s cubic-bezier(0.2, 0, 0.38, 0.9), outline 0.07s cubic-bezier(0.2, 0, 0.38, 0.9)`.
```tsx
export const TextInput = ({ label, id, placeholder, disabled, error }: InputProps) => (
<div style={{ display: 'block' }}>
<label
htmlFor={id}
style={{
display: 'block',
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-sm)', /* 14px */
fontWeight: 'var(--ibm-font-weight-medium)', /* 400 */
lineHeight: '18px',
letterSpacing: '0.16px',
color: 'rgb(51, 51, 51)',
margin: '16px 0 8px',
}}
>
{label}
</label>
<input
id={id}
placeholder={placeholder}
disabled={disabled}
aria-invalid={!!error}
style={{
display: 'block',
width: '100%',
height: 'var(--cds-layout-size-height-md)', /* 40px */
padding: '0 var(--cds-layout-density-padding-inline-normal)',
backgroundColor: 'rgb(244, 244, 244)',
border: 'none',
borderBottom: error ? '2px solid #da1e28' : '1px solid transparent',
borderRadius: '0px',
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-sm)',
color: disabled ? 'rgba(22,22,22,0.25)' : 'rgb(22, 22, 22)',
transition: 'background-color 0.07s cubic-bezier(0.2, 0, 0.38, 0.9), outline 0.07s cubic-bezier(0.2, 0, 0.38, 0.9)',
cursor: disabled ? 'not-allowed' : 'text',
}}
/>
{error && (
<p style={{ color: '#da1e28', fontSize: 'var(--ibm-font-size-sm)', margin: '4px 0 0' }}>
{error}
</p>
)}
</div>
);
```
---
### 6.4 Card
**Anatomy:** Icon/image → Tag/Badge → Heading → Body text → Link CTA
| State | Background | Border | Shadow |
|---|---|---|---|
| Default | transparent | none | none |
| Hover | [TBD — extract manually] | none | none |
| Focus | focus ring via outline | — | — |
| Disabled | [TBD] | — | — |
Extracted styles: `display:block`, `border-radius:0px`, `padding:0px`, no `box-shadow`. Icon color: `rgb(15, 98, 254)`.
```tsx
export const IBMCard = ({ tag, heading, body, linkLabel, href }: CardProps) => (
<article
style={{
display: 'block',
borderRadius: '0px', /* NEVER add border-radius to cards */
padding: '0',
backgroundColor: 'transparent',
}}
>
{tag && (
<span style={{
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-sm)',
fontWeight: 'var(--ibm-font-weight-medium)',
color: 'rgb(22, 22, 22)',
lineHeight: '18px',
letterSpacing: '0.16px',
display: 'block',
marginBottom: '8px',
}}>
{tag}
</span>
)}
<h3 style={{
fontFamily: 'var(--ibm-font-sans)',
fontSize: '32px',
fontWeight: 'var(--ibm-font-weight-medium)',
lineHeight: '40px',
color: 'var(--ibm-accent)', /* h3 always IBM Blue */
marginBottom: 'var(--ibm-space-lg)',
}}>
{heading}
</h3>
<p style={{
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-md)',
fontWeight: 'var(--ibm-font-weight-medium)',
lineHeight: '24px',
color: 'rgb(22, 22, 22)',
}}>
{body}
</p>
<a
href={href}
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
gap: '4px',
fontFamily: 'var(--ibm-font-sans)',
fontSize: 'var(--ibm-font-size-sm)',
fontWeight: 'var(--ibm-font-weight-medium)',
color: 'var(--ibm-accent)',
textDecoration: 'none',
marginBottom: 'var(--ibm-space-md)',
}}
>
{linkLabel}
</a>
</article>
);
```
---
### 6.5 Tab (`role="tab"`)
**Anatomy:** Tab list → Tab buttons → Tab panel
| State | Background | Filter | Radius |
|---|---|---|---|
| Inactive | `rgb(244, 244, 244)` | `grayscale(1) opacity(0.8)` | `4px 0 0 4px` |
| Active | `rgb(244, 244, 244)` | `none` | `4px 0 0 4px` |
| Hover | `var(--cds-layer-hover)` | — | `4px 0 0 4px` |
| Focus | focus ring inset | none | `4px 0 0 4px` |
Extracted: `padding:32px`, `display:flex`, `justify-content:center`, `align-items:center`.
Transition: `background 0.3s cubic-bezier(0.2, 0, 0.38, 0.9), filter 0.3s cubic-bezier(0.2, 0, 0.38, 0.9)`.
---
### 6.6 Tooltip
Extracted: `font-size:14px`, `line-height:18px`, `border-radius:0px`, `text-align:left`, `padding:0`. Background and border color [TBD — extract manually from tooltip open state].
---
### 6.7 Dropdown
Extracted: `font-size:14px`, `line-height:14px`, `letter-spacing:normal`, `padding:0 16px`, `border-radius:0px`, `color:rgb(51,51,51)`, `margin:24px 0 48px`.
---
## 7. Elevation & Depth
IBM Carbon explicitly avoids shadow-based elevation. Surfaces are differentiated by **background color and borders only**.
```css
:root {
/* IBM Carbon uses NO decorative box-shadows for elevation */
/* The only shadows are functional: focus rings and button separators */
/* Focus ring — applied via box-shadow inset */
--ibm-shadow-focus:
inset 0 0 0 1px var(--cds-button-focus-color, #0f62fe),
inset 0 0 0 2px var(--cds-background, #fff);
/* Button set separator */
--ibm-shadow-btn-separator:
-0.0625rem 0 0 0 var(--cds-button-separator, #e0e0e0);
/* Stacked button separator */
--ibm-shadow-btn-separator-stacked:
0 -0.0625rem 0 0 var(--cds-button-separator, #e0e0e0);
/* Accessibility focus (consent/TrustArc): distinct blue halo */
--ibm-shadow-focus-halo:
rgb(255, 255, 255) 0px 0px 0px 1px,
rgb(54, 153, 241) 0px 0px 0px 4px;
}
```
### Z-Index Scale
```css
:root {
/* Inferred from Carbon popover and sticky header usage */
--z-base: 1;
--z-dropdown: 1000;
--z-sticky: 1100;
--z-popover: 6001; /* --cds-popover-tab-tip z-index extracted */
--z-modal: 9000; /* inferred from role_dialog */
--z-toast: 9100; /* inferred */
--z-tooltip: 9200; /* inferred */
}
```
**Layering principle:** No shadows. Overlapping surfaces use `z-index` + solid background, never `box-shadow: 0 4px 8px rgba(0,0,0,0.1)` style decorative shadows.
---
## 8. Motion
```css
:root {
/* Duration */
--ibm-duration-fast: 0.07s; /* micro: input bg, button bg — extracted */
--ibm-duration-moderate: 0.3s; /* tabs, tooltips, tooltipfade — extracted from role_tab */
--ibm-duration-slow: [TBD — extract manually]; /* page transitions */
/* Easing */
--ibm-ease-default: ease; /* generic — extracted */
--ibm-ease-productive: cubic-bezier(0.2, 0, 0.38, 0.9); /* Carbon productive — extracted from input/tab */
--ibm-ease-expressive: cubic-bezier(0.4, 0.14, 0.3, 1); /* Carbon expressive — inferred */
}
```
### Keyframe Animations (extracted)
| Name | Purpose | Duration |
|---|---|---|
| `cds--skeleton` | Skeleton loading shimmer | Continuous |
| `cds--tooltip-fade` | Tooltip appear/disappear | `--ibm-duration-moderate` |
| `cds--hide-feedback` | Copy feedback disappear | `--ibm-duration-fast` |
| `cds--show-feedback` | Copy feedback appear | `--ibm-duration-fast` |
| `cds--progress-bar-indeterminate` | Progress bar loading | Continuous |
| `expand` / `collapse` | Accordion open/close | `--ibm-duration-moderate` |
| `sticky-header-slide-in` | Nav re-attach on scroll | `--ibm-duration-moderate` |
| `fp-fade-in` / `fp-fade-out` | Slide/carousel transitions | `--ibm-duration-moderate` |
### Motion Rules
- **Micro-interactions** (button bg, input bg): `0.07s ease` — barely perceptible, feels responsive
- **Component state changes** (tab active, tooltip): `0.3s cubic-bezier(0.2, 0, 0.38, 0.9)` — productive motion
- **Skeleton loading**: Use `cds--skeleton` keyframe animation — never fake with opacity pulse alone
- **NEVER animate layout properties** (width, height, margin) — only `background-color`, `opacity`, `transform`, `box-shadow`
- **Respect prefers-reduced-motion** — wrap all animations in `@media (prefers-reduced-motion: no-preference)`
---
## 9. Anti-Patterns & Constraints
1. **Hardcoded colour values → Why it fails → What to do instead.**
AI agents default to writing `color: #0f62fe` directly in component code. When IBM updates brand blue or when theming is applied, all hardcoded values must be manually hunted down across the codebase. **Use `var(--ibm-accent)` or `var(--cds-border-interactive, #0f62fe)` everywhere. The fallback value documents intent while the variable enables theming.**
2. **Rounded button corners → Why it fails → What to do instead.**
Agents trained on Bootstrap/Material patterns automatically add `border-radius: 4px` or `border-radius: 8px` to buttons. IBM Carbon buttons are **strictly square** (`border-radius: 0px`). Adding any radius breaks the Carbon design language and fails IBM brand review. **Explicitly set `border-radius: 0` on every button, input, card, and tab. Only the Watson chat launcher (a third-party widget) uses 28px radius — do not use this as a precedent.**
3. **Wrong font family → Why it fails → What to do instead.**
Agents default to Inter, Roboto, or system-ui because these are the most common modern web fonts. IBM.com's entire identity is built on IBM Plex Sans. Using any other font breaks typographic brand fidelity immediately. **Always declare `font-family: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif` — never omit the "IBM Plex Sans" first entry, never swap in Inter or Roboto.**
4. **12-column grid instead of 16 → Why it fails → What to do instead.**
Bootstrap and most CSS frameworks use 12-column grids. Agents trained on Bootstrap will generate `col-md-6` (6/12 = 50%) for two-column layouts, which is technically correct but misses Carbon's intent. IBM Carbon uses **16 columns** (`--cds-grid-columns: 16`) — a 50% column is 8 of 16 columns. **Always specify `grid-template-columns: repeat(16, 1fr)` and size spans accordingly.**
5. **Arbitrary spacing values → Why it fails → What to do instead.**
Agents generate `margin: 20px` or `padding: 15px` when they approximate spacing from visual inspection. IBM Carbon uses a strict 8px base grid with `--cds-layout-size-height-*` and `--ibm-space-*` tokens. Off-grid values (e.g. the extracted `1px` space) break visual rhythm and fail grid alignment. **Every margin and padding must map to a spacing token. If no token exists, round to the nearest 8px multiple.**
6. **Missing interactive states → Why it fails → What to do instead.**
Agents frequently implement only `default` and `hover` states, omitting `focus`, `active`, and `disabled`. IBM Carbon's accessibility requirements mandate visible `focus` rings (the inset double-ring: `inset 0 0 0 1px #0f62fe, inset 0 0 0 2px #fff`) and explicit `disabled` cursor (`not-allowed`). Missing these causes WCAG failures. **Implement all five states: default, hover, focus, active, disabled — in every interactive component.**
7. **Box shadows for card elevation → Why it fails → What to do instead.**
Agents applying Material Design conventions add `box-shadow: 0 2px 8px rgba(0,0,0,0.15)` to cards to signal elevation. IBM Carbon explicitly rejects decorative shadows — all surface elevation is expressed through background colour (`rgb(244,244,244)` vs `#ffffff`) or subtle border. **NEVER add decorative box-shadow to cards, modals, or panels. Use background-color differentiation only.**
8. **Dynamic Tailwind class construction → Why it fails → What to do instead.**
In Tailwind projects, agents write `className={\`bg-[\${color}]\`}` with dynamic interpolation. Tailwind's JIT compiler cannot scan dynamic string concatenation and will purge the class, rendering the component unstyled in production. **Always use complete static class names: `bg-[var(--ibm-accent)]`. For truly dynamic values, use inline `style` with CSS custom properties.**
9. **Using font-weight 700 (bold) → Why it fails → What to do instead.**
Agents default to `font-weight: bold` or `font-weight: 700` for emphasis. IBM Plex Sans's weight scale tops at `600` (SemiBold). Weight 700 is not included in any of the loaded font files and will cause the browser to synthesise a faux-bold, degrading typographic quality. **Use `--ibm-font-weight-semibold: 600` for maximum emphasis. Never use 700 or `bold`.**
10. **Inline styles over CSS custom properties → Why it fails → What to do instead.**
Agents writing quick components hardcode `style={{ backgroundColor: '#0f62fe' }}` as a shortcut. This makes theming impossible, breaks dark mode support, and creates maintenance debt. Every literal value must be traced to its source when the brand updates. **Always reference design tokens: `style={{ backgroundColor: 'var(--ibm-accent)' }}`. Inline styles are acceptable only when they reference CSS custom properties.**
11. **Absolute positioning for layout structure → Why it fails → What to do instead.**
Agents use `position: absolute` to align nav items or card badges because it "works" visually at one viewport. IBM Carbon's navigation and grid are built on `display:flex` and `display:grid`. Absolute positioning breaks responsive reflow and accessibility tab order. **Use `display: flex` with `justify-content` and `align-items`, or `display: grid` with the 16-column system. Reserve `position: absolute` only for true overlays (tooltips, popovers, modals).**
12. **Adding `!important` to override Carbon → Why it fails → What to do instead.**
When integrating with the existing Carbon stylesheet, agents add `!important` to "win" specificity battles. This creates an unresolvable specificity arms race and makes the stylesheet unmaintainable. It also signals that the component is fighting the design system rather than working with it. **Understand Carbon's BEM class structure (`cds--btn--primary`) and apply overrides at the same or higher specificity using the component's own class hierarchy, or use CSS custom property overrides at `:root`.**
---
## 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 (43) */
--brand-primary-cta: rgb(15, 98, 254); /* Primary CTA background, dominant on 2 buttons — e.g. "Wechseln" /* mined from computed styles */ */
--ibm-accent: rgb(15, 98, 254);
--primitive-blue-60: rgb(15, 98, 254);
--primitive-blue-70: rgb(0, 80, 230);
--primitive-blue-80: rgb(0, 45, 156);
--primitive-blue-40: rgb(0, 67, 206);
--primitive-black-100: rgb(22, 22, 22);
--primitive-gray-80: rgb(57, 57, 57);
--primitive-gray-70: rgb(82, 82, 82);
--primitive-gray-60: rgb(111, 111, 111);
--primitive-gray-40: rgb(141, 141, 141);
--primitive-gray-30: rgb(224, 224, 224);
--primitive-gray-10: rgb(244, 244, 244);
--primitive-white: rgb(255, 255, 255);
--primitive-label: rgb(51, 51, 51);
--primitive-red-60: rgb(218, 30, 40);
--primitive-red-70: rgb(184, 25, 33);
--primitive-red-80: rgb(117, 14, 19);
--cds-border-interactive: #0f62fe;
--cds-focus: #0f62fe;
--cds-background: #fff;
--cds-button-primary-hover: #0050e6;
--cds-button-primary-active: #002d9c;
--cds-button-secondary-hover: #474747;
--cds-button-secondary-active: #6f6f6f;
--cds-button-tertiary-hover: #0050e6;
--cds-button-tertiary-active: #002d9c;
--cds-button-danger-primary: #da1e28;
--cds-button-danger-hover: #b81921;
--cds-button-danger-active: #750e13;
--cds-button-focus-color: var(--cds-focus, #0f62fe);
--cds-button-separator: #e0e0e0;
--cds-text-on-color: #fff;
--cds-text-on-color-disabled: #8d8d8d;
--cds-text-disabled: rgba(22, 22, 22, 0.25);
--cds-text-inverse: #fff;
--cds-link-primary: rgb(15, 98, 254);
--cds-link-primary-hover: #0043ce;
--cds-layer-hover: hsla(0, 0%, 55.3%, 0.12);
--cds-background-hover: hsla(0, 0%, 55.3%, 0.12);
--cds-background-active: hsla(0, 0%, 55.3%, 0.5);
--cds-layer-accent-01: #e0e0e0;
--cds-icon-on-color: #fff;
/* Typography (33) */
--cds-layout-size-height-xs: 24px;
--cds-layout-size-height-sm: 32px;
--cds-layout-size-height-md: 40px;
--cds-layout-size-height-lg: 48px;
--cds-layout-size-height-xl: 64px;
--cds-layout-size-height-2xl: 80px;
--cds-layout-size-height-min: 0px;
--cds-layout-size-height-max: 999999999px;
--font-size-xs: 13.3333px; /* 4 elements — e.g. button "1", button "2", button "3" /* mined from computed styles */ */
--font-size-sm: 14px; /* 35 elements — e.g. span "Webinar", span "Insight", span "Report" /* mined from computed styles */ */
--font-size-md: 16px; /* 57 elements — e.g. h5 "Recommended for you", p "A New Way to Make AI", p "IBM Launches Sports " /* mined from computed styles */ */
--font-size-lg: 21.8824px; /* 5 elements — e.g. p "From next-generation", span "From next-generation", a "software" /* mined from computed styles */ */
--font-size-2xl: 42px; /* 2 elements — e.g. div "USD 4.5 Billion", div "15K" /* mined from computed styles */ */
--font-size-3xl: 53.6469px; /* 6 elements — e.g. h1 "Become an AI-first e", h2 "Products announced a", h2 "Smarter business. Re" /* mined from computed styles */ */
--font-weight-regular: 300; /* 6 elements — e.g. h1 "Become an AI-first e", h2 "Products announced a", h2 "Smarter business. Re" /* mined from computed styles */ */
--font-weight-medium: 400; /* 108 elements — e.g. h2 "Stay connected", h2 "What's New at IBM ne", h3 "IBM" /* mined from computed styles */ */
--font-weight-semibold: 600; /* 1 element — e.g. h5 "Recommended for you" /* mined from computed styles */ */
--line-height-tight: 18.0001px; /* 34 elements — e.g. span "Webinar", span "Insight", span "Report" /* mined from computed styles */ */
--line-height-normal: 22px; /* 15 elements — e.g. p "Sie scheinen sich in", span "Explore 5 plays to b", span "See what you missed " /* mined from computed styles */ */
--ibm-font-sans: "IBM Plex Sans", "Helvetica Neue", Arial, sans-serif;
--ibm-font-mono: "IBM Plex Mono", "Courier New", monospace;
--ibm-font-size-xs: 13.3333px;
--ibm-font-size-sm: 14px;
--ibm-font-size-md: 16px;
--ibm-font-size-lg: 21.8824px;
--ibm-font-size-2xl: 42px;
--ibm-font-size-3xl: 53.6469px;
--ibm-font-weight-regular: 300;
--ibm-font-weight-medium: 400;
--ibm-font-weight-semibold: 600;
--ibm-font-serif: "IBM Plex Serif", Georgia, serif;
--ibm-line-height-tight: 18.0001px;
--ibm-line-height-normal: 22px;
/* Spacing (24) */
--cds-grid-gutter: 2rem;
--cds-grid-margin: 1.5rem;
--cds-layout-density-padding-inline-condensed: 8px;
--cds-layout-density-padding-inline-normal: 16px;
--cds-layout-density-padding-inline-min: 0px;
--cds-layout-density-padding-inline-max: 999999999px;
--vertical-spacing-default: clamp(2rem, 0.9908rem + 3.6697cqi, 4rem);
--vertical-spacing-reduced: calc(var(--vertical-spacing-default) * 0.75);
--vertical-spacing-expanded: calc(var(--vertical-spacing-default) * 1.5);
--vertical-spacing: var(--vertical-spacing-default);
--space-xs: 1px; /* 4 elements — e.g. div .cmp-tabs__tabs-container, div .cmp-tabs__tabs-container, div .cmp-tabs__tabs-container /* mined from computed styles */ */
--space-md: 24px; /* 2 elements — e.g. div .tile-group-container, div .tile-group-container /* mined from computed styles */ */
--space-lg: 32px; /* 17 elements — e.g. section .cds--grid, section .cds--grid, section .cds--grid /* mined from computed styles */ */
--space-xl: 48px; /* 3 elements — e.g. div .tile-group-container, div .tile-group-container, div .intro-section--flex /* mined from computed styles */ */
--space-2xl: 72px; /* 1 element — e.g. div .cds--row /* mined from computed styles */ */
--ibm-space-md: 24px;
--ibm-space-lg: 32px;
--ibm-space-xl: 48px;
--cds-layout-size-height-xs: 24px;
--cds-layout-size-height-sm: 32px;
--cds-layout-size-height-md: 40px;
--cds-layout-size-height-lg: 48px;
--cds-layout-size-height-xl: 64px;
--cds-layout-size-height-2xl: 80px;
/* Radius (5) */
--radius-sm: 0px 8px 0px 0px; /* 4 elements — e.g. button .cds--btn--icon-only, button .cds--btn--icon-only, button .cds--btn--icon-only /* mined from computed styles */ */
--radius-md: 4px; /* 1 element — e.g. button .mktoButton "Subscribe" /* mined from computed styles */ */
--radius-lg: 8px 0px 0px; /* 2 elements — e.g. button .cds--btn--icon-only, button .cds--btn--icon-only /* mined from computed styles */ */
--radius-full: 28px; /* 2 elements — e.g. button .WACLauncher__Button, button .WACLauncher__Button /* mined from computed styles */ */
--ibm-radius-md: 4px;
/* Effects (5) */
--cds-grid-columns: 16;
--ibm-shadow-focus: inset 0 0 0 1px #0f62fe, inset 0 0 0 2px #fff;
--ibm-shadow-btn-separator: -0.0625rem 0 0 0 var(--cds-button-separator, #e0e0e0);
--ibm-shadow-btn-separator-stacked: 0 -0.0625rem 0 0 var(--cds-button-separator, #e0e0e0);
--ibm-shadow-focus-halo: rgb(255, 255, 255) 0px 0px 0px 1px,
rgb(54, 153, 241) 0px 0px 0px 4px;
/* Motion (78) */
----motion-cds--hide-feedback: @keyframes cds--hide-feedback {
0% { opacity: 1; visibility: inherit; }
100% { opacity: 0; visibility: hidden; }
}; /* @keyframes cds--hide-feedback */
----motion-cds--show-feedback: @keyframes cds--show-feedback {
0% { opacity: 0; visibility: hidden; }
100% { opacity: 1; visibility: inherit; }
}; /* @keyframes cds--show-feedback */
----motion-cds--skeleton: @keyframes cds--skeleton {
0% { opacity: 0.3; transform: scaleX(0); transform… <0.5KB elided>; /* @keyframes cds--skeleton */
----motion-cds--tooltip-fade: @keyframes cds--tooltip-fade {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes cds--tooltip-fade */
----motion-expand: @keyframes expand {
0% { max-block-size: 0px; overflow-y: hidden; }
100% { max-block-size: 100%; }
}; /* @keyframes expand */
----motion-collapse: @keyframes collapse {
0% { max-block-size: 100vh; }
100% { max-block-size: 0px; }
}; /* @keyframes collapse */
----motion-loading-animation: @keyframes loading-animation {
0% { background-position: 0px 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0px 50%; }
}; /* @keyframes loading-animation */
----motion-sticky-header-slide-in: @keyframes sticky-header-slide-in {
0% { inset-block-start: -100%; }
100% { inset-block-start: var(--c4d-sticky-header-height); }
}; /* @keyframes sticky-header-slide-in */
----motion-loadingAnimation: @keyframes loadingAnimation {
0% { background-position: 0px 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0px 50%; }
}; /* @keyframes loadingAnimation */
----motion-spin: @keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(1turn); }
}; /* @keyframes spin */
----motion-ajo-jc-skeleton-pulse: @keyframes ajo-jc-skeleton-pulse {
0% { opacity: 1; }
50% { opacity: 0.4; }
100% { opacity: 1; }
}; /* @keyframes ajo-jc-skeleton-pulse */
----motion-ajo-tc-skeleton-pulse: @keyframes ajo-tc-skeleton-pulse {
0% { opacity: 1; }
50% { opacity: 0.4; }
100% { opacity: 1; }
}; /* @keyframes ajo-tc-skeleton-pulse */
----motion-wrap-border: @keyframes wrap-border {
0% { --percentage: 0%; }
100% { --percentage: 100%; }
}; /* @keyframes wrap-border */
----motion-fp-fade-in-down: @keyframes fp-fade-in-down {
0% { opacity: 0; transform: translate3d(0px, -20px, 0px); }
100% { opacity: 1; transform: translateZ(0px); }
}; /* @keyframes fp-fade-in-down */
----motion-fp-slide-left: @keyframes fp-slide-left {
0% { transform: translateZ(0px); }
100% { transform: translate3d(-100%, 0px, 0px); }
}; /* @keyframes fp-slide-left */
----motion-fp-slide-left-new: @keyframes fp-slide-left-new {
0% { transform: translate3d(100%, 0px, 0px); }
100% { transform: translateZ(0px); }
}; /* @keyframes fp-slide-left-new */
----motion-fp-slide-right: @keyframes fp-slide-right {
0% { transform: translateZ(0px); }
100% { transform: translate3d(100%, 0px, 0px); }
}; /* @keyframes fp-slide-right */
----motion-fp-slide-right-new: @keyframes fp-slide-right-new {
0% { transform: translate3d(-100%, 0px, 0px); }
100% { transform: translateZ(0px); }
}; /* @keyframes fp-slide-right-new */
----motion-fp-fade-out: @keyframes fp-fade-out {
0% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes fp-fade-out */
----motion-fp-fade-in: @keyframes fp-fade-in {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes fp-fade-in */
----motion-cds--rotate: @keyframes cds--rotate {
0% { transform: rotate(0deg); }
100% { transform: rotate(1turn); }
}; /* @keyframes cds--rotate */
----motion-cds--rotate-end-p1: @keyframes cds--rotate-end-p1 {
100% { transform: rotate(1turn); }
}; /* @keyframes cds--rotate-end-p1 */
----motion-cds--rotate-end-p2: @keyframes cds--rotate-end-p2 {
100% { transform: rotate(-1turn); }
}; /* @keyframes cds--rotate-end-p2 */
----motion-cds--init-stroke: @keyframes cds--init-stroke {
0% { stroke-dashoffset: 276.461; }
100% { stroke-dashoffset: 52.5276; }
}; /* @keyframes cds--init-stroke */
----motion-cds--stroke-end: @keyframes cds--stroke-end {
0% { stroke-dashoffset: 52.5276; }
100% { stroke-dashoffset: 276.461; }
}; /* @keyframes cds--stroke-end */
----motion-prefix--stroke: @keyframes prefix--stroke {
100% { stroke-dashoffset: 0; }
}; /* @keyframes prefix--stroke */
----motion-cds--progress-bar-indeterminate: @keyframes cds--progress-bar-indeterminate {
0% { background-position-x: 25%; }
80%, 100% { background-position-x: -105%; }
}; /* @keyframes cds--progress-bar-indeterminate */
----motion-cds--progress-bar-indeterminate-rtl: @keyframes cds--progress-bar-indeterminate-rtl {
0% { background-position-x: -105%; }
80%, 100% { background-position-x: 25%; }
}; /* @keyframes cds--progress-bar-indeterminate-rtl */
----motion-ai-skeleton-animation: @keyframes ai-skeleton-animation {
0% { transform: translateX(-100%); }
100% { transform: translateX(100%); }
}; /* @keyframes ai-skeleton-animation */
----motion-WACFadeIn: @keyframes WACFadeIn {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes WACFadeIn */
----motion-WACFadeInUp: @keyframes WACFadeInUp {
0% { opacity: 0; transform: translateY(32px); }
50% { transform: translateY(0px); }
100% { opacity: 1; }
}; /* @keyframes WACFadeInUp */
----motion-WACFadeOut: @keyframes WACFadeOut {
0% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes WACFadeOut */
----motion-WACSlideInFromRight: @keyframes WACSlideInFromRight {
0% { left: 100%; }
100% { left: 0px; }
}; /* @keyframes WACSlideInFromRight */
----motion-WACSlideOutToRight: @keyframes WACSlideOutToRight {
0% { left: 0px; }
100% { left: 100%; }
}; /* @keyframes WACSlideOutToRight */
----motion-WACSlideOutToTop: @keyframes WACSlideOutToTop {
0% { top: 0px; }
100% { top: -100%; }
}; /* @keyframes WACSlideOutToTop */
----motion-WACSlideInFromLeft: @keyframes WACSlideInFromLeft {
0% { right: 100%; }
100% { right: 0px; }
}; /* @keyframes WACSlideInFromLeft */
----motion-WACSlideOutToLeft: @keyframes WACSlideOutToLeft {
0% { right: 0px; }
100% { right: 100%; }
}; /* @keyframes WACSlideOutToLeft */
----motion-WACSlideInFromBottom: @keyframes WACSlideInFromBottom {
0% { top: 100%; }
100% { top: 0px; }
}; /* @keyframes WACSlideInFromBottom */
----motion-WACSlideOutToBottom: @keyframes WACSlideOutToBottom {
0% { top: 0px; }
100% { top: 100%; }
}; /* @keyframes WACSlideOutToBottom */
----motion-WACLauncherIn: @keyframes WACLauncherIn {
0% { bottom: calc(var(--cds-chat-LAUNCHER-position-bottom) - 16px); opacity: 0; }
100% { bottom: var(--cds-chat-LAUNCHER-position-bottom); opacity: 1; }
}; /* @keyframes WACLauncherIn */
----motion-WACAnimateHeight: @keyframes WACAnimateHeight {
0% { height: var(--cds-chat-Animate-Start-Height); }
100% { height: var(--cds-chat-Animate-End-Height); }
}; /* @keyframes WACAnimateHeight */
----motion-WACFadeInUpBackButton: @keyframes WACFadeInUpBackButton {
0% { opacity: 0; transform: translate(-50%… <0.2KB elided>; /* @keyframes WACFadeInUpBackButton */
----motion-WACAnimAlternateSuggestionsContainer__Button--slide-in: @keyframes WACAnimAlternateSuggestionsContainer__Button--slide-in {
0% { bottom: -48px; }
100% { bottom: 6px; }
}; /* @keyframes WACAnimAlternateSuggestionsContainer__Button--slide-in */
----motion-WACAnimAlternateSuggestionsContainer__Button--slide-out: @keyframes WACAnimAlternateSuggestionsContainer__Button--slide-out {
0% { bottom: 0px; }
100% { bottom: -48px; }
}; /* @keyframes WACAnimAlternateSuggestionsContainer__Button--slide-out */
----motion-WACAnimAlternateSuggestionsContainer__Button--bounce-in: @keyframes WACAnimAlternateSuggestionsContainer__Button--bounce-in {
0% { bottom: 6px; }
100% { bottom: 0px; }
}; /* @keyframes WACAnimAlternateSuggestionsContainer__Button--bounce-in */
----motion-WACAnimAlternateSuggestionsOptionsPanel: @keyframes WACAnimAlternateSuggestionsOptionsPanel {
0% { top: var(--cds-chat… <0.2KB elided>; /* @keyframes WACAnimAlternateSuggestionsOptionsPanel */
----motion-WACLauncherBounce: @keyframes WACLauncherBounce {
0% { transform: translateY(0px); }
30% { tra… <0.2KB elided>; /* @keyframes WACLauncherBounce */
----motion-WACAnimLauncherComplex__FadeInSlideUp: @keyframes WACAnimLauncherComplex__FadeInSlideUp {
0% { bottom: calc(16px + v… <0.4KB elided>; /* @keyframes WACAnimLauncherComplex__FadeInSlideUp */
----motion-WACAnimLauncherComplex__FadeInText: @keyframes WACAnimLauncherComplex__FadeInText {
0% { opacity: 0; }
40% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes WACAnimLauncherComplex__FadeInText */
----motion-WACAnimLauncherComplex__SmallLauncherResizeReposition: @keyframes WACAnimLauncherComplex__SmallLauncherResizeReposition {
0% { right… <0.4KB elided>; /* @keyframes WACAnimLauncherComplex__SmallLauncherResizeReposition */
----motion-WACAnimLauncherComplex__SmallLauncherResizeRepositionRTL: @keyframes WACAnimLauncherComplex__SmallLauncherResizeRepositionRTL {
0% { le… <0.4KB elided>; /* @keyframes WACAnimLauncherComplex__SmallLauncherResizeRepositionRTL */
----motion-WACAnimLauncherComplex__FadeInCloseButton: @keyframes WACAnimLauncherComplex__FadeInCloseButton {
0% { opacity: 0; }
80% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes WACAnimLauncherComplex__FadeInCloseButton */
----motion-WACAnimLauncherComplex__AvatarResize: @keyframes WACAnimLauncherComplex__AvatarResize {
0% { height: 32px; width: 32px; }
100% { height: 48px; width: 48px; }
}; /* @keyframes WACAnimLauncherComplex__AvatarResize */
----motion-WACAnimLauncherComplex__FadeInSlideUpSmallExpandedLauncher: @keyframes WACAnimLauncherComplex__FadeInSlideUpSmallExpandedLauncher {
0% { bottom: -160px; opacity: 0; }
30% { opacity: 0; }
100% { bottom: -80px; opacity: 1; }
}; /* @keyframes WACAnimLauncherComplex__FadeInSlideUpSmallExpandedLauncher */
----motion-WACAnimLauncherComplex__FadeOutSlideDown: @keyframes WACAnimLauncherComplex__FadeOutSlideDown {
0% { bottom: 64px; back… <0.4KB elided>; /* @keyframes WACAnimLauncherComplex__FadeOutSlideDown */
----motion-WACAnimLauncherComplex__FadeOut: @keyframes WACAnimLauncherComplex__FadeOut {
0% { opacity: 1; }
40% { opacity: 0; }
100% { opacity: 0; }
}; /* @keyframes WACAnimLauncherComplex__FadeOut */
----motion-WACAnimLauncherComplex__SmallLauncherDefaultSizePosition: @keyframes WACAnimLauncherComplex__SmallLauncherDefaultSizePosition {
0% { ri… <0.4KB elided>; /* @keyframes WACAnimLauncherComplex__SmallLauncherDefaultSizePosition */
----motion-WACAnimLauncherComplex__SmallLauncherDefaultSizePositionRTL: @keyframes WACAnimLauncherComplex__SmallLauncherDefaultSizePositionRTL {
0% {… <0.4KB elided>; /* @keyframes WACAnimLauncherComplex__SmallLauncherDefaultSizePositionRTL */
----motion-WACLauncherIconTo32: @keyframes WACLauncherIconTo32 {
0% { width: 24px; }
100% { width: 32px; }
}; /* @keyframes WACLauncherIconTo32 */
----motion-WACLauncherIconTo24: @keyframes WACLauncherIconTo24 {
0% { width: 32px; }
100% { width: 24px; }
}; /* @keyframes WACLauncherIconTo24 */
----motion-WACLauncherPartiallyRound: @keyframes WACLauncherPartiallyRound {
0% { border-radius: 28px; }
100% { border-radius: 14px; }
}; /* @keyframes WACLauncherPartiallyRound */
----motion-WACLauncherCompletelyRound: @keyframes WACLauncherCompletelyRound {
0% { border-radius: 14px; }
100% { border-radius: 28px; }
}; /* @keyframes WACLauncherCompletelyRound */
----motion-WACLauncherExtend: @keyframes WACLauncherExtend {
0% { width: var(--cds-chat-LAUNCHER-default-size); }
100% { width: var(--cds-chat--LAUNCHER-EXTENDED-width); }
}; /* @keyframes WACLauncherExtend */
----motion-WACLauncherReduce: @keyframes WACLauncherReduce {
0% { width: var(--cds-chat--LAUNCHER-EXTENDED-width); }
100% { width: var(--cds-chat-LAUNCHER-default-size); }
}; /* @keyframes WACLauncherReduce */
----motion-WACLauncherExtendedElementFadeIn: @keyframes WACLauncherExtendedElementFadeIn {
0% { bottom: -12px; opacity: 0; }
50%, 100% { bottom: 0px; opacity: 1; }
}; /* @keyframes WACLauncherExtendedElementFadeIn */
----motion-WACLauncherExtendedElementFadeOut: @keyframes WACLauncherExtendedElementFadeOut {
0% { top: 0px; opacity: 1; }
50%, 100% { top: -12px; opacity: 0; }
}; /* @keyframes WACLauncherExtendedElementFadeOut */
----motion-swiper-preloader-spin: @keyframes swiper-preloader-spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(1turn); }
}; /* @keyframes swiper-preloader-spin */
----motion-WACfadeInImg: @keyframes WACfadeInImg {
0% { opacity: 0; filter: grayscale(100%); }
100% { opacity: 1; filter: grayscale(0); }
}; /* @keyframes WACfadeInImg */
----motion-WACWidgetIn: @keyframes WACWidgetIn {
0% { bottom: calc(var(--cds-chat-BASE-bottom-position) - 32px); opacity: 0; }
100% { bottom: var(--cds-chat-BASE-bottom-position); opacity: 1; }
}; /* @keyframes WACWidgetIn */
----motion-WACWidgetOut: @keyframes WACWidgetOut {
0% { opacity: 1; }
100% { opacity: 0; }
}; /* @keyframes WACWidgetOut */
----motion-WACAnimBackgroundCover: @keyframes WACAnimBackgroundCover {
0% { opacity: 0; }
100% { opacity: 0.5; }
}; /* @keyframes WACAnimBackgroundCover */
----motion-WACLoadingBar__ConnectingAnimationKeyFrames: @keyframes WACLoadingBar__ConnectingAnimationKeyFrames {
0% { background-position: 0px 0px; }
100% { background-position: -200% 0px; }
}; /* @keyframes WACLoadingBar__ConnectingAnimationKeyFrames */
----motion-WACMessageIn: @keyframes WACMessageIn {
0% { opacity: 0; }
100% { opacity: 1; }
}; /* @keyframes WACMessageIn */
----motion-spin-flow-status: @keyframes spin-flow-status {
0% { transform: rotate(0deg); }
100% { transform: rotate(1turn); }
}; /* @keyframes spin-flow-status */
----motion-c-inline-spinner-kf: @keyframes c-inline-spinner-kf {
0% { transform: rotate(0deg); }
100% { transform: rotate(1turn); }
}; /* @keyframes c-inline-spinner-kf */
----motion-shimmer: @keyframes shimmer {
0% { stroke: var(--cds-layer-accent-01,#e0e0e0); }
20% { stroke: rgb(255, 255, 255); opacity: 0.5; }
100% { stroke: var(--cds-layer-accent-01,#e0e0e0); }
}; /* @keyframes shimmer */
--duration-fast: 0.07s; /* 52 elements — e.g. button, button, button /* mined from computed styles */ */
--ease-default: ease; /* 219 elements — e.g. button, button, button /* mined from computed styles */ */
```
## Appendix B: Token Source Metadata
```
tokenSource: extracted-css-vars
site: ibm.com
extractionDate: [TBD]
confidence: medium
cssVarsFound: 19 custom properties in :root / computed styles
curatedTokens: 24 tokens mapped to --ibm-* prefix
librariesDetected: IBM Carbon Design System (cds--* classes), Bootstrap (overlap)
fontFiles: IBM Plex Sans (300/400/600 normal+italic), IBM Plex Mono (300/400/600),
IBM Plex Serif (300/400/600 via Watson widget), ibm_icons (icon font)
```
**Confidence notes:**
- `--ibm-accent: rgb(15, 98, 254)` — **high confidence** (extracted from `--brand-primary-cta`, confirmed on 2+ button computed styles and h3 color)
- Font size/weight tokens — **high confidence** (extracted from multiple element computed styles with element counts)
- `--ibm-space-md/lg/xl` — **high confidence** (appear in heading margins, component padding, dropdown margins)
- `--ibm-radius-sm: 0px 8px 0px 0px` and `--ibm-radius-lg: 8px 0px 0px` — **low confidence for brand use** (found only on `cds--btn--icon-only` elements; likely Carbon internal; NEVER use for standard buttons)
- `--ibm-radius-full: 28px` — **low confidence for brand use** (found only on Watson chat launcher widget, not IBM brand UI)
- `--ibm-space-2xl: 999999999px` — **excluded as artifact** (maps to `--cds-layout-density-padding-inline-max`, a Carbon sentinel value, not a real spacing token)
- Colour tokens beyond `--ibm-accent` — **medium confidence** (synthesised from button hover/active CSS rules which reference Carbon fallback values)
- Section layout (Section 5) — **inferred** (no screenshots; derived from component inventory counts: 143 cards, 53 buttons, 54 content instances, computed style layout properties)
**Clustering method for synthesised tokens:**
Spacing values clustered into 8px grid multiples: 8px (condensed density), 16px (normal density), 24px, 32px, 48px. Values of `1px` and `999999999px` excluded as off-grid artifacts. Colour values clustered by hue family (IBM Blue at #0f62fe with hover/active variants at -10E/#0050e6 and -20E/#002d9c).More from the gallery
Browse all kits →You may also like

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

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

Monzo
MITDark, modern fintech design system with navy foundations, coral accents, and fluid typography—built for fast-moving financial products and developer teams
00
darkfintechdeveloper-toolsaas