function showToast(message, type = 'info') { const container = document.getElementById('toastContainer'); const toast = document.createElement('div'); toast.className = `toast ${type}`; toast.textContent = message; container.appendChild(toast); setTimeout(() => { toast.remove(); }, 3000); } function escapeHtml(str) { const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } function formatDate(iso) { if (!iso) return '-'; return new Date(iso).toLocaleString(); } function formatBytes(bytes) { if (bytes === 0) return '0 B'; const k = 1024; const sizes = ['B', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i]; } function getStatusColor(status) { switch (status) { case 'online': case 'healthy': case 'pass': return 'var(--green)'; case 'warn': case 'warning': return 'var(--yellow)'; case 'offline': case 'error': case 'fail': return 'var(--red)'; default: return 'var(--text2)'; } } function toggleSidebar() { document.getElementById('sidebar').classList.toggle('closed'); } function toggleTheme() { const html = document.documentElement; const current = html.getAttribute('data-theme'); const next = current === 'dark' ? 'light' : 'dark'; html.setAttribute('data-theme', next); localStorage.setItem('theme', next); api.updateSettings({ theme: next }).catch(() => {}); } function loadTheme() { const saved = localStorage.getItem('theme'); if (saved) document.documentElement.setAttribute('data-theme', saved); }