engine/bauhaus library

The Bauhaus family (id 15): the Weimar / Dessau poster and the workshop toy — only red, yellow and blue plus black and cream (sometimes ochre), only primitives (block, disc, quarter-disc, half-disc, triangle, bar), flat opaque colour, no shadow, gradient, outline, texture or glow. Pure Dart: part of the generator, so every constant here is part of the family's engine-v3 definition and must not change once it ships.

  • Silhouettes carry meaning (the recorded non-colour cue, OperatorCue.shape): digit and function keys are blocks, operators discs, = a big disc, a quarter-disc fan or a triangle — or, one theme in eight, digits are discs, operators blocks and = a triangle (Kandinsky's circle / square / triangle; BauhausComposition). KeyShapeSpec.kind is the digit silhouette, operatorKind the operator one and operatorM3eShape the = figure (read only by the Bauhaus renderer and validateBauhaus; every other reader looks at it only under KeyShapeKind.m3eMorph).
  • Primaries at fixed lightness: red (25–33°; 25–28° crimson at the Accessible lock's darker lightness), a warm yellow (88–92°, always light: never a disliked dark yellow) and ultramarine blue (260–268°); operator and = are always two different primaries, and function keys are ink, cream, graphite or the third primary.
  • Five variants (BauhausVariant): parchment paper, grid (an ink field behind the keypad so the key gaps read as thick black rules), warm ochre stock, night (graphite on warm black) and negative (cream blocks on warm black).
  • Display: an opaque sheet (surface) with a thick rule (shadow: ink — the field's ink on grid —, cream on the night sheet, red on the negative's cream sheet) and a quarter-disc in the = primary (highlight); every display text sits on the sheet only.
  • Scene (BackgroundKind.bauhausComposition): the ground, the grid field behind the keypad, a small masthead (bar, square, triangle, disc) in the free middle of the toolbar and, where the screen has margins beside the calculator column, a poster composition in them. BackgroundSpec.colors = [ground, field, blue, red, triangle, sceneInk]; angleTenths ∈ {0, 900, 1800, 2700} mirrors / flips it.
  • Press: a concentric figure–ground inversion (the renderer keeps a ring of the resting face and swaps face and label inside it in the first frame), uniform scale 0.96, no depth, no tint layer.

Every draw comes from the generator's named sub-streams (palette and its retry streams, background, shape, style, type, motion, name), so a theme is a pure function of (seed, engineVersion, accessible). The shape, style, type and motion streams never read the palette stream, so a retry or the Accessible lock changes colours only.

Classes

BauhausDraw
Every value the palette stream draws for one Bauhaus theme, in draw order (see drawBauhausPalette); assembleBauhausPalette turns it into a Palette and the scene colours without further draws. Public so the hero tool and the tests can build palettes from chosen values.
BauhausPrimaryRanges
How one primary is drawn: hue, lightness (standard and under the Accessible lock) and chroma relative to the gamut edge, capped.

Enums

BauhausComposition
The four key compositions (shape stream; see bauhausCompositionOf).
BauhausPrimary
The three primaries.
BauhausVariant
The five sub-variants. Never stored: bauhausVariantOf derives it.

Constants

bauhausAccentDeltaE → const double
Lowest ΔEOK between the function keys' corner accent and their face.
bauhausAccentOnDenominator → const int
bauhausAccentOnNumerator → const int
One theme in three (style stream) leaves the function keys' corner accent off.
bauhausBlackChromaMilli → const IntRange
bauhausBlackLMilli → const IntRange
Warm black ground (night and negative).
bauhausBlockEqualsFigures → const List<Weighted<M3eShape>>
= figures for block digits: big disc, quarter-disc fan, triangle.
bauhausBlue → const BauhausPrimaryRanges
Ultramarine for keys in the light variants (cream labels ≥ 6:1).
bauhausCreamChromaMilli → const IntRange
bauhausCreamLMilli → const IntRange
Cream lightness and chroma × 1000.
bauhausDarkAssignments → const List<Weighted<BauhausAssignment>>
Night and negative: no blue keys (blue on warm black is too dark). Red operator discs most often — yellow operators on warm black sit close to NeoPOP's amber-on-black and to a stock dark calculator.
bauhausDarkRanges → const RoleRanges
Dark ranges (the night variant; negative is in the builder).
bauhausDarkVariantWeights → const List<int>
Dark themes: [night, negative] weights (the negative is the stronger poster, and night alone sits close to a stock dark calculator).
bauhausDefinition → const FamilyDefinition
Bauhaus: flat primaries, primitive silhouettes, a figure–ground inversion on press (hardPress in, effectsDefault out seeded × {0.9, 1, 1.1}, ζ 1, scale 0.96, no depth), a pop entry 0.90 → 1 on effectsDefault, Jost type and the wood pack (the workshop's wooden building toys). The palette is built by buildBauhausCandidate.
bauhausDigitVisibility → const double
Lowest contrast between the digit face and what it sits on (ground or field).
bauhausDisplayAccentDeltaE → const double
The display accent's floor against the sheet.
bauhausFieldChromaMilli → const IntRange
bauhausFieldLMilli → const IntRange
The grid variant's ink field behind the keypad.
bauhausGridAssignments → const List<Weighted<BauhausAssignment>>
Grid: function keys take the third primary.
bauhausInkChromaMilli → const IntRange
bauhausInkLMilli → const IntRange
Ink (near-black) lightness and chroma × 1000.
bauhausKeyVisibility → const double
Lowest contrast between an operator or = face and what it sits on (ground or field): the silhouette is the recorded cue, so it must not rest on hue alone.
bauhausLightRanges → const RoleRanges
Light ranges (the paper variant; grid and ochre are in the builder). Only the definition-sanity test reads these: the builder draws from the per-variant constants above, which these mirror.
bauhausLightVariantWeights → const List<int>
Light themes: [paper, grid, ochre] weights.
bauhausMaxCornerPermille → const int
Highest corner radius of a block, permille of the short side (blocks stay square next to discs).
bauhausNeutralHueTenths → const IntRange
Neutral hue (warm), tenths: every neutral but the ochre ground uses it.
bauhausNeutralMaxChroma → const double
Highest chroma of a neutral face.
bauhausOchreAssignments → const List<Weighted<BauhausAssignment>>
Ochre: no yellow keys (yellow on ochre is hue-adjacent and faint).
bauhausOchreChromaMilli → const IntRange
bauhausOchreHueTenths → const IntRange
bauhausOchreLMilli → const IntRange
Ochre stock: lightness, chroma and its own hue — the tan of the stock itself (the warmer end reads as apricot, the greener and stronger end as mustard).
bauhausPaperAssignments → const List<Weighted<BauhausAssignment>>
Paper: blue discs and a red = most often.
bauhausParchmentChromaMilli → const IntRange
bauhausParchmentLMilli → const IntRange
Parchment ground (paper and grid).
bauhausParchmentUnderYellowLMilli → const IntRange
Parchment lightness under yellow operator or = discs (paper).
bauhausPrimaryMinChroma → const double
Lowest chroma a primary face may have (after repairs).
bauhausRed → const BauhausPrimaryRanges
Bauhaus red (cream labels 4.5:1, 7:1 at the accessible lightness). At the Accessible lock's darker lightness the orange end (29–33°) reads as brick next to ochre, so the lock draws the crimson end only.
bauhausSceneBlue → const BauhausPrimaryRanges
The lighter ultramarine of the dark variants' scene (never a key: blue on warm black is only ≈ 2.4:1). Its cap lets it reach ultramarine chroma at this lightness instead of a cornflower.
bauhausSceneShapeDeltaE → const double
Lowest ΔEOK between each scene shape colour and the ground.
bauhausSheetChromaMilli → const IntRange
bauhausSheetLMilli → const IntRange
Light display sheet (paper, grid).
bauhausSteeredAccentApartDeg → const double
bauhausSteeredAccentMinChroma → const double
Steered Bauhaus (engine v5): the least chroma of an operator or = accent, and how far apart (degrees) their hues must sit.
bauhausSteeredEqualsApartTenths → const int
How far (tenths) a steered second colour must sit from the first to colour Bauhaus's = key (a margin over bauhausSteeredAccentApartDeg).
bauhausYellow → const BauhausPrimaryRanges
Bauhaus yellow: always light (ink labels ≥ 10:1), never a dark yellow, and warm (the cool end past 92° reads as a lemon highlighter next to parchment and red).
bauhausYellowOnParchment → const BauhausPrimaryRanges
Yellow when it is an operator or = face on parchment: at most L 0.85, over a parchment of at least L 0.905 (bauhausParchmentUnderYellowLMilli), so the disc stays ≥ 1.10:1 off the ground (bauhausKeyVisibility) — hue alone would carry it, and tritan vision loses most of that.

Functions

assembleBauhausPalette(BauhausDraw d, {required bool accentOn, required bool accessible, required List<int> bgs}) → Palette
Builds the palette of d: labels solved on their faces (ink on light faces, cream on dark ones, kept when they already pass), display texts on the sheet only, the focus ring on the scene samples bgs ([ground] or [ground, field]). accentOn (style stream) decides function.edge: the accent colour, or fully transparent for none.
bauhausCompositionOf(KeyShapeSpec shape) → BauhausComposition?
The key composition of shape (null when it is not a Bauhaus one).
bauhausDisplayAccent(int equals, int operator, int bar, int surface) → int
The display sheet's corner accent: the = face when it stands out from the sheet (min ΔEOK over normal + CVD ≥ bauhausDisplayAccentDeltaE), else the operator face, else the rule colour bar.
bauhausDisplayBackdrops(ThemeSpec spec, List<int> surfaces, List<int> bgs) → List<int>?
Display text only ever sits on the opaque sheet (the rule and the accent stay outside the display's text padding), so the sheet is the only backdrop (Liquid Glass precedent).
bauhausFunctionAccent(BauhausDraw d) → int
The function keys' corner accent colour of d (before the style stream's on/off). On grid, where the function blocks are a primary set into the ink field, the accent is the = primary (an ink corner there read as one oddly rounded corner, not an accent).
bauhausPrimaryOf(int argb) → BauhausPrimary?
The primary argb reads as (chroma ≥ 0.08 and the hue inside one window: red 18–40°, yellow 82–100° with L ≥ 0.78, blue 250–280°), or null.
bauhausSceneColors(BauhausDraw d) → List<int>
The scene colours of d (BackgroundSpec.colors): ground, keypad field (= ground without one), blue, red, the triangle colour (yellow; cream on ochre, where yellow would vanish) and the scene ink (bars, quarter-disc).
bauhausSceneSamples(BackgroundSpec bg) → List<int>?
Guardrail background samples of the scene: the ground, plus the grid field when there is one. Nothing else is ever painted under a key, label, focus ring, toolbar control (icons and the mode button) or display text (the scene keeps its shapes in the toolbar's free middle, clear of the mode button, and in the screen margins).
bauhausVariantOf(ThemeSpec spec) → BauhausVariant
The variant of a Bauhaus spec (not stored): grid ⇔ a keypad field; ochre ⇔ light with a ground below L 0.87; night ⇔ dark with digits below L 0.5.
buildBauhausCandidate(int seed, FamilyDefinition def, int engineVersion, {int attempt = 0, bool accessible = false}) → ThemeSpec
Builds one unvalidated Bauhaus candidate (the generator repairs and validates it, retries with palette/retry/n and finally falls back to a Bauhaus hero).
drawBauhausPalette(Rng p, FamilyDefinition def, {required bool accessible}) → BauhausDraw
Draws every palette value of one theme from the palette stream p in the family's fixed order: brightness, variant, assignment, neutral hue, red / yellow / blue, ink, cream, ground, field (grid), digit face, function face (neutral ones), panel.
repairBauhausExtras(Palette p, ThemeSpec spec, GuardrailLimits lim, List<int> bgs) → Palette?
Family repairs after labels and display texts: the sheet opaque, the rule re-solved to ≥ 3:1 on it, and accent / highlight following the (possibly repaired) = face (bauhausDisplayAccent). Faces are never touched here. Null when the rule cannot reach 3:1.
validateBauhaus(ThemeSpec spec, GuardrailLimits lim, List<int> bgs) → List<GuardrailViolation>
The Bauhaus rules (called from validateTheme for Bauhaus specs only):

Typedefs

BauhausAssignment = ({BauhausPrimary eq, BauhausPrimary? fn, BauhausPrimary op})
A primary assignment: operator, = and (grid) the function face.