export const accents = { green: '#d2ef92', blue: '#8ac7ff', red: '#ff9e99' }; export function palette(color, light = false) { color = /^#[0-9a-f]{6}$/i.test(color) ? color : accents.green; const rgb = [1, 3, 5].map(i => parseInt(color.slice(i, i + 2), 16)); const luminance = c => { const n = c / 255; return n <= .04045 ? n / 12.92 : ((n + .055) / 1.055) ** 2.4; }; const lum = values => values.map(luminance).reduce((n, v, i) => n + v * [.2126, .7152, .0722][i], 0); // Maintain readable accent text on either background, even for arbitrary colors. for (let i = 0; i < 40 && (light ? lum(rgb) > .17 : lum(rgb) < .36); i++) { rgb.forEach((n, j) => rgb[j] = Math.round(light ? n * .9 : n + (255 - n) * .12)); } return { accent: `#${rgb.map(n => n.toString(16).padStart(2, '0')).join('')}`, ink: light ? '#ffffff' : '#101313' }; } export function applyTheme(storage) { const light = storage.get('theme') === 'light'; const color = accents[storage.get('accent', 'green')] || storage.get('customColor', accents.green); const values = palette(color, light); document.body.classList.toggle('light', light); document.body.classList.toggle('digital-dials', storage.get('dialStyle') === 'digital'); document.body.classList.toggle('luminous-dials', storage.get('dialStyle') === 'luminous'); document.querySelectorAll('.gauge > svg').forEach(svg => svg.setAttribute('viewBox', '12 10 276 340')); document.body.style.setProperty('--accent', values.accent); document.body.style.setProperty('--ink', values.ink); document.dispatchEvent(new Event('caria-theme')); }