From 04e4f875af627764717464f08b6f5636a4b54dc9 Mon Sep 17 00:00:00 2001 From: daniel-c-harvey Date: Fri, 31 Jul 2026 12:40:15 -0400 Subject: [PATCH] instrument: reassign loop-marker role off tertiary, onto secondary Loop span/markers and the envelope overlay trace shared tertiary purple in the same overlay rect. Loop markers now draw secondary; envelope overlay keeps tertiary. Adds a theme-level distinctness regression guard. --- src/shell/instrument/editor_paint_waveform.cpp | 10 +++++++--- tests/test_theme.cpp | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/shell/instrument/editor_paint_waveform.cpp b/src/shell/instrument/editor_paint_waveform.cpp index 8bdc423..6af07fe 100644 --- a/src/shell/instrument/editor_paint_waveform.cpp +++ b/src/shell/instrument/editor_paint_waveform.cpp @@ -24,10 +24,14 @@ using namespace reasampler::instrument::ui; // lanes + waveform geometry using audio::computeEnvelope; namespace { -// Marker roles — semantic, drawn through the kit's palette: start = teal (secondary), loop -// start/end = purple (tertiary). The loop-span fill is a faint purple. +// Marker roles — semantic, drawn through the kit's palette: start AND loop start/end both +// = teal (secondary). Loop markers moved off tertiary/purple so the loop span + bars no +// longer share a role with the envelope overlay trace, which owns tertiary exclusively in +// this region (measured RGB was identical: #C2AAE8 for both). Secondary-vs-primary contrast +// here measures 1.12:1, below tertiary's 1.37:1 — accepted deliberately: markers are bars +// and a span fill, not the 1px trace that pairing was moved off of. constexpr Role kRoleStartMarker = Role::AccentSecondary; -constexpr Role kRoleLoopMarker = Role::AccentTertiary; +constexpr Role kRoleLoopMarker = Role::AccentSecondary; } // namespace void ReaSamplerEditor::paintWaveform(LICE_IBitmap* bmp, const Rect& band) { diff --git a/tests/test_theme.cpp b/tests/test_theme.cpp index 69dc5db..5810310 100644 --- a/tests/test_theme.cpp +++ b/tests/test_theme.cpp @@ -147,6 +147,16 @@ static void testOverlayAccentSeparatesFromTheWaveformAccent() { CHECK(delta >= 60); } +// editor_paint_waveform.cpp draws the loop span/markers and the envelope overlay trace into +// the SAME overlay rect. Loop markers are secondary (this track's reassignment, off tertiary, +// which the envelope overlay now owns exclusively there); a future palette edit that collapses +// the two back to one role must fail here rather than silently recreating the finding. +static void testLoopMarkerAndEnvelopeOverlayRolesAreDistinct() { + const KitColor loopMarker = roleColor(Role::AccentSecondary); + const KitColor envelopeOverlay = roleColor(Role::AccentTertiary); + CHECK(!(loopMarker == envelopeOverlay)); +} + static void testWarnClearsStateFloorOnBackground() { // warn (destructive) must be unmistakable -> clears the state floor on the base. CHECK(contrastRatio(roleColor(Role::Warn), roleColor(Role::BgBase)) @@ -264,6 +274,7 @@ int main() { testTextOnHoverSurfaceClearsFloor(); testSecondaryTertiaryAreDistinguishable(); testOverlayAccentSeparatesFromTheWaveformAccent(); + testLoopMarkerAndEnvelopeOverlayRolesAreDistinct(); testWarnClearsStateFloorOnBackground(); testLabelOnActiveSurfaceClearsFloor(); testRolesAreDistinctAndElevationMonotonic();