1<!DOCTYPE html>
2<html lang="en">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Body text viewport edge — Should Flag vs Should Pass</title>
7 <style>
8 /* Fixture for the body-text-viewport-edge rule. The rule fires
9 when a <p> or <li> with substantial text content has rect.left
10 within 16px of the viewport edge (or rect.right within 16px
11 of viewport.width) AND the element has no own background-color
12 AND is not inside <nav>/<header> AND is in normal flow. */
13 body { font: 14px/1.5 system-ui, sans-serif; margin: 0; color: #111; background: #fff; }
14 .grid { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; padding: 24px; max-width: 1400px; margin: 0 auto; }
15 .col h2 { font: 600 14px/1 system-ui; text-transform: uppercase; letter-spacing: 0.05em; margin: 0 0 16px; color: #475569; }
16 .case-label { display: block; font-size: 12px; color: #64748b; margin: 16px 0 4px; font-style: italic; }
17 .container-good { max-width: 720px; margin: 0 auto; padding: 16px 32px; }
18 .container-tight { padding: 16px 32px; }
19 .full-bleed-section { background: #fef3c7; padding: 24px 16px; }
20 nav.site-nav { padding: 12px 24px; background: #f5f5f5; }
21 header.banner { padding: 12px 24px; background: #e5e7eb; }
22
23 /* Override the grid container's own padding so we can demonstrate
24 a paragraph that genuinely bleeds to the viewport edge inside
25 the flag column — the col itself shouldn't reset its padding. */
26 .flag-fullwidth-p { /* no container; placed directly in body via .escape */ }
27 .escape { position: relative; left: 50%; right: 50%; margin-left: -50vw; margin-right: -50vw; width: 100vw; padding: 0; }
28 .edge-list { margin: 0; padding: 0; list-style-position: inside; }
29 .edge-list li { margin: 0; }
30 </style>
31</head>
32<body>
33
34 <!-- ════════════════════════════════════════════════════════════
35 FLAG CASES — body text bleeds to viewport edge.
36 These paragraphs are placed OUTSIDE the .grid container so
37 their bounding rect actually touches the viewport edges.
38 ═══════════════════════════════════════════════════════════ -->
39 <div class="escape">
40 <p>Lucia opened this place in 1978. She cooked every night for fifty years, making the same dishes: spaghetti carbonara, eggplant parmigiana, veal saltimbocca, fresh lasagna. She did not change a single recipe in all that time. Her grandson Anthony runs the kitchen now, using the same recipes with the same care.</p>
41 </div>
42 <div class="escape">
43 <p>This second flush-to-edge paragraph confirms the rule fires on every body paragraph that touches the viewport, not just one. The rendered width should be the full viewport, with text starting essentially at x=0.</p>
44 </div>
45 <div class="escape">
46 <ul class="edge-list">
47 <li>This is a list item whose text content is substantially long enough to qualify as body content. It also runs flush against the viewport edge with no left padding.</li>
48 </ul>
49 </div>
50
51 <!-- ════════════════════════════════════════════════════════════
52 PASS CASES — body text with adequate container padding.
53 ═══════════════════════════════════════════════════════════ -->
54 <div class="grid">
55 <div class="col" data-col="pass">
56 <h2>Should pass</h2>
57
58 <span class="case-label">paragraph in centered container with 32px padding</span>
59 <div class="container-good">
60 <p>This paragraph sits inside a max-width container that's centered and has 32px horizontal padding. It does not touch the viewport edges and should not trigger the rule.</p>
61 </div>
62
63 <span class="case-label">paragraph inside <nav> (excluded — nav can bleed)</span>
64 <nav class="site-nav">
65 <p>This nav legitimately bleeds to the edges as a full-width header strip; the rule excludes elements inside <nav> or <header> so this does not flag.</p>
66 </nav>
67
68 <span class="case-label">paragraph inside <header> (excluded — header can bleed)</span>
69 <header class="banner">
70 <p>Banner headers commonly bleed to viewport edges with their own internal layout. The rule excludes <header> descendants.</p>
71 </header>
72
73 <span class="case-label">paragraph inside full-bleed section with own background</span>
74 <section class="full-bleed-section">
75 <p>This paragraph sits in a full-bleed section that has its own background-color set (intentional design move). The rule excludes paragraphs whose element has its own background-color.</p>
76 </section>
77
78 <span class="case-label">short label / button-ish text (excluded — < 40 chars)</span>
79 <p class="container-tight">Short label.</p>
80 </div>
81
82 <div class="col" data-col="flag-notes">
83 <h2>Notes</h2>
84 <p>The flag cases above (rendered outside this grid) demonstrate the failure. The pass cases here show acceptable patterns. The rule gates aggressively to avoid false positives: it only flags <p> and <li> with >40 chars whose width spans more than 50% of the viewport AND whose rect.left or rect.right is within 16px of a viewport edge AND which are not inside nav/header AND which have no own background-color AND which are in normal flow (not position:fixed/absolute).</p>
85 </div>
86 </div>
87
88 <script src="/js/detect-antipatterns-browser.js"></script>
89</body>
90</html>