diff --git a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/DualPodsCard.kt b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/DualPodsCard.kt
index a5a73f59..9052f952 100644
--- a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/DualPodsCard.kt
+++ b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/DualPodsCard.kt
@@ -50,6 +50,7 @@ import eu.darken.capod.monitor.core.visibleAncModes
import eu.darken.capod.main.ui.overview.cards.components.AncModeSelector
import eu.darken.capod.main.ui.overview.cards.components.BatteryCapsule
import eu.darken.capod.main.ui.overview.cards.components.CompactBatterySummary
+import eu.darken.capod.main.ui.overview.cards.components.batteryTierState
import eu.darken.capod.main.ui.overview.cards.components.DebugSection
import eu.darken.capod.main.ui.overview.cards.components.DeviceConnectionBadge
import eu.darken.capod.main.ui.overview.cards.components.MissingPairedDeviceBanner
@@ -330,7 +331,7 @@ private fun PodGauge(
val ringColor = tier.fillColor()
Column(
- modifier = modifier,
+ modifier = modifier.batteryTierState(tier),
horizontalAlignment = Alignment.CenterHorizontally,
) {
// Ring with icon inside
@@ -420,7 +421,9 @@ private fun CaseRow(
Row(
verticalAlignment = Alignment.CenterVertically,
- modifier = Modifier.fillMaxWidth(),
+ modifier = Modifier
+ .fillMaxWidth()
+ .batteryTierState(tier),
) {
Image(
painter = painterResource(device.caseIcon),
diff --git a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/SinglePodsCard.kt b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/SinglePodsCard.kt
index 8b1a35fc..2082a444 100644
--- a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/SinglePodsCard.kt
+++ b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/SinglePodsCard.kt
@@ -52,6 +52,7 @@ import eu.darken.capod.main.ui.overview.cards.components.DeviceConnectionBadge
import eu.darken.capod.main.ui.overview.cards.components.MissingPairedDeviceBanner
import eu.darken.capod.main.ui.overview.cards.components.SignalIndicator
import eu.darken.capod.main.ui.overview.cards.components.StatusChip
+import eu.darken.capod.main.ui.overview.cards.components.batteryTierState
import eu.darken.capod.common.SystemTimeSource
import eu.darken.capod.common.compose.Preview2
import eu.darken.capod.common.compose.PreviewWrapper
@@ -231,7 +232,9 @@ private fun ColumnScope.SinglePodsCardExpanded(
) {
Box(
contentAlignment = Alignment.Center,
- modifier = Modifier.size(88.dp),
+ modifier = Modifier
+ .size(88.dp)
+ .batteryTierState(tier),
) {
// Track ring
CircularProgressIndicator(
diff --git a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/BatteryTierSemantics.kt b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/BatteryTierSemantics.kt
new file mode 100644
index 00000000..51f7a0f6
--- /dev/null
+++ b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/BatteryTierSemantics.kt
@@ -0,0 +1,23 @@
+package eu.darken.capod.main.ui.overview.cards.components
+
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.semantics.semantics
+import androidx.compose.ui.semantics.stateDescription
+import eu.darken.capod.R
+import eu.darken.capod.monitor.core.battery.BatteryTier
+
+/**
+ * Announces a low or critical level on a battery slot — crossing either threshold is otherwise
+ * only visible as a colour change. A no-op at the other tiers, which make no claim to announce.
+ */
+@Composable
+fun Modifier.batteryTierState(tier: BatteryTier): Modifier {
+ val description = when (tier) {
+ BatteryTier.CRITICAL -> stringResource(R.string.battery_state_critical_cd)
+ BatteryTier.WARN -> stringResource(R.string.battery_state_low_cd)
+ BatteryTier.UNKNOWN, BatteryTier.GOOD -> return this
+ }
+ return semantics(mergeDescendants = true) { stateDescription = description }
+}
diff --git a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/CompactBatterySummary.kt b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/CompactBatterySummary.kt
index 4513c568..8b42ef63 100644
--- a/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/CompactBatterySummary.kt
+++ b/app/src/main/java/eu/darken/capod/main/ui/overview/cards/components/CompactBatterySummary.kt
@@ -142,7 +142,7 @@ private fun MiniPodRing(
val ringColor = tier.fillColor()
Row(
- modifier = modifier,
+ modifier = modifier.batteryTierState(tier),
verticalAlignment = Alignment.CenterVertically,
) {
Box(
@@ -197,7 +197,7 @@ private fun MiniCaseCluster(
val tier = batteryTier(device.batteryCase)
Row(
- modifier = modifier,
+ modifier = modifier.batteryTierState(tier),
verticalAlignment = Alignment.CenterVertically,
) {
Image(
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dfe3a53b..c7318939 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -274,6 +274,8 @@
R
Case
Battery unavailable
+ Battery low
+ Battery critically low
Open
Closed
Not connected to a device