Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

CSS Architecture

This document details how the generated CSS works. Whether you use the CLI or the Runtime, the underlying CSS model is the same.

Generated Tokens

When you run the Theme Builder (CLI or UI), it generates a CSS rule for each surface. Inside that rule, it assigns values to a standard set of Local Tokens.

For a surface named card, the .surface-card class defines:

TokenDescription
--surface-tokenThe background color of the surface itself.
--text-high-tokenThe color for high-emphasis text (e.g., headings) on this surface.
--text-subtle-tokenThe color for medium-emphasis text (e.g., body) on this surface.
--text-subtlest-tokenThe color for low-emphasis text (e.g., metadata) on this surface.
--border-dec-tokenA low-contrast border color for decorative separation.
--border-int-tokenA higher-contrast border color for interactive boundaries (inputs, buttons).

How they are used

These tokens are scoped to the surface class. They reuse the same names (e.g., --text-high-token) but have different values depending on which surface you are inside.

.surface-card {
  /* The background uses the surface token directly */
  --surface-token: light-dark(...);

  /* The text tokens are exposed to children via Context Variables */
  --context-text-high: var(--text-high-token);
  --context-text-subtle: var(--text-subtle-token);
  --context-text-subtlest: var(--text-subtlest-token);
  --context-border-decorative: var(--border-dec-token);
  --context-border-interactive: var(--border-int-token);
}

This means you rarely use --text-high-token directly. Instead, you use the utility class .text-strong, which consumes --context-text-high.

The Context Model

We use a Context Provider/Consumer pattern to handle composition and nesting. This allows surfaces to be nested infinitely without the child needing to know about the parent.

1. Provider (The Surface)

A surface class (like .surface-card) does two things:

  1. Sets its own background: It uses the generated token for its background color.
  2. Sets the Context: It redefines the “meaning” of generic variables for its children.
.surface-card {
  /* 1. Set Background */
  background-color: var(--lightness-surface-card);

  /* 2. Set Context for Children */
  /* "When inside a card, 'subtle text' should look like this..." */
  --context-text-subtle: var(--lightness-subtle-on-card);
  --context-border-decorative: var(--border-decorative-on-card);
}

2. Consumer (The Utility)

A utility class (like .text-subtle) is “dumb”. It doesn’t know what color it is. It just asks the context.

.text-subtle {
  /* "I don't know where I am, but I'll use whatever my parent says is 'subtle'" */
  --surface-text-lightness: var(--context-text-subtle);
}

Why this matters

This ensures Orthogonality:

  • Adding a new surface doesn’t require updating every utility class.
  • You can nest a .surface-card inside a .surface-sidebar inside a .surface-page, and the text will always have the correct contrast for its immediate parent.

Accessibility Implementation

The system handles accessibility automatically through Taxonomy Alignment.

Forced Colors (Windows High Contrast)

We use a Variable Swap trick to support Forced Colors mode without needing manual overrides for every surface.

  1. The Engine: All surfaces use the variable --computed-surface for their background.
  2. The Swap: In engine.css, we detect Forced Colors mode and swap the definition of that variable globally.
/* Normal Mode */
:root {
  /* Calculated from tokens */
  --computed-surface: oklch(...);
}

/* Forced Colors Mode */
@media (forced-colors: active) {
  :root {
    /* Swapped to System Color */
    --computed-surface: Canvas;
    --computed-fg-color: CanvasText;
  }
}

What this means for you:

  • Custom Surfaces: Any surface you create (e.g., .surface-sidebar) automatically becomes Canvas (Background) and CanvasText (Foreground) in High Contrast mode. You don’t need to do anything.
  • Semantic Overrides: If you are building a custom button surface, you may want to map it to ButtonFace. You can do this with a simple CSS override:
@media (forced-colors: active) {
  .surface-my-button {
    --computed-surface: ButtonFace;
    --computed-fg-color: ButtonText;
  }
}

High Contrast (APCA)

Good News: The default themes generated by this system are already highly accessible.

  • Body text targets Lc 60+ (roughly WCAG AA/AAA).
  • Headings target Lc 75+.
  • Spotlights target Lc 90.

For most users, the standard theme is sufficient.

Prefers Contrast Some users explicitly request even higher contrast via their OS settings (prefers-contrast: more). This is supported on macOS and Windows.

The system automatically handles this by generating a High Contrast Variant during the build process. This variant:

  1. Widens Anchors: Pushes background and foreground anchors to pure Black (0%) and White (100%).
  2. Desaturates: Removes chroma from text and surfaces to reduce visual noise.

This variant is automatically appended to your theme.css inside a @media (prefers-contrast: more) block.

/* Standard Theme (Default) */
.surface-card {
  ...;
}

/* High Contrast Override (Automatic) */
@media (prefers-contrast: more) {
  :root {
    --base-chroma: 0; /* Force Grayscale */
  }
  .surface-card {
    /* Re-generated tokens with widened anchors */
    --surface-token: ...;
    --text-subtle-token: ...;
  }
}

This allows you to maintain your brand identity while satisfying users who need sharper edges and deeper blacks, with zero runtime cost.