Skip to content

[Bug] detect: analytic-gradient+alpha contrast composites over black, reporting 17.6:1 text as 1.2:1 #881

Description

@lisandrovico

Scanning a light page whose background is a radial-gradient/linear-gradient fading to transparent makes low-contrast report near-black text as almost invisible. The reported ratios match, to two decimals, the ratio against black — so the analytic-gradient+alpha path appears to composite the transparent portion of the gradient over black rather than over the underlying page background.

Evidence

Two findings from one real page, and the arithmetic behind them:

Text colour Reported by detect Ratio vs black True ratio (on the actual white/lavender ground)
#18191c (an h1) 1.2:1 1.19:1 17.58:1 on white, 14.45:1 at the gradient’s darkest stop
#67696f (body copy) 3.8:1 3.83:1 5.49:1 on white

The match against black is exact. Every finding in the cluster carries via analytic-gradient+alpha, and they collapse onto three repeated ratios (1.2 / 3.5 / 3.8) regardless of which element is sampled.

Repro

A page with color: #18191c text over a background such as:

background:
  radial-gradient(ellipse at 75% 42%, #e9e7f9b8 0, transparent 58%),
  linear-gradient(to bottom, #f2f0fa, transparent 75%),
  #fff;
impeccable detect http://localhost:3020/pricing
[low-contrast] browser contrast 1.2:1 median 1.2:1 (need 3:1) via analytic-gradient+alpha "Start small."
[low-contrast] browser contrast 3.8:1 median 3.8:1 (need 4.5:1) via analytic-gradient+alpha "1 GB = 1,000 MB."

The gradient stops fade to transparent, and the opaque #fff layer underneath them is what the eye actually sees.

Impact

On one 7-page site this produced 44 false positives, all on the darkest text present. Because they are reported as the most severe contrast failures on the page, they crowd out real ones — in the same run the detector missed genuine sub-AA text (#a3a3a3 at 12px = 2.52:1, 11 instances) that a manual sweep found.

Expected

Composite each gradient layer over the resolved background stack beneath it (ultimately the opaque page background) before computing luminance, rather than over a black or zeroed base.

Environment

  • skill 4.3.1, engine 0.1.5 (darwin-arm64), Chrome 153, macOS 15.6 (Darwin 25.6.0)
  • Target: static Astro output served over http://localhost, light-only, no dark token set

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

needs triageNew or reopened issue awaiting maintainer triage

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions