diff --git a/src/core/style.zig b/src/core/style.zig index 73f503a..3d8770d 100644 --- a/src/core/style.zig +++ b/src/core/style.zig @@ -1048,12 +1048,13 @@ fn deriveDarkPalette(base: Color) PanelColorScheme { .etiquetas = white.darken(30), // ~70% brightness .placeholder = gray, - // Header: darkened base color - .header = base.darken(60), + // Header: darkened using HSL (preserves hue better than RGB darken) + .header = base.darkenHsl(50), - // Selection: where the base color SHINES - .seleccion_fondo_con_focus = base, // Full color! - .seleccion_fondo_sin_focus = base.blendTowards(gray, 50), // Muted + // Selection: base color at full strength when focused + .seleccion_fondo_con_focus = base, + // Unfocused: desaturated and slightly lightened (HSL-based, more elegant) + .seleccion_fondo_sin_focus = base.desaturate(60).lightenHsl(10), // Borders: accent on focus, subtle otherwise .borde_con_focus = base, @@ -1079,12 +1080,13 @@ fn deriveLightPalette(base: Color) PanelColorScheme { .etiquetas = black.lighten(40), // ~60% darkness .placeholder = gray, - // Header: very light version of base - .header = base.blendTowards(white, 85), + // Header: lightened using HSL (preserves hue better) + .header = base.lightenHsl(40), - // Selection: base color (slightly lightened for readability) + // Selection: base color at full strength when focused .seleccion_fondo_con_focus = base, - .seleccion_fondo_sin_focus = base.blendTowards(white, 60), + // Unfocused: desaturated and lightened (HSL-based) + .seleccion_fondo_sin_focus = base.desaturate(50).lightenHsl(30), // Borders: accent on focus, subtle otherwise .borde_con_focus = base, @@ -1092,6 +1094,17 @@ fn deriveLightPalette(base: Color) PanelColorScheme { }; } +/// Get appropriate text color (black or white) based on background luminosity. +/// Uses the HSL lightness value to determine contrast. +pub fn contrastTextColor(background: Color) Color { + const hsl = background.toHsl(); + // If background is light (L > 0.5), use dark text; otherwise use light text + return if (hsl.l > 0.5) + Color.rgb(20, 20, 25) // Dark text for light backgrounds + else + Color.rgb(245, 245, 245); // Light text for dark backgrounds +} + // ============================================================================= // Z-Design Tests // ============================================================================= @@ -1149,3 +1162,20 @@ test "derivePanelPalette light mode" { try std.testing.expect(palette.fondo_con_focus.g > 245); try std.testing.expect(palette.fondo_con_focus.b > 250); } + +test "contrastTextColor" { + // Dark background should get light text + const dark_bg = Color.rgb(30, 30, 30); + const text_on_dark = contrastTextColor(dark_bg); + try std.testing.expect(text_on_dark.r > 200); // Light text + + // Light background should get dark text + const light_bg = Color.rgb(240, 240, 240); + const text_on_light = contrastTextColor(light_bg); + try std.testing.expect(text_on_light.r < 50); // Dark text + + // Mid-gray (128/255 = 0.502 > 0.5) gets dark text + const mid_gray = Color.rgb(128, 128, 128); + const text_on_mid = contrastTextColor(mid_gray); + try std.testing.expect(text_on_mid.r < 50); // Dark text (L = 0.502 > 0.5) +}