html-semantics-accessibility-review
Review HTML markup and rendered DOM structure for correct native-element usage, valid heading/landmark hierarchy, and WAI-ARIA APG-conformant custom-widget patterns; produce a WCAG 2.2-grounded verdict with APG pattern citations for every custom interactive control, flagging anyt
Install
npx skills add https://github.com/VincentChuWaiChow/vanguard-frontier-agentic/tree/master/skills/frontend/html-semantics-accessibility-review
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install vincentchuwaichow-vanguard-frontier-agentic@llmmart
git clone https://github.com/VincentChuWaiChow/vanguard-frontier-agentic.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole vincentchuwaichow/vanguard-frontier-agentic collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
HTML Semantics & Accessibility Review
Purpose
Automated a11y linters (axe, Lighthouse) catch roughly 30-50% of WCAG issues by design — they cannot verify whether a custom widget's keyboard interaction matches its intended pattern, whether ARIA correctly reflects (or wrongly overrides) native semantics, or whether a heading/landmark outline actually helps a screen-reader user navigate. This skill performs the manual, spec-grounded review that closes that gap: matching every custom interactive element against a specific WAI-ARIA APG pattern, verifying heading/landmark structure, and catching redundant or conflicting ARIA before it ships.
When to use
Use this skill when the user asks to:
- review a pull request or component for HTML semantics or accessibility correctness,
- verify a custom widget (modal, dropdown, tabs, combobox, accordion, etc.) against WAI-ARIA APG patterns,
- audit heading level and landmark structure on a page or component tree,
- check whether ARIA roles/states/properties are correctly applied or redundant/conflicting with native semantics,
- assess WCAG 2.2 conformance risk for markup changes ahead of a compliance audit.
Context7 Documentation Protocol
Element semantics, implicit ARIA-role mappings, and attribute-support tables change as the HTML and ARIA specs evolve — never assert them from memory.
- Call
ToolSearchwith query"context7"(or"select:mcp__Context7__resolve-library-id,mcp__Context7__query-docs") to load the Context7 tools if they are not already loaded in this session. - Call
mcp__Context7__resolve-library-idfor the relevant documentation set — for this skill that is almost always MDN (/mdn/content, or/websites/developer_mozilla_en-usif the former lacks coverage for the query). Resolve the WAI-ARIA APG or WCAG spec source too if the review needs primary-spec wording rather than MDN's paraphrase. - Call
mcp__Context7__query-docsfor the specific element, role, or attribute in question — e.g. "implicit ARIA role for<nav>", "APG combobox keyboard pattern", "tabindex focus-order behavior" — before ruling on it. Do this per review, not once from memory of a prior session. - Prefer the official spec/MDN wording over this skill's own paraphrase when the two could be read to disagree; cite the resolved doc URL in the finding.
- If Context7 is unavailable or returns no relevant match, fall back to the URLs in
official_docs/references/apg-pattern-index.md, and explicitly mark the claimdocumentation-based (Context7 unavailable)rather than presenting it as freshly verified. - Never invent an ARIA role, state, property, or implicit-semantics mapping that no queried source confirms.
Lean operating rules
- First rule of ARIA: no ARIA is better than bad ARIA. Prefer a native element (
<button>,<dialog>,<details>,<nav>) over a JS-reimplemented equivalent with ARIA bolted on, unless the platform genuinely has no equivalent. - Never accept 'axe/Lighthouse passed' as sufficient evidence for a custom interactive widget — manually match it against a specific APG pattern URL, including its full keyboard model (not just Tab/Enter — Escape, Home, End, Arrow keys per the pattern).
- Treat heading-level skips (h1→h3) and missing/duplicate landmarks as blocking findings, not style notes — they break screen-reader page-navigation shortcuts.
- Never approve positive
tabindexvalues; requiretabindex="0"/"-1"plus correct DOM order instead. - Flag
aria-hidden="true"on any ancestor of a focusable/interactive descendant — this creates an unreachable-but-focusable or reachable-but-hidden trap. - Query current MDN/WAI-ARIA APG docs (see Context7 Documentation Protocol) for the specific element/role in question before ruling; element semantics and ARIA support tables change with spec updates — never assert support/behavior from memory.
- Anything requiring live screen-reader verification (actual NVDA/JAWS/VoiceOver behavior) gets flagged as a residual risk, not asserted as verified from static review alone.
- Label every claim as
live evidence,spec-cited,documentation-based, orinferenceso the reviewer knows what's actually been verified vs. reasoned about.
References
Load these only when needed:
- WCAG success-criterion mapping — use when a finding needs to be tied to a specific WCAG 2.2 success criterion for a compliance-audit deliverable.
- APG pattern quick-index — use when identifying which APG pattern matches a given custom widget (modal, combobox, tabs, tree, menu, disclosure, etc.) before doing the deep keyboard-model comparison.
- Heading and landmark structure rules — use when auditing page-level or component-tree-level outline structure, including nested-landmark and multiple-landmark-of-same-type edge cases.
Response minimum
Return, at minimum:
- the element/component in scope and its semantic verdict (native-element compliant / needs ARIA / needs restructure),
- for any custom interactive widget: the specific APG pattern URL cited, or an explicit flag that none matches and a native element should be used instead,
- the heading/landmark outline diff (before/after) when structure changed,
- every ARIA attribute added or removed, with its WAI-ARIA 1.2 role/state justification,
- residual risk notes for anything requiring live assistive-technology verification beyond this static review.
Files (vanguard-frontier-agentic)
-
references
-
apg-pattern-index.md 4.9 KB
# APG Pattern Quick-Index Use this reference when a component under review is a custom (JS-driven) interactive widget and you need to identify which WAI-ARIA Authoring Practices Guide (APG) pattern applies before comparing its actual keyboard/role/state implementation against the canonical model. ## What people get wrong The common bad assumption is: > "I added `role="button"` and a click handler, so it's accessible." Wrong. A role only tells assistive technology what the element *is*; it does nothing for keyboard operability, focus management, or state exposure. Every non-trivial custom widget corresponds to exactly one (sometimes zero) APG pattern, and that pattern defines a full contract: role, required/optional states and properties, and a specific keyboard interaction model — not just "Enter activates it." > Version note: WAI-ARIA and the APG evolve. Confirm the pattern's current keyboard model and required ARIA attributes via Context7 (`/mdn/content`) or the live `https://www.w3.org/WAI/ARIA/apg/patterns/` page before ruling — do not cite this file's summaries as the final word. ## Non-negotiable design rule: match first, judge second Before writing any finding about a custom widget, identify its APG pattern by name. If no pattern fits, that itself is a finding: either the widget should not exist as a custom control (use a native element), or it needs a `role="group"`/`role="region"` treatment with no interactive-widget semantics at all. Never invent ad-hoc ARIA for a shape that doesn't match a documented pattern. ## Common widget → pattern map (starting point, not exhaustive) | Widget seen in markup | Likely APG pattern | Minimum keyboard model to verify | |---|---|---| | Modal / overlay dialog | Dialog (Modal) | Focus moves into dialog on open; `Tab`/`Shift+Tab` trapped inside; `Escape` closes; focus returns to trigger on close | | Non-modal panel toggle | Disclosure (Show/Hide) | `Enter`/`Space` toggles; `aria-expanded` reflects state; no focus trap | | Dropdown menu (app-style, not `<select>`) | Menu / Menu Button | `Enter`/`Space`/`ArrowDown` opens; `ArrowUp`/`ArrowDown` moves; `Escape` closes and returns focus; `Home`/`End` jump to first/last | | Custom text input with suggestions | Combobox | `ArrowDown` opens/moves listbox; `Escape` closes without selecting; `Enter` selects active option; `aria-activedescendant` or roving `tabindex` tracks active option | | Tab strip | Tabs | Arrow keys move between tabs (auto- or manual-activation, pick one and document which); `Tab` key exits to panel; only active tab is in the sequential tab order | | Accordion | Accordion (built from Disclosure) | Each header toggles its own panel independently; heading semantics preserved (see heading-landmark-rules.md) | | Tree view (file explorer style) | Tree View | `ArrowUp`/`ArrowDown` moves; `ArrowRight`/`ArrowLeft` expands/collapses or moves to child/parent; `*` expands all siblings (optional) | | Custom slider | Slider | `ArrowLeft`/`ArrowRight` (or `Up`/`Down`) adjusts by step; `Home`/`End` jump to min/max; `aria-valuenow`/`aria-valuemin`/`aria-valuemax` kept in sync | | Toast / live status message | Alert or Status (live region, not a focusable widget) | No keyboard model — it must not steal focus; verify `role="alert"` (assertive, interrupting) vs `role="status"` (polite) is the deliberate choice, not a default | ## Verification targets For each matched pattern, confirm in the markup/code: - the root and child elements carry the pattern's required roles (native-implicit or explicit `role=`), - every required `aria-*` state/property from the pattern is present and kept in sync with actual UI state (not just set once at mount), - the full keyboard model is implemented, not a subset — a widget with only mouse/click handlers and no `keydown` logic fails regardless of correct roles, - focus is visible (no `outline: none` without a replacement focus style) and moves predictably on open/close/select. ## High-risk assumptions to kill - "It has the right `role`, so it's done" — role without keyboard model and state sync is theater. - "Semantic-sounding class name (`.dropdown-menu`) means it follows the Menu pattern" — check the actual DOM/role/keydown handlers, not the class name. - "We tested with the mouse and it felt fine" — APG conformance is a keyboard-first and AT-first contract; mouse-only QA proves nothing about it. - "It matched a pattern last time we reviewed it" — widgets drift as code changes; re-verify against the current implementation every review, not from memory of a prior review. ## When to push back Push back if the user asks to: - add ARIA roles/states to make a widget "look accessible" without implementing the pattern's keyboard model, - ship a custom widget where a native element (`<select>`, `<details>`, `<dialog>`) would satisfy the requirement with less code and less risk, - treat "no pattern fits perfectly" as license to skip APG entirely rather than picking the closest pattern or reconsidering the widget design. -
heading-landmark-rules.md 4.7 KB
# Heading and Landmark Structure Rules Use this reference when auditing the document outline of a page or component tree — heading hierarchy, landmark regions, and how components compose into a whole page's navigation structure. ## What people get wrong The common bad assumption is: > "Headings are for visual size; I'll pick whichever `<h*>` looks right at this font size, and CSS will fix the rest." Wrong. Screen-reader users navigate primarily by heading level and landmark region — jumping "next heading," "next level-2 heading," or "next landmark" without reading surrounding text. A heading chosen for visual weight instead of document structure breaks that navigation model even when the page looks fine visually. ## Non-negotiable design rules ### 1. Heading levels must not skip `<h1>` → `<h3>` with no `<h2>` between them is a structural break, not a style inconsistency. It reads to a screen-reader user as "I jumped past something — did I miss content?" Every component that renders a heading must accept its heading level as a prop/parameter from its parent context rather than hardcoding a level, so composed pages stay contiguous. ### 2. Exactly one `<h1>` per page (not per component) A component library that hardcodes `<h1>` internally breaks the instant it's composed twice on one page, or nested inside a page that already has its own `<h1>`. Components should default to accepting a level and render the semantically-correct `<h1>`–`<h6>` element for that level (not just visually restyle a `<div>`). ### 3. Landmarks must be unique-per-page or explicitly labeled A page may have only one unlabeled `<main>`, one unlabeled `<banner>` (`<header>` at the top level, not nested in `<article>`/`<section>`), and one unlabeled `<contentinfo>` (`<footer>` at the top level). Multiple instances of the same landmark type (e.g., two `<nav>` regions — primary nav and breadcrumb nav) MUST each carry a distinct accessible name via `aria-label` or `aria-labelledby`, or AT users hear "navigation, navigation" with no way to distinguish them. ### 4. Prefer semantic elements over `role=` on `<div>` `<nav>`, `<main>`, `<header>`, `<footer>`, `<aside>`, `<section>` (with an accessible name) carry implicit landmark roles. Adding `role="navigation"` to a `<div>` works but is strictly worse than using `<nav>` — it adds a maintenance burden (the role can drift out of sync with a renamed/refactored element) for no benefit. Flag `role=` landmark attributes on generic elements as a downgrade unless there's a documented reason (e.g., legacy browser support matrix) — see MDN ARIA landmark-role guidance via the Context7 Documentation Protocol in SKILL.md for the "semantic HTML first" rule. ### 5. `<section>` and `<aside>` need an accessible name to count as landmarks A bare `<section>` with no `aria-label`/`aria-labelledby`/heading-derived name does not expose as a landmark to most assistive technology — it is a generic grouping only. Do not report "landmark added" unless the accessible-name requirement is also met. ## Minimal safe audit flow 1. Extract the full heading tree (level + text) for the page or component in isolation. 2. Extract the full landmark tree (type + accessible name, or "unlabeled" if none). 3. Diff both trees against the pre-change version when reviewing a delta; against W3C rules from scratch when reviewing a new page. 4. Flag: any level skip, any second unlabeled instance of a unique-landmark type, any component that hardcodes a heading level instead of accepting one from its parent. 5. For component-tree-only reviews (no full-page context available), state explicitly that heading-level correctness cannot be fully verified without knowing the mount context, and flag it as a residual risk rather than asserting compliance. ## Verification targets - Render (or read) the full page and extract the accessibility tree / heading outline via a real DOM inspection when live evidence is available; note this as `live evidence`. - When only source is available (no live render), derive the outline from JSX/template structure and label the finding `inference` — a dynamically-computed heading level (e.g., `level={depth + 1}`) cannot be fully verified statically without knowing all call sites. ## When to push back Push back if the user says: - "just use `<div class="h2">`, we'll style it to look right" — that produces zero navigable structure for AT users regardless of visual styling, - "we don't need `aria-label` on the second nav, screen-reader users will figure it out from context" — they cannot; landmark lists present regions out of visual context, - "heading levels don't matter as long as visually it looks like a hierarchy" — visual hierarchy and semantic hierarchy are independent axes; both must be correct. -
wcag-criterion-mapping.md 4.5 KB
# WCAG 2.2 Success-Criterion Mapping Use this reference when a finding from this skill needs to be tied to a specific WCAG 2.2 success criterion (SC) for a compliance-audit deliverable — e.g. when the output feeds an ADA / Section 508 / EN 301 549 conformance report and "looks wrong" is not an acceptable citation. ## Grounding rule This file gives a starting map from common findings to likely SC numbers so review output cites *something* concrete instead of vague prose. It does not replace reading the actual SC "Understanding" doc for edge cases — verify exact wording and Level (A/AA/AAA) against `https://www.w3.org/TR/WCAG22/` or via the Context7 Documentation Protocol before finalizing a compliance-facing citation, since SC numbering and scope can be easy to misremember (e.g., confusing 4.1.2 Name/Role/Value with 1.3.1 Info and Relationships). ## Finding → likely success criterion | Finding category | Likely SC (Level) | Why | |---|---|---| | Heading level skip / missing heading structure | 1.3.1 Info and Relationships (A) | Structure conveyed visually must also be conveyed programmatically | | Duplicate unlabeled landmark of the same type | 1.3.1 Info and Relationships (A), 2.4.1 Bypass Blocks (A) | Landmarks are the mechanism for bypassing repeated content; ambiguous landmarks break that mechanism | | Custom widget missing/incorrect role | 4.1.2 Name, Role, Value (A) | AT must be able to programmatically determine the role of every UI component | | Custom widget state (`aria-expanded`, `aria-checked`, etc.) not kept in sync with actual UI state | 4.1.2 Name, Role, Value (A) | Same SC — "Value" includes states that change | | Custom widget missing full keyboard operability (e.g. no `Escape`, no arrow-key navigation per its APG pattern) | 2.1.1 Keyboard (A) | All functionality must be operable through a keyboard interface | | Positive `tabindex` values / illogical focus order | 2.4.3 Focus Order (A) | Focus order must preserve meaning and operability | | `outline: none` / removed focus indicator with no replacement | 2.4.7 Focus Visible (AA) | Keyboard focus indicator must be visible | | `aria-hidden="true"` trapping a focusable descendant | 4.1.2 Name, Role, Value (A), 2.1.1 Keyboard (A) | Element is reachable by keyboard but hidden from AT (or vice versa) — a dual failure | | Toast/alert stealing focus or interrupting unexpectedly | 4.1.3 Status Messages (AA) | Status messages must be programmatically determinable without receiving focus | | Native element replaced with unlabeled `<div>`/`<span>` + click handler (fake button/link) | 4.1.2 Name, Role, Value (A), 2.1.1 Keyboard (A) | No role exposed, no keyboard access by default | | Missing/incorrect accessible name on interactive control (icon-only button, ambiguous link text) | 4.1.2 Name, Role, Value (A), 2.4.4 Link Purpose (In Context) (A) | Control lacks a determinable/discriminable accessible name | ## Non-negotiable rule for compliance-facing output Never present an SC citation as authoritative without the Level (A/AA/AAA) attached — an auditor reading "1.3.1" without a level cannot assess conformance-target scope (most orgs target AA). If uncertain of the exact SC number for a novel finding, say so explicitly (`inference — needs SC verification`) rather than guessing a plausible-sounding number; a wrong citation in a compliance deliverable is worse than an honest gap. ## Verification targets - Cross-check any SC number cited in this table against the live WCAG 2.2 "Understanding" page for that SC before it goes into a compliance-audit-facing deliverable (not required for a routine PR review comment, where this table's mapping is sufficient). - For AAA-level findings, flag explicitly that AAA is rarely a required conformance target — do not imply a blocking failure at AAA carries the same severity as an A/AA failure unless the user has stated AAA is their target. ## When to push back Push back if the user asks to: - label every accessibility finding as a single generic "WCAG violation" for a compliance deliverable without SC-level granularity — auditors and legal teams need the specific criterion and level, - downgrade a Level A finding to "nice to have" — Level A is the floor of any recognized conformance claim (WCAG A/AA/AAA, Section 508, EN 301 549 all build on Level A as mandatory), - treat this skill's static-review findings as a substitute for a full conformance audit — this skill narrows and grounds findings but does not replace testing with real assistive technology across the criteria this file does not cover (e.g., color contrast, captions, timing).
-
-
metadata.json 1.5 KB
{ "id": "html-semantics-accessibility-review", "name": "HTML Semantics & Accessibility Review", "type": "skill", "provider": "frontend", "harnesses": [ "claude-code", "cursor", "codex", "gemini", "kiro", "other" ], "summary": "Reviews markup for correct native-element usage, valid heading/landmark structure, and WAI-ARIA APG-conformant custom-widget patterns, producing a WCAG-grounded verdict with APG citations for every custom interactive element and flags for anything needing live assistive-technology verification.", "source_type": "original", "official_docs": [ "https://html.spec.whatwg.org/multipage/", "https://www.w3.org/WAI/ARIA/apg/", "https://www.w3.org/TR/wai-aria-1.2/", "https://www.w3.org/TR/WCAG22/", "https://developer.mozilla.org/en-US/docs/Web/HTML", "https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA" ], "security_notes": "Do not hardcode or request user PII, real screen-reader session logs, or authenticated-app URLs in review examples. Flag markup that binds unsanitized user content directly into the DOM (innerHTML/outerHTML/document.write) as an XSS-adjacent finding even though the primary fix is JS-side. Treat WCAG conformance findings as compliance-relevant (ADA/Section 508/EN 301 549 exposure) and label them as such rather than 'style nitpicks'.", "last_verified": "2026-07-02", "path": "skills/frontend/html-semantics-accessibility-review", "author": "github: VincentChuWaiChow", "version": "0.1.0" } -
SKILL.md 6 KB
--- name: html-semantics-accessibility-review description: Review HTML markup and rendered DOM structure for correct native-element usage, valid heading/landmark hierarchy, and WAI-ARIA APG-conformant custom-widget patterns; produce a WCAG 2.2-grounded verdict with APG pattern citations for every custom interactive control, flagging anything that needs live screen-reader verification beyond static review. allowed-tools: Read Grep Glob Bash(git diff:*) WebFetch metadata: author: "github: VincentChuWaiChow" version: "0.1.0" updated: "2026-07-02" category: compliance --- # HTML Semantics & Accessibility Review ## Purpose Automated a11y linters (axe, Lighthouse) catch roughly 30-50% of WCAG issues by design — they cannot verify whether a custom widget's keyboard interaction matches its intended pattern, whether ARIA correctly reflects (or wrongly overrides) native semantics, or whether a heading/landmark outline actually helps a screen-reader user navigate. This skill performs the manual, spec-grounded review that closes that gap: matching every custom interactive element against a specific WAI-ARIA APG pattern, verifying heading/landmark structure, and catching redundant or conflicting ARIA before it ships. ## When to use Use this skill when the user asks to: - review a pull request or component for HTML semantics or accessibility correctness, - verify a custom widget (modal, dropdown, tabs, combobox, accordion, etc.) against WAI-ARIA APG patterns, - audit heading level and landmark structure on a page or component tree, - check whether ARIA roles/states/properties are correctly applied or redundant/conflicting with native semantics, - assess WCAG 2.2 conformance risk for markup changes ahead of a compliance audit. ## Context7 Documentation Protocol Element semantics, implicit ARIA-role mappings, and attribute-support tables change as the HTML and ARIA specs evolve — never assert them from memory. 1. Call `ToolSearch` with query `"context7"` (or `"select:mcp__Context7__resolve-library-id,mcp__Context7__query-docs"`) to load the Context7 tools if they are not already loaded in this session. 2. Call `mcp__Context7__resolve-library-id` for the relevant documentation set — for this skill that is almost always MDN (`/mdn/content`, or `/websites/developer_mozilla_en-us` if the former lacks coverage for the query). Resolve the WAI-ARIA APG or WCAG spec source too if the review needs primary-spec wording rather than MDN's paraphrase. 3. Call `mcp__Context7__query-docs` for the specific element, role, or attribute in question — e.g. "implicit ARIA role for `<nav>`", "APG combobox keyboard pattern", "tabindex focus-order behavior" — before ruling on it. Do this per review, not once from memory of a prior session. 4. Prefer the official spec/MDN wording over this skill's own paraphrase when the two could be read to disagree; cite the resolved doc URL in the finding. 5. If Context7 is unavailable or returns no relevant match, fall back to the URLs in `official_docs` / `references/apg-pattern-index.md`, and explicitly mark the claim `documentation-based (Context7 unavailable)` rather than presenting it as freshly verified. 6. Never invent an ARIA role, state, property, or implicit-semantics mapping that no queried source confirms. ## Lean operating rules - First rule of ARIA: no ARIA is better than bad ARIA. Prefer a native element (`<button>`, `<dialog>`, `<details>`, `<nav>`) over a JS-reimplemented equivalent with ARIA bolted on, unless the platform genuinely has no equivalent. - Never accept 'axe/Lighthouse passed' as sufficient evidence for a custom interactive widget — manually match it against a specific APG pattern URL, including its full keyboard model (not just Tab/Enter — Escape, Home, End, Arrow keys per the pattern). - Treat heading-level skips (h1→h3) and missing/duplicate landmarks as blocking findings, not style notes — they break screen-reader page-navigation shortcuts. - Never approve positive `tabindex` values; require `tabindex="0"`/`"-1"` plus correct DOM order instead. - Flag `aria-hidden="true"` on any ancestor of a focusable/interactive descendant — this creates an unreachable-but-focusable or reachable-but-hidden trap. - Query current MDN/WAI-ARIA APG docs (see Context7 Documentation Protocol) for the specific element/role in question before ruling; element semantics and ARIA support tables change with spec updates — never assert support/behavior from memory. - Anything requiring live screen-reader verification (actual NVDA/JAWS/VoiceOver behavior) gets flagged as a residual risk, not asserted as verified from static review alone. - Label every claim as `live evidence`, `spec-cited`, `documentation-based`, or `inference` so the reviewer knows what's actually been verified vs. reasoned about. ## References Load these only when needed: - [WCAG success-criterion mapping](references/wcag-criterion-mapping.md) — use when a finding needs to be tied to a specific WCAG 2.2 success criterion for a compliance-audit deliverable. - [APG pattern quick-index](references/apg-pattern-index.md) — use when identifying which APG pattern matches a given custom widget (modal, combobox, tabs, tree, menu, disclosure, etc.) before doing the deep keyboard-model comparison. - [Heading and landmark structure rules](references/heading-landmark-rules.md) — use when auditing page-level or component-tree-level outline structure, including nested-landmark and multiple-landmark-of-same-type edge cases. ## Response minimum Return, at minimum: - the element/component in scope and its semantic verdict (native-element compliant / needs ARIA / needs restructure), - for any custom interactive widget: the specific APG pattern URL cited, or an explicit flag that none matches and a native element should be used instead, - the heading/landmark outline diff (before/after) when structure changed, - every ARIA attribute added or removed, with its WAI-ARIA 1.2 role/state justification, - residual risk notes for anything requiring live assistive-technology verification beyond this static review.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.