Repository navigation
Description
Context: I've been using HyperFrames every day for the past two weeks to make Korean Shorts and long-form videos, and it's been great to work with. This is one of a batch of things I ran into along the way (most came as small PRs from me today) — sorry for the pile-up, and thanks for your patience.
What happens
A source label sits under an opaque cover, a full-width card or a video placed over it:
<div id="label" style="position:absolute;left:60px;top:300px;font:40px sans-serif;color:#ccc">Source: Example Agency</div>
<div id="cover" style="position:absolute;left:0;top:200px;width:1080px;height:800px;background:#c8c4bc;z-index:2"></div>hyperframes check --no-cache --json (main affa03b6, CLI 0.9.43):
layout text_occluded error #label Text is hidden beneath an opaque element.
contrast contrast_aa_failure error #label Contrast is 1.08:1; WCAG AA requires 3:1. fg rgb(204,204,204) bg rgb(200,196,188)
One hidden element produces two errors. The second is not a measurement of anything a viewer sees: bg rgb(200,196,188) is the cover. The contrast audit hides the label's glyphs and samples the pixels inside the label's box, and the cover is what sits there. Its suggested fix ("Try rgb(…)") would recolour text nobody can see.
Current behaviour is partly intentional
#2366 made contrast skip fully covered text, but only under data-layout-allow-occlusion. Its description calls the covered-text ratios "meaningless low ratios". The probe comment in contrast-audit.browser.js (isClippedAway) says the probe runs "only when a clip-path is in effect … so genuinely-occluded but unclipped text is not skipped". So keeping unflagged occluded text in the contrast audit looks deliberate. That is why this is an issue, not a PR.
Proposal
When the layout audit reports text_occluded for an element at a sample time, leave that element out of the contrast audit at the same time. The occlusion error already names the problem, and the contrast number for that sample is measured against the occluder. Text that is only partly covered and still reported text_occluded (atomic labels flag at any hit) would also be left out for that sample, because its sample box mixes the occluder in.
Implementation sketch: collectSampleAt (packages/cli/src/utils/checkPipeline.ts) already has the layout issues for the time (issuesAtTime) before collectContrastAt. Hand the text_occluded selectors to collectContrast and drop those candidates in prepareContrast's page evaluate, by element identity (document.querySelector(selector) === restore.el). The two audits format selectors differently, so matching selector strings in Node would miss elements without ids.
Repro (index.html above) and main output are kept.
Activity