# Themes Three themes ship, and the same palettes drive the diagrams as well as the pages. `soleprint` is the default; the others are switched to on purpose. | Theme | Reads as | For | | --- | --- | --- | | `soleprint` | dark, rounded, amber | the default — tools and dev chrome | | `mcrn` | dark, square, monospace, orange glow | the terminal look, matched to mariano.mcrn.ar | | `lucid` | light, hairline, printable | regulated documents, and sitting beside a real lucid.app export | Switch with `?theme=lucid`, or the toggle in the corner. The choice persists. ## Where it lives ``` soleprint/common/theme/ tokens.css the vocabulary + neutral defaults themes/*.css one file per theme theme.js resolve, apply, remember bake.py inline the defaults into pages ``` Served together at `/theme.css` — tokens first, then every theme, each scoped to `[data-theme="..."]`. Adding a theme is adding a file: `run.py` lists the directory rather than carrying a hardcoded list. ## Two naming families, one set of values Both are answered, because both were already in use and renaming across a dozen templates would have been the larger change: - `--bg` / `--surface` / `--border` / `--text` / `--muted` / `--accent` — the station tools and the docs site - `--surface-0..3` / `--text-primary` / `--panel-radius` — `common/ui`'s Vue components The second family is derived from the first in `tokens.css`, so a page using either name gets the same colour and a theme author fills in one set. ## Order matters ```html ``` The theme has to load **before** the page's styles, so its element defaults underpin the page rather than override it. Get this backwards and `tokens.css`'s `body { background: var(--bg) }` flattens whatever the page wanted — which is exactly how artery, atlas and station briefly lost their coloured content columns. ## Baked defaults, and why `/theme.css` is an absolute path, and soleprint is not always at the root — in a room's nginx it sits under `/spr/` while `location /` goes to the frontend. A page that says `background: var(--bg)` and never receives `--bg` does not fall back to something plainer: the declaration is invalid at computed-value time, so the background goes transparent and the text goes initial-black on a design that assumed dark. Unstyled, not merely unbranded. So every page carries a generated `:root` block **before** the link. Both are `:root`, so document order decides: the served stylesheet wins when it loads, and the baked block is what is left when it does not. ```bash python3 common/theme/bake.py # regenerate python3 common/theme/bake.py --check # fail if a page is stale ``` Only the variables a page actually uses are emitted, so the blocks stay small. ## No webfonts The stacks name faces that exist on the target rather than fetching any: ```css --font-ui: "Segoe UI", Inter, system-ui, -apple-system, Arial, sans-serif; --font-mono: "Cascadia Mono", "JetBrains Mono", Consolas, "SF Mono", monospace; ``` Segoe UI and Consolas ship with Windows. A regulated network blocks `fonts.googleapis.com` and `file://` stalls on it, and neither failure looks like a missing font — they look like a broken page. ## Diagrams follow `docs/graphs/themes/*.gvpr` carry the same palettes for graphviz, so a diagram and the page around it are one visual language. See [the graphs README](https://git.mcrn.ar/mariano/soleprint/src/branch/main/docs/graphs/README.md) and [Export / Compile](#export). ```bash make docs graphs # every graph, every theme ``` Diagrams are baked per theme rather than styled by CSS, because the docs embed them with `` — which makes the SVG a separate document the page's stylesheet cannot reach. A plexus that **inlines** the SVG can style it live, and the bundle plexus does exactly that. ## Contrast `lucid` is the first light theme, and the palette was measured rather than guessed — against both `#ffffff` and the `#f5f7fa` panel, at the sizes actually used. `--dim` drives 11px notes and `--status-warn` drives 10px labels, so both need 4.5:1 rather than the 3:1 large text gets away with. The obvious lighter greys came in at 3.4–3.8 and were dropped for that reason.