# D32. The theme's rules are defaults under the components; overrides are said (13 Oct 2026)

The session that built « Nietzsche et la grande santé » (13 Oct) lost time to a theme rule, `.t-figure img { width: 100%; height: auto }`, that silently beat its « atelier » layout's own rule for its small plate: from 6 October the theme came after the component stylesheets, so it could restyle them without fighting specificity. The layout's value had to move into `theme.css`, a component's style living in two files and lost once the component is published to a library. The theme winning over components was a design flaw.
- **Order** (`render/cascade.ts`): `elabora.base` < `elabora.theme` < `elabora.components` < `elabora.overrides`. The theme stylesheet's rules are the course's defaults; a component's stylesheet wins over them and is complete on its own. What the theme overrides in components on purpose goes in its top-level `@layer overrides { … }` blocks, the layer `elabora.overrides` (a package keeps them in `elabora/overrides.css`; the theme file keeps its line numbers). This is the order the cascade-layers literature recommends (reset and defaults, then components, then overrides) and the one CSS authors and agents already know.
- **Weighed and set aside.** Tokens alone (components read custom properties, the theme only sets them): kept as the advice for what a component wants tuned (`var(--<name>, <default>)`, never set by the component), but a theme is free CSS on the player's hooks, and tokens do not stop a general rule from reaching inside a component. Splitting the theme by selector (a rule that names a component overrides it, the others are defaults): no syntax to learn, but magic that devtools do not show, a selector analyser to maintain, and rules that change layer with their selector. A second file for overrides: as explicit, but one more file to know for a rare need. Keeping the theme last with a diagnostic only: the trap stays, and the diagnostic would fire on every component that uses a player hook.
- **Courses keep their look.** A course whose `course.json` has no `theme.cascade` keeps the order of 6–13 October (`theme-over-components`: `elabora.base` < `elabora.components` < `elabora.theme` < `elabora.overrides`) and is told (`I_THEME_CASCADE_OLD`, printed by `elabora validate`); `elabora init` writes `components-over-theme`. No format version: the field is optional, its absence the old order. `elabora theme upgrade` (MCP `elabora_upgrade_theme`, `@elabora/node` edit `upgradeThemeCascade`) moves a course to the new order in one undoable change without changing its look: the theme's declarations of properties that any component stylesheet of the course also sets go into an `@layer overrides` block, in order, inside their rules and at-rules, before the theme's own overrides blocks; `@keyframes` and `@property` a component defines too go along; a component or a theme that sets `all` moves the whole theme. Properties that act on one another (a shorthand and its longhands, logical and physical sides, aliases) share a family and move together (`propertyFamily`), so every declaration of a family stays in one layer and the theme's rules keep their outcome among themselves; against the components and the player, moved declarations stay above as before and the others meet no component. Measured on the « Nietzsche » module (22 screens, initial and answered at 1600×900, and 375×812): no pixel changed beyond capture noise; 135 declarations of 63 rules moved. The block is coarse (every theme rule on a property some component sets), so the upgrade says to move out the course-wide defaults afterwards. The examples got `theme.cascade` directly: their captures did not change, except the gloss notes of medieval-charts, whose emphasis is roman as the gloss component always asked (`.mc-gloss-body em { font-style: normal }`, overridden until now by the theme's `.t-text em`).
- **Measured in the page** (`@elabora/node` `style-cascade.ts`, run by `elabora look`, MCP `elabora_look` and `elabora fit`, the canvas and packages alike): for each rule of a component stylesheet and each theme rule that match one element and set one property, a declaration is taken out of its rule for a moment and the computed value read again, so media and container queries, specificity, layers and `!important` are the browser's own. `W_STYLE_COMPONENT_OVERRIDDEN`: a component's declaration overridden by a theme rule that does not name the component (the old order, or a broad rule in `@layer overrides`). `W_STYLE_THEME_UNDER_COMPONENT`: a theme rule that names a component (its `.t-block--<id>`, `.t-layout--<id>` or the classes of its own stylesheet) and gives way to it, outside `@layer overrides`. On that module it found two more cases of the same trap than the one reported: `.t-text { line-height }` overriding the « carte » and « frise » components.
*Revisit if:* authors need the theme to win in general again (a per-course setting exists: `theme-over-components`), the upgrade's block proves too coarse to edit (it could be narrowed with the page's measure, at the cost of exactness across states nobody captured), or browsers give stylesheets a native way to scope a theme under components (`@scope` with lower proximity).
