diff --git a/app/src/main/java/com/m57/hermescontrol/theme/THEMES.md b/app/src/main/java/com/m57/hermescontrol/theme/THEMES.md new file mode 100644 index 00000000..c59958bc --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/THEMES.md @@ -0,0 +1,113 @@ +# Themes + +How theming works in Hermes Control, and how to add or edit a theme. + +## Where themes live + +All theme code is under: + +``` +app/src/main/java/com/m57/hermescontrol/theme/ +├── Theme.kt # dispatcher — resolves scheme + status colors per preset +├── Color.kt # brand design tokens (DarkSurface, HermesPurple, StatusGreen, …) +├── HermesStatusColors.kt # semantic status color model (success/warning/error/info + on*) +├── Type.kt / Shapes.kt # typography + shape tokens +├── Spacing.kt / Motion.kt # spacing + motion tokens +└── presets/ # one file per ThemePreset + ├── DefaultScheme.kt + ├── MonochromeScheme.kt + ├── GruvboxScheme.kt + ├── CatppuccinScheme.kt + ├── AmoledScheme.kt + └── NeonNoirScheme.kt +``` + +## The 4-token shape + +Every file in `presets/` is uniform — it exports the same four tokens: + +| Token | Type | Purpose | +|-------|------|---------| +| `XxxDarkColorScheme` | `ColorScheme` | dark-mode Material 3 scheme | +| `XxxLightColorScheme` | `ColorScheme` | light-mode Material 3 scheme | +| `XxxDarkStatusColors` | `HermesStatusColors` | dark semantic status colors | +| `XxxLightStatusColors` | `HermesStatusColors` | light semantic status colors | + +A preset with no bespoke status set (MONOCHROME, AMOLED) aliases the defaults: + +```kotlin +val MonochromeDarkStatusColors = DefaultDarkStatusColors +val MonochromeLightStatusColors = DefaultLightStatusColors +``` + +AMOLED has no bespoke light scheme, so it aliases the default light scheme too: + +```kotlin +val AmoledLightColorScheme = DefaultLightColorScheme +``` + +## The dispatcher + +`Theme.kt` is a **pure lookup** — no special-casing. Given a `ThemePreset` +and a dark flag, it returns the matching scheme/status from the preset file: + +```kotlin +private fun resolveColorScheme(preset: ThemePreset, darkTheme: Boolean) = when (preset) { + ThemePreset.DEFAULT -> if (darkTheme) DefaultDarkColorScheme else DefaultLightColorScheme + ThemePreset.MONOCHROME -> if (darkTheme) MonochromeDarkColorScheme else MonochromeLightColorScheme + // …one line per preset… +} + +private fun resolveStatusColors(preset: ThemePreset, darkTheme: Boolean) = when (preset) { + ThemePreset.DEFAULT -> if (darkTheme) DefaultDarkStatusColors else DefaultLightStatusColors + // …one line per preset… +} +``` + +Dynamic (Material You) color on API 31+ overrides the resolved scheme when +`useDynamicColors = true`. + +## DEFAULT uses design tokens — that's intentional + +`DefaultScheme.kt` imports ~47 named tokens from `Color.kt` +(`DarkBackground`, `HermesPurple`, `StatusGreenContainer`, …) and builds its +schemes from them. This is **by design**: DEFAULT is the brand reference theme, +so a palette change in `Color.kt` flows straight through. + +The other presets are hand-authored community palettes and use **raw hex** +(`Color(0xFFFE8019)`), so they only import `Color` (+ `HermesStatusColors`). +Do **not** "fix" DEFAULT to raw hex to match them — that would break the token +linkage. The asymmetry is semantic, not sloppy. + +## Adding a new theme + +1. **Create** `presets/Scheme.kt` exporting the 4 tokens: + ```kotlin + package com.m57.hermescontrol.theme.presets + + import androidx.compose.material3.darkColorScheme + import androidx.compose.material3.lightColorScheme + import androidx.compose.ui.graphics.Color + import com.m57.hermescontrol.theme.HermesStatusColors + + val MyThemeDarkColorScheme = darkColorScheme(/* … */) + val MyThemeLightColorScheme = lightColorScheme(/* … */) + val MyThemeDarkStatusColors = HermesStatusColors(/* … */) + val MyThemeLightStatusColors = HermesStatusColors(/* … */) + ``` +2. **Add 2 lines** to each `when` in `Theme.kt` (`resolveColorScheme` + + `resolveStatusColors`), importing the new tokens at the top of the file. +3. **Add the enum entry** `MY_THEME` to `ThemePreset` in `Theme.kt`. +4. **Wire the UI**: add the label + selection in + `ui/settings/components/AppearanceSection.kt` (and any string resource). +5. **Verify**: + ```bash + ./ktlint --format app/src/main/java/com/m57/hermescontrol/theme/presets/Scheme.kt + ./gradlew compileDebugKotlin + ``` + +## Conventions + +- ktlint 1.2.1 is enforced in CI. Run `./ktlint --format` before committing. +- Import order is ASCII-lexicographic (uppercase before lowercase). +- Every change goes through a PR — never push directly to `main`. diff --git a/app/src/main/java/com/m57/hermescontrol/theme/Theme.kt b/app/src/main/java/com/m57/hermescontrol/theme/Theme.kt index cb256059..ec9b9392 100644 --- a/app/src/main/java/com/m57/hermescontrol/theme/Theme.kt +++ b/app/src/main/java/com/m57/hermescontrol/theme/Theme.kt @@ -3,15 +3,36 @@ package com.m57.hermescontrol.theme import android.os.Build import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.darkColorScheme import androidx.compose.material3.dynamicDarkColorScheme import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.compositionLocalOf -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import com.m57.hermescontrol.theme.presets.AmoledDarkColorScheme +import com.m57.hermescontrol.theme.presets.AmoledDarkStatusColors +import com.m57.hermescontrol.theme.presets.AmoledLightColorScheme +import com.m57.hermescontrol.theme.presets.AmoledLightStatusColors +import com.m57.hermescontrol.theme.presets.CatppuccinDarkColorScheme +import com.m57.hermescontrol.theme.presets.CatppuccinDarkStatusColors +import com.m57.hermescontrol.theme.presets.CatppuccinLightColorScheme +import com.m57.hermescontrol.theme.presets.CatppuccinLightStatusColors +import com.m57.hermescontrol.theme.presets.DefaultDarkColorScheme +import com.m57.hermescontrol.theme.presets.DefaultDarkStatusColors +import com.m57.hermescontrol.theme.presets.DefaultLightColorScheme +import com.m57.hermescontrol.theme.presets.DefaultLightStatusColors +import com.m57.hermescontrol.theme.presets.GruvboxDarkColorScheme +import com.m57.hermescontrol.theme.presets.GruvboxDarkStatusColors +import com.m57.hermescontrol.theme.presets.GruvboxLightColorScheme +import com.m57.hermescontrol.theme.presets.GruvboxLightStatusColors +import com.m57.hermescontrol.theme.presets.MonochromeDarkColorScheme +import com.m57.hermescontrol.theme.presets.MonochromeDarkStatusColors +import com.m57.hermescontrol.theme.presets.MonochromeLightColorScheme +import com.m57.hermescontrol.theme.presets.MonochromeLightStatusColors +import com.m57.hermescontrol.theme.presets.NeonNoirDarkColorScheme +import com.m57.hermescontrol.theme.presets.NeonNoirDarkStatusColors +import com.m57.hermescontrol.theme.presets.NeonNoirLightColorScheme +import com.m57.hermescontrol.theme.presets.NeonNoirLightStatusColors import kotlinx.serialization.Serializable @Serializable @@ -26,274 +47,41 @@ enum class BottomNavDisplayMode { ICON_AND_TEXT, ICON_ONLY, TEXT_ONLY } val LocalThemePreference = compositionLocalOf { ThemePreference.SYSTEM } val LocalThemePreset = compositionLocalOf { ThemePreset.DEFAULT } -private val HermesDarkColorScheme = - darkColorScheme( - primary = HermesPurple, - onPrimary = Color.White, - primaryContainer = HermesPurpleContainer, - onPrimaryContainer = HermesPurpleOnContainer, - secondary = HermesAmber, - onSecondary = Color.Black, - secondaryContainer = Color(0xFF3D2F0F), - onSecondaryContainer = HermesAmberLight, - tertiary = HermesAmberLight, - onTertiary = Color.Black, - background = DarkBackground, - onBackground = DarkOnSurface, - surface = DarkSurface, - onSurface = DarkOnSurface, - surfaceVariant = DarkSurfaceVariant, - onSurfaceVariant = DarkOnSurfaceVariant, - surfaceTint = HermesPurple, - surfaceContainer = DarkSurfaceContainer, - surfaceContainerHigh = DarkSurfaceContainerHigh, - surfaceContainerHighest = DarkSurfaceContainerHighest, - inverseSurface = DarkInverseSurface, - inverseOnSurface = DarkInverseOnSurface, - error = StatusRed, - onError = Color.White, - errorContainer = StatusRedContainer, - onErrorContainer = Color(0xFFFFB4B4), - outline = DarkOutline, - outlineVariant = DarkOutlineVariant, - scrim = DarkScrim, - ) +/** + * Resolve the Material 3 [ColorScheme] for a preset + dark flag. + * + * Every preset exports both a dark and light scheme. AMOLED's light scheme is + * an explicit alias of the brand default light scheme. + */ +private fun resolveColorScheme( + preset: ThemePreset, + darkTheme: Boolean, +) = when (preset) { + ThemePreset.DEFAULT -> if (darkTheme) DefaultDarkColorScheme else DefaultLightColorScheme + ThemePreset.MONOCHROME -> if (darkTheme) MonochromeDarkColorScheme else MonochromeLightColorScheme + ThemePreset.GRUVBOX -> if (darkTheme) GruvboxDarkColorScheme else GruvboxLightColorScheme + ThemePreset.CATPPUCCIN -> if (darkTheme) CatppuccinDarkColorScheme else CatppuccinLightColorScheme + ThemePreset.AMOLED -> if (darkTheme) AmoledDarkColorScheme else AmoledLightColorScheme + ThemePreset.NEON_NOIR -> if (darkTheme) NeonNoirDarkColorScheme else NeonNoirLightColorScheme +} -private val HermesLightColorScheme = - lightColorScheme( - primary = HermesPurpleDark, - onPrimary = Color.White, - primaryContainer = HermesPurpleLight, - onPrimaryContainer = Color(0xFF1E0F66), - secondary = HermesAmberDark, - onSecondary = Color.White, - secondaryContainer = HermesAmberLight, - onSecondaryContainer = Color(0xFF3D2F0F), - tertiary = HermesAmberDark, - onTertiary = Color.White, - background = LightBackground, - onBackground = LightOnSurface, - surface = LightSurface, - onSurface = LightOnSurface, - surfaceVariant = LightSurfaceVariant, - onSurfaceVariant = LightOnSurfaceVariant, - surfaceTint = HermesPurple, - surfaceContainer = LightSurfaceContainer, - surfaceContainerHigh = LightSurfaceContainerHigh, - surfaceContainerHighest = LightSurfaceContainerHighest, - inverseSurface = LightInverseSurface, - inverseOnSurface = LightInverseOnSurface, - error = Color(0xFFB3261E), - onError = Color.White, - errorContainer = Color(0xFFF9DEDC), - onErrorContainer = Color(0xFF410E0B), - outline = LightOutline, - outlineVariant = LightOutlineVariant, - scrim = LightScrim, - ) - -private val MonochromeDarkColorScheme = - darkColorScheme( - primary = Color.White, - onPrimary = Color.Black, - primaryContainer = Color(0xFF2B2B2B), - onPrimaryContainer = Color.White, - secondary = Color(0xFFB0B0B0), - onSecondary = Color.Black, - secondaryContainer = Color(0xFF222222), - onSecondaryContainer = Color(0xFFE0E0E0), - background = Color(0xFF121212), - onBackground = Color(0xFFE0E0E0), - surface = Color(0xFF1E1E1E), - onSurface = Color(0xFFE0E0E0), - surfaceVariant = Color(0xFF2B2B2B), - onSurfaceVariant = Color(0xFFB0B0B0), - outline = Color(0xFF666666), - ) - -private val MonochromeLightColorScheme = - lightColorScheme( - primary = Color.Black, - onPrimary = Color.White, - primaryContainer = Color(0xFFE0E0E0), - onPrimaryContainer = Color.Black, - secondary = Color(0xFF4A4A4A), - onSecondary = Color.White, - secondaryContainer = Color(0xFFF0F0F0), - onSecondaryContainer = Color(0xFF111111), - background = Color(0xFFFFFFFF), - onBackground = Color(0xFF111111), - surface = Color(0xFFF5F5F5), - onSurface = Color(0xFF111111), - surfaceVariant = Color(0xFFE0E0E0), - onSurfaceVariant = Color(0xFF4A4A4A), - outline = Color(0xFF888888), - ) - -private val GruvboxDarkColorScheme = - darkColorScheme( - primary = Color(0xFFFE8019), - onPrimary = Color(0xFF282828), - primaryContainer = Color(0xFFD65D0E), - onPrimaryContainer = Color(0xFFFBF1C7), - secondary = Color(0xFFFABD2F), - onSecondary = Color(0xFF282828), - secondaryContainer = Color(0xFF3C3836), - onSecondaryContainer = Color(0xFFBDAE93), - background = Color(0xFF282828), - onBackground = Color(0xFFFBF1C7), - surface = Color(0xFF32302F), - onSurface = Color(0xFFFBF1C7), - surfaceVariant = Color(0xFF3C3836), - onSurfaceVariant = Color(0xFFBDAE93), - outline = Color(0xFF665C54), - ) - -private val GruvboxLightColorScheme = - lightColorScheme( - primary = Color(0xFFD65D0E), - onPrimary = Color(0xFFFBF1C7), - primaryContainer = Color(0xFFFE8019), - onPrimaryContainer = Color(0xFF282828), - secondary = Color(0xFF458588), - onSecondary = Color(0xFFFBF1C7), - secondaryContainer = Color(0xFFEBDBB2), - onSecondaryContainer = Color(0xFF3C3836), - background = Color(0xFFFBF1C7), - onBackground = Color(0xFF282828), - surface = Color(0xFFF2E5BC), - onSurface = Color(0xFF282828), - surfaceVariant = Color(0xFFEBDBB2), - onSurfaceVariant = Color(0xFF7C6F64), - outline = Color(0xFFA89984), - ) - -private val CatppuccinDarkColorScheme = - darkColorScheme( - primary = Color(0xFFCBA6F7), - onPrimary = Color(0xFF11111B), - primaryContainer = Color(0xFF585B70), - onPrimaryContainer = Color(0xFFF5E0DC), - secondary = Color(0xFF89B4FA), - onSecondary = Color(0xFF11111B), - secondaryContainer = Color(0xFF313244), - onSecondaryContainer = Color(0xFFBAC2DE), - background = Color(0xFF1E1E2E), - onBackground = Color(0xFFCDD6F4), - surface = Color(0xFF252538), - onSurface = Color(0xFFCDD6F4), - surfaceVariant = Color(0xFF313244), - onSurfaceVariant = Color(0xFFA6ADC8), - outline = Color(0xFF585B70), - ) - -private val CatppuccinLightColorScheme = - lightColorScheme( - primary = Color(0xFF8839EF), - onPrimary = Color(0xFFEFF1F5), - primaryContainer = Color(0xFFCCD0DA), - onPrimaryContainer = Color(0xFF4C4F69), - secondary = Color(0xFF1E66F5), - onSecondary = Color(0xFFEFF1F5), - secondaryContainer = Color(0xFFE6E9EF), - onSecondaryContainer = Color(0xFF4C4F69), - background = Color(0xFFEFF1F5), - onBackground = Color(0xFF4C4F69), - surface = Color(0xFFE6E9EF), - onSurface = Color(0xFF4C4F69), - surfaceVariant = Color(0xFFCCD0DA), - onSurfaceVariant = Color(0xFF6C6F85), - outline = Color(0xFF9CA0B0), - ) - -private val AmoledDarkColorScheme = - darkColorScheme( - primary = HermesPurple, - onPrimary = Color.White, - primaryContainer = Color(0xFF1A1040), - onPrimaryContainer = HermesPurpleOnContainer, - secondary = HermesAmber, - onSecondary = Color.Black, - secondaryContainer = Color(0xFF2A2000), - onSecondaryContainer = HermesAmberLight, - background = Color.Black, - onBackground = Color(0xFFE8E6EE), - surface = Color(0xFF08080A), - onSurface = Color(0xFFE8E6EE), - surfaceVariant = Color(0xFF121218), - onSurfaceVariant = Color(0xFFB6B2C4), - outline = Color(0xFF3A3A4A), - ) - -private val NeonNoirDarkColorScheme = - darkColorScheme( - primary = Color(0xFFFF6BF4), - onPrimary = Color(0xFF1A001A), - primaryContainer = Color(0xFF3A003A), - onPrimaryContainer = Color(0xFFFFCCF2), - secondary = Color(0xFFA78BFA), - onSecondary = Color(0xFF0F0B1A), - secondaryContainer = Color(0xFF2B1F59), - onSecondaryContainer = Color(0xFFD9CCFF), - tertiary = Color(0xFF60F0FF), - onTertiary = Color(0xFF003B40), - tertiaryContainer = Color(0xFF004F59), - onTertiaryContainer = Color(0xFFBFFAFF), - background = Color(0xFF0F0B1A), - onBackground = Color(0xFFE8E0F0), - surface = Color(0xFF1A1530), - onSurface = Color(0xFFE8E0F0), - surfaceVariant = Color(0xFF2B2540), - onSurfaceVariant = Color(0xFF9A90B0), - surfaceTint = Color(0xFFFF6BF4), - surfaceContainer = Color(0xFF1A1530), - surfaceContainerHigh = Color(0xFF252040), - surfaceContainerHighest = Color(0xFF2F2A50), - inverseSurface = Color(0xFFE8E0F0), - inverseOnSurface = Color(0xFF0F0B1A), - error = Color(0xFFFF3D68), - onError = Color.White, - errorContainer = Color(0xFF3A0A14), - onErrorContainer = Color(0xFFFFB3C0), - outline = Color(0xFF3A3060), - outlineVariant = Color(0xFF2E2545), - scrim = Color(0xFF000000), - ) - -private val NeonNoirLightColorScheme = - lightColorScheme( - primary = Color(0xFFC440A8), - onPrimary = Color.White, - primaryContainer = Color(0xFFFFD9F2), - onPrimaryContainer = Color(0xFF3A003A), - secondary = Color(0xFF7C4DFF), - onSecondary = Color.White, - secondaryContainer = Color(0xFFEDE0FF), - onSecondaryContainer = Color(0xFF1E0066), - tertiary = Color(0xFF0098A6), - onTertiary = Color.White, - tertiaryContainer = Color(0xFFBFFAFF), - onTertiaryContainer = Color(0xFF003B40), - background = Color(0xFFF5F0FA), - onBackground = Color(0xFF0F0B1A), - surface = Color.White, - onSurface = Color(0xFF0F0B1A), - surfaceVariant = Color(0xFFEDE6F5), - onSurfaceVariant = Color(0xFF7A7090), - surfaceTint = Color(0xFFC440A8), - surfaceContainer = Color(0xFFFDF8FF), - surfaceContainerHigh = Color(0xFFF0EDF5), - surfaceContainerHighest = Color(0xFFE6E0ED), - inverseSurface = Color(0xFF0F0B1A), - inverseOnSurface = Color(0xFFE8E0F0), - error = Color(0xFFB3261E), - onError = Color.White, - errorContainer = Color(0xFFF9DEDC), - onErrorContainer = Color(0xFF410E0B), - outline = Color(0xFFBFB8CC), - outlineVariant = Color(0xFFD9D2E3), - scrim = Color(0xFF000000), - ) +/** + * Resolve the semantic status colors for a preset + dark flag. + * + * Every preset exports both a dark and light status set. MONOCHROME and AMOLED + * alias the brand default status colors (they have no bespoke semantic set). + */ +private fun resolveStatusColors( + preset: ThemePreset, + darkTheme: Boolean, +) = when (preset) { + ThemePreset.DEFAULT -> if (darkTheme) DefaultDarkStatusColors else DefaultLightStatusColors + ThemePreset.MONOCHROME -> if (darkTheme) MonochromeDarkStatusColors else MonochromeLightStatusColors + ThemePreset.GRUVBOX -> if (darkTheme) GruvboxDarkStatusColors else GruvboxLightStatusColors + ThemePreset.CATPPUCCIN -> if (darkTheme) CatppuccinDarkStatusColors else CatppuccinLightStatusColors + ThemePreset.AMOLED -> if (darkTheme) AmoledDarkStatusColors else AmoledLightStatusColors + ThemePreset.NEON_NOIR -> if (darkTheme) NeonNoirDarkStatusColors else NeonNoirLightStatusColors +} @Composable fun HermesControlTheme( @@ -312,165 +100,17 @@ fun HermesControlTheme( val context = LocalContext.current val dynamicAvailable = useDynamicColors && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S val colorScheme = - when { - dynamicAvailable && darkTheme -> { + if (dynamicAvailable) { + if (darkTheme) { dynamicDarkColorScheme(context) - } - - dynamicAvailable && !darkTheme -> { + } else { dynamicLightColorScheme(context) } - - else -> { - when (themePreset) { - ThemePreset.DEFAULT -> if (darkTheme) HermesDarkColorScheme else HermesLightColorScheme - ThemePreset.MONOCHROME -> if (darkTheme) MonochromeDarkColorScheme else MonochromeLightColorScheme - ThemePreset.GRUVBOX -> if (darkTheme) GruvboxDarkColorScheme else GruvboxLightColorScheme - ThemePreset.CATPPUCCIN -> if (darkTheme) CatppuccinDarkColorScheme else CatppuccinLightColorScheme - ThemePreset.AMOLED -> if (darkTheme) AmoledDarkColorScheme else HermesLightColorScheme - ThemePreset.NEON_NOIR -> if (darkTheme) NeonNoirDarkColorScheme else NeonNoirLightColorScheme - } - } + } else { + resolveColorScheme(themePreset, darkTheme) } - val statusColors = - when { - themePreset == ThemePreset.GRUVBOX && darkTheme -> { - HermesStatusColors( - success = Color(0xFFB8BB26), - successContainer = Color(0xFF32302F), - onSuccess = Color(0xFF282828), - warning = Color(0xFFFABD2F), - warningContainer = Color(0xFF3C3836), - onWarning = Color(0xFF282828), - error = Color(0xFFFB4934), - errorContainer = Color(0xFF282828), - onError = Color(0xFF282828), - info = Color(0xFF83A598), - infoContainer = Color(0xFF3C3836), - onInfo = Color(0xFF282828), - ) - } - - themePreset == ThemePreset.GRUVBOX && !darkTheme -> { - HermesStatusColors( - success = Color(0xFF98971A), - successContainer = Color(0xFFEBDBB2), - onSuccess = Color(0xFFEBDBB2), - warning = Color(0xFFD79921), - warningContainer = Color(0xFFEBDBB2), - onWarning = Color(0xFFEBDBB2), - error = Color(0xFFCC241D), - errorContainer = Color(0xFFEBDBB2), - onError = Color(0xFFEBDBB2), - info = Color(0xFF458588), - infoContainer = Color(0xFFEBDBB2), - onInfo = Color(0xFFEBDBB2), - ) - } - - themePreset == ThemePreset.CATPPUCCIN && darkTheme -> { - HermesStatusColors( - success = Color(0xFFA6E3A1), - successContainer = Color(0xFF313244), - onSuccess = Color(0xFF11111B), - warning = Color(0xFFF9E2AF), - warningContainer = Color(0xFF313244), - onWarning = Color(0xFF11111B), - error = Color(0xFFF38BA8), - errorContainer = Color(0xFF313244), - onError = Color(0xFF11111B), - info = Color(0xFF89B4FA), - infoContainer = Color(0xFF313244), - onInfo = Color(0xFF11111B), - ) - } - - themePreset == ThemePreset.CATPPUCCIN && !darkTheme -> { - HermesStatusColors( - success = Color(0xFF40A02B), - successContainer = Color(0xFFE6E9EF), - onSuccess = Color(0xFFE6E9EF), - warning = Color(0xFFDF8E1D), - warningContainer = Color(0xFFE6E9EF), - onWarning = Color(0xFFE6E9EF), - error = Color(0xFFD20F39), - errorContainer = Color(0xFFE6E9EF), - onError = Color(0xFFE6E9EF), - info = Color(0xFF1E66F5), - infoContainer = Color(0xFFE6E9EF), - onInfo = Color(0xFFE6E9EF), - ) - } - - themePreset == ThemePreset.NEON_NOIR && darkTheme -> { - HermesStatusColors( - success = Color(0xFF6FEA8B), - successContainer = Color(0xFF0A3A14), - onSuccess = Color(0xFF0F0B1A), - warning = Color(0xFFFFB347), - warningContainer = Color(0xFF3A2000), - onWarning = Color(0xFF0F0B1A), - error = Color(0xFFFF3D68), - errorContainer = Color(0xFF3A0A14), - onError = Color(0xFF0F0B1A), - info = Color(0xFF60F0FF), - infoContainer = Color(0xFF003B40), - onInfo = Color(0xFF0F0B1A), - ) - } - - themePreset == ThemePreset.NEON_NOIR && !darkTheme -> { - HermesStatusColors( - success = Color(0xFF1B873A), - successContainer = Color(0xFFD7F5E0), - onSuccess = Color(0xFFFDF8FF), - warning = Color(0xFFB87800), - warningContainer = Color(0xFFFFEAB3), - onWarning = Color(0xFFFDF8FF), - error = Color(0xFFB3261E), - errorContainer = Color(0xFFF9DEDC), - onError = Color(0xFFFDF8FF), - info = Color(0xFF2E6FBD), - infoContainer = Color(0xFFD4E7FF), - onInfo = Color(0xFFFDF8FF), - ) - } - - darkTheme -> { - HermesStatusColors( - success = StatusGreen, - successContainer = StatusGreenContainer, - onSuccess = StatusGreyLight, - warning = StatusYellow, - warningContainer = StatusYellowContainer, - onWarning = StatusGreyLight, - error = StatusRed, - errorContainer = StatusRedContainer, - onError = StatusGreyLight, - info = StatusBlue, - infoContainer = StatusBlueContainer, - onInfo = StatusGreyLight, - ) - } - - else -> { - HermesStatusColors( - success = Color(0xFF1B873A), - successContainer = Color(0xFFD7F5E0), - onSuccess = Color(0xFFFDF8FF), - warning = HermesAmberDark, - warningContainer = Color(0xFFFFEAB3), - onWarning = Color(0xFFFDF8FF), - error = Color(0xFFB3261E), - errorContainer = Color(0xFFF9DEDC), - onError = Color(0xFFFDF8FF), - info = Color(0xFF2E6FBD), - infoContainer = Color(0xFFD4E7FF), - onInfo = Color(0xFFFDF8FF), - ) - } - } + val statusColors = resolveStatusColors(themePreset, darkTheme) CompositionLocalProvider( LocalThemePreference provides themePreference, diff --git a/app/src/main/java/com/m57/hermescontrol/theme/presets/AmoledScheme.kt b/app/src/main/java/com/m57/hermescontrol/theme/presets/AmoledScheme.kt new file mode 100644 index 00000000..55a352ae --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/presets/AmoledScheme.kt @@ -0,0 +1,44 @@ +package com.m57.hermescontrol.theme.presets + +import androidx.compose.material3.darkColorScheme +import androidx.compose.ui.graphics.Color +import com.m57.hermescontrol.theme.HermesAmber +import com.m57.hermescontrol.theme.HermesAmberLight +import com.m57.hermescontrol.theme.HermesPurple +import com.m57.hermescontrol.theme.HermesPurpleOnContainer + +/** + * AMOLED color scheme (dark only). + * + * AMOLED has no light variant — callers fall back to the brand default light + * scheme for light mode. + */ +val AmoledDarkColorScheme = + darkColorScheme( + primary = HermesPurple, + onPrimary = Color.White, + primaryContainer = Color(0xFF1A1040), + onPrimaryContainer = HermesPurpleOnContainer, + secondary = HermesAmber, + onSecondary = Color.Black, + secondaryContainer = Color(0xFF2A2000), + onSecondaryContainer = HermesAmberLight, + background = Color.Black, + onBackground = Color(0xFFE8E6EE), + surface = Color(0xFF08080A), + onSurface = Color(0xFFE8E6EE), + surfaceVariant = Color(0xFF121218), + onSurfaceVariant = Color(0xFFB6B2C4), + outline = Color(0xFF3A3A4A), + ) + +/** + * AMOLED has no bespoke light scheme — reuse the brand default light scheme. + */ +val AmoledLightColorScheme = DefaultLightColorScheme + +/** AMOLED status colors (dark) — reuses the brand default set. */ +val AmoledDarkStatusColors = DefaultDarkStatusColors + +/** AMOLED status colors (light) — reuses the brand default set. */ +val AmoledLightStatusColors = DefaultLightStatusColors diff --git a/app/src/main/java/com/m57/hermescontrol/theme/presets/CatppuccinScheme.kt b/app/src/main/java/com/m57/hermescontrol/theme/presets/CatppuccinScheme.kt new file mode 100644 index 00000000..fc709c0e --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/presets/CatppuccinScheme.kt @@ -0,0 +1,80 @@ +package com.m57.hermescontrol.theme.presets + +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.ui.graphics.Color +import com.m57.hermescontrol.theme.HermesStatusColors + +/** Catppuccin color scheme (dark). */ +val CatppuccinDarkColorScheme = + darkColorScheme( + primary = Color(0xFFCBA6F7), + onPrimary = Color(0xFF11111B), + primaryContainer = Color(0xFF585B70), + onPrimaryContainer = Color(0xFFF5E0DC), + secondary = Color(0xFF89B4FA), + onSecondary = Color(0xFF11111B), + secondaryContainer = Color(0xFF313244), + onSecondaryContainer = Color(0xFFBAC2DE), + background = Color(0xFF1E1E2E), + onBackground = Color(0xFFCDD6F4), + surface = Color(0xFF252538), + onSurface = Color(0xFFCDD6F4), + surfaceVariant = Color(0xFF313244), + onSurfaceVariant = Color(0xFFA6ADC8), + outline = Color(0xFF585B70), + ) + +/** Catppuccin color scheme (light). */ +val CatppuccinLightColorScheme = + lightColorScheme( + primary = Color(0xFF8839EF), + onPrimary = Color(0xFFEFF1F5), + primaryContainer = Color(0xFFCCD0DA), + onPrimaryContainer = Color(0xFF4C4F69), + secondary = Color(0xFF1E66F5), + onSecondary = Color(0xFFEFF1F5), + secondaryContainer = Color(0xFFE6E9EF), + onSecondaryContainer = Color(0xFF4C4F69), + background = Color(0xFFEFF1F5), + onBackground = Color(0xFF4C4F69), + surface = Color(0xFFE6E9EF), + onSurface = Color(0xFF4C4F69), + surfaceVariant = Color(0xFFCCD0DA), + onSurfaceVariant = Color(0xFF6C6F85), + outline = Color(0xFF9CA0B0), + ) + +/** Catppuccin status colors (dark). */ +val CatppuccinDarkStatusColors = + HermesStatusColors( + success = Color(0xFFA6E3A1), + successContainer = Color(0xFF313244), + onSuccess = Color(0xFF11111B), + warning = Color(0xFFF9E2AF), + warningContainer = Color(0xFF313244), + onWarning = Color(0xFF11111B), + error = Color(0xFFF38BA8), + errorContainer = Color(0xFF313244), + onError = Color(0xFF11111B), + info = Color(0xFF89B4FA), + infoContainer = Color(0xFF313244), + onInfo = Color(0xFF11111B), + ) + +/** Catppuccin status colors (light). */ +val CatppuccinLightStatusColors = + HermesStatusColors( + success = Color(0xFF40A02B), + successContainer = Color(0xFFE6E9EF), + onSuccess = Color(0xFFE6E9EF), + warning = Color(0xFFDF8E1D), + warningContainer = Color(0xFFE6E9EF), + onWarning = Color(0xFFE6E9EF), + error = Color(0xFFD20F39), + errorContainer = Color(0xFFE6E9EF), + onError = Color(0xFFE6E9EF), + info = Color(0xFF1E66F5), + infoContainer = Color(0xFFE6E9EF), + onInfo = Color(0xFFE6E9EF), + ) diff --git a/app/src/main/java/com/m57/hermescontrol/theme/presets/DefaultScheme.kt b/app/src/main/java/com/m57/hermescontrol/theme/presets/DefaultScheme.kt new file mode 100644 index 00000000..e69e6acb --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/presets/DefaultScheme.kt @@ -0,0 +1,151 @@ +package com.m57.hermescontrol.theme.presets + +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.ui.graphics.Color +import com.m57.hermescontrol.theme.DarkBackground +import com.m57.hermescontrol.theme.DarkInverseOnSurface +import com.m57.hermescontrol.theme.DarkInverseSurface +import com.m57.hermescontrol.theme.DarkOnSurface +import com.m57.hermescontrol.theme.DarkOnSurfaceVariant +import com.m57.hermescontrol.theme.DarkOutline +import com.m57.hermescontrol.theme.DarkOutlineVariant +import com.m57.hermescontrol.theme.DarkScrim +import com.m57.hermescontrol.theme.DarkSurface +import com.m57.hermescontrol.theme.DarkSurfaceContainer +import com.m57.hermescontrol.theme.DarkSurfaceContainerHigh +import com.m57.hermescontrol.theme.DarkSurfaceContainerHighest +import com.m57.hermescontrol.theme.DarkSurfaceVariant +import com.m57.hermescontrol.theme.HermesAmber +import com.m57.hermescontrol.theme.HermesAmberDark +import com.m57.hermescontrol.theme.HermesAmberLight +import com.m57.hermescontrol.theme.HermesPurple +import com.m57.hermescontrol.theme.HermesPurpleContainer +import com.m57.hermescontrol.theme.HermesPurpleDark +import com.m57.hermescontrol.theme.HermesPurpleLight +import com.m57.hermescontrol.theme.HermesPurpleOnContainer +import com.m57.hermescontrol.theme.HermesStatusColors +import com.m57.hermescontrol.theme.LightBackground +import com.m57.hermescontrol.theme.LightInverseOnSurface +import com.m57.hermescontrol.theme.LightInverseSurface +import com.m57.hermescontrol.theme.LightOnSurface +import com.m57.hermescontrol.theme.LightOnSurfaceVariant +import com.m57.hermescontrol.theme.LightOutline +import com.m57.hermescontrol.theme.LightOutlineVariant +import com.m57.hermescontrol.theme.LightScrim +import com.m57.hermescontrol.theme.LightSurface +import com.m57.hermescontrol.theme.LightSurfaceContainer +import com.m57.hermescontrol.theme.LightSurfaceContainerHigh +import com.m57.hermescontrol.theme.LightSurfaceContainerHighest +import com.m57.hermescontrol.theme.LightSurfaceVariant +import com.m57.hermescontrol.theme.StatusBlue +import com.m57.hermescontrol.theme.StatusBlueContainer +import com.m57.hermescontrol.theme.StatusGreen +import com.m57.hermescontrol.theme.StatusGreenContainer +import com.m57.hermescontrol.theme.StatusGreyLight +import com.m57.hermescontrol.theme.StatusRed +import com.m57.hermescontrol.theme.StatusRedContainer +import com.m57.hermescontrol.theme.StatusYellow +import com.m57.hermescontrol.theme.StatusYellowContainer + +/** Brand default color scheme (dark) — Voltage Purple primary. */ +val DefaultDarkColorScheme = + darkColorScheme( + primary = HermesPurple, + onPrimary = Color.White, + primaryContainer = HermesPurpleContainer, + onPrimaryContainer = HermesPurpleOnContainer, + secondary = HermesAmber, + onSecondary = Color.Black, + secondaryContainer = Color(0xFF3D2F0F), + onSecondaryContainer = HermesAmberLight, + tertiary = HermesAmberLight, + onTertiary = Color.Black, + background = DarkBackground, + onBackground = DarkOnSurface, + surface = DarkSurface, + onSurface = DarkOnSurface, + surfaceVariant = DarkSurfaceVariant, + onSurfaceVariant = DarkOnSurfaceVariant, + surfaceTint = HermesPurple, + surfaceContainer = DarkSurfaceContainer, + surfaceContainerHigh = DarkSurfaceContainerHigh, + surfaceContainerHighest = DarkSurfaceContainerHighest, + inverseSurface = DarkInverseSurface, + inverseOnSurface = DarkInverseOnSurface, + error = StatusRed, + onError = Color.White, + errorContainer = StatusRedContainer, + onErrorContainer = Color(0xFFFFB4B4), + outline = DarkOutline, + outlineVariant = DarkOutlineVariant, + scrim = DarkScrim, + ) + +/** Brand default color scheme (light) — Voltage Purple primary. */ +val DefaultLightColorScheme = + lightColorScheme( + primary = HermesPurpleDark, + onPrimary = Color.White, + primaryContainer = HermesPurpleLight, + onPrimaryContainer = Color(0xFF1E0F66), + secondary = HermesAmberDark, + onSecondary = Color.White, + secondaryContainer = HermesAmberLight, + onSecondaryContainer = Color(0xFF3D2F0F), + tertiary = HermesAmberDark, + onTertiary = Color.White, + background = LightBackground, + onBackground = LightOnSurface, + surface = LightSurface, + onSurface = LightOnSurface, + surfaceVariant = LightSurfaceVariant, + onSurfaceVariant = LightOnSurfaceVariant, + surfaceTint = HermesPurple, + surfaceContainer = LightSurfaceContainer, + surfaceContainerHigh = LightSurfaceContainerHigh, + surfaceContainerHighest = LightSurfaceContainerHighest, + inverseSurface = LightInverseSurface, + inverseOnSurface = LightInverseOnSurface, + error = Color(0xFFB3261E), + onError = Color.White, + errorContainer = Color(0xFFF9DEDC), + onErrorContainer = Color(0xFF410E0B), + outline = LightOutline, + outlineVariant = LightOutlineVariant, + scrim = LightScrim, + ) + +/** Default status colors (dark). */ +val DefaultDarkStatusColors = + HermesStatusColors( + success = StatusGreen, + successContainer = StatusGreenContainer, + onSuccess = StatusGreyLight, + warning = StatusYellow, + warningContainer = StatusYellowContainer, + onWarning = StatusGreyLight, + error = StatusRed, + errorContainer = StatusRedContainer, + onError = StatusGreyLight, + info = StatusBlue, + infoContainer = StatusBlueContainer, + onInfo = StatusGreyLight, + ) + +/** Default status colors (light). */ +val DefaultLightStatusColors = + HermesStatusColors( + success = Color(0xFF1B873A), + successContainer = Color(0xFFD7F5E0), + onSuccess = Color(0xFFFDF8FF), + warning = HermesAmberDark, + warningContainer = Color(0xFFFFEAB3), + onWarning = Color(0xFFFDF8FF), + error = Color(0xFFB3261E), + errorContainer = Color(0xFFF9DEDC), + onError = Color(0xFFFDF8FF), + info = Color(0xFF2E6FBD), + infoContainer = Color(0xFFD4E7FF), + onInfo = Color(0xFFFDF8FF), + ) diff --git a/app/src/main/java/com/m57/hermescontrol/theme/presets/GruvboxScheme.kt b/app/src/main/java/com/m57/hermescontrol/theme/presets/GruvboxScheme.kt new file mode 100644 index 00000000..14ec27a1 --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/presets/GruvboxScheme.kt @@ -0,0 +1,80 @@ +package com.m57.hermescontrol.theme.presets + +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.ui.graphics.Color +import com.m57.hermescontrol.theme.HermesStatusColors + +/** Gruvbox color scheme (dark). */ +val GruvboxDarkColorScheme = + darkColorScheme( + primary = Color(0xFFFE8019), + onPrimary = Color(0xFF282828), + primaryContainer = Color(0xFFD65D0E), + onPrimaryContainer = Color(0xFFFBF1C7), + secondary = Color(0xFFFABD2F), + onSecondary = Color(0xFF282828), + secondaryContainer = Color(0xFF3C3836), + onSecondaryContainer = Color(0xFFBDAE93), + background = Color(0xFF282828), + onBackground = Color(0xFFFBF1C7), + surface = Color(0xFF32302F), + onSurface = Color(0xFFFBF1C7), + surfaceVariant = Color(0xFF3C3836), + onSurfaceVariant = Color(0xFFBDAE93), + outline = Color(0xFF665C54), + ) + +/** Gruvbox color scheme (light). */ +val GruvboxLightColorScheme = + lightColorScheme( + primary = Color(0xFFD65D0E), + onPrimary = Color(0xFFFBF1C7), + primaryContainer = Color(0xFFFE8019), + onPrimaryContainer = Color(0xFF282828), + secondary = Color(0xFF458588), + onSecondary = Color(0xFFFBF1C7), + secondaryContainer = Color(0xFFEBDBB2), + onSecondaryContainer = Color(0xFF3C3836), + background = Color(0xFFFBF1C7), + onBackground = Color(0xFF282828), + surface = Color(0xFFF2E5BC), + onSurface = Color(0xFF282828), + surfaceVariant = Color(0xFFEBDBB2), + onSurfaceVariant = Color(0xFF7C6F64), + outline = Color(0xFFA89984), + ) + +/** Gruvbox status colors (dark). */ +val GruvboxDarkStatusColors = + HermesStatusColors( + success = Color(0xFFB8BB26), + successContainer = Color(0xFF32302F), + onSuccess = Color(0xFF282828), + warning = Color(0xFFFABD2F), + warningContainer = Color(0xFF3C3836), + onWarning = Color(0xFF282828), + error = Color(0xFFFB4934), + errorContainer = Color(0xFF282828), + onError = Color(0xFF282828), + info = Color(0xFF83A598), + infoContainer = Color(0xFF3C3836), + onInfo = Color(0xFF282828), + ) + +/** Gruvbox status colors (light). */ +val GruvboxLightStatusColors = + HermesStatusColors( + success = Color(0xFF98971A), + successContainer = Color(0xFFEBDBB2), + onSuccess = Color(0xFFEBDBB2), + warning = Color(0xFFD79921), + warningContainer = Color(0xFFEBDBB2), + onWarning = Color(0xFFEBDBB2), + error = Color(0xFFCC241D), + errorContainer = Color(0xFFEBDBB2), + onError = Color(0xFFEBDBB2), + info = Color(0xFF458588), + infoContainer = Color(0xFFEBDBB2), + onInfo = Color(0xFFEBDBB2), + ) diff --git a/app/src/main/java/com/m57/hermescontrol/theme/presets/MonochromeScheme.kt b/app/src/main/java/com/m57/hermescontrol/theme/presets/MonochromeScheme.kt new file mode 100644 index 00000000..fe5a0ed8 --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/presets/MonochromeScheme.kt @@ -0,0 +1,51 @@ +package com.m57.hermescontrol.theme.presets + +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.ui.graphics.Color + +/** Monochrome color scheme (dark). */ +val MonochromeDarkColorScheme = + darkColorScheme( + primary = Color.White, + onPrimary = Color.Black, + primaryContainer = Color(0xFF2B2B2B), + onPrimaryContainer = Color.White, + secondary = Color(0xFFB0B0B0), + onSecondary = Color.Black, + secondaryContainer = Color(0xFF222222), + onSecondaryContainer = Color(0xFFE0E0E0), + background = Color(0xFF121212), + onBackground = Color(0xFFE0E0E0), + surface = Color(0xFF1E1E1E), + onSurface = Color(0xFFE0E0E0), + surfaceVariant = Color(0xFF2B2B2B), + onSurfaceVariant = Color(0xFFB0B0B0), + outline = Color(0xFF666666), + ) + +/** Monochrome color scheme (light). */ +val MonochromeLightColorScheme = + lightColorScheme( + primary = Color.Black, + onPrimary = Color.White, + primaryContainer = Color(0xFFE0E0E0), + onPrimaryContainer = Color.Black, + secondary = Color(0xFF4A4A4A), + onSecondary = Color.White, + secondaryContainer = Color(0xFFF0F0F0), + onSecondaryContainer = Color(0xFF111111), + background = Color(0xFFFFFFFF), + onBackground = Color(0xFF111111), + surface = Color(0xFFF5F5F5), + onSurface = Color(0xFF111111), + surfaceVariant = Color(0xFFE0E0E0), + onSurfaceVariant = Color(0xFF4A4A4A), + outline = Color(0xFF888888), + ) + +/** Monochrome status colors (dark) — reuses the brand default set. */ +val MonochromeDarkStatusColors = DefaultDarkStatusColors + +/** Monochrome status colors (light) — reuses the brand default set. */ +val MonochromeLightStatusColors = DefaultLightStatusColors diff --git a/app/src/main/java/com/m57/hermescontrol/theme/presets/NeonNoirScheme.kt b/app/src/main/java/com/m57/hermescontrol/theme/presets/NeonNoirScheme.kt new file mode 100644 index 00000000..5e3a3e80 --- /dev/null +++ b/app/src/main/java/com/m57/hermescontrol/theme/presets/NeonNoirScheme.kt @@ -0,0 +1,112 @@ +package com.m57.hermescontrol.theme.presets + +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.ui.graphics.Color +import com.m57.hermescontrol.theme.HermesStatusColors + +/** Neon Noir color scheme (dark). */ +val NeonNoirDarkColorScheme = + darkColorScheme( + primary = Color(0xFFFF6BF4), + onPrimary = Color(0xFF1A001A), + primaryContainer = Color(0xFF3A003A), + onPrimaryContainer = Color(0xFFFFCCF2), + secondary = Color(0xFFA78BFA), + onSecondary = Color(0xFF0F0B1A), + secondaryContainer = Color(0xFF2B1F59), + onSecondaryContainer = Color(0xFFD9CCFF), + tertiary = Color(0xFF60F0FF), + onTertiary = Color(0xFF003B40), + tertiaryContainer = Color(0xFF004F59), + onTertiaryContainer = Color(0xFFBFFAFF), + background = Color(0xFF0F0B1A), + onBackground = Color(0xFFE8E0F0), + surface = Color(0xFF1A1530), + onSurface = Color(0xFFE8E0F0), + surfaceVariant = Color(0xFF2B2540), + onSurfaceVariant = Color(0xFF9A90B0), + surfaceTint = Color(0xFFFF6BF4), + surfaceContainer = Color(0xFF1A1530), + surfaceContainerHigh = Color(0xFF252040), + surfaceContainerHighest = Color(0xFF2F2A50), + inverseSurface = Color(0xFFE8E0F0), + inverseOnSurface = Color(0xFF0F0B1A), + error = Color(0xFFFF3D68), + onError = Color.White, + errorContainer = Color(0xFF3A0A14), + onErrorContainer = Color(0xFFFFB3C0), + outline = Color(0xFF3A3060), + outlineVariant = Color(0xFF2E2545), + scrim = Color(0xFF000000), + ) + +/** Neon Noir color scheme (light). */ +val NeonNoirLightColorScheme = + lightColorScheme( + primary = Color(0xFFC440A8), + onPrimary = Color.White, + primaryContainer = Color(0xFFFFD9F2), + onPrimaryContainer = Color(0xFF3A003A), + secondary = Color(0xFF7C4DFF), + onSecondary = Color.White, + secondaryContainer = Color(0xFFEDE0FF), + onSecondaryContainer = Color(0xFF1E0066), + tertiary = Color(0xFF0098A6), + onTertiary = Color.White, + tertiaryContainer = Color(0xFFBFFAFF), + onTertiaryContainer = Color(0xFF003B40), + background = Color(0xFFF5F0FA), + onBackground = Color(0xFF0F0B1A), + surface = Color.White, + onSurface = Color(0xFF0F0B1A), + surfaceVariant = Color(0xFFEDE6F5), + onSurfaceVariant = Color(0xFF7A7090), + surfaceTint = Color(0xFFC440A8), + surfaceContainer = Color(0xFFFDF8FF), + surfaceContainerHigh = Color(0xFFF0EDF5), + surfaceContainerHighest = Color(0xFFE6E0ED), + inverseSurface = Color(0xFF0F0B1A), + inverseOnSurface = Color(0xFFE8E0F0), + error = Color(0xFFB3261E), + onError = Color.White, + errorContainer = Color(0xFFF9DEDC), + onErrorContainer = Color(0xFF410E0B), + outline = Color(0xFFBFB8CC), + outlineVariant = Color(0xFFD9D2E3), + scrim = Color(0xFF000000), + ) + +/** Neon Noir status colors (dark). */ +val NeonNoirDarkStatusColors = + HermesStatusColors( + success = Color(0xFF6FEA8B), + successContainer = Color(0xFF0A3A14), + onSuccess = Color(0xFF0F0B1A), + warning = Color(0xFFFFB347), + warningContainer = Color(0xFF3A2000), + onWarning = Color(0xFF0F0B1A), + error = Color(0xFFFF3D68), + errorContainer = Color(0xFF3A0A14), + onError = Color(0xFF0F0B1A), + info = Color(0xFF60F0FF), + infoContainer = Color(0xFF003B40), + onInfo = Color(0xFF0F0B1A), + ) + +/** Neon Noir status colors (light). */ +val NeonNoirLightStatusColors = + HermesStatusColors( + success = Color(0xFF1B873A), + successContainer = Color(0xFFD7F5E0), + onSuccess = Color(0xFFFDF8FF), + warning = Color(0xFFB87800), + warningContainer = Color(0xFFFFEAB3), + onWarning = Color(0xFFFDF8FF), + error = Color(0xFFB3261E), + errorContainer = Color(0xFFF9DEDC), + onError = Color(0xFFFDF8FF), + info = Color(0xFF2E6FBD), + infoContainer = Color(0xFFD4E7FF), + onInfo = Color(0xFFFDF8FF), + )