Themes
Themes are named style sets that you define once and reference across your entire .kern file with the $ prefix.
Defining a theme
A theme node has a name and a style block with the same shorthand syntax as inline styles:
theme primary {bg:#f97316,c:#fff,br:8,p:12}
theme danger {bg:#ef4444,c:#fff,br:8,p:12}
theme muted {bg:#27272a,c:#a1a1aa,br:8,p:8}The name can be a bare identifier after the theme keyword — no name= required:
theme primary {bg:#f97316} ← bare word becomes name=primary
theme name=primary {bg:#f97316} ← equivalent explicit formReferencing themes: $ref
Apply a theme to any node with the $ prefix followed by the theme name:
theme primary {bg:#f97316,c:#fff,br:8,p:12}
button text="Save" $primary
button text="Cancel" $primary
card $muted
text value="Hint text"The $ token is parsed as a themeRef — the parser collects all $refs on a line and attaches them to the node.
Style merging
Theme styles merge with inline styles. Inline styles override theme styles when both specify the same property:
theme primary {bg:#f97316,c:#fff,br:8,p:12}
button text="Save" $primary {bg:#ea580c}
// Result: bg=#ea580c (overridden), c=#fff, br=8, p=12 (from theme)The compiler first applies all theme ref styles in order, then overlays inline styles. This means:
- Theme styles provide the base
- Inline styles override specific properties
- Multiple
$refsmerge left to right
Multiple theme references
A node can reference multiple themes. They merge left to right:
theme card-base {bg:#18181b,br:12,p:24}
theme card-elevated {"box-shadow":"0 4px 12px rgba(0,0,0,0.3)"}
card $card-base $card-elevated
text value="Elevated card with both style sets"How themes compile
Theme nodes are collected in a pre-pass before rendering. They don't produce any output themselves — they only provide styles for $ref resolution.
React (web target)
Theme styles expand through the shorthand system and become inline React style objects:
// KERN source
theme primary {bg:#f97316,c:#fff,br:8}
button text="Save" $primary
// Compiled React output
<button style={{
backgroundColor: '#f97316',
color: '#fff',
borderRadius: 8
}}>Save</button>Tailwind target
In the Tailwind target, theme styles are converted to utility classes where possible:
// KERN source
theme primary {bg:#f97316,c:#fff,br:8}
button text="Save" $primary
// Compiled Tailwind output
<button className="bg-[#f97316] text-white rounded-lg">Save</button>Scope
Themes are scoped to the file they are defined in. The compiler collects theme definitions by walking the IR tree before rendering any nodes. A theme defined at any level of the tree is available to all nodes in the same file.
Theme + pseudo-selectors
Themes support the same pseudo-selector syntax as inline styles:
theme interactive {bg:#f97316,c:#fff,:hover:bg:#ea580c,:press:bg:#c2410c}
button text="Click me" $interactiveThe pseudo-styles from the theme are merged into the node's pseudoStyles map and compiled to framework-specific hover/active handling.
CSS escape hatch in themes
Themes support the same quoted-key escape hatch as inline styles for any CSS property not in the 30-shorthand map:
theme glass {
bg:rgba(255,255,255,0.1),
"backdrop-filter":"blur(8px)",
"border":"1px solid rgba(255,255,255,0.2)",
br:16
}
card $glass
text value="Frosted glass effect"