diff --git a/.agents/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.agents/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.agents/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.agents/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.agents/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.agents/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.agents/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.agents/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.agents/skills/impeccable/scripts/detector/rules/checks.mjs b/.agents/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.agents/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.agents/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.claude/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.claude/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.claude/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.claude/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.claude/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.claude/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.claude/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.claude/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.claude/skills/impeccable/scripts/detector/rules/checks.mjs b/.claude/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.claude/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.claude/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.cursor/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.cursor/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.cursor/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.cursor/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.cursor/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.cursor/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.cursor/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.cursor/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.cursor/skills/impeccable/scripts/detector/rules/checks.mjs b/.cursor/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.cursor/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.cursor/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.gemini/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.gemini/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.gemini/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.gemini/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.gemini/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.gemini/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.gemini/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.gemini/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.gemini/skills/impeccable/scripts/detector/rules/checks.mjs b/.gemini/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.gemini/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.gemini/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.github/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.github/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.github/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.github/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.github/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.github/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.github/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.github/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.github/skills/impeccable/scripts/detector/rules/checks.mjs b/.github/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.github/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.github/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.grok/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.grok/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.grok/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.grok/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.grok/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.grok/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.grok/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.grok/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.grok/skills/impeccable/scripts/detector/rules/checks.mjs b/.grok/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.grok/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.grok/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.hermes/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.hermes/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.hermes/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.hermes/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.hermes/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.hermes/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.hermes/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.hermes/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.hermes/skills/impeccable/scripts/detector/rules/checks.mjs b/.hermes/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.hermes/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.hermes/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.kiro/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.kiro/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.kiro/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.kiro/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.kiro/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.kiro/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.kiro/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.kiro/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.kiro/skills/impeccable/scripts/detector/rules/checks.mjs b/.kiro/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.kiro/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.kiro/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.opencode/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.opencode/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.opencode/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.opencode/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.opencode/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.opencode/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.opencode/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.opencode/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.opencode/skills/impeccable/scripts/detector/rules/checks.mjs b/.opencode/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.opencode/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.opencode/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.pi/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.pi/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.pi/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.pi/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.pi/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.pi/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.pi/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.pi/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.pi/skills/impeccable/scripts/detector/rules/checks.mjs b/.pi/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.pi/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.pi/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.qoder/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.qoder/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.qoder/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.qoder/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.qoder/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.qoder/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.qoder/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.qoder/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.qoder/skills/impeccable/scripts/detector/rules/checks.mjs b/.qoder/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.qoder/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.qoder/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.rovodev/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.rovodev/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.rovodev/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.rovodev/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.rovodev/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.rovodev/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.rovodev/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.rovodev/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.rovodev/skills/impeccable/scripts/detector/rules/checks.mjs b/.rovodev/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.rovodev/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.rovodev/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.trae-cn/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.trae-cn/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.trae-cn/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.trae-cn/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.trae-cn/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.trae-cn/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.trae-cn/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.trae-cn/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.trae-cn/skills/impeccable/scripts/detector/rules/checks.mjs b/.trae-cn/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.trae-cn/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.trae-cn/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.trae/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.trae/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.trae/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.trae/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.trae/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.trae/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.trae/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.trae/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.trae/skills/impeccable/scripts/detector/rules/checks.mjs b/.trae/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.trae/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.trae/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/.vibe/skills/impeccable/scripts/detector/browser/injected/index.mjs b/.vibe/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/.vibe/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/.vibe/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.vibe/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/.vibe/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/.vibe/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/.vibe/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/.vibe/skills/impeccable/scripts/detector/rules/checks.mjs b/.vibe/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/.vibe/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/.vibe/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); diff --git a/plugin/skills/impeccable/scripts/detector/browser/injected/index.mjs b/plugin/skills/impeccable/scripts/detector/browser/injected/index.mjs index 4cf648906..6eb971450 100644 --- a/plugin/skills/impeccable/scripts/detector/browser/injected/index.mjs +++ b/plugin/skills/impeccable/scripts/detector/browser/injected/index.mjs @@ -626,7 +626,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -688,7 +688,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -985,7 +985,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -1115,7 +1115,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/plugin/skills/impeccable/scripts/detector/detect-antipatterns-browser.js b/plugin/skills/impeccable/scripts/detector/detect-antipatterns-browser.js index 8d70e1987..8893bb323 100644 --- a/plugin/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +++ b/plugin/skills/impeccable/scripts/detector/detect-antipatterns-browser.js @@ -3990,7 +3990,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310); @@ -7285,7 +7285,7 @@ if (IS_BROWSER) { if (currentStyle.filter && currentStyle.filter !== 'none') reasons.add('filter'); if (currentStyle.backdropFilter && currentStyle.backdropFilter !== 'none') reasons.add('backdrop filter'); - const solidBg = parseRgb(currentStyle.backgroundColor); + const solidBg = parseRgb(currentStyle.backgroundColor) || parseAnyColor(currentStyle.backgroundColor); if (solidBg && solidBg.a >= 0.95 && (!bgImage || bgImage === 'none')) break; current = current.parentElement; } @@ -7347,7 +7347,7 @@ if (IS_BROWSER) { // starve the url()-backed texts this mode exists to sample. if (options.imageOnly && !reasons.includes('image background')) continue; - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); const fontSize = parseFloat(style.fontSize) || 16; const fontWeight = parseInt(style.fontWeight) || 400; const isLargeText = fontSize >= WCAG_LARGE_TEXT_PX || (fontSize >= WCAG_LARGE_BOLD_TEXT_PX && fontWeight >= 700); @@ -7644,7 +7644,7 @@ if (IS_BROWSER) { return sample; } } - const bg = parseRgb(style.backgroundColor); + const bg = parseRgb(style.backgroundColor) || parseAnyColor(style.backgroundColor); if (bg && bg.a > 0.05) return { status: 'sampled', color: bg, method: 'solid-background' }; return { status: 'unresolved', reason: 'no readable background' }; } @@ -7774,7 +7774,7 @@ if (IS_BROWSER) { } const style = getComputedStyle(el); - const textColor = parseRgb(style.color) || candidate.textColor; + const textColor = parseRgb(style.color) || parseAnyColor(style.color) || candidate.textColor; if (!textColor) return { ...candidate, status: 'unresolved', confidence: 'none', reason: 'unreadable text color' }; const rect = getDirectTextRect(el) || el.getBoundingClientRect(); diff --git a/plugin/skills/impeccable/scripts/detector/rules/checks.mjs b/plugin/skills/impeccable/scripts/detector/rules/checks.mjs index 031501513..ee65af7af 100644 --- a/plugin/skills/impeccable/scripts/detector/rules/checks.mjs +++ b/plugin/skills/impeccable/scripts/detector/rules/checks.mjs @@ -2748,7 +2748,7 @@ function checkElementAIPaletteDOM(el) { } // Check for neon text (vivid cyan/purple color on dark background) - const textColor = parseRgb(style.color); + const textColor = parseRgb(style.color) || parseAnyColor(style.color); if (textColor && hasChroma(textColor, 80)) { const hue = getHue(textColor); const isAIPalette = (hue >= 160 && hue <= 200) || (hue >= 260 && hue <= 310);