diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts
index ad7b917..a9c3c03 100644
--- a/android/app/build.gradle.kts
+++ b/android/app/build.gradle.kts
@@ -68,6 +68,8 @@ dependencies {
implementation("com.squareup.okhttp3:okhttp:4.12.0")
// background sync driver (M5)
implementation("androidx.work:work-runtime-ktx:2.9.0")
+ // MediaStyle pill buttons in the recording notification (system-rendered).
+ implementation("androidx.media:media:1.7.0")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.9.0")
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 581f284..089ad87 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -8,6 +8,9 @@
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_stat_rec_dot.xml b/android/app/src/main/res/drawable/ic_stat_rec_dot.xml
new file mode 100644
index 0000000..61c284d
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_stat_rec_dot.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_widget_badge_paused.xml b/android/app/src/main/res/drawable/ic_widget_badge_paused.xml
new file mode 100644
index 0000000..30809f3
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_widget_badge_paused.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_widget_badge_rec.xml b/android/app/src/main/res/drawable/ic_widget_badge_rec.xml
new file mode 100644
index 0000000..873ac59
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_widget_badge_rec.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/ic_widget_mic.xml b/android/app/src/main/res/drawable/ic_widget_mic.xml
new file mode 100644
index 0000000..0a570c3
--- /dev/null
+++ b/android/app/src/main/res/drawable/ic_widget_mic.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/notif_pill.xml b/android/app/src/main/res/drawable/notif_pill.xml
new file mode 100644
index 0000000..a4d839f
--- /dev/null
+++ b/android/app/src/main/res/drawable/notif_pill.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/notif_pill_accent.xml b/android/app/src/main/res/drawable/notif_pill_accent.xml
new file mode 100644
index 0000000..e0fb2d2
--- /dev/null
+++ b/android/app/src/main/res/drawable/notif_pill_accent.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/android/app/src/main/res/layout/notification_confirm_delete.xml b/android/app/src/main/res/layout/notification_confirm_delete.xml
new file mode 100644
index 0000000..f747668
--- /dev/null
+++ b/android/app/src/main/res/layout/notification_confirm_delete.xml
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/layout/notification_recording.xml b/android/app/src/main/res/layout/notification_recording.xml
new file mode 100644
index 0000000..96d3e8d
--- /dev/null
+++ b/android/app/src/main/res/layout/notification_recording.xml
@@ -0,0 +1,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/layout/notification_recording_small.xml b/android/app/src/main/res/layout/notification_recording_small.xml
new file mode 100644
index 0000000..1fff372
--- /dev/null
+++ b/android/app/src/main/res/layout/notification_recording_small.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/layout/shonar_widget.xml b/android/app/src/main/res/layout/shonar_widget.xml
new file mode 100644
index 0000000..0e49dfb
--- /dev/null
+++ b/android/app/src/main/res/layout/shonar_widget.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml
index 5101d8d..9b82bb0 100644
--- a/android/app/src/main/res/values/colors.xml
+++ b/android/app/src/main/res/values/colors.xml
@@ -1,3 +1,10 @@
#0B1220
+
+ #E6121C2E
+ #4FD1C5
+ #E6EDF3
+ #9FB3C8
+ #FF5252
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index 6d44739..7c10317 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -1,3 +1,13 @@
SHONAR
+
+ Recording
+ Shonar recording controls. Kept silent so takes stay clean.
+ Shonar is recording
+ Shonar recording paused
+
+ Record
+ Recording…
+ Paused
+ Shonar recording widget
diff --git a/android/app/src/main/res/xml/shonar_widget_info.xml b/android/app/src/main/res/xml/shonar_widget_info.xml
new file mode 100644
index 0000000..ad07359
--- /dev/null
+++ b/android/app/src/main/res/xml/shonar_widget_info.xml
@@ -0,0 +1,14 @@
+
+
diff --git a/desktop/app/src/main/kotlin/com/shonar/desktop/DesktopState.kt b/desktop/app/src/main/kotlin/com/shonar/desktop/DesktopState.kt
index 0e60972..fa1e93c 100644
--- a/desktop/app/src/main/kotlin/com/shonar/desktop/DesktopState.kt
+++ b/desktop/app/src/main/kotlin/com/shonar/desktop/DesktopState.kt
@@ -857,10 +857,17 @@ class DesktopState(private val appDir: File = defaultAppDir()) {
.orEmpty()
d0.jobs = jobs
jobLabel(jobs)?.let { d0.busy = it }
+ // Mirror live progress onto the library row too — otherwise
+ // reprocess looks like "nothing happened" after leaving the
+ // detail screen (the pump path already does this via setLive).
+ setLive(d0.file.name, jobProgress(jobs))
+ rescanStatuses()
_detail.value = d0.copy()
val st = jobs.firstOrNull { it.jobType == job }?.status
if (st == null || st in TERMINAL) break
}
+ setLive(d0.file.name, null)
+ rescanStatuses()
val failed = d0.jobs.firstOrNull { it.jobType == job && it.status == "failed" }
if (failed != null) {
d0.busy = null