Styles and tokens
A StyleDef is a token set plus selector rules; tokens become CSS custom properties and rules apply to every matching node.
Styles and tokens
A StyleDef is a token set plus rules: tokens become CSS custom properties any node can reference with var(--token), and rules apply properties to every node matching a selector.
Examples
A minimal style with a heading rule and a primary button:
A style with named keyframes reachable from animate:
Anatomy
Tokens become CSS custom properties. Any node prop may reference one with var(--token).
Rules apply properties to every node matching a selector. Selectors are nodeType optionally filtered by a prop: text, button[variant=primary], icon[name=coffee]. A selector ending in :hover, :active or :focus styles that interaction state theme-wide.
Keyframes a style names are motion animate can reach when the preset registry has no word for it: keys are names, values are @keyframes bodies. The registry resolves first (a style cannot shadow slide-up); a style keyframe runs once for 1000ms at ease-in-out unless the node says otherwise; a body that will not parse is a validation error.
The style in force resolves through a cascade: an explicit override → screen.style → project.defaultStyle → the built-in default.
Built-in tokens
The default style defines these, and your tokens override them by name:
| Token | Default | Purpose |
|---|---|---|
--bg-primary | #f0f0f0 | Screen background |
--bg-surface | #ffffff | Cards, sheets |
--bg-sidebar | #f7f7f7 | Sidebars |
--bg-overlay | #e8e8e8 | Overlays |
--bg-accent-light | #e8eeff | Accent tint |
--border | #d0d0d0 | Borders |
--text-primary | #2a2a2a | Body text |
--text-muted | #888888 | Secondary text |
--accent | #4a7cff | Accent |
--btn-primary-bg | #333333 | Primary button fill |
--font-body | 'DM Sans', sans-serif | Body font |
--font-heading | 'Inter', sans-serif | Heading font |
--screen-padding | 16px | Screen gutter |
Background tokens
The background prop accepts these semantic names, which resolve to the matching --bg-* token: surface, sidebar, background, overlay, accent-light, none. It also accepts a raw hex value, a CSS gradient string (linear-gradient(...), radial-gradient(...), conic-gradient(...)), or a url(...) image fill — gradients and image fills route to the CSS background shorthand, and gradient-scrim composites work ("linear-gradient(rgba(0,0,0,.5), rgba(0,0,0,.5)), url(hero.jpg) center/cover").
Brands
A BrandDef captures identity — palette, typography, shape, tone, language rules — that a StyleDef can be generated from. Styles record their origin in brandId, so a regenerated style is traceable to the brand it came from. Brands are optional; a style stands alone perfectly well.
Stability
Style tokens, rules, keyframes and the built-in token names are part of the format contract. Adding a token or rule capability is additive; renaming a built-in token or changing how var(--token) resolves is breaking. Two-face styles (modes.light / modes.dark) are covered on Theming & modes.
State and expressions
Each screen declares stateVars as a string map; showWhen/hideWhen take a small expression language over that state, $env and $hover (the pointer inside the nearest hoverGroup).
Validation
validate() returns errors for structural problems and warnings for things that render fine and are probably still wrong.