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 layerelabora.overrides(a package keeps them inelabora/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.jsonhas notheme.cascadekeeps 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 byelabora validate);elabora initwritescomponents-over-theme. No format version: the field is optional, its absence the old order.elabora theme upgrade(MCPelabora_upgrade_theme,@elabora/nodeeditupgradeThemeCascade) 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 overridesblock, in order, inside their rules and at-rules, before the theme’s own overrides blocks;@keyframesand@propertya component defines too go along; a component or a theme that setsallmoves 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 gottheme.cascadedirectly: 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/nodestyle-cascade.ts, run byelabora look, MCPelabora_lookandelabora 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!importantare 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 (@scopewith lower proximity).