fix(style): Z-Design V5 - Blend fijo sin compensación perceptual
Simplificación consensuada: - Eliminar compensación perceptual (causaba más problemas) - Blend fijo para TODOS los colores: - Focus: 18% base / 82% negro - Unfocus: 6% base / 94% negro La fluidez viene de pasar bg_transition.current a widgets, no de compensar matemáticamente.
This commit is contained in:
parent
23204bdd0a
commit
f41e502f9c
1 changed files with 33 additions and 52 deletions
|
|
@ -1375,46 +1375,31 @@ pub const DerivedPanelColors = struct {
|
||||||
|
|
||||||
/// Derive panel frame colors from a single base color.
|
/// Derive panel frame colors from a single base color.
|
||||||
///
|
///
|
||||||
/// Z-Design V4: "El rojo es el estándar"
|
/// Z-Design V5: Sincronía Atmosférica (2025-12-31)
|
||||||
/// - Colores brillantes (L > 0.2, ej: rojo): 22% color visible (el estándar bueno)
|
/// - SIN compensación perceptual (causaba más problemas que soluciones)
|
||||||
/// - Colores oscuros (L <= 0.2, ej: azul): 35% color visible (boost para compensar)
|
/// - Blend fijo y generoso para TODOS los colores:
|
||||||
|
/// - Fondo con focus: 18% base / 82% negro
|
||||||
|
/// - Fondo sin focus: 6% base / 94% negro
|
||||||
///
|
///
|
||||||
/// El objetivo es que TODOS los paneles tengan la vibrancia del rojo.
|
/// La clave de la fluidez está en pasar bg_transition.current a los widgets,
|
||||||
/// El azul debe "saltar" del negro tanto como lo hace el rojo.
|
/// NO en compensar matemáticamente los colores.
|
||||||
///
|
|
||||||
/// Luminance L = 0.2126*R + 0.7152*G + 0.0722*B
|
|
||||||
/// - Rojo puro: L ~= 0.21 (justo en el límite, usa estándar 22%)
|
|
||||||
/// - Azul puro: L ~= 0.07 (muy bajo, usa boost 35%)
|
|
||||||
/// - Verde puro: L ~= 0.72 (alto, usa estándar 22%)
|
|
||||||
pub fn derivePanelFrameColors(base: Color) DerivedPanelColors {
|
pub fn derivePanelFrameColors(base: Color) DerivedPanelColors {
|
||||||
const L = base.perceptualLuminance();
|
|
||||||
|
|
||||||
// Z-Design V4: Threshold-based boost
|
|
||||||
// El rojo (~22%) es el estándar de "buena vibrancia"
|
|
||||||
// Colores oscuros como el azul necesitan más intensidad para verse igual
|
|
||||||
const blend_factor: f32 = if (L > 0.2)
|
|
||||||
0.22 // Estándar: colores brillantes (rojo, verde, amarillo)
|
|
||||||
else
|
|
||||||
0.35; // Boost: colores oscuros (azul, violeta)
|
|
||||||
|
|
||||||
// Convert to percentage for blendTowards (inverted: 100% = all black)
|
|
||||||
// focus: full blend, unfocus: half blend
|
|
||||||
const focus_pct: u8 = @intFromFloat((1.0 - blend_factor) * 100.0);
|
|
||||||
const unfocus_pct: u8 = @intFromFloat((1.0 - blend_factor * 0.5) * 100.0);
|
|
||||||
|
|
||||||
const black = Color.soft_black;
|
const black = Color.soft_black;
|
||||||
|
|
||||||
|
// Blend fijo: 18% color con focus, 6% sin focus
|
||||||
|
// blendTowards(black, 82) = 18% base + 82% black
|
||||||
|
// blendTowards(black, 94) = 6% base + 94% black
|
||||||
return .{
|
return .{
|
||||||
.focus_bg = base.blendTowards(black, focus_pct),
|
.focus_bg = base.blendTowards(black, 82),
|
||||||
.unfocus_bg = base.blendTowards(black, unfocus_pct),
|
.unfocus_bg = base.blendTowards(black, 94),
|
||||||
.border_focus = base,
|
.border_focus = base,
|
||||||
.border_unfocus = base.darken(30),
|
.border_unfocus = base.darken(30),
|
||||||
.title_color = base.lightenHsl(20),
|
.title_color = base.lightenHsl(20),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
test "derivePanelFrameColors blue gets boost" {
|
test "derivePanelFrameColors fixed blend" {
|
||||||
// Pure blue has L ~= 0.07, which is < 0.2, so it gets 35% boost
|
// Z-Design V5: All colors use same fixed blend (18% focus, 6% unfocus)
|
||||||
const blue = Color.rgb(0, 0, 255);
|
const blue = Color.rgb(0, 0, 255);
|
||||||
const derived = derivePanelFrameColors(blue);
|
const derived = derivePanelFrameColors(blue);
|
||||||
|
|
||||||
|
|
@ -1423,34 +1408,30 @@ test "derivePanelFrameColors blue gets boost" {
|
||||||
try std.testing.expectEqual(blue.g, derived.border_focus.g);
|
try std.testing.expectEqual(blue.g, derived.border_focus.g);
|
||||||
try std.testing.expectEqual(blue.b, derived.border_focus.b);
|
try std.testing.expectEqual(blue.b, derived.border_focus.b);
|
||||||
|
|
||||||
// Focus bg should have significant blue visible (35% boost)
|
// Focus bg: 18% blue + 82% soft_black(17,17,20)
|
||||||
// 35% of 255 = ~89, blended with soft_black (17,17,20)
|
// 0.18 * 255 + 0.82 * 20 = 45.9 + 16.4 = 62.3
|
||||||
try std.testing.expect(derived.focus_bg.b > 70); // Should be vibrant blue
|
try std.testing.expect(derived.focus_bg.b > 50);
|
||||||
|
try std.testing.expect(derived.focus_bg.b < 80);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "derivePanelFrameColors red is standard" {
|
test "derivePanelFrameColors same blend for all colors" {
|
||||||
// Red has L ~= 0.21, which is > 0.2, so it gets standard 22%
|
// V5: No perceptual correction - same blend for red and blue
|
||||||
|
const blue = Color.rgb(0, 0, 255);
|
||||||
const red = Color.rgb(255, 0, 0);
|
const red = Color.rgb(255, 0, 0);
|
||||||
const derived = derivePanelFrameColors(red);
|
|
||||||
|
|
||||||
// Focus bg should have standard red visibility (22%)
|
|
||||||
// 22% of 255 = ~56, blended with soft_black
|
|
||||||
try std.testing.expect(derived.focus_bg.r > 40);
|
|
||||||
try std.testing.expect(derived.focus_bg.r < 100); // Not too bright
|
|
||||||
}
|
|
||||||
|
|
||||||
test "derivePanelFrameColors threshold behavior" {
|
|
||||||
// Test that blue (L < 0.2) gets MORE visibility than red (L > 0.2)
|
|
||||||
const blue = Color.rgb(0, 0, 255); // L ~= 0.07
|
|
||||||
const red = Color.rgb(255, 0, 0); // L ~= 0.21
|
|
||||||
|
|
||||||
const blue_derived = derivePanelFrameColors(blue);
|
const blue_derived = derivePanelFrameColors(blue);
|
||||||
const red_derived = derivePanelFrameColors(red);
|
const red_derived = derivePanelFrameColors(red);
|
||||||
|
|
||||||
// Blue gets 35% blend, red gets 22%
|
// Both should have ~18% of their primary color channel
|
||||||
// So blue's color channel should be proportionally MORE visible
|
// Blue: ~18% of 255 = ~46, Red: ~18% of 255 = ~46
|
||||||
// Blue: 35% of 255 ~= 89
|
// (plus soft_black contribution)
|
||||||
// Red: 22% of 255 ~= 56
|
const blue_intensity = blue_derived.focus_bg.b;
|
||||||
// Blue should have higher relative intensity
|
const red_intensity = red_derived.focus_bg.r;
|
||||||
try std.testing.expect(blue_derived.focus_bg.b > red_derived.focus_bg.r);
|
|
||||||
|
// Should be approximately equal (within tolerance for soft_black blend)
|
||||||
|
const diff = if (blue_intensity > red_intensity)
|
||||||
|
blue_intensity - red_intensity
|
||||||
|
else
|
||||||
|
red_intensity - blue_intensity;
|
||||||
|
try std.testing.expect(diff < 10); // Close enough
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue