diff --git a/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/MainActivity.kt b/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/MainActivity.kt index 13b7d41..e0ef4e0 100644 --- a/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/MainActivity.kt +++ b/apps/mobile/android/app/src/main/java/cloud/molberg/hermesmobile/MainActivity.kt @@ -46,9 +46,7 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChatBubble import androidx.compose.material.icons.filled.CheckCircle -import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.Folder -import androidx.compose.material.icons.filled.Key import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Save @@ -58,9 +56,6 @@ import androidx.compose.material.icons.filled.Wifi import androidx.compose.material.icons.filled.WifiOff import androidx.compose.material.icons.outlined.Article import androidx.compose.material.icons.outlined.Bolt -import androidx.compose.material.icons.outlined.Diamond -import androidx.compose.material.icons.outlined.LocalFireDepartment -import androidx.compose.material.icons.outlined.EmojiEvents import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.Card @@ -110,11 +105,11 @@ import java.net.URLEncoder import java.util.concurrent.TimeUnit enum class Screen(val label: String, val icon: ImageVector, val title: String, val kicker: String) { - Quest("Quest", Icons.Filled.ChatBubble, "Quest", "Hermes training path"), - Files("Files", Icons.Filled.Folder, "Backpack", "Workspace loot"), - Terminal("Terminal", Icons.Filled.Terminal, "Power move", "Run a command"), - Status("Status", Icons.Outlined.EmojiEvents, "League", "Companion stats"), - Settings("Settings", Icons.Filled.Settings, "Nest", "Connection setup") + Quest("Chat", Icons.Filled.ChatBubble, "Agent", "Claude Code mobile client"), + Files("Files", Icons.Filled.Folder, "Workspace", "Project files"), + Terminal("Terminal", Icons.Filled.Terminal, "Terminal", "Run commands"), + Status("Status", Icons.Outlined.Bolt, "Sessions", "Companion status"), + Settings("Settings", Icons.Filled.Settings, "Settings", "Pair companion") } data class FileEntry(val name: String, val path: String, val type: String, val size: Long) @@ -247,8 +242,8 @@ fun HermesNativeApp() { colorScheme = darkColorScheme( background = Cream, surface = Paper, - primary = Green, - onPrimary = Color.White, + primary = Teal, + onPrimary = Color.Black, onBackground = Ink, onSurface = Ink ) @@ -317,25 +312,23 @@ fun NativeTopBar(screen: Screen, online: Boolean) { .padding(horizontal = 16.dp, vertical = 10.dp), verticalArrangement = Arrangement.spacedBy(10.dp) ) { - Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) { - RaisedCircle(color = Green, shadow = GreenDark, content = "⚡") + Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) { + RaisedCircle(color = Purple, shadow = PurpleDark, content = "H") Column(Modifier.weight(1f)) { TinyLabel(screen.kicker) - Text(screen.title, fontSize = 31.sp, fontWeight = FontWeight.Black, color = Ink, lineHeight = 31.sp) + Text(screen.title, fontSize = 30.sp, fontWeight = FontWeight.Black, color = Ink, lineHeight = 31.sp) } - StatChip(Icons.Outlined.LocalFireDepartment, "7", Orange) - StatChip(Icons.Outlined.Diamond, "550", Blue) - StatChip(Icons.Filled.Favorite, "3", Red) + StatusDot(online) } RaisedCard( - color = if (online) PaleGreen else PaleOrange, - shadow = if (online) GreenShadow else OrangeShadow, - border = if (online) GreenBorder else OrangeBorder, + color = if (online) TealPanel else WarningPanel, + shadow = PanelShadow, + border = if (online) TealBorder else WarningBorder, modifier = Modifier.fillMaxWidth() ) { Row(Modifier.padding(12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) { - Icon(if (online) Icons.Filled.Wifi else Icons.Filled.WifiOff, contentDescription = null, tint = if (online) GreenDark else Orange) - Text(if (online) "Companion online — ready for quests" else "Companion offline — check Settings", color = if (online) GreenDark else Orange, fontWeight = FontWeight.Black) + Icon(if (online) Icons.Filled.Wifi else Icons.Filled.WifiOff, contentDescription = null, tint = if (online) Teal else Orange) + Text(if (online) "Companion connected" else "Set companion URL and access key", color = if (online) Teal else Orange, fontWeight = FontWeight.Black) } } } @@ -359,9 +352,9 @@ fun NativeBottomBar(current: Screen, onSelect: (Screen) -> Unit) { icon = { Icon(item.icon, contentDescription = item.label) }, label = { Text(item.label, fontWeight = FontWeight.Black, fontSize = 11.sp) }, colors = NavigationBarItemDefaults.colors( - selectedIconColor = GreenDark, - selectedTextColor = GreenDark, - indicatorColor = PaleGreen, + selectedIconColor = Teal, + selectedTextColor = Teal, + indicatorColor = TealPanel, unselectedIconColor = Muted, unselectedTextColor = Muted ) @@ -380,10 +373,10 @@ fun QuestScreen(api: CompanionApi) { val messages = remember { mutableStateListOf() } ScreenList { - HeroCard(icon = Icons.Filled.ChatBubble, title = "Give Hermes one clean mission.", label = "Daily quest", text = "Short, direct prompts work best. The native app calls the local companion server.") + HeroCard(icon = Icons.Filled.ChatBubble, title = "Claude Code from anywhere.", label = "Agent control", text = "Send prompts to your local Hermes companion and continue work from your phone.") Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) { - PathPill(Icons.Filled.CheckCircle, "Check", true) - PathPill(Icons.Outlined.Bolt, "Ask", true, current = true) + PathPill(Icons.Filled.CheckCircle, "Connect", true) + PathPill(Icons.Outlined.Bolt, "Prompt", true, current = true) PathPill(Icons.Filled.ChatBubble, "Review", false) } if (messages.isEmpty()) EmptyLesson() @@ -391,8 +384,8 @@ fun QuestScreen(api: CompanionApi) { if (error.isNotBlank()) ErrorCard(error) RaisedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { - AppTextField(value = prompt, onValue = { prompt = it }, placeholder = "What should Hermes do?", minLines = 3) - PrimaryButton(text = if (busy) "Working…" else "Start quest", icon = Icons.Filled.PlayArrow, enabled = !busy && prompt.isNotBlank()) { + AppTextField(value = prompt, onValue = { prompt = it }, placeholder = "Message Hermes", minLines = 3) + PrimaryButton(text = if (busy) "Working…" else "Send", icon = Icons.Filled.PlayArrow, enabled = !busy && prompt.isNotBlank()) { val p = prompt.trim() prompt = "" messages.add(ChatMessage("You", p)) @@ -427,7 +420,7 @@ fun FilesScreen(api: CompanionApi) { LaunchedEffect(Unit) { load(".") } ScreenList { - CompactQuest(title = "Workspace files", label = "Backpack", text = "Tap folders to go deeper. Files open in a native editor.", icon = Icons.Filled.Folder) { load() } + CompactQuest(title = "Project files", label = "Workspace", text = "Browse and edit files through the companion server.", icon = Icons.Filled.Folder) { load() } RaisedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) { Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) { @@ -468,7 +461,7 @@ fun TerminalScreen(api: CompanionApi) { var busy by remember { mutableStateOf(false) } ScreenList { - HeroCard(icon = Icons.Filled.Terminal, title = "Run one safe command.", label = "Power move", text = "Commands execute through the companion server inside the configured workspace.", orbColor = Blue, orbShadow = BlueDark) + HeroCard(icon = Icons.Filled.Terminal, title = "Run workspace commands.", label = "Terminal", text = "Execute commands on the paired machine without leaving the app.", orbColor = Purple, orbShadow = PurpleDark) RaisedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { FieldLabel("Working directory") @@ -495,7 +488,7 @@ fun StatusScreen(api: CompanionApi) { fun refresh() = scope.launch { health = runCatching { api.health() }.getOrElse { HealthState(false, it.message ?: "Health check failed") } } ScreenList { - CompactQuest(title = "Companion status", label = "League board", text = health.status, icon = Icons.Outlined.EmojiEvents, orbColor = Gold, orbShadow = GoldDark) { refresh() } + CompactQuest(title = "Companion status", label = "Sessions", text = health.status, icon = Icons.Outlined.Bolt, orbColor = Teal, orbShadow = TealDark) { refresh() } Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) { Metric("Hermes", if (health.hermesCli.startsWith("Found")) "Ready" else "—", Modifier.weight(1f)) Metric("Uptime", health.uptime, Modifier.weight(1f)) @@ -522,7 +515,7 @@ fun SettingsScreen(api: CompanionApi) { var status by remember { mutableStateOf("Paste the companion access key, then test the connection.") } ScreenList { - CompactQuest(title = "Pair your companion", label = "Nest setup", text = status, icon = Icons.Filled.Settings, orbColor = Green, orbShadow = GreenDark) {} + CompactQuest(title = "Pair companion", label = "Settings", text = status, icon = Icons.Filled.Settings, orbColor = Purple, orbShadow = PurpleDark) {} RaisedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) { FieldLabel("Companion server URL") @@ -562,7 +555,7 @@ fun RaisedCard(modifier: Modifier = Modifier, color: Color = Paper, shadow: Colo } @Composable -fun HeroCard(icon: ImageVector, title: String, label: String, text: String, orbColor: Color = Green, orbShadow: Color = GreenDark) { +fun HeroCard(icon: ImageVector, title: String, label: String, text: String, orbColor: Color = Teal, orbShadow: Color = TealDark) { RaisedCard(Modifier.fillMaxWidth()) { Row(Modifier.padding(16.dp), horizontalArrangement = Arrangement.spacedBy(14.dp), verticalAlignment = Alignment.Top) { RaisedIcon(icon, orbColor, orbShadow) @@ -572,7 +565,7 @@ fun HeroCard(icon: ImageVector, title: String, label: String, text: String, orbC } @Composable -fun CompactQuest(title: String, label: String, text: String, icon: ImageVector, orbColor: Color = Green, orbShadow: Color = GreenDark, onRefresh: () -> Unit) { +fun CompactQuest(title: String, label: String, text: String, icon: ImageVector, orbColor: Color = Teal, orbShadow: Color = TealDark, onRefresh: () -> Unit) { RaisedCard(Modifier.fillMaxWidth()) { Row(Modifier.padding(14.dp), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) { RaisedIcon(icon, orbColor, orbShadow, size = 58) @@ -583,45 +576,46 @@ fun CompactQuest(title: String, label: String, text: String, icon: ImageVector, } @Composable fun RaisedIcon(icon: ImageVector, color: Color, shadow: Color, size: Int = 66) { Box(Modifier.size(size.dp), contentAlignment = Alignment.Center) { Box(Modifier.matchParentSize().padding(top = 5.dp).clip(CircleShape).background(shadow)); Box(Modifier.matchParentSize().padding(bottom = 5.dp).clip(CircleShape).background(color), contentAlignment = Alignment.Center) { Icon(icon, null, tint = Color.White, modifier = Modifier.size((size / 2).dp)) } } } -@Composable fun RaisedCircle(color: Color, shadow: Color, content: String) { Box(Modifier.size(54.dp), contentAlignment = Alignment.Center) { Box(Modifier.matchParentSize().padding(top = 5.dp).clip(RoundedCornerShape(18.dp)).background(shadow)); Box(Modifier.matchParentSize().padding(bottom = 5.dp).clip(RoundedCornerShape(18.dp)).background(color), contentAlignment = Alignment.Center) { Text(content, fontSize = 24.sp) } } } -@Composable fun StatChip(icon: ImageVector, value: String, color: Color) { Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(2.dp), modifier = Modifier.clip(RoundedCornerShape(99.dp)).background(Paper).padding(horizontal = 7.dp, vertical = 3.dp)) { Icon(icon, null, tint = color, modifier = Modifier.size(15.dp)); Text(value, color = color, fontWeight = FontWeight.Black, fontSize = 12.sp) } } +@Composable fun RaisedCircle(color: Color, shadow: Color, content: String) { Box(Modifier.size(54.dp), contentAlignment = Alignment.Center) { Box(Modifier.matchParentSize().padding(top = 5.dp).clip(RoundedCornerShape(18.dp)).background(shadow)); Box(Modifier.matchParentSize().padding(bottom = 5.dp).clip(RoundedCornerShape(18.dp)).background(color), contentAlignment = Alignment.Center) { Text(content, fontSize = 24.sp, fontWeight = FontWeight.Black, color = Color.White) } } } +@Composable fun StatusDot(online: Boolean) { Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(6.dp), modifier = Modifier.clip(RoundedCornerShape(99.dp)).background(if (online) TealPanel else WarningPanel).padding(horizontal = 10.dp, vertical = 7.dp)) { Box(Modifier.size(8.dp).clip(CircleShape).background(if (online) Teal else Orange)); Text(if (online) "LIVE" else "SETUP", color = if (online) Teal else Orange, fontWeight = FontWeight.Black, fontSize = 11.sp) } } @Composable fun TinyLabel(text: String) { Text(text.uppercase(), color = Muted, fontSize = 11.sp, fontWeight = FontWeight.Black, letterSpacing = 0.7.sp) } @Composable fun FieldLabel(text: String) { Text(text.uppercase(), color = Muted, fontSize = 12.sp, fontWeight = FontWeight.Black) } -@Composable fun PathPill(icon: ImageVector, text: String, done: Boolean, current: Boolean = false) { Row(Modifier.clip(RoundedCornerShape(99.dp)).background(if (current) Green else if (done) PaleGreen else Surface).padding(horizontal = 12.dp, vertical = 10.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(5.dp)) { Icon(icon, null, tint = if (current) Color.White else GreenDark, modifier = Modifier.size(18.dp)); Text(text, color = if (current) Color.White else GreenDark, fontWeight = FontWeight.Black, fontSize = 13.sp) } } -@Composable fun EmptyLesson() { RaisedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(18.dp), horizontalAlignment = Alignment.CenterHorizontally) { Text("🪽", fontSize = 42.sp); Text("No mission yet", color = Ink, fontWeight = FontWeight.Black, fontSize = 20.sp); Text("Try: check PM2 status or summarize logs.", color = Muted, fontWeight = FontWeight.ExtraBold) } } } -@Composable fun Bubble(msg: ChatMessage) { RaisedCard(Modifier.fillMaxWidth().padding(start = if (msg.role == "You") 28.dp else 0.dp, end = if (msg.role == "You") 0.dp else 28.dp), color = if (msg.role == "You") PaleGreen else PaleGold) { Column(Modifier.padding(12.dp)) { TinyLabel(msg.role); Text(msg.content, color = Ink, fontWeight = FontWeight.ExtraBold, lineHeight = 19.sp) } } } +@Composable fun PathPill(icon: ImageVector, text: String, done: Boolean, current: Boolean = false) { Row(Modifier.clip(RoundedCornerShape(99.dp)).background(if (current) Teal else if (done) TealPanel else Surface).padding(horizontal = 12.dp, vertical = 10.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(5.dp)) { Icon(icon, null, tint = if (current) Color.Black else Teal, modifier = Modifier.size(18.dp)); Text(text, color = if (current) Color.Black else Teal, fontWeight = FontWeight.Black, fontSize = 13.sp) } } +@Composable fun EmptyLesson() { RaisedCard(Modifier.fillMaxWidth()) { Column(Modifier.padding(18.dp), horizontalAlignment = Alignment.CenterHorizontally) { Text("\$ happy", color = Teal, fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace, fontWeight = FontWeight.Black, fontSize = 24.sp); Text("No messages yet", color = Ink, fontWeight = FontWeight.Black, fontSize = 20.sp); Text("Try: check PM2 status or summarize logs.", color = Muted, fontWeight = FontWeight.ExtraBold) } } } +@Composable fun Bubble(msg: ChatMessage) { RaisedCard(Modifier.fillMaxWidth().padding(start = if (msg.role == "You") 28.dp else 0.dp, end = if (msg.role == "You") 0.dp else 28.dp), color = if (msg.role == "You") TealPanel else Surface) { Column(Modifier.padding(12.dp)) { TinyLabel(msg.role); Text(msg.content, color = Ink, fontWeight = FontWeight.ExtraBold, lineHeight = 19.sp) } } } @Composable fun ErrorCard(text: String) { RaisedCard(Modifier.fillMaxWidth(), color = PaleRed, shadow = RedShadow, border = RedBorder) { Text(text, Modifier.padding(12.dp), color = Red, fontWeight = FontWeight.Black) } } @Composable fun CodeCard(text: String) { RaisedCard(Modifier.fillMaxWidth()) { Text(text, Modifier.padding(14.dp), color = BlueDark, fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace, fontSize = 13.sp, lineHeight = 18.sp) } } @Composable fun FileRow(entry: FileEntry, onClick: () -> Unit) { RaisedCard(Modifier.fillMaxWidth()) { Row(Modifier.clickable(onClick = onClick).padding(10.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(10.dp)) { Box(Modifier.size(42.dp).clip(RoundedCornerShape(14.dp)).background(if (entry.type == "directory") PaleBlue else PaleGold), contentAlignment = Alignment.Center) { Icon(if (entry.type == "directory") Icons.Filled.Folder else Icons.Outlined.Article, null, tint = if (entry.type == "directory") Blue else GoldDark) }; Text(entry.name, Modifier.weight(1f), color = Ink, fontWeight = FontWeight.Black, maxLines = 1, overflow = TextOverflow.Ellipsis); Text(if (entry.type == "file") "${entry.size} B" else "dir", color = Muted, fontWeight = FontWeight.Black, fontSize = 12.sp) } } } -@Composable fun Metric(label: String, value: String, modifier: Modifier = Modifier) { RaisedCard(modifier) { Column(Modifier.padding(10.dp), horizontalAlignment = Alignment.CenterHorizontally) { Text(value, color = GreenDark, fontWeight = FontWeight.Black, fontSize = 18.sp, maxLines = 1, overflow = TextOverflow.Ellipsis); Text(label.uppercase(), color = Muted, fontWeight = FontWeight.Black, fontSize = 10.sp) } } } -@Composable fun AppTextField(value: String, onValue: (String) -> Unit, placeholder: String, minLines: Int = 1, keyboardType: KeyboardType = KeyboardType.Text, password: Boolean = false) { OutlinedTextField(value = value, onValueChange = onValue, modifier = Modifier.fillMaxWidth(), placeholder = { Text(placeholder, color = Muted) }, minLines = minLines, keyboardOptions = KeyboardOptions(keyboardType = keyboardType), visualTransformation = if (password) PasswordVisualTransformation() else androidx.compose.ui.text.input.VisualTransformation.None, shape = RoundedCornerShape(16.dp), colors = TextFieldDefaults.colors(focusedContainerColor = Surface, unfocusedContainerColor = Surface, focusedIndicatorColor = Green, unfocusedIndicatorColor = NeutralBorder, cursorColor = GreenDark)) } -@Composable fun PrimaryButton(text: String, icon: ImageVector, modifier: Modifier = Modifier, enabled: Boolean = true, onClick: () -> Unit) { Button(onClick = onClick, enabled = enabled, modifier = modifier.height(54.dp), shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors(containerColor = Green, contentColor = Color.White, disabledContainerColor = NeutralBorder), elevation = ButtonDefaults.buttonElevation(defaultElevation = 6.dp, pressedElevation = 1.dp)) { Text(text, fontWeight = FontWeight.Black); Spacer(Modifier.width(6.dp)); Icon(icon, null) } } +@Composable fun Metric(label: String, value: String, modifier: Modifier = Modifier) { RaisedCard(modifier) { Column(Modifier.padding(10.dp), horizontalAlignment = Alignment.CenterHorizontally) { Text(value, color = Teal, fontWeight = FontWeight.Black, fontSize = 18.sp, maxLines = 1, overflow = TextOverflow.Ellipsis); Text(label.uppercase(), color = Muted, fontWeight = FontWeight.Black, fontSize = 10.sp) } } } +@Composable fun AppTextField(value: String, onValue: (String) -> Unit, placeholder: String, minLines: Int = 1, keyboardType: KeyboardType = KeyboardType.Text, password: Boolean = false) { OutlinedTextField(value = value, onValueChange = onValue, modifier = Modifier.fillMaxWidth(), placeholder = { Text(placeholder, color = Muted) }, minLines = minLines, keyboardOptions = KeyboardOptions(keyboardType = keyboardType), visualTransformation = if (password) PasswordVisualTransformation() else androidx.compose.ui.text.input.VisualTransformation.None, shape = RoundedCornerShape(16.dp), colors = TextFieldDefaults.colors(focusedContainerColor = Surface, unfocusedContainerColor = Surface, focusedIndicatorColor = Teal, unfocusedIndicatorColor = NeutralBorder, cursorColor = Teal)) } +@Composable fun PrimaryButton(text: String, icon: ImageVector, modifier: Modifier = Modifier, enabled: Boolean = true, onClick: () -> Unit) { Button(onClick = onClick, enabled = enabled, modifier = modifier.height(54.dp), shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors(containerColor = Teal, contentColor = Color.Black, disabledContainerColor = NeutralBorder), elevation = ButtonDefaults.buttonElevation(defaultElevation = 6.dp, pressedElevation = 1.dp)) { Text(text, fontWeight = FontWeight.Black); Spacer(Modifier.width(6.dp)); Icon(icon, null) } } @Composable fun SecondaryButton(text: String, icon: ImageVector, modifier: Modifier = Modifier, onClick: () -> Unit) { Button(onClick = onClick, modifier = modifier.height(54.dp), shape = RoundedCornerShape(16.dp), colors = ButtonDefaults.buttonColors(containerColor = Surface, contentColor = Ink), elevation = ButtonDefaults.buttonElevation(defaultElevation = 4.dp, pressedElevation = 1.dp)) { Text(text, fontWeight = FontWeight.Black); Spacer(Modifier.width(6.dp)); Icon(icon, null) } } -@Composable fun RoundButton(icon: ImageVector, onClick: () -> Unit) { Button(onClick = onClick, modifier = Modifier.size(50.dp), shape = RoundedCornerShape(16.dp), contentPadding = androidx.compose.foundation.layout.PaddingValues(0.dp), colors = ButtonDefaults.buttonColors(containerColor = Blue, contentColor = Color.White), elevation = ButtonDefaults.buttonElevation(defaultElevation = 5.dp, pressedElevation = 1.dp)) { Icon(icon, null) } } +@Composable fun RoundButton(icon: ImageVector, onClick: () -> Unit) { Button(onClick = onClick, modifier = Modifier.size(50.dp), shape = RoundedCornerShape(16.dp), contentPadding = androidx.compose.foundation.layout.PaddingValues(0.dp), colors = ButtonDefaults.buttonColors(containerColor = Purple, contentColor = Color.White), elevation = ButtonDefaults.buttonElevation(defaultElevation = 5.dp, pressedElevation = 1.dp)) { Icon(icon, null) } } -val Green = Color(0xFF58CC02) -val GreenDark = Color(0xFF7FE83B) -val GreenShadow = Color(0xFF244B19) -val GreenBorder = Color(0xFF3D7F28) -val PaleGreen = Color(0xFF17301A) -val Blue = Color(0xFF1CB0F6) -val BlueDark = Color(0xFF73D4FF) -val PaleBlue = Color(0xFF112A3A) -val Gold = Color(0xFFFFC800) -val GoldDark = Color(0xFFFFD95A) -val PaleGold = Color(0xFF332A10) -val Orange = Color(0xFFFFA033) -val PaleOrange = Color(0xFF332312) -val OrangeBorder = Color(0xFF7B4D1C) -val OrangeShadow = Color(0xFF26180C) -val Red = Color(0xFFFF6B6B) -val PaleRed = Color(0xFF3A171B) -val RedBorder = Color(0xFF8B3D45) -val RedShadow = Color(0xFF271013) -val Cream = Color(0xFF08100E) -val Paper = Color(0xFF111B18) -val Surface = Color(0xFF17231F) -val Ink = Color(0xFFEAF7EE) -val Muted = Color(0xFF9FB4A7) -val NeutralBorder = Color(0xFF294138) -val NeutralShadow = Color(0xFF060B0A) +val Teal = Color(0xFF28DBC9) +val TealDark = Color(0xFF0F8F84) +val TealPanel = Color(0xFF0E2B2A) +val TealBorder = Color(0xFF176C66) +val Purple = Color(0xFF6701E6) +val PurpleDark = Color(0xFF3B0087) +val PurplePanel = Color(0xFF211133) +val Blue = Color(0xFF3B82F6) +val BlueDark = Color(0xFF8AB7FF) +val PaleBlue = Color(0xFF111B2B) +val GoldDark = Color(0xFFFBBF24) +val PaleGold = Color(0xFF211B10) +val Orange = Color(0xFFFBBF24) +val WarningPanel = Color(0xFF2B2111) +val WarningBorder = Color(0xFF7A5A1B) +val Red = Color(0xFFF87171) +val PaleRed = Color(0xFF311719) +val RedBorder = Color(0xFF7A363A) +val RedShadow = Color(0xFF0A0304) +val Cream = Color(0xFF000000) +val Paper = Color(0xFF0B0F12) +val Surface = Color(0xFF12181D) +val Ink = Color(0xFFF4F4F5) +val Muted = Color(0xFF9CA3AF) +val NeutralBorder = Color(0xFF2A3138) +val NeutralShadow = Color(0xFF030506) +val PanelShadow = Color(0xFF040707)