Files
pbakaus_impeccable/tests/fixtures/antipatterns/text-occlusion.html
T
Paul BakausandClaude Fable 5 ed7a6fbe4e detector: text-occlusion + first-viewport-column-overflow (57 -> 59)
Two browser-engine quality rules, both warning severity.

text-occlusion / element-overlap fires on three shapes: an opaque
decorated box painted over a text element (elementFromPoint confirms
real coverage, box >= 30%), one text run buried under another when at
least one side is a positioned layer (text >= 45%, so line-box leading
bleed between stacked flow blocks does not count), and an inline element
whose opaque fill leaks past its line onto a neighbour (the class-name
collision bug). A large headline whose edge overhangs a bounded content
card is caught as an element collision even when the text stays on top.
Gradient scrims, decorative SVG emblems, fixed/sticky overlays, floats,
and raw image backdrops (contrast territory, deduped against the pixel
low-contrast rule) are exempt.

first-viewport-column-overflow fires when a multi-column opening section
runs one column past 140% of the viewport while a sibling fits inside
one screen, the stretched-hero signature. Single-column pages and
full-page heroes with no fitting sibling are exempt.

Validated: fires on the diagnosed repros, clean across a 60-sample
sweep. Fixtures + browser tests added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 14:53:03 -07:00

82 lines
3.7 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>text-occlusion fixture</title>
<style>
* { margin: 0; box-sizing: border-box; }
body { font-family: system-ui, sans-serif; color: #111; background: #fff; }
section { padding: 40px; position: relative; }
/* ── FLAG 1: opaque box painted over text (>30%) ── */
.flag-box-wrap { position: relative; height: 120px; }
.flag-box-text { position: absolute; top: 40px; left: 40px; font-size: 20px; width: 300px; }
.flag-box-cover { position: absolute; top: 30px; left: 30px; width: 240px; height: 60px;
background: #1f7a3d; border-radius: 8px; z-index: 5; }
/* ── FLAG 2: inline element with opaque fill + leaked vertical padding ── */
.flag-leak-host { position: relative; margin-top: 30px; }
.flag-leak { display: inline; background: #2f8543; padding: 36px; border-radius: 6px; }
.flag-leak-card { background: #14202b; color: #fff; padding: 24px; border-radius: 6px; }
/* ── FLAG 3: big headline overhanging an opaque card ── */
.flag-hero { position: relative; height: 220px; }
.flag-headline { position: absolute; top: 40px; left: 0; font-size: 64px; font-weight: 800;
width: 760px; color: #b22; white-space: nowrap; }
.flag-card { position: absolute; top: 20px; left: 700px; width: 360px; height: 180px;
background: #f4f5f7; border: 1px solid #ddd; box-shadow: 0 2px 8px rgba(0,0,0,.08); border-radius: 8px; }
/* ── PASS: stacked headline with tight leading (line-box bleed, no real overlap) ── */
.pass-stack { margin-top: 40px; }
.pass-eyebrow { font-size: 14px; letter-spacing: .1em; text-transform: uppercase; color: #a33; }
.pass-title { font-size: 96px; line-height: .9; font-weight: 800; }
/* ── PASS: text over image with a scrim, text on top (readable) ── */
.pass-hero { position: relative; height: 200px; overflow: hidden; border-radius: 8px; }
.pass-hero img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.pass-hero .scrim { position: absolute; inset: 0; background: linear-gradient(transparent, rgba(0,0,0,.6)); }
.pass-hero .cap { position: absolute; bottom: 16px; left: 16px; color: #fff; font-size: 24px; z-index: 2; }
/* ── PASS: fixed status bar over content at the fold ── */
.pass-under { margin-top: 20px; font-size: 16px; }
.pass-fixedbar { position: fixed; left: 0; right: 0; bottom: 0; height: 40px; background: #b22;
color: #fff; display: flex; align-items: center; padding: 0 16px; }
</style>
</head>
<body>
<section>
<div class="flag-box-wrap">
<p class="flag-box-text">Root cause identified in four minutes</p>
<div class="flag-box-cover" aria-hidden="true"></div>
</div>
<div class="flag-leak-host">
<span class="flag-leak" aria-hidden="true"></span>
<div class="flag-leak-card">Incident closed. Missing index on the replica, found from one alert.</div>
</div>
<div class="flag-hero">
<div class="flag-headline">The trace you need is the one they sampled away.</div>
<div class="flag-card">
<p>INCIDENT 4417</p>
<p>service checkout-api</p>
</div>
</div>
<div class="pass-stack">
<p class="pass-eyebrow">Family Italian on the waterfront</p>
<h1 class="pass-title">Trattoria da Nonna Lucia</h1>
</div>
<div class="pass-hero">
<img src="data:image/gif;base64,R0lGODlhAQABAIABAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAICTAEAOw==" alt="">
<div class="scrim"></div>
<div class="cap">Villa on the cliff</div>
</div>
<p class="pass-under">Every span of every trace, kept on disk, no sampling ever applied here.</p>
</section>
<div class="pass-fixedbar">8/8 services up &middot; p99 1.20s &middot; retention infinite</div>
</body>
</html>