/* Utility functions — logging, progress, theme */ function addLog(message, type = 'info') { const logContent = document.getElementById('logContent'); const entry = document.createElement('div'); entry.className = `log-entry ${type}`; entry.setAttribute('role', type === 'error' ? 'alert' : 'status'); const timestamp = new Date().toLocaleTimeString(); entry.innerHTML = `${timestamp} ${message}`; logContent.appendChild(entry); logContent.scrollTop = logContent.scrollHeight; } function clearLog() { const logContent = document.getElementById('logContent'); logContent.innerHTML = '
Initializing...
'; } function updateProgress(percent, message) { const fill = document.getElementById('progressFill'); const pct = document.getElementById('progressPercent'); const txt = document.getElementById('progressText'); fill.style.width = percent + '%'; fill.setAttribute('aria-valuenow', percent); pct.textContent = percent + '%'; txt.textContent = message; } /* Dark mode toggle */ function toggleDarkMode() { const root = document.documentElement; const isDark = root.getAttribute('data-theme') === 'dark'; root.setAttribute('data-theme', isDark ? 'light' : 'dark'); localStorage.setItem('theme', isDark ? 'light' : 'dark'); const btn = document.getElementById('themeToggle'); if (btn) btn.textContent = isDark ? 'Dark' : 'Light'; } function loadTheme() { const saved = localStorage.getItem('theme'); if (saved === 'dark') { document.documentElement.setAttribute('data-theme', 'dark'); const btn = document.getElementById('themeToggle'); if (btn) btn.textContent = 'Light'; } } /* Severity helpers */ function getSeverityColor(severity) { const map = { CRITICAL: '#dc2626', ERROR: '#ef4444', WARNING: '#f59e0b', INFO: '#3b82f6', SUCCESS: '#10b981' }; return map[severity] || '#3b82f6'; } function getSeverityIcon(severity) { const map = { CRITICAL: '\u{1F6A8}', ERROR: '\u274C', WARNING: '\u26A0\uFE0F', INFO: '\u2139\uFE0F', SUCCESS: '\u2705' }; return map[severity] || '\u2022'; } function getCategoryIcon(category) { const icons = { 'Document Structure': '\u{1F3D7}\uFE0F', 'Metadata': '\u{1F4CB}', 'Language': '\u{1F310}', 'Text Accessibility': '\u{1F4DD}', 'Images': '\u{1F5BC}\uFE0F', 'Color Contrast': '\u{1F3A8}', 'Readability': '\u{1F4DA}', 'Link Text': '\u{1F517}', 'Forms': '\u{1F4C4}', 'Tables': '\u{1F4CA}', 'Headings': '\u{1F4D1}', 'Navigation': '\u{1F9ED}', 'Fonts': '\u{1F524}', 'Security': '\u{1F512}', 'OCR Quality': '\u{1F50D}' }; const key = Object.keys(icons).find(k => category.includes(k)); return key ? icons[key] : '\u{1F4CC}'; }