fix: derive all theme colors from web CSS files (OKLCH → P3 RGB)
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.
This commit is contained in:
parent
f1c6a88c4c
commit
4d71475995
7 changed files with 107 additions and 81 deletions
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue