{
  "$comment": "The checks no automated tool can make. Automated scanning reliably catches only about a third of WCAG failures, so this list is shipped with every report rather than hidden, see the coverage note in scan.js. Each entry is written so a non-specialist can actually carry it out.",
  "checks": [
    {
      "id": "keyboard-only",
      "title": "Operate the whole page with only the keyboard",
      "wcag": [
        "2.1.1"
      ],
      "level": "A",
      "how": "Put the mouse away. Press Tab repeatedly from the top of the page. Reach every link, button, form field, menu and popup, activate each with Enter or Space, and close anything that opens with Escape.",
      "lookFor": "Anything you cannot reach, anything you can reach but not activate, and any popup that traps you so Tab keeps cycling inside it forever.",
      "whyAutomationMisses": "A scanner can see that an element is focusable. It cannot judge whether pressing Enter on it actually does the right thing."
    },
    {
      "id": "focus-visible",
      "title": "Watch where the keyboard focus is",
      "wcag": [
        "2.4.7"
      ],
      "level": "AA",
      "how": "Tab through the page again and keep your eyes on the screen. At every step you should clearly see which element is selected.",
      "lookFor": "Steps where the outline vanishes entirely, or is so faint you have to hunt for it. Themes that set outline:none are the usual cause.",
      "whyAutomationMisses": "Whether a focus ring is visible enough is a visual judgement about contrast, thickness and the background behind it."
    },
    {
      "id": "focus-order",
      "title": "Check the tab order matches the visual order",
      "wcag": [
        "2.4.3"
      ],
      "level": "A",
      "how": "Tab through and note whether focus moves in the order things appear on screen, roughly left to right, top to bottom.",
      "lookFor": "Focus jumping to the footer and back, or entering a mobile menu that appears closed.",
      "whyAutomationMisses": "It requires comparing the code order against the rendered visual layout, including anything CSS has moved."
    },
    {
      "id": "alt-text-quality",
      "title": "Read the alt text you already have",
      "wcag": [
        "1.1.1"
      ],
      "level": "A",
      "how": "For each meaningful image, read its alt text and ask whether someone who cannot see the image would get the same information from it.",
      "lookFor": "Alt text like \"image\", \"photo\", \"DSC_0421.jpg\", or the same keyword stuffed everywhere. Also decorative images that have a description when they should have an empty one.",
      "whyAutomationMisses": "A scanner can only tell whether alt text exists, never whether it is accurate or useful."
    },
    {
      "id": "link-purpose",
      "title": "Read your links out of context",
      "wcag": [
        "2.4.4"
      ],
      "level": "A",
      "how": "Write down every link's text on its own, with no surrounding sentence. A screen reader user can pull up exactly this list.",
      "lookFor": "\"Click here\", \"Read more\", \"Learn more\" repeated a dozen times with no indication of where each goes.",
      "whyAutomationMisses": "The link has text, so it passes the automated check. Whether that text means anything is a human judgement."
    },
    {
      "id": "headings-describe",
      "title": "Check headings actually describe their sections",
      "wcag": [
        "2.4.6"
      ],
      "level": "AA",
      "how": "Read only the headings, in order, top to bottom. They should form a sensible summary of the page.",
      "lookFor": "Headings used purely to make text bigger, and sections whose heading does not match what follows.",
      "whyAutomationMisses": "The heading structure can be technically perfect while the words mean nothing."
    },
    {
      "id": "video-captions-quality",
      "title": "Watch a video with the sound off",
      "wcag": [
        "1.2.2",
        "1.2.3"
      ],
      "level": "A",
      "how": "Play each video muted with captions on. Follow it through to the end.",
      "lookFor": "Auto-generated captions with wrong words or no punctuation, missing speaker names, and important on-screen text that is never spoken or described.",
      "whyAutomationMisses": "A scanner can detect that a captions track exists but cannot assess whether it is accurate."
    },
    {
      "id": "form-errors",
      "title": "Submit your forms wrongly on purpose",
      "wcag": [
        "3.3.1",
        "3.3.3"
      ],
      "level": "A",
      "how": "Submit each form empty, then with a deliberately malformed email address. Read what comes back.",
      "lookFor": "Errors shown only as a red border with no text, messages that do not say which field is wrong, and errors that a screen reader is never told about.",
      "whyAutomationMisses": "The error state only exists after a submission, which a page scan never performs."
    },
    {
      "id": "zoom-400",
      "title": "Zoom the page to 400 percent",
      "wcag": [
        "1.4.10"
      ],
      "level": "AA",
      "how": "Set the browser window to 1280 pixels wide and press Ctrl and plus until you reach 400 percent.",
      "lookFor": "Text cut off, content requiring horizontal scrolling, and elements overlapping each other.",
      "whyAutomationMisses": "It needs the page to be rendered and visually inspected at that zoom level."
    },
    {
      "id": "text-spacing",
      "title": "Increase the text spacing",
      "wcag": [
        "1.4.12"
      ],
      "level": "AA",
      "how": "Apply increased line height, letter spacing and word spacing with a browser extension or a temporary stylesheet.",
      "lookFor": "Text overflowing its container, buttons whose labels spill out, and clipped headings.",
      "whyAutomationMisses": "It requires re-rendering the page with modified styles and judging the result visually."
    },
    {
      "id": "reflow-mobile",
      "title": "Use the site on a real phone",
      "wcag": [
        "1.4.10",
        "2.5.5"
      ],
      "level": "AA",
      "how": "Open the site on an actual phone, not just a resized desktop window. Complete a real task: find a product, fill in the contact form, reach checkout.",
      "lookFor": "Tap targets too small or too close together, menus that cannot be closed, and popups that cover the content with no reachable close button.",
      "whyAutomationMisses": "Touch target comfort and real-world usability are judgements, not measurements."
    },
    {
      "id": "motion-animation",
      "title": "Check anything that moves",
      "wcag": [
        "2.2.2",
        "2.3.1"
      ],
      "level": "A",
      "how": "Look for carousels, auto-playing video, parallax effects and animated counters. Then turn on your operating system's reduce-motion setting and reload.",
      "lookFor": "Anything moving for more than five seconds with no pause control, anything flashing more than three times a second, and animations that ignore the reduce-motion setting.",
      "whyAutomationMisses": "Flash rate and motion intensity need to be observed over time."
    },
    {
      "id": "screen-reader-pass",
      "title": "Listen to the page with a screen reader",
      "wcag": [
        "4.1.2"
      ],
      "level": "A",
      "how": "Use NVDA on Windows (free), VoiceOver on Mac or iPhone, or TalkBack on Android. Close your eyes and try to complete one real task.",
      "lookFor": "Anything announced wrongly or not at all, controls whose state is never spoken, and updates that happen silently.",
      "whyAutomationMisses": "This is the only check that tests the actual experience rather than the code behind it. It is also the most valuable one on this list."
    },
    {
      "id": "colour-meaning",
      "title": "Check nothing is explained by colour alone",
      "wcag": [
        "1.4.1"
      ],
      "level": "A",
      "how": "Look at charts, form validation, status labels, stock indicators and required-field markers in greyscale.",
      "lookFor": "Red-for-error and green-for-success with no icon or text, required fields marked only by a red asterisk colour, and charts where the only key is colour.",
      "whyAutomationMisses": "It requires understanding what the colour is being used to communicate."
    },
    {
      "id": "timeouts",
      "title": "Check any time limits",
      "wcag": [
        "2.2.1"
      ],
      "level": "A",
      "how": "Look for booking holds, checkout timers, session expiry and countdown offers.",
      "lookFor": "Any limit the visitor cannot turn off, extend or adjust, and sessions that expire silently and lose entered data.",
      "whyAutomationMisses": "Time limits only reveal themselves over time and usually only while logged in."
    },
    {
      "id": "consistent-navigation",
      "title": "Compare navigation across pages",
      "wcag": [
        "3.2.3",
        "3.2.4"
      ],
      "level": "AA",
      "how": "Visit five different pages and compare where the menu, search and contact link sit, and what they are called.",
      "lookFor": "Menu items that change order between pages, and the same function named differently in different places, \"Basket\" here, \"Cart\" there.",
      "whyAutomationMisses": "It is a comparison across pages; a single-page scan cannot see it."
    }
  ]
}
