From 4d714759951e5a41758f250fc887b053eb681a0c Mon Sep 17 00:00:00 2001 From: Bruno Deanoz Date: Sun, 21 Jun 2026 14:41:23 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20derive=20all=20theme=20colors=20from=20w?= =?UTF-8?q?eb=20CSS=20files=20(OKLCH=20=E2=86=92=20P3=20RGB)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Amber blobs were cold (blue/indigo) but web uses warm (gold/coral/honey/teal). Mono had slate chroma but web is pure achromatic (zero chroma). Aurora dark primary was magenta but web swaps to gold in dark mode. All four themes now pixel-match the web app's OKLCH values. --- .../java/dev/kaizen/app/chat/Background.kt | 4 +- .../java/dev/kaizen/app/ui/theme/Color.kt | 12 +++--- .../kaizen/app/ui/theme/themes/AmberTheme.kt | 37 +++++++++--------- .../kaizen/app/ui/theme/themes/AuroraTheme.kt | 39 ++++++++++--------- .../kaizen/app/ui/theme/themes/BlauTheme.kt | 37 +++++++++--------- .../kaizen/app/ui/theme/themes/MonoTheme.kt | 37 +++++++++--------- .../java/dev/kaizen/app/ColorPipelineTest.kt | 22 ++++++++++- 7 files changed, 107 insertions(+), 81 deletions(-) diff --git a/app/src/main/java/dev/kaizen/app/chat/Background.kt b/app/src/main/java/dev/kaizen/app/chat/Background.kt index e83d7ad..8e136df 100644 --- a/app/src/main/java/dev/kaizen/app/chat/Background.kt +++ b/app/src/main/java/dev/kaizen/app/chat/Background.kt @@ -50,7 +50,7 @@ import androidx.compose.ui.unit.dp import dev.kaizen.app.ui.theme.Amber import dev.kaizen.app.ui.theme.AmberDeep import dev.kaizen.app.ui.theme.BlobAmber -import dev.kaizen.app.ui.theme.BlobBlue +import dev.kaizen.app.ui.theme.BlobCoral import dev.kaizen.app.ui.theme.BlobTeal import dev.kaizen.app.ui.theme.DITHER_ALPHA import dev.kaizen.app.ui.theme.rememberDitherBrush @@ -81,7 +81,7 @@ fun MeshBackground(content: @Composable BoxScope.() -> Unit) { }, ) { Blob(BlobAmber, 360.dp, (-60f + drift * 30f).dp, (-40f + drift * 24f).dp, 0.30f * factor) - Blob(BlobBlue, 380.dp, (170f - drift * 44f).dp, (150f + drift * 40f).dp, 0.24f * factor) + Blob(BlobCoral, 380.dp, (170f - drift * 44f).dp, (150f + drift * 40f).dp, 0.24f * factor) Blob(BlobTeal, 300.dp, (30f + drift * 50f).dp, (560f - drift * 36f).dp, 0.22f * factor) // Vignette: darken the edges so the center comes forward (dark mode only). if (dark) { diff --git a/app/src/main/java/dev/kaizen/app/ui/theme/Color.kt b/app/src/main/java/dev/kaizen/app/ui/theme/Color.kt index 6a54aff..9770115 100644 --- a/app/src/main/java/dev/kaizen/app/ui/theme/Color.kt +++ b/app/src/main/java/dev/kaizen/app/ui/theme/Color.kt @@ -38,8 +38,10 @@ val LightText = p3(0.102f, 0.122f, 0.161f) // ≈ #1A1F29 val LightMuted = p3(0.357f, 0.392f, 0.439f) // ≈ #5B6470 val LightStroke = p3(0f, 0f, 0f, 0.08f) // outline -// ── Background blobs ─────────────────────────────────────────────────────── -val BlobAmber = p3(0.878f, 0.635f, 0.243f) // ≈ Amber -val BlobBlue = p3(0.235f, 0.373f, 0.839f) // ≈ #3C5FD6 -val BlobTeal = p3(0.169f, 0.714f, 0.651f) // ≈ #2BB6A6 -val BlobIndigo = p3(0.290f, 0.290f, 0.690f) // 4th blob for Amber theme +// ── Background blobs (Amber theme defaults, derived from amber.css) ──────── +// These are the light-mode defaults. Theme-specific blobs come from +// LocalKaizenAccent.current.blob1..4 once the theme system is wired. +val BlobAmber = p3(0.992f, 0.767f, 0.282f) // oklch(0.85 0.15 83) gold +val BlobCoral = p3(1.000f, 0.562f, 0.230f) // oklch(0.78 0.18 50) coral +val BlobHoney = p3(0.917f, 0.853f, 0.471f) // oklch(0.88 0.12 100) honey +val BlobTeal = p3(0.461f, 0.885f, 0.908f) // oklch(0.85 0.10 200) teal accent diff --git a/app/src/main/java/dev/kaizen/app/ui/theme/themes/AmberTheme.kt b/app/src/main/java/dev/kaizen/app/ui/theme/themes/AmberTheme.kt index e8bd223..91e562c 100644 --- a/app/src/main/java/dev/kaizen/app/ui/theme/themes/AmberTheme.kt +++ b/app/src/main/java/dev/kaizen/app/ui/theme/themes/AmberTheme.kt @@ -6,27 +6,28 @@ import androidx.compose.ui.graphics.colorspace.ColorSpaces private fun p3(r: Float, g: Float, b: Float): Color = Color(red = r, green = g, blue = b, colorSpace = ColorSpaces.DisplayP3) +// Derived from kaizen/app/themes/amber.css — warm blobs (gold, coral, honey, teal accent) val AmberTheme = KaizenThemeSpec( id = KaizenThemeId.AMBER, label = "Amber", - dark = KaizenAccentScheme( - primary = p3(0.878f, 0.635f, 0.243f), // Amber - primaryDeep = p3(0.784f, 0.525f, 0.165f), - onPrimary = p3(0.106f, 0.071f, 0.024f), - ring = p3(0.878f, 0.635f, 0.243f), - blob1 = p3(0.878f, 0.635f, 0.243f), // Amber - blob2 = p3(0.235f, 0.373f, 0.839f), // Blue - blob3 = p3(0.290f, 0.290f, 0.690f), // Indigo - blob4 = p3(0.169f, 0.714f, 0.651f), // Teal - ), light = KaizenAccentScheme( - primary = p3(0.784f, 0.525f, 0.165f), // AmberDeep (better contrast on white) - primaryDeep = p3(0.784f, 0.525f, 0.165f), - onPrimary = p3(1f, 1f, 1f), - ring = p3(0.878f, 0.635f, 0.243f), - blob1 = p3(0.878f, 0.635f, 0.243f), - blob2 = p3(0.235f, 0.373f, 0.839f), - blob3 = p3(0.290f, 0.290f, 0.690f), - blob4 = p3(0.169f, 0.714f, 0.651f), + primary = p3(0.811f, 0.608f, 0.126f), // oklch(0.72 0.14 83) + primaryDeep = p3(0.811f, 0.608f, 0.126f), + onPrimary = p3(0.015f, 0.013f, 0.009f), // oklch(0.10 0.005 83) + ring = p3(0.811f, 0.608f, 0.126f), + blob1 = p3(0.992f, 0.767f, 0.282f), // oklch(0.85 0.15 83) gold + blob2 = p3(1.000f, 0.562f, 0.230f), // oklch(0.78 0.18 50) coral + blob3 = p3(0.917f, 0.853f, 0.471f), // oklch(0.88 0.12 100) honey + blob4 = p3(0.461f, 0.885f, 0.908f), // oklch(0.85 0.10 200) teal accent + ), + dark = KaizenAccentScheme( + primary = p3(0.862f, 0.658f, 0.201f), // oklch(0.76 0.14 83) + primaryDeep = p3(0.811f, 0.608f, 0.126f), + onPrimary = p3(0.015f, 0.013f, 0.009f), // oklch(0.10 0.005 83) + ring = p3(0.862f, 0.658f, 0.201f), + blob1 = p3(0.619f, 0.394f, 0.000f), // oklch(0.55 0.16 83) deep gold + blob2 = p3(0.628f, 0.087f, 0.000f), // oklch(0.45 0.18 40) deep coral + blob3 = p3(0.404f, 0.407f, 0.084f), // oklch(0.50 0.10 110) olive + blob4 = p3(0.000f, 0.405f, 0.436f), // oklch(0.45 0.12 200) deep teal ), ) diff --git a/app/src/main/java/dev/kaizen/app/ui/theme/themes/AuroraTheme.kt b/app/src/main/java/dev/kaizen/app/ui/theme/themes/AuroraTheme.kt index 1a44385..4cd332f 100644 --- a/app/src/main/java/dev/kaizen/app/ui/theme/themes/AuroraTheme.kt +++ b/app/src/main/java/dev/kaizen/app/ui/theme/themes/AuroraTheme.kt @@ -6,27 +6,30 @@ import androidx.compose.ui.graphics.colorspace.ColorSpaces private fun p3(r: Float, g: Float, b: Float): Color = Color(red = r, green = g, blue = b, colorSpace = ColorSpaces.DisplayP3) +// Derived from kaizen/app/themes/aurora.css +// Light: purple primary, blobs = purple/gold/green/teal +// Dark: GOLD primary (swaps!), blobs = deep purple/gold/green/teal val AuroraTheme = KaizenThemeSpec( id = KaizenThemeId.AURORA, label = "Aurora", - dark = KaizenAccentScheme( - primary = p3(0.850f, 0.310f, 0.750f), // Magenta P3 - primaryDeep = p3(0.680f, 0.220f, 0.620f), - onPrimary = p3(0.106f, 0.024f, 0.090f), - ring = p3(0.850f, 0.310f, 0.750f), - blob1 = p3(0.850f, 0.310f, 0.750f), // Magenta - blob2 = p3(0.169f, 0.714f, 0.800f), // Cyan - blob3 = p3(0.545f, 0.361f, 0.859f), // Violet - blob4 = p3(0.520f, 0.850f, 0.310f), // Lime (accent) - ), light = KaizenAccentScheme( - primary = p3(0.490f, 0.270f, 0.690f), // Violet-600 P3 - primaryDeep = p3(0.490f, 0.270f, 0.690f), - onPrimary = p3(1f, 1f, 1f), - ring = p3(0.850f, 0.310f, 0.750f), - blob1 = p3(0.850f, 0.310f, 0.750f), - blob2 = p3(0.169f, 0.714f, 0.800f), - blob3 = p3(0.545f, 0.361f, 0.859f), - blob4 = p3(0.520f, 0.850f, 0.310f), + primary = p3(0.724f, 0.328f, 0.812f), // oklch(0.62 0.20 320) purple + primaryDeep = p3(0.724f, 0.328f, 0.812f), + onPrimary = p3(1.000f, 0.979f, 1.000f), // oklch(0.99 0.01 320) + ring = p3(0.724f, 0.328f, 0.812f), + blob1 = p3(0.855f, 0.540f, 0.926f), // oklch(0.75 0.16 320) purple + blob2 = p3(0.931f, 0.738f, 0.291f), // oklch(0.82 0.14 85) gold + blob3 = p3(0.433f, 0.822f, 0.455f), // oklch(0.78 0.16 145) green + blob4 = p3(0.227f, 0.808f, 0.837f), // oklch(0.78 0.12 200) teal + ), + dark = KaizenAccentScheme( + primary = p3(0.890f, 0.684f, 0.156f), // oklch(0.78 0.15 85) GOLD (swapped!) + primaryDeep = p3(0.724f, 0.328f, 0.812f), + onPrimary = p3(0.034f, 0.020f, 0.003f), // oklch(0.12 0.02 85) + ring = p3(0.890f, 0.684f, 0.156f), + blob1 = p3(0.495f, 0.141f, 0.569f), // oklch(0.45 0.18 320) deep purple + blob2 = p3(0.600f, 0.405f, 0.000f), // oklch(0.55 0.15 85) deep gold + blob3 = p3(0.000f, 0.459f, 0.000f), // oklch(0.48 0.18 145) deep green + blob4 = p3(0.000f, 0.410f, 0.445f), // oklch(0.45 0.13 200) deep teal ), ) diff --git a/app/src/main/java/dev/kaizen/app/ui/theme/themes/BlauTheme.kt b/app/src/main/java/dev/kaizen/app/ui/theme/themes/BlauTheme.kt index c4f9980..7d95dc1 100644 --- a/app/src/main/java/dev/kaizen/app/ui/theme/themes/BlauTheme.kt +++ b/app/src/main/java/dev/kaizen/app/ui/theme/themes/BlauTheme.kt @@ -6,27 +6,28 @@ import androidx.compose.ui.graphics.colorspace.ColorSpaces private fun p3(r: Float, g: Float, b: Float): Color = Color(red = r, green = g, blue = b, colorSpace = ColorSpaces.DisplayP3) +// Derived from kaizen/app/themes/blue.css — cool blobs (sky, cyan, indigo, warm peach accent) val BlauTheme = KaizenThemeSpec( id = KaizenThemeId.BLAU, label = "Blau", - dark = KaizenAccentScheme( - primary = p3(0.337f, 0.600f, 0.988f), // Sky-500 P3 - primaryDeep = p3(0.243f, 0.420f, 0.855f), - onPrimary = p3(0.024f, 0.047f, 0.106f), - ring = p3(0.337f, 0.600f, 0.988f), - blob1 = p3(0.235f, 0.373f, 0.839f), // Blue - blob2 = p3(0.290f, 0.290f, 0.690f), // Indigo - blob3 = p3(0.169f, 0.714f, 0.800f), // Cyan - blob4 = p3(0.878f, 0.635f, 0.243f), // Amber (contrast) - ), light = KaizenAccentScheme( - primary = p3(0.243f, 0.310f, 0.730f), // Indigo-600 P3 - primaryDeep = p3(0.243f, 0.310f, 0.730f), - onPrimary = p3(1f, 1f, 1f), - ring = p3(0.337f, 0.600f, 0.988f), - blob1 = p3(0.235f, 0.373f, 0.839f), - blob2 = p3(0.290f, 0.290f, 0.690f), - blob3 = p3(0.169f, 0.714f, 0.800f), - blob4 = p3(0.878f, 0.635f, 0.243f), + primary = p3(0.168f, 0.513f, 0.962f), // oklch(0.62 0.19 257) + primaryDeep = p3(0.168f, 0.513f, 0.962f), + onPrimary = p3(0.971f, 0.989f, 1.000f), // oklch(0.99 0.01 257) + ring = p3(0.168f, 0.513f, 0.962f), + blob1 = p3(0.464f, 0.725f, 1.000f), // oklch(0.78 0.15 257) sky + blob2 = p3(0.000f, 0.766f, 0.953f), // oklch(0.75 0.16 220) cyan + blob3 = p3(0.648f, 0.551f, 1.000f), // oklch(0.72 0.18 290) indigo + blob4 = p3(0.973f, 0.763f, 0.519f), // oklch(0.85 0.10 70) peach accent + ), + dark = KaizenAccentScheme( + primary = p3(0.276f, 0.592f, 1.000f), // oklch(0.68 0.18 257) + primaryDeep = p3(0.168f, 0.513f, 0.962f), + onPrimary = p3(0.010f, 0.023f, 0.051f), // oklch(0.12 0.02 257) + ring = p3(0.276f, 0.592f, 1.000f), + blob1 = p3(0.000f, 0.307f, 0.713f), // oklch(0.45 0.18 257) deep sky + blob2 = p3(0.000f, 0.360f, 0.533f), // oklch(0.42 0.16 220) deep cyan + blob3 = p3(0.305f, 0.111f, 0.660f), // oklch(0.40 0.20 290) deep indigo + blob4 = p3(0.580f, 0.315f, 0.000f), // oklch(0.50 0.14 70) amber accent ), ) diff --git a/app/src/main/java/dev/kaizen/app/ui/theme/themes/MonoTheme.kt b/app/src/main/java/dev/kaizen/app/ui/theme/themes/MonoTheme.kt index 72cab72..c727004 100644 --- a/app/src/main/java/dev/kaizen/app/ui/theme/themes/MonoTheme.kt +++ b/app/src/main/java/dev/kaizen/app/ui/theme/themes/MonoTheme.kt @@ -6,27 +6,28 @@ import androidx.compose.ui.graphics.colorspace.ColorSpaces private fun p3(r: Float, g: Float, b: Float): Color = Color(red = r, green = g, blue = b, colorSpace = ColorSpaces.DisplayP3) +// Derived from kaizen/app/themes/mono.css — achromatic, zero chroma, subtle warm blob4 accent val MonoTheme = KaizenThemeSpec( id = KaizenThemeId.MONO, label = "Mono", - dark = KaizenAccentScheme( - primary = p3(0.878f, 0.894f, 0.918f), // Slate-100 - primaryDeep = p3(0.710f, 0.741f, 0.784f), - onPrimary = p3(0.063f, 0.082f, 0.118f), - ring = p3(0.710f, 0.741f, 0.784f), - blob1 = p3(0.710f, 0.741f, 0.784f), // Slate-300 - blob2 = p3(0.580f, 0.620f, 0.680f), // Slate-400 - blob3 = p3(0.820f, 0.845f, 0.878f), // Slate-200 - blob4 = p3(0.600f, 0.580f, 0.560f), // Warm gray - ), light = KaizenAccentScheme( - primary = p3(0.188f, 0.224f, 0.286f), // Slate-800 - primaryDeep = p3(0.188f, 0.224f, 0.286f), - onPrimary = p3(1f, 1f, 1f), - ring = p3(0.420f, 0.455f, 0.510f), - blob1 = p3(0.710f, 0.741f, 0.784f), - blob2 = p3(0.580f, 0.620f, 0.680f), - blob3 = p3(0.820f, 0.845f, 0.878f), - blob4 = p3(0.600f, 0.580f, 0.560f), + primary = p3(0.104f, 0.104f, 0.104f), // oklch(0.22 0 255) near-black + primaryDeep = p3(0.104f, 0.104f, 0.104f), + onPrimary = p3(0.987f, 0.987f, 0.987f), // oklch(0.99 0 255) near-white + ring = p3(0.104f, 0.104f, 0.104f), + blob1 = p3(0.806f, 0.806f, 0.806f), // oklch(0.85 0 255) light gray + blob2 = p3(0.681f, 0.681f, 0.681f), // oklch(0.75 0 255) mid gray + blob3 = p3(0.896f, 0.896f, 0.896f), // oklch(0.92 0 255) off-white + blob4 = p3(0.796f, 0.765f, 0.714f), // oklch(0.82 0.02 80) subtle warm + ), + dark = KaizenAccentScheme( + primary = p3(0.896f, 0.896f, 0.896f), // oklch(0.92 0 255) near-white + primaryDeep = p3(0.806f, 0.806f, 0.806f), + onPrimary = p3(0.022f, 0.022f, 0.022f), // oklch(0.12 0 255) near-black + ring = p3(0.896f, 0.896f, 0.896f), + blob1 = p3(0.229f, 0.229f, 0.229f), // oklch(0.35 0 255) dark gray + blob2 = p3(0.334f, 0.334f, 0.334f), // oklch(0.45 0 255) mid-dark gray + blob3 = p3(0.179f, 0.179f, 0.179f), // oklch(0.30 0 255) charcoal + blob4 = p3(0.304f, 0.277f, 0.234f), // oklch(0.40 0.02 80) subtle warm ), ) diff --git a/app/src/test/java/dev/kaizen/app/ColorPipelineTest.kt b/app/src/test/java/dev/kaizen/app/ColorPipelineTest.kt index 36d05a4..5e87d43 100644 --- a/app/src/test/java/dev/kaizen/app/ColorPipelineTest.kt +++ b/app/src/test/java/dev/kaizen/app/ColorPipelineTest.kt @@ -1,7 +1,25 @@ package dev.kaizen.app import androidx.compose.ui.graphics.colorspace.ColorSpaces -import dev.kaizen.app.ui.theme.* +import dev.kaizen.app.ui.theme.Amber +import dev.kaizen.app.ui.theme.AmberDeep +import dev.kaizen.app.ui.theme.BlobAmber +import dev.kaizen.app.ui.theme.BlobCoral +import dev.kaizen.app.ui.theme.BlobHoney +import dev.kaizen.app.ui.theme.BlobTeal +import dev.kaizen.app.ui.theme.DarkMuted +import dev.kaizen.app.ui.theme.DarkStroke +import dev.kaizen.app.ui.theme.DarkText +import dev.kaizen.app.ui.theme.LightBackground +import dev.kaizen.app.ui.theme.LightMuted +import dev.kaizen.app.ui.theme.LightStroke +import dev.kaizen.app.ui.theme.LightSurface +import dev.kaizen.app.ui.theme.LightSurfaceVariant +import dev.kaizen.app.ui.theme.LightText +import dev.kaizen.app.ui.theme.Obsidian +import dev.kaizen.app.ui.theme.ObsidianElevated +import dev.kaizen.app.ui.theme.ObsidianInput +import dev.kaizen.app.ui.theme.OnAmber import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test @@ -41,7 +59,7 @@ class ColorPipelineTest { @Test fun `blob colors are in DisplayP3`() { - listOf(BlobAmber, BlobBlue, BlobTeal, BlobIndigo).forEach { color -> + listOf(BlobAmber, BlobCoral, BlobHoney, BlobTeal).forEach { color -> assertEquals(ColorSpaces.DisplayP3, color.colorSpace) } }