package com.peachpasswords.ui.theme import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.widthIn import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.drawscope.withTransform import kotlin.math.abs import kotlin.math.max /** * The two-bloom shell background that sits behind every screen. * * Mirrors the browser shell (spec §6.3 / popup.css): * radial-gradient(120% 80% at 0% 0%, accent 8%, transparent 65%) * radial-gradient(85% 100% at 100% 100%, accent 6%, transparent 70%) * over a flat --bg fill. * * Both blooms are elliptical. A circular approximation drifts off on tall * phones — the top-left bloom's vertical extent (0.8·h) outgrows its * horizontal extent (1.2·w) once the aspect ratio passes ~1.5, so we draw a * circular gradient and squash it to the CSS ellipse with a non-uniform scale. */ @Composable fun ShellBackground( modifier: Modifier = Modifier, content: @Composable BoxScope.() -> Unit, ) { val accent = LocalPeachAccent.current val base = MaterialTheme_background() Box( modifier = modifier .fillMaxSize() .drawBehind { drawRect(color = base) drawBloom( center = Offset(0f, 0f), radiusX = size.width * 1.2f, radiusY = size.height * 0.8f, color = accent.copy(alpha = 0.08f), transparentAt = 0.65f, ) drawBloom( center = Offset(size.width, size.height), radiusX = size.width * 0.85f, radiusY = size.height * 1.0f, color = accent.copy(alpha = 0.06f), transparentAt = 0.70f, ) }, content = content, ) } /** * Widest a *form* column grows before it stops. Deliberately NOT applied to * every screen: lists and detail views should use a foldable's full width, * and blanket-capping them just moved the wasted space to the margins. */ val CONTENT_MAX_WIDTH = 480.dp /** * Draw one elliptical radial bloom. [transparentAt] is the fraction of the * ellipse radius where the colour has fully faded — matching the CSS * `transparent ` stop so the warmth stays concentrated in its corner. */ private fun DrawScope.drawBloom( center: Offset, radiusX: Float, radiusY: Float, color: Color, transparentAt: Float, ) { val r = max(radiusX, radiusY) val sx = radiusX / r val sy = radiusY / r withTransform({ scale(sx, sy, pivot = center) }) { // The screen rect, mapped back through the scale, is the area we must // paint so the squashed gradient still covers every visible pixel. val left = center.x + (0f - center.x) / sx val right = center.x + (size.width - center.x) / sx val top = center.y + (0f - center.y) / sy val bottom = center.y + (size.height - center.y) / sy drawRect( brush = Brush.radialGradient( 0f to color, transparentAt to Color.Transparent, center = center, radius = r, ), topLeft = Offset(minOf(left, right), minOf(top, bottom)), size = Size(abs(right - left), abs(bottom - top)), ) } } @Composable private fun MaterialTheme_background(): Color = androidx.compose.material3.MaterialTheme.colorScheme.background