/* ───────────────────────────────────────────────────────── * 暖记 Theme Switcher * Handles theme toggling + localStorage persistence * ───────────────────────────────────────────────────────── */ (function () { var THEMES = [ { id: 'warm', name: '暖阳', swatch: '#E07A5F' }, { id: 'pine', name: '松风', swatch: '#4A7B9D' } ]; var STORAGE_KEY = 'warmnotes-theme'; function getCurrent() { return localStorage.getItem(STORAGE_KEY) || 'warm'; } function apply(id) { if (id === 'warm') { document.documentElement.removeAttribute('data-theme'); } else { document.documentElement.setAttribute('data-theme', id); } localStorage.setItem(STORAGE_KEY, id); } function cycle() { var cur = getCurrent(); var idx = 0; for (var i = 0; i < THEMES.length; i++) { if (THEMES[i].id === cur) { idx = i; break; } } var next = THEMES[(idx + 1) % THEMES.length]; apply(next.id); updateBtn(next); } function updateBtn(theme) { var btn = document.getElementById('theme-toggle-btn'); if (!btn) return; var dot = btn.querySelector('.theme-dot'); var label = btn.querySelector('.theme-label'); if (dot) dot.style.background = theme.swatch; if (label) label.textContent = theme.name; btn.setAttribute('aria-label', 'Switch theme (current: ' + theme.name + ')'); } // Apply stored theme immediately (prevent flash) var saved = getCurrent(); apply(saved); // Wait for DOM then inject toggle button function init() { if (document.getElementById('theme-toggle-btn')) return; var cur = THEMES.filter(function (t) { return t.id === saved; })[0] || THEMES[0]; var wrap = document.createElement('div'); wrap.id = 'theme-toggle-btn'; wrap.setAttribute('role', 'button'); wrap.setAttribute('tabindex', '0'); wrap.setAttribute('aria-label', 'Switch theme (current: ' + cur.name + ')'); wrap.onclick = function () { saved = getCurrent(); cycle(); }; wrap.onkeydown = function (e) { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); cycle(); } }; var style = document.createElement('style'); style.textContent = '\ #theme-toggle-btn{position:fixed;top:8px;right:8px;z-index:10000;display:flex;align-items:center;gap:6px;\ padding:5px 12px 5px 8px;border-radius:20px;border:1px solid var(--border);\ background:var(--surface);color:var(--fg);font-size:11px;font-family:var(--font-body);\ cursor:pointer;box-shadow:var(--elev-medium);transition:all .2s ease;user-select:none;line-height:1;}\ #theme-toggle-btn:hover{box-shadow:var(--elev-float);}\ #theme-toggle-btn:focus-visible{outline:none;box-shadow:var(--focus-ring);}\ .theme-dot{width:14px;height:14px;border-radius:50%;flex-shrink:0;border:1.5px solid var(--border);}\ .theme-label{white-space:nowrap;font-weight:600;}'; document.head.appendChild(style); var dot = document.createElement('span'); dot.className = 'theme-dot'; dot.style.background = cur.swatch; var label = document.createElement('span'); label.className = 'theme-label'; label.textContent = cur.name; wrap.appendChild(dot); wrap.appendChild(label); document.body.appendChild(wrap); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } // Cross-tab sync window.addEventListener('storage', function (e) { if (e.key === STORAGE_KEY && e.newValue) { apply(e.newValue); var t = THEMES.filter(function (th) { return th.id === e.newValue; })[0] || THEMES[0]; updateBtn(t); } }); })();