Theming with Athanor's tokens

Make an Athanor plugin window match the app in light and dark: the built-in styles for plain HTML, and the design tokens as CSS variables.

Native by default

Athanor puts two things into the top of every plugin window before your own HTML:

  1. Its design tokens, as CSS variables, with the values of the theme the person is using.
  2. A small stylesheet that makes plain HTML look like Athanor's: buttons, fields, menus, headings and small print.

So a plugin window with no CSS of its own already looks like part of the app, in light and in dark. You may still bring your own styles; write them with the tokens below so they follow the theme.

Plain HTML that already looks right

Write You get
<button> Athanor's pill button
<button class="primary"> The orange primary action
<button class="quiet"> A text button with no border
<input>, <select>, <textarea> Athanor's fields
<label> A small field label
<h1>, <h2>, <h3> Headings at 15, 14 and 13 pixels
<p> Body text, 13 pixels, with space below
<small>, class="hint" The dim 12-pixel line
<a> A link in the accent text color
class="row" A wrapping horizontal row with an 8-pixel gap
class="stack" A vertical column with an 8-pixel gap

The page's body uses Athanor's font at 13 pixels on a transparent background, so the window's own surface shows through. Focused controls get an outline in the accent color.

The tokens

Variable Use it for
--bg The app background
--surface A raised surface, such as a card
--surface-2 A second surface level
--text-1 Main text
--text-2 Secondary text
--text-3 Dim text and hints
--accent The accent (Athanor's orange)
--accent-text Accent-colored text and links
--accent-soft A soft accent fill
--border Hairline borders
--border-solid Opaque borders
--danger Destructive fills
--danger-text Error text
--success Success fills
--warning-text Warning text
--font-sans The interface font
--radius The standard corner radius
--radius-sm The small corner radius

color-scheme is set to light or dark to match, so scrollbars and native controls follow too.

An example

The official Periodic table plugin colors its element tiles by block using only tokens, mixed with color-mix, never new colors:

<style>
  .el { border: 1px solid color-mix(in srgb, var(--text-1) 10%, transparent); background: var(--surface, transparent); color: var(--text-1); }
  .el.b-s { background: color-mix(in srgb, var(--accent) 24%, transparent); }
  .el.b-p { background: color-mix(in srgb, var(--success, var(--accent)) 22%, transparent); }
  .el.b-d { background: color-mix(in srgb, var(--text-1) 7%, transparent); }
  .el.b-f { background: color-mix(in srgb, var(--warning-text, var(--accent)) 24%, transparent); }
  .el:hover { border-color: var(--text-3); }
  .el.on { border-color: var(--accent); box-shadow: 0 0 0 1px var(--accent); }
  .card { border: 1px solid var(--border); border-radius: 8px; }
  .card dt { color: var(--text-3); }
</style>

Give every var() a fallback where a token might be missing, as var(--surface, transparent) does.

Rules

  • Styles go inline, in a <style> element or style attributes. The window cannot load a stylesheet or a font from a URL; a font has to be a data: URL.
  • The token values are written when the window is built. A window that is open when the person switches between light and dark keeps the old values until it is opened again.
  • Do not hard-code colors that only work on one theme. Mix from the tokens instead.

Is this helpful?

Last updated Nov 11, 2026