Skip to content

Gevell PDF Accessibility Roadmap (Q4 2026 – Q3 2027)

HECVAT question: “Can you provide a current, detailed accessibility roadmap with delivery timelines?” Internal question (Larry): “What accessibility features are we missing?”

Scope: the Gevell PDF web app itself (apps/web, served at pdf.gevell.com): landing, sign-in, upload/dashboard, conversion progress, file detail/preview, the remediation tools (tag editor, reading order, tab order, alt text), account/settings, teams and tenant-admin. The quality of the documents we generate (PDF/UA, WCAG of output HTML) is a separate track in section 5.

Honesty rule for this document: a gap is listed as Verified only where code evidence was found (file + line cited). Anything else is Suspected (code pattern suggests a risk) or Needs manual test (cannot be decided from code). Nothing here has yet been through a formal screen-reader pass — that is itself roadmap item A1.


1. Current state — what exists

1.1 Test harness

AssetLocationState
test:a11y scriptapps/web/package.json → playwright test --project=a11yExists
axe-core via Playwright@axe-core/playwright in apps/web/package.json; tags wcag2a, wcag2aa, wcag21a, wcag21aa, wcag22aaExists
Playwright configapps/web/playwright.config.ts — projects smoke, a11y, mobile (iPhone 14 only)Exists
a11y specsapps/web/e2e/: home.a11y, home.keyboard.a11y (focus visible + no trap + skip link + FAQ accordion on 6 public routes), dashboard.a11y, tag-editor.a11y, crm.a11y, issues.a11ySee gaps
Help-site scan.github/workflows/docs.yml runs pa11y-ci (WCAG2AA) over help.gevell.comIn CI, gating
Flipbook viewer.github/workflows/test.yml (~line 180) — Playwright + axe on the shared flipbook playerIn CI
VPAT/ACRapps/web/VPAT.md + apps/web/vpat-evidence.json (axe run 2026-07-05 against localhost, landing page only)Draft
Public statementapps/home/src/app/accessibility/page.tsx (gevell.com/accessibility)Exists, WCAG 2.1 AA framing

1.2 Good patterns already in place (verified)

  • Drag alternatives (2.5.7): reorder by drag is always paired with buttons or keys — components/TabOrderBrowser.tsx:361-370 (“Move … earlier/later”), components/file-detail/FlyerReadingOrder.tsx:286-300 (“Move … up/down to position N” plus a polite live region at :231), packages/tag-editor-ui/src/components/TreeView.tsx (Alt+Up/Down + “Move up” buttons, role="tree"/treeitem/aria-expanded, roving tabindex), OutlineView.tsx, MillerColumns.tsx. Canvas drag in ElementOverlay.tsx:146 relies on those outline alternatives.
  • Dropzone: real <button>s for “browse” and “upload a folder” (components/upload/DropZone.tsx:~236-243); the drop target itself is not required.
  • Accessible authentication (3.3.8): email and voice OTP use a single field with autocomplete="one-time-code" + inputMode="numeric" (packages/accessible-org-ui/src/components/EmailOtpLogin.tsx:205-208, VoiceOtpLogin.tsx:213-216); password fields carry autocomplete; no CAPTCHA anywhere in apps/web; SSO and OAuth available.
  • Reduced motion: global prefers-reduced-motion override (apps/web/src/app/globals.css:1077); toasts honor it too.
  • Focus: global :focus-visible ring (globals.css:62) and a targeted fix for the shared header menu (globals.css:1089-1106).
  • Skip link + <main> landmark tested by home.keyboard.a11y.spec.ts.
  • Upload wizard progress: role="progressbar" + polite status (components/wizard/WizardStep1Upload.tsx:63,78).

2. Gap analysis

2.1 Verified gaps (code evidence)

#GapWCAG / standardEvidence
G1a11y tests are not in CI, and the two app-surface specs are non-gating and unauthenticatedProcess (supports all SC)No workflow runs test:a11y (only docs.yml pa11y and the flipbook test). e2e/dashboard.a11y.spec.ts and e2e/tag-editor.a11y.spec.ts end with expect(true).toBe(true); both load without a session, so they audit a sign-in redirect / empty shell. No specs for file detail, preview, remediation tools, wizard, settings, teams, tenant-admin, auth pages. Resolved for Gevell PDF (apps/web) by #3661: a11y (apps/web) and mobile (apps/web) jobs in test.yml run on every PR that touches apps/web or its packages and on every push to main, and gate (the required check) depends on both. The expect(true) specs are deleted. Axe runs on every customer route, signed in via a mocked session, and fails on any violation not in the allowlist (entries keyed by rule, route and selector). The allowlist also fails the build on an expired entry. Runbook: docs/admin/accessibility-ci.md. Resolved for Gevell Report Card (apps/vpat) by #3675: a11y (apps/vpat) and mobile (apps/vpat) jobs, same shape, on the shared harness packages/a11y-harness. Resolved for Gevell Org Chart (apps/org-chart) by #3676: a11y (apps/org-chart) and mobile (apps/org-chart), same harness. Resolved for Gevell Audit (apps/audit) by #3674: a11y (apps/audit) and mobile (apps/audit), same harness. All four apps named in the security packets are now gated
G2VPAT is a draft: no report date, 51 _TBD_ rows, WCAG 2.1 only (no 2.2)Procurementapps/web/VPAT.md header “Report Date: DRAFT — pending manual review”
G3Toast notifications: success/info toasts auto-dismiss after 5 s with no pause on hover/focus; fixed w-96 (384 px) width; dismiss buttons p-0.5; each toast is role="alert" nested inside a role="status" aria-live="polite" container2.2.1 Timing Adjustable (risk), 1.4.10 Reflow, 2.5.8 Target Size, 4.1.3 Status Messagespackages/accessible-org-ui/src/toast/Toast.tsx:7 (AUTO_DISMISS_MS = 5000), :98 (role="alert"), :100 (w-96), :131,:175 (p-0.5); ToastProvider.tsx:75-77. “Conversion complete” (hooks/useDashboardState.ts:560) is announced only via this toast. Resolved by A4 (#3566); line numbers are as of the audit and p-0.5 had already been fixed by #3444
G4Status changes on the dashboard are not reliably announced: live regions are mounted only while the status holds (Uploading… span exists only when status==='uploading'), and processing → completed/failed has no persistent live region4.1.3 Status Messagescomponents/dashboard/control-center/FileRow.tsx:240-247, FileCard.tsx:212-219
G5Error detail only in a title tooltip on the Retry button (unavailable to keyboard/touch and inconsistently to AT)1.3.1, 3.3.1 (risk)components/dashboard/control-center/FileRow.tsx:258
G6Small targets: notification dismiss is p-0.5 around a 14 px icon (~18 px) next to another control; dialog close buttons are p-1 + 16 px icon (24 px — AA minimum, below the 44 px project standard)2.5.8 (fails AA for the ~18 px case); project 44 px rulecomponents/dashboard/control-center/NotificationBell.tsx:137-139; components/dashboard/TagDialog.tsx:113-116, ShareDialog.tsx:~160, components/layout/ServiceBanner.tsx:24
G7Sub-12 px text: 59 uses of text-[9px]–text-[11px] across 23 non-admin files (e.g. FileCard.tsx Convert button text-[11px]); apps/web has no global 12 px floorProject standard (min 12 px); 1.4.4 risk`grep text-[(9
G8No forced-colors / Windows High Contrast handling anywhere (no forced-colors media query in apps/web or packages/accessible-org-ui); focus indication relies on Tailwind ring (box-shadow), which forced-colors mode removes1.4.11, 2.4.7 in forced-colors (needs manual confirmation of impact)repo-wide grep: zero matches for forced-colors
G9English only: one locale file, translations used in ~6 files; most UI strings hard-codedNot a WCAG AA requirement; procurement / Title VI LEP expectation; project i18n standardapps/web/locales/en.json only; useTranslations/useTranslation in 6 files
G10No end-user accessibility-features documentation (keyboard shortcuts for the tag editor — Alt+Up/Down etc. — screen-reader tips, how to report an a11y issue) on help.gevell.com3.2.6 support; procurementdocs/user/src/content/docs/ has no product-accessibility page
G11Unhedged claim on the sign-in page: tagline “WCAG 2.1 AA compliant output in seconds” violates the hedged-claims policyPolicy (docs/admin/accessibility-claims-audit.md, #3293)apps/web/src/app/auth/login/page.tsx:40
G12Loading skeleton fixed at 612 px wide in the compare PDF viewer1.4.10 Reflow (at 320 px)components/compare/PdfViewer.tsx:28-36 (style={{ width: 612 }})

2.2 Suspected gaps (pattern found; confirm manually)

#GapWCAGWhy suspected
S1Focus Not Obscured — sticky header (@anglinai/ui CorporateHeader sticky top-0 z-50), fixed mobile bottom nav (components/dashboard/control-center/Sidebar.tsx:76), fixed bottom update banner (components/VersionChecker.tsx:100), fixed top promo banner (components/marketing/AccessUBanner.tsx:12), fixed toast stack; no scroll-padding/scroll-margin anywhere in apps/web/src2.4.11 (2.2 AA)Tabbing to elements near the viewport edge can land under a fixed bar
S2Wizard progress region wraps a whole card in role="status" aria-live="polite" (WizardStep1Upload.tsx:63) — may re-announce the entire card on each progress tick4.1.3 (verbosity)Container-level live region with changing percentages
S3Multiple color schemes (classic / warm / premium-dark, components/dashboard/control-center/statusStyles.ts) multiply contrast surfaces; axe specs run only the default scheme, light mode1.4.3, 1.4.11Untested variants
S4Tenant branding colors applied directly to link text (app/tenant-admin/page.tsx:92-122 style={{ color: tenant.colors.primary }}) — contrast depends on customer input1.4.3Branding page computes “effective colors”, but these links use the raw value
S5PDF preview: react-pdf canvas + text layer (components/compare/PdfViewer.tsx:109-119) exposes flat text with no page/heading structure; workspace preview disables the text layer (components/workspace/WorkspacePdfPage.tsx:58)1.1.1 / 1.3.1The accessible HTML is the equivalent, but the relationship isn’t stated to AT users

2.3 Needs manual test (cannot decide from code)

AreaWCAGWhat to test
Tag editor canvas (packages/tag-editor-ui), reading-order and tab-order tools end-to-end with NVDA+Firefox, JAWS+Chrome, VoiceOver+Safari2.1.1, 4.1.2, 1.3.2Complete a real remediation task keyboard-only and with a screen reader
Zoom 200% / 400% reflow of dashboard, file detail, tag editor1.4.4, 1.4.101280 px viewport at 400% = 320 CSS px
Text spacing override1.4.12Bookmarklet on dashboard/file detail
Modal dialogs (TagDialog, ShareDialog, FlyerChoiceDialog, TabOrderBrowser): focus in, trap, Esc, focus return2.4.3, 2.1.2Keyboard walk
Consistent help: help/support link position across dashboard, file detail, tenant-admin, auth (only some routes render CCPageShell/footer)3.2.6 (2.2 A)Compare the location of the Support link across page templates
Redundant entry: checkout, workshop registration, SSO intake, team invites3.3.7 (2.2 A)Is previously entered info auto-filled or selectable within a flow?
Dragging: any drag-only interaction remaining (benchmark page, admin boards are internal)2.5.7Pointer-only single-click alternatives on customer-facing routes
Session/time limits in checkout (Stripe) and conversion polling2.2.1Warning + extension?
Character-key shortcuts in tag editor2.1.4Single-key shortcuts, if any, can be turned off/remapped
Mobile: iPad and Pixel 7 (config only emulates iPhone 14), touch targets, orientation1.3.4, 2.5.8Playwright device matrix + real devices
Forced-colors impact of G81.4.11, 2.4.7Windows High Contrast / Edge forced-colors emulation

3. Roadmap

Priorities: P0 = blocks an honest VPAT or is a verified AA failure on a core flow; P1 = verified gap on a secondary surface or WCAG 2.2 AA new criteria; P2 = best practice / AAA / procurement nice-to-have.

Quarters: Q4 2026 = Oct–Dec 2026 … Q3 2027 = Jul–Sep 2027. Note the ADA Title II compliance date for large public entities is April 26, 2027 — customers will scrutinize our own UI hardest in Q1 2027, so P0/P1 work is front-loaded.

IDItemWCAG SCCurrent statePriorityTarget
A1Formal manual audit (keyboard + NVDA/JAWS/VoiceOver + zoom) of all customer-facing routes; findings filed as issuesAllNot done — Needs manual testP0Q4 2026
A2Wire test:a11y into CI as a gating job; authenticated Playwright fixture; make dashboard/tag-editor specs assert zero violationsProcessDone for apps/web (#3661): the a11y (apps/web) and mobile (apps/web) jobs run on every PR that touches apps/web or its packages and on every push to main, and block merges through gate; naming them as required checks is pending #3619. Authenticated fixture: a mocked Supabase session against a mocked API; the Playwright network sandbox (apps/web/e2e/support/mock-backend.ts) aborts every request that is not local or to the mocked hosts. No spec passes unconditionally: expect(true) is gone, each route must render its own data before axe runs, and an unmocked call, blocked request or app-reported error fails the test. Done for apps/vpat (#3675): a11y (apps/vpat) and mobile (apps/vpat) gate merges through gate the same way; the sandbox also answers the app’s direct PostgREST reads from seed fixtures. The harness is shared (packages/a11y-harness). Done for apps/org-chart (#3676) the same way, plus a spec for the keyboard alternative to drag-and-drop reparenting on the preview. Done for apps/audit (#3674) the same way; the sandbox also answers its direct Supabase reads, and its scan clients now take the sandbox API host from NEXT_PUBLIC_A11Y_API_URL (production still always calls api.gevell.com)P0Q4 2026
A3Add axe specs for file detail, preview, wizard, remediation tools, settings, teams, tenant-admin (all pages), auth pages; run light + dark and each color scheme1.4.3, 4.1.2 etc.Automated part done for apps/web (#3661): every customer route (inventory apps/web/e2e/support/routes.ts, enforced by route-inventory.a11y.spec.ts) in light and dark, dashboard-shell routes in each color scheme, plus the 10 remediation-tool dialogs, the tools menu and the guided wizard; every route also at 375/768/412 px. Fixed in the same PR: dark-mode and badge contrast, duplicate <main> on login, tools-menu ARIA, unfocusable scroll panes, page reflow at 375 px, off-screen Download menu, dashboard file names hidden at 768 px, team tabs pushed off-screen. No WCAG (axe) exceptions; controls under the 44 px project standard are baselined in #3673 (expires 2027-03-31). Automated part done for apps/vpat (#3675): all 11 pages in light and dark (saved evaluation loaded from a seed record, auth error states, the audit trail and its commit drill-down with data loaded), and at 375/768/412 px with the primary flow (dashboard → saved report card → new-evaluation upload). Fixed in the same PR: dark-mode contrast on the hero, settings back link and password toggle; low-contrast confirm-page footnote; invalid <dl> nesting in the resource details; controls raised to 44 px. No WCAG (axe) exceptions; 44 px baseline in #3693 (expires 2027-03-31). Automated part done for apps/org-chart (#3676): every customer page (25 route states) in light and dark with a chart record loaded (editor, preview, branding, share in civic and radial, review), keyboard reparenting on the preview (move mode and after the move), and at 375/768/412 px with the primary flow (upload picker → editor → preview → Download menu). Fixed in the same PR: contrast on the marketing pricing copy, billing reference, usage and credit amounts, developer key field, review comment field and the radial error text; page-level overflow from the editor grid, dashboard status tabs and developer curl sample; the preview Download menu off-screen on phones; the side rail covering the left 64 px of every signed-in page on phones, and marketing/legal pages starting under the fixed header (both now caught by a new covered-control check); header, sidebar and dashboard row controls raised to 44 px. No WCAG (axe) exceptions; 44 px baseline in #3701 (expires 2027-03-31), editor people grid on phones in #3700 (expires 2026-12-31). Automated part done for apps/audit (#3674): all 6 pages (7 route states, including the sign-in error and callback landings) in light and dark with a credit balance and CI history loaded, plus a website scan and a PDF audit run against fixtures so both reports are audited with every collapsible section and markup viewer open and with the Download menu open; and at 375/768/412 px with the primary flow (scan a URL → report → PDF file picker). Fixed in the same PR: invalid <dl> in the report summary, a finding’s rule-reference link distinguished by colour alone, dark-mode contrast on the “Dark mode” finding badge, the pressed Show HTML toggle and the history summary labels; header, scan-form, history and report controls raised to 44 px. No WCAG (axe) exceptions; 44 px baseline for shared-package controls in #3772 (expires 2027-03-31). The manual keyboard/screen-reader pass is A1P0Q4 2026
A4Toast rework: pause on hover/focus, no auto-dismiss for anything with an action, single polite live region (no nested alert), max-w-[calc(100vw-2rem)], 24 px+ (target 44 px) dismiss targets2.2.1, 1.4.10, 2.5.8, 4.1.3Done (#3566): countdown pauses on hover and focus-within; toasts with an action or of type error/warning never auto-dismiss; visual toasts carry no live role — the provider owns one polite role=status region plus one assertive role=alert region for errors only; max-w-[calc(100vw-2rem)]; dismiss/copy targets were already 44 px (#3444)P0Q4 2026
A5Persistent dashboard announcer: one always-mounted polite live region announcing “X is processing / ready / failed”; throttle to state transitions4.1.3Done (#3567): useAnnounce() speaks through the toast provider’s always-mounted polite region; lib/dashboard-announcements.ts diffs file statuses on every file-list update and announces bucket changes only (uploaded / processing / ready / failed), collapsing to a count above 3 files; completion is announced once via the existing toast; wizard (S2) live role moved from the card to the phase text. Needs manual SR pass under A1P0Q4 2026
A6Replace title-only error text with visible/disclosable text linked via aria-describedby1.3.1, 3.3.1Verified (G5)P1Q4 2026
A7Target-size sweep to ≥ 24 px everywhere (AA) and 44 px on primary controls (project rule); lint rule for p-0.5/p-1 icon buttons2.5.8Verified (G6)P1Q1 2027
A8Focus-not-obscured: scroll-padding-top/bottom equal to fixed bar heights; ensure toasts/banners never cover focused elements2.4.11Suspected (S1)P1Q1 2027
A9Reflow fixes: responsive skeletons, toast width, tables → stacked layout under 640 px; verify at 400%1.4.10Partial (#3571): G12 skeleton now w-[612px] max-w-full aspect-[612/792]; G3 toast width now capped at max-w-[calc(100vw-2rem)] (done under A4, #3566). Tables step 1 (PR for #3571): all 30 rendered customer-facing tables in apps/web wrapped in TableScroller (scope: everything outside app/admin/**; excludes the unreferenced ClassicDashboard.tsx and the HTML-string report table in pipeline/page.tsx). 7 had no scroll wrapper: 5 were clipped by CCPageShell or their own overflow-hidden card, 2 forced page-level horizontal scroll. Every scroll region is now a focusable labelled group when it overflows on either axis (2.1.1), with an inset focus ring so overflow-hidden cards can’t hide it (2.4.7). Step 2 (PR for #3571): StackedTable in @accessible-org/ui collapses record-style tables into labelled cards below 640 px (real <table> kept, ARIA roles restored, data-label from headers); adopted on 14 apps/web tables (transactions ×2, budget alerts, API keys, webhook deliveries, team members + allowances, URL results, tenant-admin users/departments/domains/SSO logins, S3 + SharePoint sync events). Left scroll-in-place on purpose: comparison grids (pricing, benchmark, pipeline, remediation console ×4, font audit), the already-responsive dashboard file table, and the per-group usage matrices (tenant usage ×2, department caps/usage) whose columns are metered groups meant to be compared across a row. Step 3 (2026-09-27): manual-run 320 px sweep (tools/a11y-reflow-sweep) of 57 live public routes in light and dark found one page-scroll bug (gevell.com/why-gevell H1, fixed in #3801), one table that scrolled in an unfocusable region (orgchart /wcag, stacked in open PR #3802), and a clipped third-party API-docs button (pdf /docs/api, open). Results and the 400% manual checklist: a9-reflow-400-zoom-checklist.md. Remaining: the manual 400% pass and VoiceOver check; a CI reflow gate at 320 px (a harness VIEWPORTS entry, plus a reflow check in the nightly contrast-sweep for signed-in screens) — Needs manual testP1Q1 2027
A10Forced-colors support: @media (forced-colors: active) focus outlines (outline: 2px solid CanvasText), status badges with borders, icons with currentColor1.4.11, 2.4.7Verified absence (G8)P1Q1 2027
A11Enforce 12 px minimum text in apps/web (font-size: max(12px, 1em) floor like apps/home; replace text-[9-11px])1.4.4 (risk), project ruleVerified (G7)P1Q1 2027
A12Screen-reader UX for the tag editor & reading-order/tab-order tools: documented keyboard model, aria-keyshortcuts, announcements after every reorder, SR-test scripts2.1.1, 4.1.2, 4.1.3Partially in place (1.2); Needs manual testP1Q1 2027
A13Consistent help: a Help/Support entry in the same location on every template (header or footer), incl. file detail, tenant-admin, auth3.2.6Needs manual testP1Q1 2027
A14Redundant entry review of checkout / registration / intake / invites3.3.7Needs manual testP2Q2 2027
A15Accessible authentication re-verification (OTP paste, password-manager fill, SSO) — add to E2E3.3.8Likely supports (1.2); confirmP2Q1 2027
A16Preview semantics: state in the preview region that the accessible HTML/tagged PDF is the accessible equivalent; offer “open accessible version” link adjacent1.1.1, 1.3.1Suspected (S5)P2Q2 2027
A17Tenant branding contrast: clamp tenant colors to ≥ 4.5:1 wherever they color text (reuse branding page’s effective-color logic)1.4.3Suspected (S4)P1Q1 2027
A18Fix unhedged login tagline (G11) and add CI grep to the claims-audit guardPolicyVerified (G11)P0Q4 2026
A19Publish VPAT 2.5 (WCAG 2.2 + 508 + EN 301 549) for Gevell PDF after A1–A5, dated and signed; semi-annual refresh thereafter; ACR for each Gevell product on the same cadenceProcurementVerified draft (G2)P0Draft Q4 2026; published Q1 2027; refresh Q3 2027
A20help.gevell.com “Accessibility features” page: keyboard shortcuts, SR tips per tool, supported AT matrix, how to report issues (accessibility@gevell.com), conformance status link3.2.6 supportVerified absence (G10)P1Q1 2027
A21Mobile device matrix: add iPad + Pixel 7 projects to playwright.config.ts, run test:mobile in CI1.3.4, 1.4.10, 2.5.8Config has iPhone 14 onlyP1Q1 2027
A22Adopt WCAG 2.2 AA as the product standard (CLAUDE.md, statement page, VPAT); axe tags already include wcag22aaAll 2.2Standard is 2.1 AA todayP1Q1 2027
A23Internationalization: externalize strings (react-i18next/next-intl per project standard), ship Spanish UI first; lang switching; RTL-safe layout audit3.1.1/3.1.2 hygiene; Title VI LEPVerified gap (G9)P2Spanish Q3 2027
A24Accessibility regression dashboard: trend axe violations per route in CI artifacts; Grafana panelProcessNot presentP2Q2 2027
A25User research: 2 sessions/quarter with disabled users (screen reader, switch/voice control, low vision) on the remediation toolsAllNot presentP2Q2 2027 onward
A26AAA-leaning enhancements where cheap: 2.4.13 focus appearance (3 px #046307 ring per design system), 2.3.3 animation from interactionsAAAPartially (2 px ring today)P2Q3 2027

4. Answers to “What accessibility features are we missing?”

In order of impact:

  1. Proof. We have no current, dated conformance evidence for our own app: the VPAT is a draft with 51 TBDs and the a11y test suite isn’t run in CI (G1, G2). This matters more than any single bug for procurement.
  2. Announcements for long-running work. Screen-reader users get a 5-second toast when a conversion finishes and live regions that appear and disappear with the status (G3, G4). A persistent, throttled announcer is needed.
  3. WCAG 2.2 AA items. Focus-not-obscured (S1) and target size (G6) are the likely failures; dragging (2.5.7) and accessible authentication (3.3.8) look good.
  4. Forced-colors / high-contrast support — none at all (G8).
  5. Reflow and small text — fixed-width toast/skeleton, 59 sub-12 px text uses (G7, G12).
  6. Documentation of accessibility features for users (G10) and a published accessibility conformance cadence.
  7. Languages other than English (G9).

5. Separate track — accessibility of generated output

The product’s output quality is a different promise from the UI’s accessibility and should be reported separately in questionnaires.

IDItemCurrent stateTarget
O1PDF/UA-1 machine validation (veraPDF) on every tagged PDF, result shown to userIn place for the tagged-PDF paths (veraPDF referenced from workers/api/src/scheduler/chunk-scheduler.ts, utils/flyer-report.ts, utils/tag-tree.ts)Maintain; publish pass-rate metric quarterly — Q1 2027
O2WCAG 2.1 AA automated check of generated HTML (axe) with the hedged “passed our automated checks” languagePolicy in docs/admin/accessibility-claims-audit.mdAdd WCAG 2.2 rule tags + corpus benchmark — Q1 2027
O3Human-review requirements for reading order / alt text are surfaced to users (never “machine-verified accessible”)Partially — bulk epic #3364 requires human reviewQ2 2027
O4Corpus regression benchmark (PDF/UA pass %, alt-text coverage, table header accuracy) published to customersInternal tooling exists (tools/pdf-inventory/)External-facing summary Q2 2027
O5Output-format parity: EPUB/HTML output conformance statementNot startedQ3 2027

6. Effort (rough)

BundleItemsEngineer-days
Test harness & CI gatingA2, A3, A21, A246–8
Manual audit (internal or external firm)A15 internal days or ~$8–15k external
Announcements + toastsA4, A5, A64–5
WCAG 2.2 + visual sweepA7, A8, A9, A10, A11, A178–10
Tag editor SR hardeningA12, A165–8
Docs, VPAT, policyA13, A18, A19, A20, A225–6
i18n (Spanish)A2315–20 (+ translation cost)

7. Suggested questionnaire wording

Yes. Gevell maintains a dated accessibility roadmap for Gevell PDF, reviewed quarterly. Our product standard is WCAG 2.1 Level AA, and we are adopting WCAG 2.2 Level AA in Q1 2027. Current state: automated axe-core accessibility tests (WCAG 2.0/2.1/2.2 A and AA rules) and keyboard-navigation tests are part of our test suite; our help site is scanned against WCAG 2 AA on every change; drag-and-drop interactions have keyboard and button alternatives; sign-in supports password managers, one-time-code autofill and SSO with no cognitive tests; and the interface honors reduced-motion preferences.

Planned delivery: Q4 2026 — full manual audit with NVDA, JAWS and VoiceOver; automated accessibility testing of every authenticated page as a required check before release; improved screen-reader announcements for document-conversion progress and notifications. Q1 2027 — WCAG 2.2 AA remediation (target size, focus not obscured), Windows High Contrast / forced-colors support, 400% zoom reflow fixes, an accessibility-features guide on help.gevell.com, and a published VPAT 2.5 (WCAG 2.2, Section 508, EN 301 549). Q2–Q3 2027 — usability sessions with users with disabilities, public accessibility metrics for generated documents, Spanish-language interface, and a semi-annual VPAT refresh. Known issues are tracked and prioritized in our issue tracker; accessibility issues can be reported to accessibility@gevell.com. The roadmap document is available on request under NDA.

Do not attach this internal file as-is; send a customer-facing summary of section 3. Update the “current state” sentence as A2/A19 land — do not claim a published VPAT before A19 ships.