# ADR-0024: Themes are semantic-role data files

- **Status:** Accepted; amended by 0142
- **Date:** 2026-06-25
- **Deciders:** jka
- **Decision:** D24

## Context

The GUI should be themeable, with live switching and different typography for the
code surface and the chat. Themes that name widget paths break whenever the widget
tree changes, and themes written as Tcl scripts would execute code.

## Decision

A theme is a data file in the configuration format of ADR-0021, parsed and never
executed. It names **semantic roles**, not widgets:

- **Colours by role**, for example `editor.bg`, `editor.fg`, `editor.selection`,
  `ui.bg`, `tab.active.bg`, `gutter.fg`, `chat.bg`, `accent`. Two themes differ only
  in values.
- **Fonts by role**, through Tk named fonts (`RioEditorFont`, `RioUIFont`,
  `RioChatFont`). Reconfiguring a named font updates every widget that uses it,
  so size and theme changes need no restart.

A theme may declare `base = <theme>` and override a subset of roles. The core
serves the merged role table (`theme.get`); a small applier in the GUI maps it
onto Tk. The default theme is the plain white background and black text. Later
decisions added roles rather than hard-coded colours: `error`, the diff roles,
`syntax.*` (ADR-0032), `editor.findmatch` (ADR-0036) and `editor.currentline`
(ADR-0060). A theme that omits a role inherits the default.

## Consequences

- A new theme is a set of values, and theme files cannot break or compromise rio.
- The colour-role vocabulary is shared, so a future TUI can map the same roles onto
  a terminal palette.
- The Tk-specific mapping lives in one applier in the GUI.
- Tooltips are the one deliberate exception and ignore the theme (ADR-0063).
