L-w3: complete three-accent pastel repalette + REAPER-grey neutrals

Finish roleColor/roleColorState for the three-accent enum, re-map every
Accent consumer (primary leads live; Pool/Banks titles categorical
secondary/tertiary), make spectralColor a lime->teal->purple three-stop
sweep, and re-lock the WCAG-floor tests on the grey ladder.
This commit is contained in:
2026-07-26 22:04:29 -04:00
parent fca311b4bd
commit 6abebba69e
5 changed files with 201 additions and 98 deletions
+33 -23
View File
@@ -2,16 +2,20 @@
// theme — the REAPER-free, LICE-free palette + type-scale core of the shared drawing
// kit (Phase L, L1). This is the "one source of drawing" made testable at its root: a
// ROLE-based color model (bg/base, bg/panel, bg/cell, line/hairline, text/primary,
// text/dim, accent, accent/hot, warn), an INTERACTION-STATE model (rest/hover/active/
// pressed/dragging/focus/disabled), and the WCAG contrast math that lets a unit test
// prove every text-on-surface pair clears its floor ("punch to the floor, not past it").
// text/dim, accent/primary, accent/secondary, accent/tertiary, accent/hot, warn), an
// INTERACTION-STATE model (rest/hover/active/pressed/dragging/focus/disabled), and the
// WCAG contrast math that lets a unit test prove every text-on-surface pair clears its
// floor ("punch to the floor, not past it").
//
// THE SINGLE POINT OF CHANGE (DS-2): every role color is produced by roleColor() from
// ONE direction constants block (kDirection*, below) carrying the settled B (Neon
// Console) + C spectral values. Switching the visual direction is editing that block and
// nothing else — no shell hardcodes a color; the shell asks the theme by role. The
// spectral (Direction C) hue ramp lives here too (spectralColor) so the signature
// keyboard strip's L3 consumer derives its per-note hue from the same source.
// THE SINGLE POINT OF CHANGE (DS-2 revised): every role color is produced by roleColor()
// from ONE direction constants block (kDirection*, below) carrying the settled B (Neon
// Console) neutrals — now REAPER-theme mid-grey, not near-black — plus the three-accent
// pastel system (primary lime / secondary teal / tertiary purple) and the C pastel
// spectral ramp. Switching the visual direction is editing that block and nothing else —
// no shell hardcodes a color; the shell asks the theme by role. The spectral (Direction C)
// hue ramp lives here too (spectralColor) so the signature keyboard strip's L3 consumer
// derives its per-note hue from the same source (a pastel sweep anchored on the three
// accents: primary lime -> secondary teal -> tertiary purple).
//
// PURE MODULE: NO REAPER types, NO SWELL, NO LICE, NO vendor/ includes. Standard library
// only. Builds and unit-tests without REAPER. Mirror of mode_switch / bank_grid — the
@@ -40,15 +44,17 @@ struct KitColor {
// The structural palette roles (direction-independent — §2.1 of the design doc). The
// direction (B/C) sets the concrete hue behind each; the shell always asks by role.
enum class Role {
BgBase, // window canvas
BgPanel, // a raised region (list, waveform pane)
BgCell, // a control / row surface
LineHairline,// separators (used sparingly — elevation carries most separation)
TextPrimary, // labels, values
TextDim, // secondary / units
Accent, // selection / active / focus — where the punch lives
AccentHot, // hover / live / drag feedback (a brighter accent tint)
Warn, // clip / destructive (prune, delete) — reserved for byte-deleting states
BgBase, // window canvas
BgPanel, // a raised region (list, waveform pane)
BgCell, // a control / row surface
LineHairline, // separators (used sparingly — elevation carries most separation)
TextPrimary, // labels, values
TextDim, // secondary / units
AccentPrimary, // the live / active / selected signal — where the punch lives (pastel lime)
AccentSecondary,// categorical role A (pastel teal) — a distinct KIND, never intensity
AccentTertiary,// categorical role B (pastel purple) — a distinct KIND, never intensity
AccentHot, // hover / live / drag feedback (a brighter tint OF the primary accent)
Warn, // clip / destructive (prune, delete) — reserved for byte-deleting states
};
// The interaction-state model every kit component honors (§3.3). A component draws its
@@ -83,11 +89,15 @@ KitColor roleColor(Role role);
// Rest returns roleColor(role) unchanged.
KitColor roleColorState(Role role, InteractionState state);
// Direction C's spectral hue ramp: maps a normalized position t in [0, 1] (low note ->
// high note across the keyboard strip) to a color, cool-blue at 0 -> hot-magenta at 1
// (§4 Direction C). The signature keyboard-strip surface (an L3 consumer) derives each
// note/zone's hue from this ONE function so the spectrum is defined in the same place as
// the rest of the palette. t is clamped to [0, 1].
// Direction C's spectral hue ramp (DS-2 revised — a PASTEL sweep anchored on the three
// accents, not the old neon cool-blue -> hot-magenta): maps a normalized position t in
// [0, 1] (low note -> high note across the keyboard strip) to a color that runs
// accent/primary (pastel lime, low) -> accent/secondary (pastel teal, mid) ->
// accent/tertiary (pastel purple, high). The same three hues that mean "live / category A
// / category B" elsewhere are the endpoints and midpoint here, so the strip reads as an
// extension of the accent system, not a separate flourish. The signature keyboard-strip
// surface (an L3 consumer) derives each note/zone's hue from this ONE function so the
// spectrum is defined in the same place as the rest of the palette. t is clamped to [0, 1].
KitColor spectralColor(double t);
// --- WCAG contrast (the "punch" rule, made testable) --------------------------