diff --git a/app/src/main/kotlin/com/shonar/desktop/Main.kt b/app/src/main/kotlin/com/shonar/desktop/Main.kt index 09013c7..1799ee6 100644 --- a/app/src/main/kotlin/com/shonar/desktop/Main.kt +++ b/app/src/main/kotlin/com/shonar/desktop/Main.kt @@ -1,5 +1,6 @@ package com.shonar.desktop +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row @@ -32,6 +33,7 @@ import androidx.compose.ui.input.key.type import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.dp +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.painter.BitmapPainter import androidx.compose.ui.graphics.toComposeImageBitmap import androidx.compose.ui.window.Window @@ -109,8 +111,19 @@ fun main() = application { val baseDensity = LocalDensity.current val themeMode by state.themeMode.collectAsState() ShonarTheme(mode = themeMode) { + // Meridian page backdrop: faint top-to-bottom luminance + // ramp; the Surface itself goes transparent so it shows + // through behind all screens. + Box( + Modifier.fillMaxSize().background( + Brush.verticalGradient( + listOf(Shonar.BackgroundTop, Shonar.BackgroundBottom), + ), + ), + ) { Surface( - Modifier.fillMaxSize().onPreviewKeyEvent { e -> + color = androidx.compose.ui.graphics.Color.Transparent, + modifier = Modifier.fillMaxSize().onPreviewKeyEvent { e -> if (e.type != KeyEventType.KeyDown) return@onPreviewKeyEvent false // Esc leaves Detail → Library; Alt+←/→ page recordings. // (Plain arrows stay with text fields.) @@ -207,6 +220,7 @@ fun main() = application { } } } + } } } } diff --git a/app/src/main/kotlin/com/shonar/desktop/Theme.kt b/app/src/main/kotlin/com/shonar/desktop/Theme.kt index ce1802d..6c198ed 100644 --- a/app/src/main/kotlin/com/shonar/desktop/Theme.kt +++ b/app/src/main/kotlin/com/shonar/desktop/Theme.kt @@ -74,6 +74,9 @@ data class ShonarPalette( * selected-row wash) — decorative emphasis, not an error color. */ val highlight: Color = Color(0xFFFB3F7F), val highlightTint: Color = Color(0x26FB3F7F), + /** Vertical page gradient endpoints; default flat = [background]. */ + val backgroundTop: Color = background, + val backgroundBottom: Color = background, ) /** Charcoal with a faint blue cast, per the reference: page #16181C, @@ -94,8 +97,10 @@ private val DarkPalette = ShonarPalette( textMuted = Color(0xFF6B7080), error = Color(0xFFF85149), // true red, distinct from highlight onError = Color(0xFF1A0B0D), - // Faint highlight per reference: the wash IS the red — a muted - // mauve sampled at #573440 — not a saturated hot pink. + // Meridian page gradient (per reference ramp): a faintly lighter + // band at the top edge deepening to near-black at the bottom. + backgroundTop = Color(0xFF1B1D21), + backgroundBottom = Color(0xFF101113), highlight = Color(0xFFB4768B), // dusty rose for title text highlightTint = Color(0xFF573440), // exact mauve row wash ) @@ -131,6 +136,9 @@ object Shonar { // ---- color tokens (theme-aware: readable inside any composable) ---- val Background: Color @Composable get() = LocalPalette.current.background + /** Meridian page gradient endpoints (top lighter, bottom darker). */ + val BackgroundTop: Color @Composable get() = LocalPalette.current.backgroundTop + val BackgroundBottom: Color @Composable get() = LocalPalette.current.backgroundBottom val Surface: Color @Composable get() = LocalPalette.current.surface val SurfaceAlt: Color @Composable get() = LocalPalette.current.surfaceAlt val Border: Color @Composable get() = LocalPalette.current.border