The Solver
The Solver is the engine that powers the color system. It takes your high-level Intent and turns it into precise CSS Tokens.
You can interact with the Theme Builder in two ways:
- The UI: The interactive web interface (for exploration).
- The CLI: The
axiomaticcommand line tool (for production).
Both use the exact same “Solver” logic under the hood.
The “Theme Builder” Model
Section titled “The “Theme Builder” Model”To understand the solver, it helps to think about the controls you see in the Theme Builder UI. The solver is simply the code that runs every time you move a slider or add a surface.
1. Anchors: Defining the Playing Field
Section titled “1. Anchors: Defining the Playing Field”In the Theme Builder, you set the Anchors. These are the boundaries of your color system.
Page Anchors
Defines the lightness range for the "Page" polarity.
The solver takes these values and asks: “Can I fit readable text inside this range?” If the answer is “No” (and the anchor is adjustable), the solver moves the slider for you until the text is readable.
2. Surfaces: The “Steps”
Section titled “2. Surfaces: The “Steps””In the Theme Builder, you add Surfaces to a list.
Surfaces
.surface-page
Passes
.surface-card
Passes
.surface-sidebar
Passes
The solver’s job is to place these surfaces evenly between your Start and End anchors. It doesn’t just divide the lightness evenly (e.g., 10%, 20%, 30%). It divides the Contrast Space evenly. This ensures that the visual “step” from Page to Card looks the same as the step from Card to Sidebar.
Why Contrast Space?
Section titled “Why Contrast Space?”If we just divided the lightness values evenly (Linear Lightness), the steps would look uneven to the human eye. Dark colors bunch up, and light colors spread out. By dividing by Contrast (Linear Perception), every step feels visually consistent.
Linear Lightness (Bad)
Linear Contrast (Good)
3. The Result: Generated Tokens
Section titled “3. The Result: Generated Tokens”Finally, the solver outputs the CSS tokens that the Theme Builder (and your app) uses.
Generated CSS
--lightness-surface-page: light-dark(0.98, 0.12);
--lightness-surface-card: light-dark(0.95, 0.15);
--lightness-surface-sidebar: light-dark(0.92, 0.18);
The Pipeline
Section titled “The Pipeline”When you run npx axiomatic (or change a setting in the Builder), this pipeline executes:
- Hydrate: Read your
color-config.json. - Adjust Anchors: Ensure the range supports High Contrast text.
- Distribute: Calculate the target contrast for each surface based on the available range and any
gapBeforesettings. - Solve Lightness: Use binary search to find the exact lightness value that hits that contrast target.
- Solve Text: Find the text colors that sit accessibly on top of those surfaces (APCA-compliant).
- Generate: Write the CSS tokens.
High Contrast Generation
Section titled “High Contrast Generation”The solver runs a second pass to generate a High Contrast variant (@media (prefers-contrast: more)).
In this pass:
- Key Colors are removed (forced to grayscale).
- Anchors are pushed to pure Black (0) and White (1).
- Chroma is disabled.
This ensures that users who need maximum legibility get a strictly accessible, high-contrast version of your theme automatically.