diff --git a/src/core/theme.ts b/src/core/theme.ts
index 7cbe378..638a13c 100644
--- a/src/core/theme.ts
+++ b/src/core/theme.ts
@@ -1,6 +1,8 @@
-import { store } from "@store/state.svelte";
+import { store, updateSettings } from "@store/state.svelte";
let themeStyleEl: HTMLStyleElement | null = null;
+let mediaQuery: MediaQueryList | null = null;
+let mediaHandler: (() => void) | null = null;
export function applyTheme() {
const themeId = store.settings.theme ?? "dark";
@@ -34,3 +36,32 @@ export function applyTheme() {
themeStyleEl.textContent = css;
document.documentElement.setAttribute("data-theme", "custom");
}
+
+function applySystemTheme(dark: boolean) {
+ const themeId = dark
+ ? (store.settings.systemThemeDark ?? "dark")
+ : (store.settings.systemThemeLight ?? "light");
+ updateSettings({ theme: themeId });
+}
+
+export function mountSystemThemeSync() {
+ if (mediaQuery && mediaHandler) {
+ mediaQuery.removeEventListener("change", mediaHandler);
+ mediaHandler = null;
+ }
+
+ if (!store.settings.systemThemeSync) return;
+
+ mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
+ mediaHandler = () => applySystemTheme(mediaQuery!.matches);
+ mediaQuery.addEventListener("change", mediaHandler);
+ applySystemTheme(mediaQuery.matches);
+}
+
+export function unmountSystemThemeSync() {
+ if (mediaQuery && mediaHandler) {
+ mediaQuery.removeEventListener("change", mediaHandler);
+ mediaHandler = null;
+ mediaQuery = null;
+ }
+}
\ No newline at end of file
diff --git a/src/features/settings/components/Settings.css b/src/features/settings/components/Settings.css
index 8de23f1..25507c2 100644
--- a/src/features/settings/components/Settings.css
+++ b/src/features/settings/components/Settings.css
@@ -226,7 +226,8 @@
flex-shrink: 0;
transition: background var(--t-base), border-color var(--t-base);
}
-.s-toggle.on { background: var(--accent); border-color: var(--accent); }
+.s-toggle.on,
+.s-toggle-on { background: var(--accent); border-color: var(--accent); }
.s-toggle-thumb {
position: absolute;
@@ -238,12 +239,46 @@
background: var(--text-faint);
transition: transform var(--t-base), background var(--t-base);
}
-.s-toggle.on .s-toggle-thumb {
+.s-toggle.on .s-toggle-thumb,
+.s-toggle-on .s-toggle-thumb {
transform: translateX(15px);
background: var(--bg-void);
}
+/* ── System theme sync pair ───────────────────────────────────────── */
+.s-sync-pair {
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: 1px;
+ border-top: 1px solid var(--border-dim);
+ background: var(--border-dim);
+}
+
+.s-sync-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--sp-3);
+ padding: 8px var(--sp-4);
+ background: var(--bg-raised);
+}
+
+.s-sync-label {
+ font-family: var(--font-ui);
+ font-size: var(--text-xs);
+ color: var(--text-faint);
+ letter-spacing: var(--tracking-wide);
+ flex-shrink: 0;
+}
+
+.s-sync-item .s-select-btn {
+ font-size: var(--text-xs);
+ min-width: 0;
+ padding: 4px 8px;
+}
+
+
/* ── Stepper ──────────────────────────────────────────────────────── */
.s-stepper {
display: flex;
diff --git a/src/features/settings/components/Settings.svelte b/src/features/settings/components/Settings.svelte
index 04f656b..0edb693 100644
--- a/src/features/settings/components/Settings.svelte
+++ b/src/features/settings/components/Settings.svelte
@@ -162,7 +162,7 @@
{#if tab === "general"}
Theme