|
|
|
@@ -0,0 +1,431 @@
|
|
|
|
|
import { normalizeHex, scaleLightness, withAlpha, mix, desaturate } from './colorMath.js';
|
|
|
|
|
import type { ThemeConfig, DokiColors } from './types.js';
|
|
|
|
|
|
|
|
|
|
const FALLBACK = '#FF00FF'; // magenta — visually obvious if a key is missing
|
|
|
|
|
|
|
|
|
|
function get(p: DokiColors, key: string, fallback = FALLBACK): string {
|
|
|
|
|
const v = p[key];
|
|
|
|
|
if (!v) {
|
|
|
|
|
console.warn(` warning: missing palette key "${key}", using fallback`);
|
|
|
|
|
return fallback;
|
|
|
|
|
}
|
|
|
|
|
return normalizeHex(v);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Primary scale deltas (dark theme: dark-N lighter, light-N darker; light theme: reversed)
|
|
|
|
|
const PRIMARY_DARK_DELTAS = [0.10, 0.17, 0.24, 0.30, 0.40, 0.52, 0.62];
|
|
|
|
|
const PRIMARY_LIGHT_DELTAS = [0.10, 0.17, 0.24, 0.30, 0.40, 0.52, 0.62];
|
|
|
|
|
|
|
|
|
|
// Secondary scale deltas
|
|
|
|
|
const SECONDARY_DARK_DELTAS = [0.04, 0.08, 0.14, 0.20, 0.26, 0.31, 0.36, 0.40, 0.43, 0.46, 0.50, 0.53, 0.55];
|
|
|
|
|
const SECONDARY_LIGHT_DELTAS = [0.04, 0.08, 0.14, 0.20];
|
|
|
|
|
|
|
|
|
|
const ALPHA_STEPS = [
|
|
|
|
|
[10, 0x19], [20, 0x33], [30, 0x4b], [40, 0x66], [50, 0x80],
|
|
|
|
|
[60, 0x99], [70, 0xb3], [80, 0xcc], [90, 0xe1],
|
|
|
|
|
] as const;
|
|
|
|
|
|
|
|
|
|
const DARK_NAMED_COLORS = {
|
|
|
|
|
red: '#CC4848', redLight: '#D15A5A', redDark1: '#C23636', redDark2: '#AD3030',
|
|
|
|
|
orange: '#CC580C', orangeLight: '#F6A066', orangeDark1: '#F38236', orangeDark2: '#F16E17',
|
|
|
|
|
yellow: '#CC9903', yellowLight: '#EAAF03', yellowDark1: '#B88A03', yellowDark2: '#A37A02',
|
|
|
|
|
olive: '#91A313', oliveLight: '#ABC016', oliveDark1: '#839311', oliveDark2: '#74820F',
|
|
|
|
|
green: '#87AB63', greenLight: '#93B373', greenDark1: '#7A9E55', greenDark2: '#6C8C4C',
|
|
|
|
|
teal: '#00918A', tealLight: '#00B6AD', tealDark1: '#00837C', tealDark2: '#00746E',
|
|
|
|
|
blue: '#3A8AC6', blueLight: '#4E96CC', blueDark1: '#347CB3', blueDark2: '#2E6E9F',
|
|
|
|
|
violet: '#906AE1', violetLight: '#9B79E4', violetDark1: '#7B4EDB', violetDark2: '#6733D6',
|
|
|
|
|
purple: '#B259D0', purpleLight: '#BA6AD5', purpleDark1: '#A742C9', purpleDark2: '#9834B9',
|
|
|
|
|
pink: '#D22E8B', pinkLight: '#D74397', pinkDark1: '#BE297D', pinkDark2: '#A9246F',
|
|
|
|
|
brown: '#A47252', brownLight: '#B08061', brownDark1: '#94674A', brownDark2: '#835B42',
|
|
|
|
|
black: '#202225', blackLight: '#45484E', blackDark1: '#2E3033', blackDark2: '#292B2E',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const LIGHT_NAMED_COLORS = {
|
|
|
|
|
red: '#DB2828', redLight: '#E45E5E', redDark1: '#C82121', redDark2: '#B11E1E',
|
|
|
|
|
orange: '#F2711C', orangeLight: '#F59555', orangeDark1: '#E6630D', orangeDark2: '#CC580C',
|
|
|
|
|
yellow: '#FBBD08', yellowLight: '#FCCE46', yellowDark1: '#E5AC04', yellowDark2: '#CC9903',
|
|
|
|
|
olive: '#B5CC18', oliveLight: '#D3E942', oliveDark1: '#A3B816', oliveDark2: '#91A313',
|
|
|
|
|
green: '#21BA45', greenLight: '#46DE6A', greenDark1: '#1EA73E', greenDark2: '#1A9537',
|
|
|
|
|
teal: '#00B5AD', tealLight: '#08FFF4', tealDark1: '#00A39C', tealDark2: '#00918A',
|
|
|
|
|
blue: '#2185D0', blueLight: '#51A5E3', blueDark1: '#1E78BB', blueDark2: '#1A6AA6',
|
|
|
|
|
violet: '#6435C9', violetLight: '#8B67D7', violetDark1: '#5A30B5', violetDark2: '#502AA1',
|
|
|
|
|
purple: '#A333C8', purpleLight: '#BB64D8', purpleDark1: '#932EB4', purpleDark2: '#8229A0',
|
|
|
|
|
pink: '#E03997', pinkLight: '#E86BB1', pinkDark1: '#DB228A', pinkDark2: '#C21E7B',
|
|
|
|
|
brown: '#A5673F', brownLight: '#C58B66', brownDark1: '#955D39', brownDark2: '#845232',
|
|
|
|
|
black: '#1D2328', blackLight: '#4B5B68', blackDark1: '#2C3339', blackDark2: '#131619',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const SERIES_16 = {
|
|
|
|
|
'--color-series-16-0': '#7DB233',
|
|
|
|
|
'--color-series-16-1': '#499A37',
|
|
|
|
|
'--color-series-16-2': '#CE4751',
|
|
|
|
|
'--color-series-16-3': '#8F9121',
|
|
|
|
|
'--color-series-16-4': '#AC32A6',
|
|
|
|
|
'--color-series-16-5': '#7445E9',
|
|
|
|
|
'--color-series-16-6': '#C67D28',
|
|
|
|
|
'--color-series-16-7': '#4DB392',
|
|
|
|
|
'--color-series-16-8': '#AA4D30',
|
|
|
|
|
'--color-series-16-9': '#2A6F84',
|
|
|
|
|
'--color-series-16-10': '#C45327',
|
|
|
|
|
'--color-series-16-11': '#3D965C',
|
|
|
|
|
'--color-series-16-12': '#792A93',
|
|
|
|
|
'--color-series-16-13': '#439D73',
|
|
|
|
|
'--color-series-16-14': '#103AAD',
|
|
|
|
|
'--color-series-16-15': '#982E85',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export function buildVariables(theme: ThemeConfig): Record<string, string> {
|
|
|
|
|
const p = theme.palette;
|
|
|
|
|
const isDark = theme.colorScheme === 'dark';
|
|
|
|
|
|
|
|
|
|
const primary = get(p, 'accentColor');
|
|
|
|
|
const secondary = get(p, 'borderColor', get(p, 'secondaryBackground'));
|
|
|
|
|
const body = get(p, 'baseBackground');
|
|
|
|
|
const fg = get(p, 'foregroundColor');
|
|
|
|
|
const headerColor = get(p, 'headerColor');
|
|
|
|
|
const contrastColor = get(p, 'contrastColor');
|
|
|
|
|
const inactiveBackground = get(p, 'inactiveBackground', get(p, 'secondaryBackground'));
|
|
|
|
|
|
|
|
|
|
const named = isDark ? DARK_NAMED_COLORS : LIGHT_NAMED_COLORS;
|
|
|
|
|
const sign = isDark ? 1 : -1;
|
|
|
|
|
|
|
|
|
|
const vars: Record<string, string> = {};
|
|
|
|
|
|
|
|
|
|
// ─── Section 1: is-dark-theme ────────────────────────────────────────────────
|
|
|
|
|
vars['--is-dark-theme'] = isDark ? 'true' : 'false';
|
|
|
|
|
|
|
|
|
|
// ─── Section 2: Primary color system ─────────────────────────────────────────
|
|
|
|
|
vars['--color-primary'] = primary;
|
|
|
|
|
vars['--color-primary-contrast'] = get(p, 'accentContrastColor', '#FFFFFF');
|
|
|
|
|
|
|
|
|
|
PRIMARY_DARK_DELTAS.forEach((d, i) => {
|
|
|
|
|
vars[`--color-primary-dark-${i + 1}`] = scaleLightness(primary, sign * d);
|
|
|
|
|
});
|
|
|
|
|
PRIMARY_LIGHT_DELTAS.forEach((d, i) => {
|
|
|
|
|
vars[`--color-primary-light-${i + 1}`] = scaleLightness(primary, -sign * d);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ALPHA_STEPS.forEach(([pct, alpha]) => {
|
|
|
|
|
vars[`--color-primary-alpha-${pct}`] = withAlpha(primary, alpha);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
vars['--color-primary-hover'] = 'var(--color-primary-dark-1)';
|
|
|
|
|
vars['--color-primary-active'] = 'var(--color-primary-dark-2)';
|
|
|
|
|
|
|
|
|
|
// ─── Section 3: Secondary color system ───────────────────────────────────────
|
|
|
|
|
vars['--color-secondary'] = secondary;
|
|
|
|
|
|
|
|
|
|
SECONDARY_DARK_DELTAS.forEach((d, i) => {
|
|
|
|
|
vars[`--color-secondary-dark-${i + 1}`] = scaleLightness(secondary, sign * d);
|
|
|
|
|
});
|
|
|
|
|
SECONDARY_LIGHT_DELTAS.forEach((d, i) => {
|
|
|
|
|
vars[`--color-secondary-light-${i + 1}`] = scaleLightness(secondary, -sign * d);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
ALPHA_STEPS.forEach(([pct, alpha]) => {
|
|
|
|
|
vars[`--color-secondary-alpha-${pct}`] = withAlpha(secondary, alpha);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
vars['--color-secondary-button'] = 'var(--color-secondary-dark-4)';
|
|
|
|
|
vars['--color-secondary-hover'] = isDark ? 'var(--color-secondary-dark-3)' : 'var(--color-secondary-dark-5)';
|
|
|
|
|
vars['--color-secondary-active'] = isDark ? 'var(--color-secondary-dark-2)' : 'var(--color-secondary-dark-6)';
|
|
|
|
|
|
|
|
|
|
// ─── Section 4: Console colors ────────────────────────────────────────────────
|
|
|
|
|
vars['--color-console-fg'] = fg;
|
|
|
|
|
vars['--color-console-fg-subtle'] = get(p, 'lineNumberColor');
|
|
|
|
|
vars['--color-console-bg'] = contrastColor;
|
|
|
|
|
vars['--color-console-border'] = secondary;
|
|
|
|
|
vars['--color-console-hover-bg'] = scaleLightness(contrastColor, isDark ? 0.05 : -0.05);
|
|
|
|
|
vars['--color-console-active-bg'] = scaleLightness(contrastColor, isDark ? 0.10 : -0.10);
|
|
|
|
|
vars['--color-console-menu-bg'] = mix(contrastColor, body, 0.5);
|
|
|
|
|
vars['--color-console-menu-border'] = secondary;
|
|
|
|
|
vars['--color-console-link'] = get(p, 'lineNumberColor');
|
|
|
|
|
|
|
|
|
|
// ─── Section 5: Named semantic colors (12 hues) ───────────────────────────────
|
|
|
|
|
vars['--color-red'] = named.red;
|
|
|
|
|
vars['--color-red-light'] = named.redLight;
|
|
|
|
|
vars['--color-red-dark-1'] = named.redDark1;
|
|
|
|
|
vars['--color-red-dark-2'] = named.redDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-orange'] = named.orange;
|
|
|
|
|
vars['--color-orange-light'] = named.orangeLight;
|
|
|
|
|
vars['--color-orange-dark-1'] = named.orangeDark1;
|
|
|
|
|
vars['--color-orange-dark-2'] = named.orangeDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-yellow'] = named.yellow;
|
|
|
|
|
vars['--color-yellow-light'] = named.yellowLight;
|
|
|
|
|
vars['--color-yellow-dark-1'] = named.yellowDark1;
|
|
|
|
|
vars['--color-yellow-dark-2'] = named.yellowDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-olive'] = named.olive;
|
|
|
|
|
vars['--color-olive-light'] = named.oliveLight;
|
|
|
|
|
vars['--color-olive-dark-1'] = named.oliveDark1;
|
|
|
|
|
vars['--color-olive-dark-2'] = named.oliveDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-green'] = named.green;
|
|
|
|
|
vars['--color-green-light'] = named.greenLight;
|
|
|
|
|
vars['--color-green-dark-1'] = named.greenDark1;
|
|
|
|
|
vars['--color-green-dark-2'] = named.greenDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-teal'] = named.teal;
|
|
|
|
|
vars['--color-teal-light'] = named.tealLight;
|
|
|
|
|
vars['--color-teal-dark-1'] = named.tealDark1;
|
|
|
|
|
vars['--color-teal-dark-2'] = named.tealDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-blue'] = named.blue;
|
|
|
|
|
vars['--color-blue-light'] = named.blueLight;
|
|
|
|
|
vars['--color-blue-dark-1'] = named.blueDark1;
|
|
|
|
|
vars['--color-blue-dark-2'] = named.blueDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-violet'] = named.violet;
|
|
|
|
|
vars['--color-violet-light'] = named.violetLight;
|
|
|
|
|
vars['--color-violet-dark-1'] = named.violetDark1;
|
|
|
|
|
vars['--color-violet-dark-2'] = named.violetDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-purple'] = named.purple;
|
|
|
|
|
vars['--color-purple-light'] = named.purpleLight;
|
|
|
|
|
vars['--color-purple-dark-1'] = named.purpleDark1;
|
|
|
|
|
vars['--color-purple-dark-2'] = named.purpleDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-pink'] = named.pink;
|
|
|
|
|
vars['--color-pink-light'] = named.pinkLight;
|
|
|
|
|
vars['--color-pink-dark-1'] = named.pinkDark1;
|
|
|
|
|
vars['--color-pink-dark-2'] = named.pinkDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-brown'] = named.brown;
|
|
|
|
|
vars['--color-brown-light'] = named.brownLight;
|
|
|
|
|
vars['--color-brown-dark-1'] = named.brownDark1;
|
|
|
|
|
vars['--color-brown-dark-2'] = named.brownDark2;
|
|
|
|
|
|
|
|
|
|
vars['--color-black'] = named.black;
|
|
|
|
|
vars['--color-black-light'] = named.blackLight;
|
|
|
|
|
vars['--color-black-dark-1'] = named.blackDark1;
|
|
|
|
|
vars['--color-black-dark-2'] = named.blackDark2;
|
|
|
|
|
|
|
|
|
|
// ─── Section 6: ANSI colors ───────────────────────────────────────────────────
|
|
|
|
|
const ansiBlack = contrastColor;
|
|
|
|
|
const ansiRed = get(p, 'terminal.ansiRed', named.red);
|
|
|
|
|
const ansiGreen = get(p, 'terminal.ansiGreen', named.green);
|
|
|
|
|
const ansiYellow = get(p, 'terminal.ansiYellow', named.yellow);
|
|
|
|
|
const ansiBlue = get(p, 'terminal.ansiBlue', named.blue);
|
|
|
|
|
const ansiMagenta = get(p, 'terminal.ansiMagenta', get(p, 'accentColor'));
|
|
|
|
|
const ansiCyan = get(p, 'terminal.ansiCyan', named.teal);
|
|
|
|
|
|
|
|
|
|
vars['--color-ansi-black'] = ansiBlack;
|
|
|
|
|
vars['--color-ansi-red'] = ansiRed;
|
|
|
|
|
vars['--color-ansi-green'] = ansiGreen;
|
|
|
|
|
vars['--color-ansi-yellow'] = ansiYellow;
|
|
|
|
|
vars['--color-ansi-blue'] = ansiBlue;
|
|
|
|
|
vars['--color-ansi-magenta'] = ansiMagenta;
|
|
|
|
|
vars['--color-ansi-cyan'] = ansiCyan;
|
|
|
|
|
vars['--color-ansi-white'] = 'var(--color-console-fg-subtle)';
|
|
|
|
|
vars['--color-ansi-bright-black'] = scaleLightness(ansiBlack, 0.12);
|
|
|
|
|
vars['--color-ansi-bright-red'] = scaleLightness(ansiRed, 0.08);
|
|
|
|
|
vars['--color-ansi-bright-green'] = scaleLightness(ansiGreen, 0.08);
|
|
|
|
|
vars['--color-ansi-bright-yellow'] = scaleLightness(ansiYellow, 0.08);
|
|
|
|
|
vars['--color-ansi-bright-blue'] = scaleLightness(ansiBlue, 0.08);
|
|
|
|
|
vars['--color-ansi-bright-magenta'] = scaleLightness(ansiMagenta, 0.08);
|
|
|
|
|
vars['--color-ansi-bright-cyan'] = scaleLightness(ansiCyan, 0.08);
|
|
|
|
|
vars['--color-ansi-bright-white'] = 'var(--color-console-fg)';
|
|
|
|
|
|
|
|
|
|
// ─── Section 7: Chart/series colors (fixed) ───────────────────────────────────
|
|
|
|
|
Object.assign(vars, SERIES_16);
|
|
|
|
|
|
|
|
|
|
// ─── Section 8: Utility colors ────────────────────────────────────────────────
|
|
|
|
|
const grey = desaturate(secondary);
|
|
|
|
|
vars['--color-grey'] = grey;
|
|
|
|
|
vars['--color-grey-light'] = scaleLightness(grey, 0.08);
|
|
|
|
|
vars['--color-gold'] = isDark ? '#B1983B' : '#A1882B';
|
|
|
|
|
vars['--color-white'] = '#FFFFFF';
|
|
|
|
|
|
|
|
|
|
// ─── Section 9: Diff colors ───────────────────────────────────────────────────
|
|
|
|
|
const diffInserted = get(p, 'diff.inserted', '#1B3B1C');
|
|
|
|
|
const diffDeleted = get(p, 'diff.deleted', '#565656');
|
|
|
|
|
const diffModified = get(p, 'diff.modified', '#203952');
|
|
|
|
|
|
|
|
|
|
// Mix diff color at ~80% alpha over body background
|
|
|
|
|
const diffAddedRowBg = mix(body, diffInserted, 0.8);
|
|
|
|
|
const diffRemovedRowBg = mix(body, diffDeleted, 0.8);
|
|
|
|
|
const diffMovedRowBg = mix(body, diffModified, 0.8);
|
|
|
|
|
|
|
|
|
|
vars['--color-diff-added-fg'] = ansiGreen;
|
|
|
|
|
vars['--color-diff-added-linenum-bg'] = scaleLightness(diffAddedRowBg, -0.05);
|
|
|
|
|
vars['--color-diff-added-row-bg'] = diffAddedRowBg;
|
|
|
|
|
vars['--color-diff-added-row-border'] = scaleLightness(diffAddedRowBg, -0.10);
|
|
|
|
|
vars['--color-diff-added-word-bg'] = scaleLightness(diffAddedRowBg, -0.15);
|
|
|
|
|
|
|
|
|
|
vars['--color-diff-removed-fg'] = named.red;
|
|
|
|
|
vars['--color-diff-removed-linenum-bg'] = scaleLightness(diffRemovedRowBg, -0.05);
|
|
|
|
|
vars['--color-diff-removed-row-bg'] = diffRemovedRowBg;
|
|
|
|
|
vars['--color-diff-removed-row-border'] = scaleLightness(diffRemovedRowBg, -0.10);
|
|
|
|
|
vars['--color-diff-removed-word-bg'] = scaleLightness(diffRemovedRowBg, -0.15);
|
|
|
|
|
|
|
|
|
|
vars['--color-diff-moved-row-bg'] = diffMovedRowBg;
|
|
|
|
|
vars['--color-diff-moved-row-border'] = scaleLightness(diffMovedRowBg, 0.15);
|
|
|
|
|
vars['--color-diff-inactive'] = scaleLightness(body, isDark ? -0.05 : 0.05);
|
|
|
|
|
|
|
|
|
|
// ─── Section 10: Status/alert colors ─────────────────────────────────────────
|
|
|
|
|
const errorText = get(p, 'errorColor', get(p, 'stopColor', '#FF5555'));
|
|
|
|
|
vars['--color-error-border'] = withAlpha(errorText, 0x66);
|
|
|
|
|
vars['--color-error-bg'] = withAlpha(errorText, 0x1a);
|
|
|
|
|
vars['--color-error-bg-active'] = withAlpha(errorText, 0x33);
|
|
|
|
|
vars['--color-error-bg-hover'] = withAlpha(errorText, 0x26);
|
|
|
|
|
vars['--color-error-text'] = errorText;
|
|
|
|
|
|
|
|
|
|
const successText = ansiGreen;
|
|
|
|
|
vars['--color-success-border'] = withAlpha(successText, 0x66);
|
|
|
|
|
vars['--color-success-bg'] = withAlpha(successText, 0x1a);
|
|
|
|
|
vars['--color-success-text'] = successText;
|
|
|
|
|
|
|
|
|
|
const warningText = ansiYellow;
|
|
|
|
|
vars['--color-warning-border'] = withAlpha(warningText, 0x66);
|
|
|
|
|
vars['--color-warning-bg'] = withAlpha(warningText, 0x1a);
|
|
|
|
|
vars['--color-warning-text'] = warningText;
|
|
|
|
|
|
|
|
|
|
const infoText = ansiBlue;
|
|
|
|
|
vars['--color-info-border'] = withAlpha(infoText, 0x66);
|
|
|
|
|
vars['--color-info-bg'] = withAlpha(infoText, 0x1a);
|
|
|
|
|
vars['--color-info-text'] = infoText;
|
|
|
|
|
|
|
|
|
|
const priorityText = named.violet;
|
|
|
|
|
vars['--color-priority-border'] = withAlpha(priorityText, 0x66);
|
|
|
|
|
vars['--color-priority-bg'] = withAlpha(priorityText, 0x1a);
|
|
|
|
|
vars['--color-priority-text'] = priorityText;
|
|
|
|
|
|
|
|
|
|
// ─── Section 11: Badge colors ─────────────────────────────────────────────────
|
|
|
|
|
vars['--color-red-badge'] = named.red;
|
|
|
|
|
vars['--color-red-badge-bg'] = withAlpha(named.red, 0x1a);
|
|
|
|
|
vars['--color-red-badge-hover-bg'] = withAlpha(named.red, 0x4d);
|
|
|
|
|
|
|
|
|
|
vars['--color-green-badge'] = named.green;
|
|
|
|
|
vars['--color-green-badge-bg'] = withAlpha(named.green, 0x1a);
|
|
|
|
|
vars['--color-green-badge-hover-bg'] = withAlpha(named.green, 0x4d);
|
|
|
|
|
|
|
|
|
|
vars['--color-yellow-badge'] = named.yellow;
|
|
|
|
|
vars['--color-yellow-badge-bg'] = withAlpha(named.yellow, 0x1a);
|
|
|
|
|
vars['--color-yellow-badge-hover-bg'] = withAlpha(named.yellow, 0x4d);
|
|
|
|
|
|
|
|
|
|
vars['--color-orange-badge'] = named.orange;
|
|
|
|
|
vars['--color-orange-badge-bg'] = withAlpha(named.orange, 0x1a);
|
|
|
|
|
vars['--color-orange-badge-hover-bg'] = withAlpha(named.orange, 0x4d);
|
|
|
|
|
|
|
|
|
|
// ─── Section 12: Brand colors (fixed) ─────────────────────────────────────────
|
|
|
|
|
vars['--color-git'] = '#F05133';
|
|
|
|
|
vars['--color-logo'] = '#609926';
|
|
|
|
|
|
|
|
|
|
// ─── Section 13: Semantic / target-based colors ───────────────────────────────
|
|
|
|
|
const boxBody = contrastColor;
|
|
|
|
|
const boxBodyHighlight = isDark
|
|
|
|
|
? scaleLightness(boxBody, 0.04)
|
|
|
|
|
: withAlpha(primary, 0x10);
|
|
|
|
|
|
|
|
|
|
vars['--color-body'] = body;
|
|
|
|
|
vars['--color-box-header'] = isDark ? contrastColor : headerColor;
|
|
|
|
|
vars['--color-box-body'] = contrastColor;
|
|
|
|
|
vars['--color-box-body-highlight'] = boxBodyHighlight;
|
|
|
|
|
vars['--color-text-dark'] = isDark ? get(p, 'selectionForeground') : fg;
|
|
|
|
|
vars['--color-text'] = fg;
|
|
|
|
|
vars['--color-text-light'] = scaleLightness(fg, isDark ? -0.08 : 0.08);
|
|
|
|
|
vars['--color-text-light-1'] = get(p, 'buttonFont');
|
|
|
|
|
vars['--color-text-light-2'] = get(p, 'lineNumberColor');
|
|
|
|
|
vars['--color-text-light-3'] = get(p, 'disabledColor');
|
|
|
|
|
vars['--color-footer'] = 'var(--color-nav-bg)';
|
|
|
|
|
vars['--color-timeline'] = secondary;
|
|
|
|
|
vars['--color-input-text'] = 'var(--color-text-dark)';
|
|
|
|
|
vars['--color-input-background'] = get(p, 'textEditorBackground');
|
|
|
|
|
vars['--color-input-toggle-background'] = secondary;
|
|
|
|
|
vars['--color-input-border'] = 'var(--color-secondary-dark-1)';
|
|
|
|
|
// Subtle overlay tint — fixed neutral values that work on any background
|
|
|
|
|
vars['--color-light'] = isDark ? '#F3F3F406' : '#00001706';
|
|
|
|
|
vars['--color-light-border'] = isDark ? '#F3F3F428' : '#0000171D';
|
|
|
|
|
vars['--color-hover'] = isDark ? withAlpha(fg, 0x19) : '#00001708';
|
|
|
|
|
vars['--color-hover-opaque'] = scaleLightness(body, isDark ? 0.06 : -0.05);
|
|
|
|
|
vars['--color-active'] = isDark ? withAlpha(fg, 0x24) : '#00001714';
|
|
|
|
|
vars['--color-menu'] = inactiveBackground;
|
|
|
|
|
vars['--color-card'] = inactiveBackground;
|
|
|
|
|
vars['--color-markup-table-row'] = isDark ? withAlpha(fg, 0x0f) : withAlpha(primary, 0x0a);
|
|
|
|
|
vars['--color-markup-code-block'] = isDark ? withAlpha(fg, 0x12) : withAlpha(primary, 0x10);
|
|
|
|
|
vars['--color-markup-code-inline'] = isDark ? withAlpha(fg, 0x28) : withAlpha(primary, 0x12);
|
|
|
|
|
vars['--color-button'] = get(p, 'buttonColor', contrastColor);
|
|
|
|
|
vars['--color-code-bg'] = get(p, 'codeBlock');
|
|
|
|
|
vars['--color-shadow'] = isDark ? withAlpha(body, 0x58) : '#00001726';
|
|
|
|
|
vars['--color-shadow-opaque'] = isDark ? contrastColor : scaleLightness(body, -0.12);
|
|
|
|
|
vars['--color-secondary-bg'] = get(p, 'secondaryBackground');
|
|
|
|
|
vars['--color-expand-button'] = get(p, 'highlightColor');
|
|
|
|
|
vars['--color-placeholder-text'] = 'var(--color-text-light-3)';
|
|
|
|
|
vars['--color-editor-line-highlight'] = isDark ? 'var(--color-secondary-alpha-40)' : 'var(--color-secondary-alpha-30)';
|
|
|
|
|
vars['--color-editor-selection'] = isDark ? 'var(--color-primary-alpha-50)' : 'var(--color-primary-alpha-30)';
|
|
|
|
|
vars['--color-project-column-bg'] = isDark ? 'var(--color-secondary-light-2)' : 'var(--color-secondary-light-4)';
|
|
|
|
|
vars['--color-caret'] = isDark ? 'var(--color-text)' : 'var(--color-text-dark)';
|
|
|
|
|
vars['--color-reaction-bg'] = isDark ? withAlpha(fg, 0x12) : '#0000170A';
|
|
|
|
|
vars['--color-reaction-hover-bg'] = isDark ? 'var(--color-primary-light-4)' : 'var(--color-primary-light-5)';
|
|
|
|
|
vars['--color-reaction-active-bg'] = isDark ? 'var(--color-primary-light-5)' : 'var(--color-primary-light-6)';
|
|
|
|
|
vars['--color-tooltip-text'] = isDark ? '#FAFAFA' : '#FBFDFF';
|
|
|
|
|
vars['--color-tooltip-bg'] = isDark ? '#0B0B0CF0' : '#000017F0';
|
|
|
|
|
vars['--color-nav-bg'] = headerColor;
|
|
|
|
|
vars['--color-nav-hover-bg'] = 'var(--color-secondary-light-1)';
|
|
|
|
|
vars['--color-nav-text'] = 'var(--color-text)';
|
|
|
|
|
vars['--color-secondary-nav-bg'] = scaleLightness(headerColor, isDark ? 0.02 : -0.02);
|
|
|
|
|
vars['--color-label-text'] = 'var(--color-text)';
|
|
|
|
|
vars['--color-label-bg'] = withAlpha(secondary, 0x4b);
|
|
|
|
|
vars['--color-label-hover-bg'] = withAlpha(secondary, 0xa0);
|
|
|
|
|
vars['--color-label-active-bg'] = withAlpha(secondary, 0xff);
|
|
|
|
|
vars['--color-accent'] = 'var(--color-primary-light-1)';
|
|
|
|
|
vars['--color-small-accent'] = isDark ? 'var(--color-primary-light-5)' : 'var(--color-primary-light-6)';
|
|
|
|
|
vars['--color-highlight-fg'] = get(p, 'searchForeground', get(p, 'selectionForeground'));
|
|
|
|
|
vars['--color-highlight-bg'] = get(p, 'searchBackground', withAlpha(primary, 0x66));
|
|
|
|
|
vars['--color-overlay-backdrop'] = '#080808C0';
|
|
|
|
|
vars['--color-danger'] = 'var(--color-red)';
|
|
|
|
|
vars['--color-transparency-grid-light'] = isDark ? '#2A2A2A' : '#FAFAFA';
|
|
|
|
|
vars['--color-transparency-grid-dark'] = isDark ? '#1A1A1A' : '#E2E2E2';
|
|
|
|
|
vars['--color-workflow-edge-hover'] = scaleLightness(secondary, isDark ? 0.2 : -0.2);
|
|
|
|
|
|
|
|
|
|
// ─── Section 14: Syntax highlighting ──────────────────────────────────────────
|
|
|
|
|
const syntaxComment = get(p, 'comments');
|
|
|
|
|
const diffRemovedSolid = normalizeHex(diffRemovedRowBg);
|
|
|
|
|
const diffAddedSolid = normalizeHex(diffAddedRowBg);
|
|
|
|
|
|
|
|
|
|
vars['--color-syntax-keyword'] = get(p, 'keywordColor');
|
|
|
|
|
vars['--color-syntax-bool'] = ansiCyan;
|
|
|
|
|
vars['--color-syntax-control'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-name'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-type'] = get(p, 'classNameColor');
|
|
|
|
|
vars['--color-syntax-number'] = get(p, 'constantColor', get(p, 'keyColor'));
|
|
|
|
|
vars['--color-syntax-operator'] = get(p, 'keywordColor');
|
|
|
|
|
vars['--color-syntax-regexp'] = ansiMagenta;
|
|
|
|
|
vars['--color-syntax-string'] = get(p, 'stringColor');
|
|
|
|
|
vars['--color-syntax-comment'] = syntaxComment;
|
|
|
|
|
vars['--color-syntax-invalid'] = errorText;
|
|
|
|
|
vars['--color-syntax-link'] = 'var(--color-primary)';
|
|
|
|
|
vars['--color-syntax-tag'] = get(p, 'htmlTagColor', get(p, 'keywordColor'));
|
|
|
|
|
vars['--color-syntax-attribute'] = ansiMagenta;
|
|
|
|
|
vars['--color-syntax-property'] = get(p, 'keyColor');
|
|
|
|
|
vars['--color-syntax-variable'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-string-special'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-escape'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-entity'] = ansiMagenta;
|
|
|
|
|
vars['--color-syntax-preproc'] = ansiGreen;
|
|
|
|
|
vars['--color-syntax-preproc-file'] = get(p, 'constantColor', get(p, 'keyColor'));
|
|
|
|
|
vars['--color-syntax-decorator'] = ansiGreen;
|
|
|
|
|
vars['--color-syntax-namespace'] = fg;
|
|
|
|
|
vars['--color-syntax-name-pseudo'] = ansiMagenta;
|
|
|
|
|
vars['--color-syntax-comment-special'] = scaleLightness(syntaxComment, 0.08);
|
|
|
|
|
vars['--color-syntax-text'] = isDark ? fg : 'inherit';
|
|
|
|
|
vars['--color-syntax-text-alt'] = scaleLightness(fg, -0.10);
|
|
|
|
|
vars['--color-syntax-punctuation'] = isDark ? fg : 'inherit';
|
|
|
|
|
vars['--color-syntax-whitespace'] = get(p, 'disabledColor');
|
|
|
|
|
vars['--color-syntax-diff-fg'] = isDark ? '#FFFFFF' : '#000000';
|
|
|
|
|
vars['--color-syntax-deleted-bg'] = diffRemovedSolid;
|
|
|
|
|
vars['--color-syntax-inserted-bg'] = diffAddedSolid;
|
|
|
|
|
vars['--color-syntax-emph'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-strong'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-heading'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-subheading'] = get(p, 'stringColor');
|
|
|
|
|
vars['--color-syntax-output'] = syntaxComment;
|
|
|
|
|
vars['--color-syntax-prompt'] = ansiYellow;
|
|
|
|
|
vars['--color-syntax-traceback'] = errorText;
|
|
|
|
|
vars['--color-syntax-matching-bracket-bg'] = withAlpha(named.teal, 0x48);
|
|
|
|
|
vars['--color-syntax-nonmatching-bracket-bg'] = withAlpha(named.red, 0x48);
|
|
|
|
|
|
|
|
|
|
return vars;
|
|
|
|
|
}
|