| Pass | Required Colour contrast | Audited with axe-core across every page, both themes, at desktop width and 375px, as recorded on the Accessibility policy page. |
| Fail | Optional Automatic contrasting colour | Text-on-brand-color pairings are hand-picked (a fixed dark ink color) rather than computed with the CSS contrast-color() function. |
| Partial | Recommended Forced colours mode | The forced-colors media feature hides decorative shapes and solidifies hairline borders, but this has been reasoned through rather than tested in an actual forced-colors environment. |
| Pass | Required Image alt text | Every img has an alt attribute; a dedicated quality pass found and fixed two weak ones (a post featured image labelled with the post title instead of what the photo shows) and confirmed the rest are genuinely descriptive. |
| Pass | Required Form labels | Every input this codebase controls (the search box) is properly labelled. The Contact and Speaking pages embed Meteor Forms' and Cal.com's own forms in an iframe; their internal labelling is a different origin's markup, not this site's, the same way a linked-to page's accessibility isn't scored as part of this one. |
| Pass | Required Keyboard navigation | A keyboard-only walkthrough (skip link, header controls, mobile menu, search dialog, FAQ disclosure, cookie banner, Display settings panel) found and fixed one real bug: opening Display settings left focus behind on the trigger, so Tab skipped straight past the now-open panel to the next header button instead of into it (it is mounted after Footer, far from its trigger in DOM order). It now moves focus to the panel heading on open, matching the cookie banner's existing pattern. |
| Pass | Required Visible focus indicators | A two-ring :focus-visible outline is defined sitewide, with an optional thicker "enhanced focus" mode. |
| Pass | Recommended Focus not obscured | Checked directly at phone width: with the cookie banner or Display settings panel open, several footer links (Cookie settings, the policy links, the text-only-version link) were completely hidden behind the fixed panel with no way to scroll them into view, since the document was already at max scroll. Both panels now measure their own rendered height and reserve that much extra scroll room (and matching scroll-padding-bottom) while open, confirmed against the same links: none end up fully hidden any more, in either panel, and the reserved space disappears again on close. |
| Pass | Required Skip links | A "Skip to main content" link is the first focusable element on every page. |
| Partial | Recommended The inert attribute | The native search dialog gets this for free from showModal(); the custom Display settings and cookie banner panels do not inert the rest of the page, relying on visual layering instead. |
| Pass | Required Semantic HTML and landmarks | header, nav, main and footer are used throughout, confirmed during the axe-core audit. |
| Pass | Recommended ARIA: first rule of ARIA | Native elements are preferred everywhere; ARIA is added only where nothing native fits, such as the custom panels. |
| Pass | Required Descriptive link text | Links describe their destination ("Read the original," "See all posts in English"); generic "click here" text is not used. |
| Pass | Avoid Empty links and buttons | Every icon-only control (search, theme toggle, close buttons) carries an aria-label or visually hidden text. |
| Not applicable | Required Accessible form errors | This site has no form of its own that produces a validation error; the Contact and Speaking page forms are entirely Meteor Forms' and Cal.com's own embedded UI. |
| Pass | Recommended Status messages | Confirmed in SearchPanel.svelte: the result-count text sits in its own role="status" aria-live="polite" element, separate from the results list, so a screen reader announces count changes without the results themselves needing to be re-read. |
| Not applicable | Recommended Accessible authentication | There are no accounts or logins anywhere on this site. |
| Not applicable | Recommended Redundant entry | There is no multi-step process anywhere on the site that would ask for the same information twice. |
| Pass | Recommended Consistent help | Search, Display settings, the theme toggle, and now Cookie settings, all sit in the same header or footer position on every page. |
| Pass | Required Document and parts language | html lang is always set correctly per language; the site's content does not currently mix languages mid-paragraph. |
| Pass | Required Reduced motion | prefers-reduced-motion is respected sitewide, and the site has little decorative animation to begin with. |
| Pass | Avoid Accessibility overlays | No third-party accessibility widget is used; the Display settings panel is this site's own first-party code, not a bolted-on overlay. |
| Not applicable | Required Captions and transcripts | The site has no video or audio content. |
| Pass | Required Accessible data tables | Markdown tables get a focusable, scrollable wrapper, scope="col" on every header cell, and an sr-only caption drawn from the heading that introduces the table, all applied automatically by rehype-table-scroll.ts so future tables get them for free. |
| Pass | Required Touch target size | Interactive elements meet the 24 by 24 CSS px minimum sitewide, checked during the layout audit. |
| Not applicable | Recommended Dragging movements | The one candidate, the Writing carousel, uses native browser scrolling with arrow-button alternatives, not a custom drag gesture, so there is no drag-only interaction to provide an alternative for. |
| Pass | Recommended Hidden until found | The About page's "Training and courses" disclosure and the Contact page's FAQ accordions are plain native <details>, which auto-expands for find-in-page and fragment navigation on its own (Chrome 97+, Firefox 139+, Safari 26.2) without needing hidden="until-found" (a separate mechanism for hand-hidden, non-<details> content, which this site does not use). |
| Pass | Recommended Mobile-friendly form inputs | This site's own search input is a plain, correctly-typed text field, the only input this codebase controls. The embedded Meteor Forms and Cal.com forms' input types are a different origin's markup, the same reasoning as Form labels above. |
| Partial | Recommended Native interactive elements | button, a, details and a native dialog (search) are used throughout, but the Display settings panel and cookie banner are deliberately custom, non-modal panels rather than native dialog elements. |
| Fail | Recommended CSS state and relational selectors | :has(), :user-invalid and :focus-within are not used; this site has very little custom form UI for them to apply to. |