diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
index 9b109a2..afde5c6 100644
--- a/DEVELOPMENT.md
+++ b/DEVELOPMENT.md
@@ -317,3 +317,24 @@ and commit the regenerated native drawables and license.
Run `./gradlew :app:testDebugUnitTest --tests '*AdaptiveFilesTest'` for adaptive selection,
saved-state, and rendering checks. Rendering captures are written under
`app/build/outputs/design/`; these use Robolectric native graphics, not a device.
+
+## Brand icons
+
+The Feiya mark combines an F with two swept wings, using plum, off-white, and lime.
+`res/drawable/ic_launcher_foreground.xml` is the color vector source; keep its shape
+within the adaptive safe circle. `ic_launcher_monochrome.xml` supplies themed icons,
+and `ic_notification.xml` uses an opaque white silhouette on transparency at 24 dp.
+Both foreground-service notification builders must use the notification drawable.
+The splash screen shares the adaptive foreground and background color.
+
+After editing the vectors or `values/ic_launcher_background.xml`, regenerate legacy
+launcher density PNGs and the in-app logo:
+
+```sh
+python3 -m venv /tmp/feiya-icons-venv
+/tmp/feiya-icons-venv/bin/pip install CairoSVG==2.9.1
+/tmp/feiya-icons-venv/bin/python scripts/update-brand-icons.py
+./gradlew :app:processDebugResources
+```
+
+CairoSVG requires the native Cairo library.
diff --git a/app/src/main/java/com/storyteller_f/feiya/service/AppService.kt b/app/src/main/java/com/storyteller_f/feiya/service/AppService.kt
index de8c3b1..3353112 100644
--- a/app/src/main/java/com/storyteller_f/feiya/service/AppService.kt
+++ b/app/src/main/java/com/storyteller_f/feiya/service/AppService.kt
@@ -125,7 +125,7 @@ class AppService : LifecycleService() {
private fun postForegroundNotify(message: String) {
// Foreground promotion is required even when notification permission is denied.
val notification = NotificationCompat.Builder(this, FOREGROUND_CHANNEL_ID)
- .setSmallIcon(R.mipmap.ic_launcher)
+ .setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(message)
.setOngoing(true)
@@ -139,7 +139,7 @@ class AppService : LifecycleService() {
if (managerCompat.areNotificationsEnabled()) {
val notification =
NotificationCompat.Builder(this, DEFAULT_CHANNEL_ID)
- .setSmallIcon(R.mipmap.ic_launcher)
+ .setSmallIcon(R.drawable.ic_notification)
.setContentTitle(getString(R.string.app_name))
.setContentText(message)
.build()
diff --git a/app/src/main/res/drawable-nodpi/feiya_logo.png b/app/src/main/res/drawable-nodpi/feiya_logo.png
index 6947bc4..ebb8bc7 100644
Binary files a/app/src/main/res/drawable-nodpi/feiya_logo.png and b/app/src/main/res/drawable-nodpi/feiya_logo.png differ
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
index 07d5da9..7821864 100644
--- a/app/src/main/res/drawable/ic_launcher_background.xml
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -1,170 +1,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:width="108dp" android:height="108dp"
+ android:viewportWidth="108" android:viewportHeight="108">
+
diff --git a/app/src/main/res/drawable/ic_launcher_foreground.xml b/app/src/main/res/drawable/ic_launcher_foreground.xml
index a9c5358..ff15e37 100644
--- a/app/src/main/res/drawable/ic_launcher_foreground.xml
+++ b/app/src/main/res/drawable/ic_launcher_foreground.xml
@@ -2,19 +2,11 @@
-
-
-
-
-
-
-
-
\ No newline at end of file
+ android:viewportWidth="108"
+ android:viewportHeight="108">
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_launcher_monochrome.xml b/app/src/main/res/drawable/ic_launcher_monochrome.xml
new file mode 100644
index 0000000..9f6b34a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_monochrome.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_notification.xml b/app/src/main/res/drawable/ic_notification.xml
new file mode 100644
index 0000000..24bacda
--- /dev/null
+++ b/app/src/main/res/drawable/ic_notification.xml
@@ -0,0 +1,9 @@
+
+
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
index 7353dbd..10bc7a5 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -2,4 +2,5 @@
-
\ No newline at end of file
+
+
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
index 7353dbd..10bc7a5 100644
--- a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -2,4 +2,5 @@
-
\ No newline at end of file
+
+
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
index a1ccbad..a238141 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
index 40fd740..0c85300 100644
Binary files a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
index 598acdb..d2c80fd 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
index eb3395f..292b884 100644
Binary files a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
index 76d9133..032ec14 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
index 42462ab..4257a7d 100644
Binary files a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
index 362cce4..7146bf3 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
index cc21c1b..f93bde7 100644
Binary files a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
index fc94e9d..7fb8ce1 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
index 050302e..56e0d32 100644
Binary files a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/values/ic_launcher_background.xml b/app/src/main/res/values/ic_launcher_background.xml
index f4a86db..63f012e 100644
--- a/app/src/main/res/values/ic_launcher_background.xml
+++ b/app/src/main/res/values/ic_launcher_background.xml
@@ -1,4 +1,4 @@
- #86D483
-
\ No newline at end of file
+ #48245C
+
diff --git a/scripts/update-brand-icons.py b/scripts/update-brand-icons.py
new file mode 100644
index 0000000..48b16b9
--- /dev/null
+++ b/scripts/update-brand-icons.py
@@ -0,0 +1,34 @@
+#!/usr/bin/env python3
+"""Render Feiya's VectorDrawable brand source. Requires CairoSVG 2.9.1."""
+from pathlib import Path
+import xml.etree.ElementTree as ET
+import cairosvg
+
+ROOT = Path(__file__).resolve().parent.parent
+RES = ROOT / 'app/src/main/res'
+A = '{http://schemas.android.com/apk/res/android}'
+BACKGROUND = ET.parse(RES / 'values/ic_launcher_background.xml').find('color').text
+
+
+def paths(name):
+ vector = ET.parse(RES / f'drawable/{name}.xml').getroot()
+ return ''.join(f''
+ for p in vector.findall('path'))
+
+
+def svg(content, size=108):
+ return f''
+
+
+mark = paths('ic_launcher_foreground')
+for density, pixels in [('mdpi', 48), ('hdpi', 72), ('xhdpi', 96), ('xxhdpi', 144), ('xxxhdpi', 192)]:
+ for suffix, background in [('', f''),
+ ('_round', f'')]:
+ # Legacy launchers do not apply the adaptive layer inset.
+ art = svg(background + f'{mark}')
+ cairosvg.svg2png(bytestring=art.encode(), write_to=str(RES / f'mipmap-{density}/ic_launcher{suffix}.png'),
+ output_width=pixels, output_height=pixels)
+
+logo = svg(f'' + mark)
+cairosvg.svg2png(bytestring=logo.encode(), write_to=str(RES / 'drawable-nodpi/feiya_logo.png'),
+ output_width=512, output_height=512)