The six canvas text sizes (in px), the font counterpart to the role β base
color mapping. Layered onto Theme from the embedded font_sizes.json
(see Theme::from_embedded) and tuned live by the font editor
(--font-editor). #[serde(default)] lets a partial file specify only the
sizes it overrides; the rest fall back to FontSizes::default.
A stroke described by a world-space width plus a Role β the app-side,
role-based counterpart to the canvasβs
PaletteStroke. The Style
adapter resolves the role to a Swatch (and hands the width through) when
forwarding to the palette-based renderer. Construct from a (width, role)
tuple, which wraps the literal width as a WorldPx; use
RoleStroke::NONE for no stroke.
A semantic color slot. Drawing code passes a Role to every draw call; the
renderer resolves it through the active Theme (role β Base β color),
so call sites name intent, never a literal color. Add a variant here for
each semantically-distinct color in the app.
Map an optional accent index to its accent Role: Some(0..=7) β
Role::Accent0..Role::Accent7, None or out of range β None.
Shared by every shape that carries an Option<u8> accent role (blocks,
ports, routes); each call site supplies its own fallback for the None case.
The avatar colour a name always lands on. A sum of the bytes is enough:
the requirement is that one name always picks the same colour, not that
two names rarely collide.
The overrides theme.json bakes in. One stale role name fails the whole
file, and the app then falls back to the built-in defaults without a word
on screen β so the suite holds it to parsing.