Powered by OptioAttest · Optio Labs
SmartQCompliance
Compliance, Quantified.
Daily automated scans
AI-generated fix code
Cryptographic proof

The SmartQCompliance Value

From generic "42 violations" to specific "8 of 14 widgets don't conform — 6 auto-fixable." See what static scanners miss and what SmartQCompliance delivers.

Every scanner tells you "this button lacks a name."
AI-Generated Executive Brief

What Your Team Actually Sees

Every morning, your GRC team gets a one-page executive brief written by AI — not a 200-row spreadsheet. Here's what the Widget Compliance section looks like:

WIDGET COMPLIANCE

The site contains 14 interactive widgets. 6 conform to W3C ARIA Authoring Practices.

Of the 8 non-conforming widgets:

  • 3 comboboxes missing state management properties — users cannot operate the search or filter controls with a screen reader
  • 2 dialogs without modal behavior — background content interferes with form completion
  • 3 menus without keyboard patterns — dropdown navigation requires a mouse
AUTOMATED
6 of 8 are candidates for automated correction using W3C reference implementations.

That's the kind of analysis that makes a procurement officer say "fix it" and a general counsel say "now."

W3C ARIA APG Pattern Validation

24 Widget Use Cases

Each use case shows exactly what static scanners find vs. what DeepScan finds — and the complete fix we generate from W3C reference implementations.

USE CASE 01

Search Combobox — Can't Find Products

Widget: E-commerce search bar with autocomplete dropdown
"Input missing role attribute" — SC 4.1.2
Search combobox missing aria-expanded, aria-controls, and aria-activedescendant — screen reader users cannot tell when search results appear, which result is highlighted, or navigate results with arrow keys. W3C APG Combobox pattern requires all three.
<input role="combobox"> — adds the role, widget still broken
Complete combobox with aria-expanded (toggles on open/close), aria-controls (points to results listbox), aria-activedescendant (tracks highlighted result), keyboard handler (Arrow Down opens, Arrow keys navigate, Enter selects, Escape closes) — generated from W3C combobox reference implementation
"Blind customers cannot use your product search. When they type, they don't know results appeared. When results appear, they can't navigate them. This affects every search interaction on every page."
DeepScan types in search, verifies aria-expanded toggles to true, presses Arrow Down, verifies aria-activedescendant updates, presses Escape, verifies aria-expanded returns to false
USE CASE 02

Navigation Menu — Can't Browse the Site

Widget: Top navigation with dropdown menus
"Button missing accessible name" — SC 4.1.2
Navigation menu button missing aria-haspopup, aria-expanded, and keyboard handler — screen reader users cannot discover the dropdown exists, cannot tell when it opens, and cannot navigate menu items with arrow keys. W3C APG Menu Button pattern requires aria-haspopup='menu', aria-expanded, and Arrow/Escape keyboard support.
<button aria-label="Products"> — adds the name, dropdown still invisible to screen readers
Complete menu button with aria-haspopup="menu", aria-expanded (toggles), aria-controls (points to menu), menu container with role="menu", items with role="menuitem", keyboard handler (Enter/Space/Down Arrow opens, Arrow keys navigate, Escape closes, Home/End for first/last) — from W3C Menu Button reference
"Your main navigation is unusable without a mouse. Screen reader users don't know dropdown menus exist. Keyboard users can't open them. This blocks access to every section of your site."
DeepScan presses Enter on menu button, verifies aria-expanded becomes true and focus moves into menu, presses Arrow Down, verifies focus moves to next menuitem, presses Escape, verifies menu closes and focus returns to button
USE CASE 03

Checkout Modal — Can't Complete Purchase

Widget: Checkout confirmation dialog
"Dialog missing aria-labelledby" — SC 4.1.2
Checkout dialog missing aria-modal='true' — background page content is still announced by screen readers, mixing with dialog content. Focus is not trapped within dialog — Tab key moves focus behind the dialog. Escape key does not close the dialog. W3C APG Dialog (Modal) pattern requires aria-modal, focus trapping, and Escape to close.
<div role="dialog" aria-labelledby="title"> — adds label, background still interferes, focus still escapes
Complete modal dialog with aria-modal="true", aria-labelledby pointing to visible heading, focus trap (Tab wraps within dialog), Escape closes and returns focus to trigger button, aria-describedby for instructions — from W3C Dialog Modal reference
"Customers using screen readers cannot complete checkout. The confirmation dialog lets background content interfere — they hear the entire page behind the form. They can Tab out of the dialog and lose their place. This directly blocks revenue."
DeepScan opens dialog, verifies focus moves inside, presses Tab repeatedly, verifies focus never leaves dialog, presses Escape, verifies dialog closes and focus returns to the checkout button
USE CASE 04

Product Tabs — Can't Compare Options

Widget: Product page with tabs (Description, Reviews, Specifications)
"Missing tabpanel role" — SC 1.3.1
Tab interface missing aria-selected on tabs, aria-controls linking tabs to panels, and aria-labelledby on panels. Arrow keys do not navigate between tabs. Screen reader users cannot determine which tab is active or access panel content. W3C APG Tabs pattern requires roving tabindex, aria-selected, and bidirectional linking.
<div role="tabpanel"> — adds panel role, tabs still don't communicate selection or support keyboard
Complete tab interface with role="tablist" container, each tab with role="tab", aria-selected (true on active, false on others), aria-controls pointing to its panel, each panel with role="tabpanel" and aria-labelledby pointing back to its tab, Arrow Left/Right to navigate tabs, Home/End for first/last — from W3C Tabs reference
"Customers can't compare product options. The Description, Reviews, and Specifications tabs don't respond to keyboard navigation and don't tell screen readers which tab is active. Users have to Tab through every tab to find content."
DeepScan focuses first tab, presses Arrow Right, verifies aria-selected changes to the next tab, verifies the corresponding tabpanel becomes visible and previous one hides
USE CASE 05

Cookie Consent Toggle — Can't Opt Out

Widget: Cookie preference switches (Analytics, Marketing, Functional)
"Element has no role" — SC 4.1.2
Cookie preference toggle implemented as <div> with click handler — missing role='switch' and aria-checked. Screen reader announces nothing. Keyboard users cannot activate it (no Space/Enter handler). W3C APG Switch pattern requires role='switch', aria-checked (true/false), and Space key to toggle.
<div role="checkbox"> — wrong role (switch, not checkbox), still no keyboard handler
Complete switch with role="switch", aria-checked (toggles true/false), accessible label via aria-labelledby, Space and Enter key handlers, visual state synchronized with aria-checked — from W3C Switch reference
"Users who rely on screen readers cannot manage their cookie preferences. The toggles don't announce their state and don't respond to the keyboard. Under GDPR and ePrivacy Directive, consent controls must be accessible to all users."
DeepScan focuses switch, presses Space, verifies aria-checked toggles from false to true, presses Space again, verifies it returns to false
USE CASE 06

Quantity Selector — Can't Change Order

Widget: Shopping cart quantity spin button (+/- controls)
"Button missing accessible name" — SC 4.1.2
Quantity selector missing role='spinbutton', aria-valuemin, aria-valuemax, and aria-valuenow. Arrow keys do not adjust the value. Screen reader users cannot determine the current quantity or the allowed range. W3C APG Spin Button pattern requires value properties and Arrow key support.
<button aria-label="Increase quantity"> — labels one button, the widget is still not a spinbutton
Complete spinbutton with role="spinbutton", aria-valuenow (current qty), aria-valuemin="1", aria-valuemax (stock limit), aria-label, Up/Down Arrow keys to increment/decrement, Home/End for min/max — from W3C Spin Button reference
"Customers using screen readers cannot change item quantities in the cart. They don't know the current quantity, the maximum, or how to adjust it. This blocks order modification and directly impacts cart abandonment."
DeepScan focuses spinbutton, presses Arrow Up, verifies aria-valuenow increments, presses Arrow Down, verifies it decrements, presses Home, verifies it goes to aria-valuemin
USE CASE 07

Accordion FAQ — Can't Find Answers

Widget: FAQ page with collapsible sections
"Heading structure missing" — SC 1.3.1
FAQ accordion headers missing aria-expanded and aria-controls — screen reader users cannot tell which sections are open or closed, and cannot discover that headers are expandable. W3C APG Accordion pattern requires aria-expanded on each header button and aria-controls pointing to the content region.
Add heading tags — fixes structure but accordion behavior still invisible to screen readers
Complete accordion with heading elements wrapping button elements, each button with aria-expanded (toggles true/false), aria-controls pointing to content panel, optional role="region" on panels with aria-labelledby back to header — from W3C Accordion reference
"Your FAQ page has 24 collapsible sections but screen reader users can't tell which are open or closed. They hear headings but don't know they're expandable. This defeats the purpose of the FAQ."
DeepScan activates accordion header, verifies aria-expanded changes from false to true, verifies content panel becomes visible, activates again, verifies it collapses
USE CASE 08

Date Picker — Can't Book Appointment

Widget: Appointment booking date picker (combobox + grid popup)
"Input missing label" — SC 1.3.1
Date picker combobox missing aria-expanded, calendar grid missing role='grid', day cells missing role='gridcell', selected date not marked with aria-selected. Keyboard users cannot navigate the calendar with Arrow keys. W3C APG Combobox Date Picker pattern requires combobox properties on input, grid pattern on calendar, and full arrow key navigation.
<input aria-label="Select date"> — labels the input, calendar grid still inaccessible
Complete date picker combobox with aria-expanded on input, aria-controls pointing to grid dialog, grid with role="grid", rows with role="row", cells with role="gridcell", selected date with aria-selected="true", Arrow keys navigate between days, Page Up/Down for months, Enter selects — from W3C Combobox Date Picker reference
"Customers cannot book appointments. The date picker doesn't respond to keyboard navigation and screen readers cannot identify which date is selected. This blocks the primary conversion action on the booking page."
DeepScan opens date picker, verifies aria-expanded toggles, presses Arrow Right, verifies focus moves to next day, presses Enter, verifies date is selected and aria-selected is set
USE CASE 09

Star Rating — Can't Leave Review

Widget: Product review star rating (1-5 stars)
"Image missing alt text" — SC 1.1.1
Star rating missing role='radiogroup' on container and role='radio' on each star. No aria-checked state. Arrow keys do not navigate between options. Screen reader users cannot determine current selection or change it. W3C APG Radio Group pattern requires radiogroup, radio, aria-checked, and Arrow key navigation with roving tabindex.
<img alt="3 out of 5 stars"> — makes the image readable but the interactive rating is still broken
Complete radio group with role="radiogroup" and aria-label="Rating", each star with role="radio" and aria-checked (true on selected, false on others), aria-label="1 star" through "5 stars", Arrow keys to navigate and select, roving tabindex — from W3C Radio Group reference
"Customers using screen readers cannot rate products. The star rating looks interactive but doesn't communicate its state or respond to keyboard input. This blocks customer reviews — a key trust signal for other buyers."
DeepScan focuses the rating, presses Arrow Right, verifies aria-checked moves to next star and previous star becomes unchecked
USE CASE 10

Image Carousel — Can't See Products

Widget: Homepage hero carousel with auto-rotating slides
"Missing aria-label on region" — SC 1.3.1
Carousel missing aria-roledescription='carousel', slide container missing aria-live region, no pause button for auto-rotation. When slides auto-advance, screen reader users are not notified. Users with vestibular disorders cannot pause the animation. W3C APG Carousel pattern requires aria-roledescription, aria-label, live region or tab pattern for slides, and a visible pause control.
<div role="region" aria-label="Featured products"> — labels the container, auto-rotation still inaccessible
Complete carousel with aria-roledescription="carousel", aria-label, tab interface or live region for slides, visible pause/play button, aria-live="off" when paused, respects prefers-reduced-motion — from W3C Carousel reference
"Your homepage hero rotates through products automatically but screen reader users are never told when content changes. Users with motion sensitivities cannot pause it. This is the first thing every visitor sees — it must work for everyone."
DeepScan checks for pause button, activates it, verifies aria-live changes or rotation stops, verifies prefers-reduced-motion is respected
USE CASE 11

Alert Banner — Can't Read Notifications

Widget: "Item added to cart" toast notification
Nothing — the toast appears and disappears, static scanners miss it entirely
Cart notification injected into DOM without role='alert' or aria-live region — screen reader users are never notified when items are added to cart. They must navigate to the cart icon to discover the count changed. W3C APG Alert pattern requires role='alert' (implicit aria-live='assertive') on the container so content is announced immediately.
Nothing — they don't detect dynamic content
Alert container with role="alert", content injected dynamically, not present at page load, announced immediately by screen reader without focus change — from W3C Alert reference
"When customers add items to cart, blind users don't know it happened. They get no notification. They have to navigate to the cart to check. Every 'Add to Cart' action is a dead end for screen reader users."
DeepScan triggers "Add to Cart", monitors for live region announcement in AX tree, verifies new alert content is announced
USE CASE 12

Filter Listbox — Can't Narrow Results

Widget: Product filter sidebar (size, color, price range)
"List missing role" — SC 1.3.1
Filter listbox missing aria-multiselectable — users cannot multi-select filters. Options missing aria-selected — screen reader cannot announce which filters are active. Arrow keys do not navigate options. W3C APG Listbox pattern requires listbox, option roles, aria-selected, and Shift+Click/Space for multi-select.
<ul role="list"> — wrong role entirely (list, not listbox)
Complete multi-select listbox with role="listbox", aria-multiselectable="true", aria-label="Filter by size", each option with role="option" and aria-selected, Arrow keys navigate, Space toggles selection, Shift+Space for range select — from W3C Listbox reference
"Customers can't filter products. The size and color filters don't tell screen readers which options are selected and don't respond to keyboard. Users have to buy blindly or leave."
DeepScan focuses listbox, presses Arrow Down, verifies focus moves to next option, presses Space, verifies aria-selected toggles to true
USE CASE 13

Breadcrumb — Can't Tell Where They Are

Widget: Category breadcrumb trail (Home > Shoes > Running)
"Navigation missing aria-label" — SC 2.4.8
Breadcrumb navigation missing aria-current='page' on the current page link — screen reader users cannot distinguish the current location from other breadcrumb links. W3C APG Breadcrumb pattern requires aria-current='page' on the link representing the current page.
<nav aria-label="Breadcrumb"> — labels the nav, current page still not identified
Breadcrumb with <nav aria-label="Breadcrumb">, ordered list of links, current page link with aria-current="page" — from W3C Breadcrumb reference
"Screen reader users navigating your product categories can't tell which page they're on. The breadcrumb trail reads as a list of equal links — 'Home, Shoes, Running' — with no indication that 'Running' is the current page."
DeepScan checks breadcrumb nav for aria-current="page" on the last (current) link
USE CASE 14

Price Range Slider — Can't Set Budget

Widget: Price filter with dual-thumb slider ($0 - $500)
"Element not keyboard accessible" — SC 2.1.1
Price slider missing role='slider', aria-valuemin, aria-valuemax, aria-valuenow, and aria-valuetext. Keyboard users cannot adjust the value — Arrow keys do nothing. Screen reader users cannot determine the current price range. W3C APG Slider Multi-Thumb pattern requires two slider elements with independent value ranges and Arrow key controls.
tabindex="0" — makes it focusable but Arrow keys still do nothing
Two slider thumbs each with role="slider", aria-valuemin="0", aria-valuemax="500", aria-valuenow (current value), aria-valuetext="$150" (human-readable), aria-label="Minimum price" / "Maximum price", Arrow keys adjust value, Home/End for min/max — from W3C Multi-Thumb Slider reference
"Customers can't set a price range. The slider doesn't respond to keyboard and doesn't announce the current value. Screen reader users hear nothing. Keyboard users can focus it but can't move it."
DeepScan focuses slider, presses Arrow Right, verifies aria-valuenow increments, checks aria-valuetext updates to readable price format
USE CASE 15

Toggle Button — Can't Save Preferences

Widget: "Dark Mode" / "Notifications" toggle button
"Button missing accessible name" — SC 4.1.2
Toggle button missing aria-pressed — screen reader users cannot determine whether dark mode is on or off. W3C APG Button pattern requires aria-pressed (true/false) for toggle buttons. The label must NOT change when state changes.
<button aria-label="Dark Mode"> — adds name, pressed state still unknown
Toggle button with aria-pressed (toggles true/false on activation), consistent label that doesn't change, Enter/Space to toggle — from W3C Button reference
"Users can't tell if dark mode is on or off. The button looks different visually but announces the same thing to screen readers. Preference toggles must communicate state."
DeepScan activates button, verifies aria-pressed changes from false to true, activates again, verifies it returns to false, confirms label text does not change
USE CASE 16

Disclosure Widget — Can't Read More

Widget: "Read More" / "Show Details" expandable content
"Link has no purpose" — SC 2.4.4
Disclosure button missing aria-expanded and aria-controls — screen reader users cannot tell whether content is shown or hidden, and cannot discover the relationship between the button and the content it controls. W3C APG Disclosure pattern requires aria-expanded on the trigger and aria-controls pointing to the content.
<a href="#" aria-label="Read more about product"> — adds description, still no expanded state
Disclosure with <button aria-expanded="false" aria-controls="details-panel">Read More</button>, content panel with matching ID, aria-expanded toggles on activation — from W3C Disclosure reference
"Your 'Read More' links don't tell screen readers whether content is showing or hiding. Users click and hear nothing change — they don't know the content appeared below."
DeepScan activates disclosure button, verifies aria-expanded changes to true, verifies content panel becomes visible in AX tree
USE CASE 17

Data Table — Can't Understand Data

Widget: Product comparison table with sortable columns
"Table missing caption" — SC 1.3.1
Data table with sortable columns missing aria-sort on column headers — screen reader users cannot determine sort direction (ascending, descending, none). Column headers missing role='columnheader'. W3C APG Table pattern requires aria-sort with values ascending, descending, or none on sortable headers.
<table><caption>Product Comparison</caption> — adds caption, sort state still invisible
Table with role="table" (or native <table>), column headers with role="columnheader", sortable headers with aria-sort="ascending" / "descending" / "none", aria-sort updates on click — from W3C Table reference
"Customers comparing products can't tell how the table is sorted. They click 'Price' to sort by price but the screen reader doesn't confirm the sort happened or the direction. The table looks sorted visually but sounds random."
DeepScan activates sortable column header, verifies aria-sort changes from none to ascending, activates again, verifies it changes to descending
USE CASE 18

Tree View — Can't Navigate File Structure

Widget: Document library / file browser with nested folders
"List items missing role" — SC 1.3.1
Tree view missing role='tree' on container, items missing role='treeitem', expandable folders missing aria-expanded. No aria-level on nested items. Arrow keys don't navigate the tree. W3C APG Tree View pattern requires tree, treeitem, aria-expanded on branch nodes, aria-level or DOM nesting, and full arrow key navigation.
<ul role="list"> — wrong role, no tree behavior
Complete tree with role="tree", items with role="treeitem", folders with aria-expanded, level tracking via aria-level or DOM nesting, Arrow Right to expand, Arrow Left to collapse/go to parent, Arrow Up/Down to navigate — from W3C Tree View reference
"Your document library is unusable without a mouse. Screen reader users can't navigate folders, can't tell which folders are open or closed, and can't drill into nested content."
DeepScan focuses tree, presses Arrow Right on folder, verifies aria-expanded becomes true, presses Arrow Down, verifies focus moves to first child treeitem
USE CASE 19

Toolbar — Can't Access Formatting

Widget: Rich text editor toolbar (Bold, Italic, Underline, etc.)
"Multiple buttons missing labels" — SC 4.1.2
Editor toolbar missing role='toolbar' and aria-label. Individual buttons missing aria-pressed for toggle state (Bold on/off). Arrow keys do not navigate between buttons — every button is a separate Tab stop. W3C APG Toolbar pattern requires role='toolbar', aria-label, and Left/Right Arrow key navigation with roving tabindex.
Add aria-label to each button icon — labels present but 15 Tab stops for 15 buttons, toggle state unknown
Toolbar with role="toolbar", aria-label="Formatting", Arrow keys navigate between buttons (single Tab stop for the group), toggle buttons with aria-pressed (Bold/Italic/Underline) — from W3C Toolbar reference
"Your text editor requires 15 Tab presses to reach the last formatting button. Screen reader users can't tell if Bold is currently on or off. The toolbar should be one Tab stop with arrow key navigation."
DeepScan focuses toolbar, presses Arrow Right, verifies focus moves to next button within toolbar (not Tab), activates Bold, verifies aria-pressed toggles
USE CASE 20

Alert Dialog — Can't Respond to Urgent Messages

Widget: "Are you sure you want to delete?" confirmation
"Dialog missing aria-labelledby" — SC 4.1.2
Delete confirmation uses role='dialog' but should use role='alertdialog' — this is an urgent action requiring user response. Missing aria-describedby pointing to the warning message. W3C APG Alert Dialog pattern requires alertdialog role, aria-modal, aria-labelledby for title, aria-describedby for the warning text, and focus on the least destructive action.
<div role="dialog" aria-labelledby="title"> — wrong role for urgent message, no description
Alert dialog with role="alertdialog", aria-modal="true", aria-labelledby pointing to "Delete Item?" heading, aria-describedby pointing to "This action cannot be undone" message, initial focus on "Cancel" (least destructive) — from W3C Alert Dialog reference
"When customers try to delete items, the confirmation doesn't convey urgency. Screen readers announce it as a regular dialog, not a warning. The 'Delete' button is focused first — one accidental Enter key deletes the item."
DeepScan opens alertdialog, verifies role="alertdialog", verifies aria-describedby content is announced, verifies initial focus is on Cancel (not Delete)
USE CASE 21

Meter — Can't Read Progress

Widget: Account storage usage indicator (3.2 GB of 5 GB used)
"Element has no text alternative" — SC 1.1.1
Storage meter missing role='meter', aria-valuemin, aria-valuemax, aria-valuenow, and aria-label. Screen reader users cannot determine how much storage is used or the total capacity. W3C APG Meter pattern requires all value properties and a descriptive label.
<div aria-label="Storage usage"> — labels the container, no value information
Meter with role="meter", aria-valuemin="0", aria-valuemax="5", aria-valuenow="3.2", aria-valuetext="3.2 GB of 5 GB used (64%)", aria-label="Storage usage" — from W3C Meter reference
"Users can see the storage bar is mostly full, but screen readers announce nothing. Blind users don't know they're running out of space until uploads fail."
DeepScan reads meter, verifies aria-valuenow is present and within aria-valuemin/aria-valuemax range, verifies aria-valuetext provides human-readable description
USE CASE 22

Feed — Can't Scroll Social Content

Widget: Social media feed / news feed with infinite scroll
Nothing — static scanners see the first page load only
Feed container missing role='feed', articles missing role='article' with aria-setsize and aria-posinset. No aria-busy during loading. Screen reader users cannot navigate between posts (Page Down to next article) and don't know how many posts are loaded. W3C APG Feed pattern requires feed, article, set size tracking, and busy state during load.
Nothing — they don't detect infinite scroll content
Feed with role="feed", aria-label, articles with role="article", aria-posinset (position), aria-setsize (total or -1 for unknown), aria-busy="true" during loading — from W3C Feed reference
"Your news feed loads more content as users scroll, but screen reader users don't know new content arrived. They can't navigate between posts and don't know their position in the feed."
DeepScan triggers scroll, monitors aria-busy during load, verifies new articles get correct aria-posinset, verifies aria-setsize updates
USE CASE 23

Grid — Can't Navigate Spreadsheet

Widget: Data entry grid / spreadsheet-style interface
"Table cells missing headers" — SC 1.3.1
Data grid missing aria-colcount/aria-rowcount for virtual scrolling. Cells missing aria-colindex/aria-rowindex. Arrow keys don't navigate between cells — every cell is a separate Tab stop. W3C APG Grid pattern requires grid, row, gridcell roles, index properties, and full four-directional arrow key navigation.
Add <th> headers — fixes header association but grid is still a table with 200+ Tab stops
Grid with role="grid", rows with role="row", cells with role="gridcell", column headers with role="columnheader", aria-colcount/aria-rowcount for total dimensions, aria-colindex/aria-rowindex on cells, single Tab stop for the entire grid, Arrow keys navigate between cells — from W3C Grid reference
"Your data entry screen requires hundreds of Tab presses to reach the last cell. Arrow keys don't work. This takes a keyboard user 10 minutes to fill out what takes a mouse user 30 seconds."
DeepScan focuses grid, presses Arrow Right, verifies focus moves to next cell (not Tab), presses Arrow Down, verifies focus moves to cell below
USE CASE 24

Landmark Regions — Can't Navigate the Page

Widget: Page layout with header, nav, main, sidebar, footer
"Page has no landmarks" — SC 1.3.1
Page has 3 <nav> elements but only 1 has aria-label — screen reader users see '3 navigation landmarks' but can't distinguish them (main nav vs footer nav vs sidebar nav). W3C APG Landmarks pattern requires unique aria-label on repeated landmark roles so users can distinguish between them.
Add role="navigation" — already has it via <nav>, but duplicates are still indistinguishable
Each navigation landmark with unique aria-label: <nav aria-label="Main">, <nav aria-label="Footer">, <nav aria-label="Categories">. Same for repeated <aside>, <section>, <form> elements — from W3C Landmarks reference
"Your page has 3 navigation areas but screen reader users can't tell them apart. They hear 'navigation, navigation, navigation' — which one is the main menu? Which is the footer? This forces trial-and-error on every page load."
DeepScan counts landmark roles, verifies each repeated role has a unique aria-label, reports which landmarks are indistinguishable