Brik Design System
Getting Started

The Cascade

How BDS tokens flow from Library → CSS Layer → consumer. Six disambiguated concepts (Anatomy, Tier, Library, Layer, Mode, Tenet) keep the system from drifting.

BDS resolves tokens through a strict cascade: Libraries define values, Tiers stack abstractions, Layers order the CSS @layer at runtime, and Modes vary values on orthogonal axes. Every consumer (portal, renew-pms, brikdesigns, every client site) follows the same path. Six words for six independent concepts — see Token Anatomy for the full disambiguation map.

The 30-second overview

LIBRARY                       TIER             LAYER                    MODE
─────────────────────────────────────────────────────────────────────────────────
Foundations Library      →    Raw → Primitive  →  @layer bds-tokens    × color
[Client] Brand Kit       →    Primitive →      →  @layer client-theme  × borderwidth
                              Semantic            @layer client-overrides  × spacing, etc.

                              Components consume Semantic only.

Different concepts, different words. Mixing them produces parallel-taxonomy drift (the failure mode that retired --theme-brik-* and --brand-{tier} in brik-bds#712).

CSS Layers — the runtime cascade

Every consumer's globals.css declares this @layer order before any imports:

@layer bds-tokens, bds-components, client-theme, client-overrides;

The four Layers, in cascade order (last wins):

LayerWhat lives hereEditable by consumers?
bds-tokensFoundations Library output (figma-tokens.css + figma-tokens-dark.css) — primitives + base semanticsNo — comes from BDS
bds-componentsBDS component CSS (@brikdesigns/bds/styles.css and per-component CSS files)No — comes from BDS
client-themeThe client's Brand Kit output (theme-{client}.css) — same semantic names, brand valuesYes — one per client
client-overridesPer-consumer surgical tweaks that don't belong in the Brand Kit (rare; should be temporary)Yes — keep small

Layer order is the contract. bds-tokens must declare before client-theme, and client-theme before client-overrides. Out-of-order @layer declarations break the Brand Kit's ability to override.

What's in the BDS bundle (bds-tokens + bds-components)

dist/tokens.css (shipped via @brikdesigns/bds/tokens.css) concatenates, in order:

FileLands inPurpose
figma-tokens.cssbds-tokensFoundations Library output — primitives + universal semantic defaults (light mode)
figma-tokens-dark.cssbds-tokensFoundations Library — dark mode (scoped to :root[data-theme="dark"])
theme-brand-brik.cssbds-tokensBrik's own Brand Kit baked into BDS (scoped to .theme-brand-brik) — present because Brik is BDS's first-party brand
modes-borderwidth.css, modes-spacing.cssbds-tokensMode mode overrides (see Modes below)
gap-fills.cssbds-tokensHand-authored bridge for tokens not yet in Figma — destined to migrate into Foundations Library
animations.cssbds-tokensShared keyframes (bds-spin, bds-pulse, etc.)

Do not import these files directly — they're internal to the bundle. Consumers import @brikdesigns/bds/tokens.css only. Deprecated or out-of-scope CSS:

  • bridge.css@deprecated; opt-in legacy aliases for projects not yet on canonical names
  • react-tokens.css, webflow-tokens.css, website-themes.css — superseded / surface-specific

What lives in the client-theme Layer

A consumer's theme-{client}.css overrides Brand Kit-controlled semantic tokens. Full matrix in Client Themes. Short version:

Token groupPer-client override?
Brand colors (--background-brand-primary, --text-brand-primary, --surface-brand-primary, --border-brand-primary)Required
Brand interaction states (--background-brand-primary-hover / -pressed)Required if brand colors change
Page + surface neutrals (--page-primary, --surface-primary, --surface-secondary)Recommended
Fonts (--font-family-heading / -body / -label)Optional
Status (--background-positive / -negative / -warning, etc.)Yes if brand red/green/yellow clashes
Extended status / presence / shadowsNo — system invariants

Theming Dimensions — composable per client

CSS Layers handle the values cascade. But Theming as a whole composes across four independent Theming Dimensions (each a separate decision a client makes):

Theming DimensionDecidesWhere it lives
TokensColor / type / spacing valuesBrand Kit Library → theme-{client}.css in client-theme Layer
AtmospheresAmbient decoration — grain, vignettes, orbs, spotlights@brikdesigns/bds/atmospheres/{slug}.css
Layout ArchetypesSite-header + footer shape, scroll + drawer behavior<SiteHeader> / <SiteFooter> from blueprints
BlueprintsSection composition — hero / services / testimonials shapesAuthored in BDS, tagged by mood + industry

A client picks values for each Dimension independently. Three different Dimensions == three different decisions — composing nothing cross-couples. Full Theming Tenet overview at Theming.

Atmospheres decorate; tokens decide values. Atmosphere CSS files MUST NOT override --page-*, --surface-*, --background-*, --text-*, or --border-* — those are Tokens-Dimension concerns. Atmosphere is for decorative-only properties (filters, masks, pseudo-element graphics, etc.).

Sibling Tenets — Motion and Content

The Theming Tenet handles per-client visual variation. Two peer Tenets handle the rest of what makes a client experience:

  • Motion Tenet — animation tokens (timing, easing, choreography) and motion behaviors. Canonical home: Motion.
  • Content Tenet — voice, tone, copy patterns, vocabularies (industries, brand voices, compliance). Canonical home: Content System.

Foundation, Theming, Motion, Content are the four Tenets of BDS. Tokens span Foundation (universal canon) and Theming (brand variation), but they're values inside the larger system, not the system itself.

Modes — orthogonal axes

A Mode varies a token's value on a system-wide axis any consumer can toggle. Modes are orthogonal to Library, Layer, and Tier — every semantic token can have per-mode values without changing its name.

<html data-theme="dark" data-mode-borderwidth="bold" data-mode-spacing="comfortable">
Mode collectionAttributeDefaultOther valuesWired?
colordata-theme (legacy attribute)lightdark
borderwidthdata-mode-borderwidthdefaultthin, bold
spacingdata-mode-spacingdefaultcompact, comfortable, spacious
border-radiusdata-mode-radiussoftsharp, round, pill#340
typographydata-mode-typographydefaultcompact, comfortable, spacious, expressivemodes-typography.css (heading-* only)
elevationdata-mode-elevationsubtleflat, lifted, dramatic⏳ #340
breakpointdata-mode-breakpointdefaultcompact, comfortable⏳ #340
icondata-mode-iconsolidoutline⏳ #340

Each wired mode emits a tokens/modes-{collection}.css file scoped via [data-mode-{collection}="value"]. Modes are not a substitute for Theming Dimensions (which compose subsystems per brand) or for Brand Kit overrides (which change values, not modes).

The typography axis is heading-scale-variant selection, not strictly density: compact/comfortable/spacious are uniform density steps, while expressive is a steeper modular curve (smaller small end, larger large end) for editorial / marketing surfaces. The variants are mutually exclusive — this axis owns --heading-* alone, so a second axis varying the same tokens is not added (it would collide on cascade order rather than compose). See ADR-013 amendment 2026-06-21.

Color foundations vocabulary

Semantic color tokens — the names components reference, and the only names a Brand Kit's theme-{client}.css should override:

FamilyConceptExamples
--page-*Page canvas (body fill)--page-primary, --page-secondary, --page-brand-primary
--surface-*Surfaces resting on the page (cards, navs, panels)--surface-primary, --surface-secondary, --surface-brand-primary
--background-*Interactive backgrounds (buttons, status fills, accents)--background-brand-primary, --background-positive, --background-input
--text-*Type colors--text-primary, --text-brand-primary, --text-on-color-dark
--border-*Edge colors--border-primary, --border-brand-primary, --border-input

Full registry at Color. Canonical bundle: dist/tokens.css.

Names not in the registry are not real. Inventing a --surface-paper, --text-on-ink, -soft / -warm modifier, or a --theme-brik-* / --brand-{tier} namespace creates parallel taxonomy drift. If you need a new token, add it to a Library first via Figma → Tokens Studio → Style Dictionary. See Token Anatomy for the closed forms.

<html> attribute switchboard

AttributeValuesEffect
data-themelight (default) / darkColor mode
data-mode-borderwidthdefault (omit) / thin / boldBorderwidth mode
data-mode-spacingdefault (omit) / compact / comfortable / spaciousSpacing density mode
data-audience / data-service / data-departmentPer-site conventionRe-binds canonical brand tokens within a subtree (multi-brand pattern — see Client Themes → scope binding)

Storybook's paintbrush toolbar sets data-theme automatically. React apps use <ThemeProvider>. Astro / Webflow / static consumers set attributes manually on <html>.

The adoption contract

This page is the canonical adoption contract: every consumer (portal, renew-pms, brikdesigns, every client site) wires the cascade the same way, and Installation links here as the one setup path. A consumer is compliant when all four hold:

  1. Declare the layer order@layer bds-tokens, bds-components, client-theme, client-overrides; before any imports (CSS Layers).
  2. Set the mode switches on <html>data-theme and any data-mode-* the consumer opts into (switchboard); omit an attribute to take the default.
  3. Import @brikdesigns/bds/tokens.css — never the internal bundle files directly, never a hand-rolled copy of a scale.
  4. Hold zero token redefinitions — see the rule below.

Consumers consume tokens; they do not redefine them. A consumer :root / theme / override block may not redefine a BDS-owned scale or semantic token — --heading-*, --display-*, --font-size-*, --surface-*, --text-*, --border-*, --page-*, --background-*. Redefining a real token (e.g. --heading-lg: var(--font-size-700)) is distinct from inventing one: it passes the "names not in the registry" check above yet still forks the system and drifts silently (the brikdesigns scaffold heading remap was load-bearing and invisible for ~3 months). The one exception is brand-color override via a Brand Kit theme-{client}.css in the client-theme Layer — that's the client-theme job. Need a value the scale doesn't have? Add it to a Library (Figma → Tokens Studio → Style Dictionary) or emit the Mode that carries it — never redefine in the consumer. See ADR-013.

Where the cascade is enforced

GateWhat it checksWhere it runs
scripts/lint-tokens.jsHex values in component CSS, nonexistent var() references, Primitives used outside their Semantic categoryBDS pre-commit + CI (npm run validate)
scripts/canonical-check.mjs--text-* / --surface-* / --background-* / --border-* / --color-* names exist in dist/tokens.cssBDS pre-commit + CI
@brikdesigns/bds/canonical-check (consumer dep)Same engine published for consumer reposConsumer pre-commit + CI via token-audit.sh --canonical-only
consumer-redefinition + typography family↔size ruleThe zero-redefinition clause above + font-family family matches font-size family within a ruleADR-013 §2 — BDS-owned export, imported by consumer lint-tokens

Run BDS gates locally: npm run validate. Consumer gates: ./scripts/token-audit.sh --canonical-only.

  • Token Anatomy — the six-concept disambiguation map + Tier abstraction stack
  • Library Architecture — Foundations vs Brand Kit Libraries + the Style Dictionary pipeline
  • Theming — full Theming Tenet (Tokens / Atmospheres / Layout / Blueprints Dimensions)
  • Client Themes — per-client override matrix + minimal theme-{client}.css template
  • Atmospheres — the Atmospheres Dimension
  • Color — full canonical color registry
  • tokens/CASCADE.md — file-level decision tree (cross-repo)

On this page