← back to Thesetdecorator
TSD a11y: fix WCAG 1.3.1 heading-order skips (DTD verdict A) — sr-only h2 before card-grids on 5 pages
9f62c217a59eb3cf70d05c756c3c51d883b85fac · 2026-06-03 09:07:48 -0700 · Steve
Files touched
M public/fancy-search.htmlM public/games.htmlM public/resources.htmlM public/submit.htmlM public/unions.htmlA scripts/heading-order-fix.py
Diff
commit 9f62c217a59eb3cf70d05c756c3c51d883b85fac
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Jun 3 09:07:48 2026 -0700
TSD a11y: fix WCAG 1.3.1 heading-order skips (DTD verdict A) — sr-only h2 before card-grids on 5 pages
---
public/fancy-search.html | 1 +
public/games.html | 1 +
public/resources.html | 1 +
public/submit.html | 1 +
public/unions.html | 1 +
scripts/heading-order-fix.py | 52 ++++++++++++++++++++++++++++++++++++++++++++
6 files changed, 57 insertions(+)
diff --git a/public/fancy-search.html b/public/fancy-search.html
index 9b7ad00..936678e 100644
--- a/public/fancy-search.html
+++ b/public/fancy-search.html
@@ -127,6 +127,7 @@
<section>
<div class="fs-meta" id="meta">Loading…</div>
+ <h2 class="sr-only">Search results</h2>
<div class="fs-results" id="results"></div>
</section>
</div>
diff --git a/public/games.html b/public/games.html
index 9c0d5e5..94d3da9 100644
--- a/public/games.html
+++ b/public/games.html
@@ -27,6 +27,7 @@
<h1>Play with the props.</h1>
<p class="tagline">Party games for film-set-decoration nerds. Solo or invite friends. <a href="/games/wwhl-brand-sheet.html">View the brand sheet ↗</a></p>
+ <h2 class="sr-only">Games</h2>
<div class="game-grid">
<a class="game-card" href="/games/know-your-set-dec.html" data-tilt="0">
<div class="emoji">🎬</div>
diff --git a/public/resources.html b/public/resources.html
index 6ce9b8e..6cde744 100644
--- a/public/resources.html
+++ b/public/resources.html
@@ -92,6 +92,7 @@
</div>
<p class="muted" id="meta" style="font-size:0.85rem;margin:0 0 0.6rem">Loading…</p>
+ <h2 class="sr-only">Resources</h2>
<div class="res-grid" id="grid" data-density-target></div>
</section>
</main>
diff --git a/public/submit.html b/public/submit.html
index f597a76..3ce26c6 100644
--- a/public/submit.html
+++ b/public/submit.html
@@ -72,6 +72,7 @@
<h1>Sell your photography to film + TV</h1>
<p class="lede">Share a Google Drive folder. We crawl it nightly, auto-filter people out, write set-decorator-targeted titles, list your photos for license. <strong>You keep 70%</strong>. No exclusivity. Pull any photo any time.</p>
+ <h2 class="sr-only">How it works</h2>
<div class="steps">
<div class="step"><span class="num">1</span><h3>Share a folder</h3><p>Right-click a folder in Drive → <strong>Share</strong> → enter <code id="submissions-email">submissions@thesetdecorator.com</code> → set permission to <strong>Viewer</strong>.</p></div>
<div class="step"><span class="num">2</span><h3>Tell us where</h3><p>Paste the folder URL in the form below + sign the photographer warranty (1 page, plain English).</p></div>
diff --git a/public/unions.html b/public/unions.html
index 286a27b..a4b2bf0 100644
--- a/public/unions.html
+++ b/public/unions.html
@@ -59,6 +59,7 @@
<button class="city-tab" data-filter="CA">Canada</button>
</div>
+ <h2 class="sr-only">Unions directory</h2>
<div id="union-list"></div>
</section>
</main>
diff --git a/scripts/heading-order-fix.py b/scripts/heading-order-fix.py
new file mode 100644
index 0000000..b6d43ba
--- /dev/null
+++ b/scripts/heading-order-fix.py
@@ -0,0 +1,52 @@
+#!/usr/bin/env python3
+"""Idempotent WCAG 1.3.1 heading-order fix for TSD (DTD verdict A).
+
+8 pages skipped h1->h3. Fix: insert a visually-hidden <h2 class="sr-only">
+section heading immediately before each card-grid / step container, so the
+existing repeating <h3>s become correctly-nested h1->h2->h3 descendants in the
+document outline. Zero visible change (.sr-only already exists in main.css);
+no JS-template edits. Complex/admin pages (stories, union-talk, logo-variants)
+deliberately left alone per the DTD verdict.
+
+Idempotent: skips a page that already has the sr-only h2 on the line above the
+anchor. Reversible: single <h2> line inserted per page.
+ python3 scripts/heading-order-fix.py
+"""
+import os, glob
+
+PUB = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "public")
+
+# filename -> (anchor substring that identifies the grid/container line, sr-only heading text)
+TARGETS = {
+ "games.html": ('<div class="game-grid">', "Games"),
+ "fancy-search.html": ('<div class="fs-results" id="results">', "Search results"),
+ "resources.html": ('<div class="res-grid" id="grid"', "Resources"),
+ "unions.html": ('<div id="union-list">', "Unions directory"),
+ "submit.html": ('<div class="steps">', "How it works"),
+}
+
+changed, skipped, missing = [], [], []
+for name, (anchor, heading) in TARGETS.items():
+ path = os.path.join(PUB, name)
+ if not os.path.exists(path):
+ missing.append(name); continue
+ lines = open(path, encoding="utf-8").read().splitlines(keepends=True)
+ marker = f'<h2 class="sr-only">{heading}</h2>'
+ if any(marker in ln for ln in lines):
+ skipped.append(name); continue
+ out, done = [], False
+ for ln in lines:
+ if not done and anchor in ln:
+ indent = ln[:len(ln) - len(ln.lstrip())]
+ out.append(f'{indent}{marker}\n')
+ done = True
+ out.append(ln)
+ if not done:
+ missing.append(f"{name} (anchor not found)"); continue
+ open(path, "w", encoding="utf-8").write("".join(out))
+ changed.append(name)
+
+print(f"changed ({len(changed)}): {', '.join(changed) or '-'}")
+print(f"skipped/already ({len(skipped)}): {', '.join(skipped) or '-'}")
+if missing:
+ print(f"MISSING/anchor-fail: {', '.join(missing)}")
← 1b62c7a backlog: mark loop #2 items done (favicon, canonical)
·
back to Thesetdecorator
·
backlog: mark loop #3 done (heading-order) + record audited- 1ec82e5 →