// Operator overrides for the band/mode matrix palette. // // Applied as inline custom properties on , which is what lets them be // OVERRIDES rather than a palette: the twelve themes each define their own // --mx-* ramp in style.css, an inline value wins over all of them, and removing // it hands the colour straight back to the theme. Nothing has to know which // theme is active, and switching theme with overrides off is a clean revert. export type MatrixColors = { enabled: boolean; call_confirmed: string; call_worked: string; entity_confirmed: string; entity_worked: string; not_worked: string; current_entry: string; }; // The six settings fields and the CSS custom property each one drives. Also the // display order — the same order the legend under the matrix reads in, so the // settings panel and the grid can never disagree about which green is which. export const MATRIX_VARS: { key: keyof Omit; cssVar: string; label: string }[] = [ { key: 'call_confirmed', cssVar: '--mx-call-conf', label: 'mx.callConf' }, { key: 'call_worked', cssVar: '--mx-call-work', label: 'mx.callWork' }, { key: 'entity_confirmed', cssVar: '--mx-dx-conf', label: 'mx.dxConf' }, { key: 'entity_worked', cssVar: '--mx-dx-work', label: 'mx.dxWork' }, { key: 'not_worked', cssVar: '--mx-none', label: 'mx.none' }, { key: 'current_entry', cssVar: '--mx-cur', label: 'mx.current' }, ]; export const emptyMatrixColors = (): MatrixColors => ({ enabled: false, call_confirmed: '', call_worked: '', entity_confirmed: '', entity_worked: '', not_worked: '', current_entry: '', }); // applyMatrixColors stamps (or clears) the overrides on . Safe to call as // often as you like — it is the whole rendering path, so the settings panel uses // it for a live preview and the app uses it once at startup. export function applyMatrixColors(c?: MatrixColors | null): void { const root = document.documentElement; for (const { key, cssVar } of MATRIX_VARS) { const v = c?.enabled ? String(c[key] ?? '').trim() : ''; if (v) root.style.setProperty(cssVar, v); else root.style.removeProperty(cssVar); } } // effectiveMatrixColor reads what the matrix is ACTUALLY painting right now — // the override if there is one, else the active theme's value. It is what seeds // the colour pickers, so the operator starts from the colours in front of them // instead of from a hardcoded palette that may belong to a different theme. // // A custom property's computed value has its var() references substituted, so // --mx-cur resolves to the theme's --warning rather than to the literal text. export function effectiveMatrixColor(cssVar: string): string { try { const v = getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim(); // only accepts #rrggbb. Anything else (a theme that // ever moves to oklch, an empty read during boot) falls back to mid grey // rather than silently resetting the picker to black. return /^#[0-9a-f]{6}$/i.test(v) ? v.toLowerCase() : '#808080'; } catch { return '#808080'; } }