// Assist dialog textfield readability — aggressive inline-style enforcement. // v3: directly writes inline styles on every input / textarea element and their // visible containers, bypassing CSS cascade entirely. Runs on every mutation. (function () { if (window.__assistFixLoaded) return; window.__assistFixLoaded = true; function rootComputed(varName, fallback) { const v = getComputedStyle(document.documentElement) .getPropertyValue(varName) .trim(); return v || fallback; } function applyColors(el) { if (!el || el.__assistFixStyled) return; const fg = rootComputed('--primary-text-color', '#e7e9f4'); const bg = rootComputed('--card-background-color', 'rgba(22, 24, 40, 0.92)'); const muted = rootComputed('--secondary-text-color', '#9a9cb8'); el.style.setProperty('color', fg, 'important'); el.style.setProperty('caret-color', fg, 'important'); if (el.tagName === 'INPUT' || el.tagName === 'TEXTAREA') { el.style.setProperty('background-color', 'transparent', 'important'); } else { el.style.setProperty('background-color', bg, 'important'); } // Also set the MDC variables at element level in case they're read here el.style.setProperty('--mdc-text-field-fill-color', bg, 'important'); el.style.setProperty('--mdc-text-field-ink-color', fg, 'important'); el.style.setProperty('--mdc-text-field-label-ink-color', muted, 'important'); el.style.setProperty('--mdc-filled-text-field-container-color', bg, 'important'); el.style.setProperty('--mdc-filled-text-field-input-text-color', fg, 'important'); el.style.setProperty('--mdc-filled-text-field-label-text-color', muted, 'important'); el.__assistFixStyled = true; } // Walk document + every shadow root, applying inline styles to matching elements const TARGET_SELECTORS = [ 'input', 'textarea', 'ha-textfield', 'ha-textarea', 'mwc-textfield', 'mwc-textarea', '.mdc-text-field', '.mdc-text-field--filled', '.mdc-text-field__input', '.mdc-text-area__input', ]; function walkAndStyle(root, depth = 0) { if (!root || depth > 10) return 0; let count = 0; try { TARGET_SELECTORS.forEach(sel => { root.querySelectorAll(sel).forEach(el => { applyColors(el); count++; }); }); root.querySelectorAll('*').forEach(el => { if (el.shadowRoot) count += walkAndStyle(el.shadowRoot, depth + 1); }); } catch (e) {} return count; } // Initial pass const initialCount = walkAndStyle(document); console.log('[assist-fix] v3 initial pass styled', initialCount, 'elements'); // Watch for document mutations (a dialog opening registers as a subtree mutation // in the hosting shadow root, not body — so we also periodically re-scan) const obs = new MutationObserver(() => walkAndStyle(document)); obs.observe(document.body || document.documentElement, { childList: true, subtree: true, }); // Periodic rescan every 500ms for the first 2 minutes (catches dialogs // that attach textfields lazily in their own shadow roots) let passes = 0; const iv = setInterval(() => { const n = walkAndStyle(document); if (++passes > 240) clearInterval(iv); if (n > initialCount && passes % 4 === 0) { console.log('[assist-fix] v3 total styled now', n); } }, 500); // Also listen for show-dialog events that HA fires — do an immediate sweep window.addEventListener('show-dialog', () => { setTimeout(() => { const n = walkAndStyle(document); console.log('[assist-fix] v3 post-dialog styled', n); }, 100); }); console.log('[assist-fix] v3 loaded, observing for dialogs'); })();