diff --git a/CHANGELOG.md b/CHANGELOG.md
index 06bdea55..797d4dc0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -56,7 +56,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Themes — community Theme Store
-**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1009](https://github.com/Psychotoxical/psysonic/pull/1009), [#1011](https://github.com/Psychotoxical/psysonic/pull/1011), [#1012](https://github.com/Psychotoxical/psysonic/pull/1012)**
+**By [@Psychotoxical](https://github.com/Psychotoxical), PR [#1009](https://github.com/Psychotoxical/psysonic/pull/1009), [#1011](https://github.com/Psychotoxical/psysonic/pull/1011), [#1012](https://github.com/Psychotoxical/psysonic/pull/1012), [#1013](https://github.com/Psychotoxical/psysonic/pull/1013)**
* New **Settings → Themes** tab: pick a theme, set the day/night scheduler, and browse a built-in **Theme Store** to install, update and uninstall community themes — with search, a dark/light filter, and full-size thumbnail previews.
* The app now bundles six core themes (Catppuccin Mocha & Latte, Kanagawa Wave, Stark HUD, and the colour-blind-safe Vision Dark / Vision Navy); every other palette installs on demand from the [psysonic-themes](https://github.com/Psysonic/psysonic-themes) repo. Installed themes are saved locally and apply instantly at startup, even offline.
diff --git a/src/components/settings/ThemeStoreSection.test.tsx b/src/components/settings/ThemeStoreSection.test.tsx
index 5cf8e343..523c0bdd 100644
--- a/src/components/settings/ThemeStoreSection.test.tsx
+++ b/src/components/settings/ThemeStoreSection.test.tsx
@@ -143,4 +143,14 @@ describe('ThemeStoreSection — pagination & refresh', () => {
await waitFor(() => expect(container.querySelector('.animate-spin')).toBeNull());
expect(rows(container)).toHaveLength(12);
});
+
+ it('shows an offline banner and hides the toolbar when the registry is unavailable', async () => {
+ fetchRegistryMock.mockRejectedValue(new Error('offline'));
+ renderWithProviders();
+
+ expect(await screen.findByText('The Theme Store is offline')).toBeInTheDocument();
+ // No catalogue to browse → the search/filter toolbar is not rendered.
+ expect(screen.queryByRole('searchbox')).not.toBeInTheDocument();
+ expect(screen.getByRole('button', { name: 'Retry' })).toBeInTheDocument();
+ });
});
diff --git a/src/components/settings/ThemeStoreSection.tsx b/src/components/settings/ThemeStoreSection.tsx
index 0ca205ec..708b27ab 100644
--- a/src/components/settings/ThemeStoreSection.tsx
+++ b/src/components/settings/ThemeStoreSection.tsx
@@ -1,6 +1,6 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
-import { Check, ChevronLeft, ChevronRight, Download, RefreshCw, Trash2 } from 'lucide-react';
+import { Check, ChevronLeft, ChevronRight, Download, RefreshCw, Trash2, WifiOff } from 'lucide-react';
import { open as openUrl } from '@tauri-apps/plugin-shell';
import CoverLightbox from '../CoverLightbox';
import { useThemeStore } from '../../store/themeStore';
@@ -159,7 +159,9 @@ export function ThemeStoreSection() {
- {/* Toolbar: search + mode filter + refresh */}
+ {/* Toolbar: search + mode filter + refresh. Hidden when offline with no
+ catalogue to browse — the offline banner below stands in for it. */}
+ {!error && (