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 1647960..7a9fb5e 100644 --- a/app/src/main/java/dev/kaizen/app/chat/Background.kt +++ b/app/src/main/java/dev/kaizen/app/chat/Background.kt @@ -137,8 +137,7 @@ fun KaizenOrb( .pointerInput(Unit) {}, contentAlignment = Alignment.Center ) { - // --- LAYER 1: Ambient Outer Halo (Subtle larger glow) --- - // This is the ONLY layer that is blurred, providing a soft background glow. + // --- LAYER 1: Ambient Outer Halo --- Box( Modifier .size(size * 1.5f) @@ -147,137 +146,143 @@ fun KaizenOrb( .background( Brush.radialGradient( colors = if (recording) { - listOf(Color(0xFFE0A23E).copy(alpha = 0.45f), Color.Transparent) + listOf(accent.primary.copy(alpha = 0.45f), Color.Transparent) } else { - listOf(accent.primary.copy(alpha = if (streaming) 0.55f else 0.32f), Color.Transparent) + listOf(accent.primary.copy(alpha = if (streaming) 0.50f else 0.28f), Color.Transparent) } ), CircleShape, ), ) - // --- LAYER 2: Glass Sphere body with refracted backgrounds & conic caustics --- - // DRAWN PERFECTLY SHARP (No blur modifier on the Canvas!) to ensure razor-sharp, - // solid circular boundaries that give the orb its heavy, crystal-glass volume. - Canvas( - modifier = Modifier.fillMaxSize() - ) { - val w = size.toPx() - val h = size.toPx() - val radius = w / 2f - - // Shift centers slightly in direction of gravity to simulate holographic refractive parallax - val centerShiftX = -tiltX * 0.12f * w - val centerShiftY = tiltY * 0.12f * h - - // 1. Base Gradient Fill (Refraction glow matching active theme) - val baseGradientCenter = Offset(w * 0.35f + centerShiftX, h * 0.30f + centerShiftY) - drawCircle( - brush = Brush.radialGradient( - colorStops = arrayOf( - 0.0f to Color(0xFFFFF1D6), // Ultra bright glowing cream-white core - 0.35f to Color(0xFFFFCC80), // Rich luminous warm amber - 0.75f to accent.primaryDeep, // Saturated accent - 1.0f to Color(0xFF8D4F00) // Deep bronze-amber shadow edge (creates high contrast!) - ), - center = baseGradientCenter, - radius = radius * 1.1f - ) - ) - - // 2. Heavy 3D Inner Volume Shadow (Sphere Bottom Shading) - // Adds massive physical 3D weight by darkening the sphere's lower edge. - drawCircle( - brush = Brush.radialGradient( - colorStops = arrayOf( - 0.0f to Color.Transparent, - 0.5f to Color.Transparent, - 1.0f to Color(0xFF4A2300).copy(alpha = 0.85f) // Deep dark brown shadow edge - ), - center = Offset(w * 0.35f + centerShiftX, h * 0.30f + centerShiftY), - radius = radius * 1.0f - ) - ) - - // Shift inner core in the opposite direction (parallax depth) - val coreShiftX = tiltX * 0.05f * w - val coreShiftY = -tiltY * 0.05f * h - val coreCenter = Offset(w / 2f + coreShiftX, h / 2f + coreShiftY) - - // 3. Conic Caustic Layer #1 (SweepGradient at 30° blended via BlendMode.Overlay) - val sweepBrush1 = Brush.sweepGradient( - colorStops = arrayOf( - 0.0f to Color.Transparent, - 0.16f to accent.primary.copy(alpha = 0.65f), - 0.33f to Color.White.copy(alpha = 0.55f), - 0.50f to Color.Transparent, - 0.66f to accent.primaryDeep.copy(alpha = 0.50f), - 1.0f to Color.Transparent - ), - center = coreCenter - ) - drawCircle( - brush = sweepBrush1, - radius = radius * 0.84f, - blendMode = BlendMode.Overlay - ) - - // 4. Conic Caustic Layer #2 (Secondary parallax SweepGradient at 200° via BlendMode.Softlight) - val sweepBrush2 = Brush.sweepGradient( - colorStops = arrayOf( - 0.0f to Color.Transparent, - 0.25f to Color.White.copy(alpha = 0.40f), - 0.50f to Color.Transparent, - 0.75f to accent.primary.copy(alpha = 0.50f), - 1.0f to Color.Transparent - ), - center = coreCenter - ) - drawCircle( - brush = sweepBrush2, - radius = radius * 0.72f, - blendMode = BlendMode.Softlight - ) - } - - // --- LAYER 3: Specular Highlights & Crisp Rim (Sharp reflections) --- + // --- LAYER 2: Glass body — transparent tint so background bleeds through --- Canvas(modifier = Modifier.fillMaxSize()) { val w = size.toPx() val h = size.toPx() val radius = w / 2f + val shiftX = -tiltX * 0.12f * w + val shiftY = tiltY * 0.12f * h + val lightCenter = Offset(w * 0.30f + shiftX, h * 0.25f + shiftY) - // Specular shifts with gravity to give a high-gloss interactive reflection - val specularShiftX = -tiltX * 0.08f * w - val specularShiftY = tiltY * 0.08f * h - val specularCenter1 = Offset(w * 0.28f + specularShiftX, h * 0.22f + specularShiftY) - val specularCenter2 = Offset(w * 0.70f + specularShiftX, h * 0.82f + specularShiftY) - - // 1. Primary "wet" gloss highlight (top-left) - extremely bright, solid, and sharp! + // Base: very subtle theme tint (glass, not paint) drawCircle( brush = Brush.radialGradient( - colors = listOf(Color.White, Color.Transparent), - center = specularCenter1, - radius = radius * 0.38f - ) + colorStops = arrayOf( + 0.0f to accent.primary.copy(alpha = if (isDark) 0.22f else 0.15f), + 0.6f to accent.primaryDeep.copy(alpha = if (isDark) 0.18f else 0.10f), + 1.0f to accent.primaryDeep.copy(alpha = if (isDark) 0.30f else 0.20f), + ), + center = lightCenter, + radius = radius * 1.1f, + ), ) - // 2. Secondary ambient bounce highlight (bottom-right edge glow) + // Top-left brightness (light source) + drawCircle( + brush = Brush.radialGradient( + colorStops = arrayOf( + 0.0f to Color.White.copy(alpha = if (isDark) 0.25f else 0.40f), + 0.5f to Color.White.copy(alpha = 0.05f), + 1.0f to Color.Transparent, + ), + center = lightCenter, + radius = radius * 0.8f, + ), + ) + + // Bottom-right accent bleed + drawCircle( + brush = Brush.radialGradient( + colorStops = arrayOf( + 0.0f to accent.primary.copy(alpha = if (isDark) 0.45f else 0.35f), + 0.6f to Color.Transparent, + ), + center = Offset(w * 0.72f, h * 0.78f), + radius = radius * 0.65f, + ), + ) + + // Bottom shadow for volume (subtle, not harsh) + drawCircle( + brush = Brush.radialGradient( + colorStops = arrayOf( + 0.0f to Color.Transparent, + 0.55f to Color.Transparent, + 0.85f to Color.Black.copy(alpha = if (isDark) 0.20f else 0.08f), + 1.0f to Color.Black.copy(alpha = if (isDark) 0.35f else 0.15f), + ), + center = Offset(w * 0.45f, h * 0.40f), + radius = radius, + ), + ) + + // Caustic conic layer (depth structure) + val coreShiftX = tiltX * 0.05f * w + val coreShiftY = -tiltY * 0.05f * h + val coreCenter = Offset(w / 2f + coreShiftX, h / 2f + coreShiftY) + drawCircle( + brush = Brush.sweepGradient( + colorStops = arrayOf( + 0.0f to Color.Transparent, + 0.16f to accent.primary.copy(alpha = 0.30f), + 0.33f to Color.White.copy(alpha = 0.20f), + 0.50f to Color.Transparent, + 0.66f to accent.primaryDeep.copy(alpha = 0.25f), + 1.0f to Color.Transparent, + ), + center = coreCenter, + ), + radius = radius * 0.84f, + blendMode = BlendMode.Overlay, + ) + } + + // --- LAYER 3: Specular highlights + rim --- + Canvas(modifier = Modifier.fillMaxSize()) { + val w = size.toPx() + val h = size.toPx() + val radius = w / 2f + val specShiftX = -tiltX * 0.08f * w + val specShiftY = tiltY * 0.08f * h + + // Primary specular — elliptical for realism + drawOval( + brush = Brush.radialGradient( + colors = listOf( + Color.White.copy(alpha = if (isDark) 0.70f else 0.90f), + Color.Transparent, + ), + center = Offset(w * 0.30f + specShiftX, h * 0.24f + specShiftY), + radius = radius * 0.35f, + ), + topLeft = Offset(w * 0.12f + specShiftX, h * 0.10f + specShiftY), + size = androidx.compose.ui.geometry.Size(radius * 0.7f, radius * 0.55f), + ) + + // Secondary bounce (bottom-right, warm) drawCircle( brush = Brush.radialGradient( colors = listOf( - Color(0xFFFFD180).copy(alpha = 0.80f), // Bright warm amber light refraction - Color.Transparent + accent.primary.copy(alpha = if (isDark) 0.50f else 0.35f), + Color.Transparent, ), - center = specularCenter2, - radius = radius * 0.28f - ) + center = Offset(w * 0.72f + specShiftX, h * 0.80f + specShiftY), + radius = radius * 0.25f, + ), ) - // 3. Ultra-sharp outer rim (1px hairline highlight for crisp crystal reflection) + // Crisp rim hairline drawCircle( - color = Color.White.copy(alpha = if (isDark) 0.12f else 0.45f), + color = Color.White.copy(alpha = if (isDark) 0.10f else 0.30f), radius = radius - 0.5f, - style = Stroke(width = 1.5f) + style = Stroke(width = 1f), + ) + + // Inner rim (inset edge for refraction feel) + drawCircle( + color = Color.White.copy(alpha = if (isDark) 0.05f else 0.12f), + radius = radius - 2f, + style = Stroke(width = 0.5f), ) } }