Accessibility
Last full sweep September 6, 2026 · the code checks below last run August 29, 2026
This is a report card, not a pledge. Every number below came from a check we run against our own code, and where a check reports something bad, the bad number is on this page. We would rather publish a real 43 than a comfortable claim about “full keyboard support”.
We target WCAG 2.1 Level AA. We have not been independently audited against it and we do not claim conformance — what follows is what we measured ourselves.
Where we stand, and how we know
The standard we aim at is WCAG 2.1 Level AA. We test against WCAG 2.0, 2.1 and 2.2 at levels A and AA, and we pass some 2.2 criteria — but passing some is not conforming, so we claim 2.2 nowhere.
How the September 6 sweep was run. Two instruments, because neither one is enough. An automated pass with axe-core 4.13 over every page this site has — all 36 addresses, plus the district card’s nine tabs and the map with its sidebar open — at desktop and phone width, in light mode and dark, with real data loaded rather than empty screens. That is 46 screens and 184 runs. Then a keyboard walk of all 36 by hand: tab through the page, check the order, check the focus outline, try to escape every panel that opens.
What that cannot tell you, stated plainly. Automated checking finds a minority of accessibility problems. Deque, who make the checker we use, measured their own tooling at about 57% of issues found across 13,000 pages; the older industry figure is 20–30%. Counted a third way — by how many of the rules it can even have an opinion about — axe-core 4.13 has at least one test for 23 of the 55 WCAG 2.2 A and AA success criteria, and no test at all for the other 32. Nothing automated can judge whether a heading describes what follows it, whether an error message tells you how to fix the error, or whether the tab order matches the reading order. Those need a person, and a person we have not hired.
What does not conform right now
Three WCAG success criteria fail somewhere on this site, in eleven separate places. On September 5 it was five criteria in 57 places; what changed in between is listed under “what we fixed” below, and nothing has been removed from this list for any other reason. Each is named in plain language with the number of separate places it occurs — counted once per place, not once per screen size, because the same button measured four times is one problem.
- Text too faint against its background (1.4.3, AA) — 8 places. Five of them are the milestone badges on your Civic Record, drawn at 45% opacity until you earn them, which takes their label down to 1.84:1 against a 4.5:1 requirement — the worst number in this sweep, on exactly the text that tells you what you have not done yet. Two are the draft-notice banners on the legal pages. One is a small purple level tag in the map sidebar.
- A control a screen reader cannot name (4.1.2, A) — 1 place. The map preview on the homepage. Our checker reports it and we have not been able to reproduce it by hand, so we are not going to describe it as settled either way.
- Touch targets under 24 pixels (2.5.8, AA, from WCAG 2.2) — 2 places. The show-password button on the password-reset page, which measures 13×13, and the clear-location button in the map sidebar.
Two more that no automated checker reports, both about the sign-in dialog: it does not return you to where you were when you close it, and it does not tell a screen reader that the rest of the page is inactive while it is open. The search panel does both of these correctly, which is how we know they are fixable.
One thing on this page was wrong and is corrected here rather than quietly deleted. On September 5 we published that the Recent / Most copied sort control on the letters page “cannot be reached by keyboard at all”. It can. That claim came from reading the page’s code rather than pressing the keys: the control hands its keyboard stop inward at the moment focus arrives, which a code reading cannot see. Driven for real, it is reached by tabbing and the arrow keys move between the two options. What was broken — the sort buttons pointing at a panel that did not exist — is fixed.
What we fixed between September 5 and September 6. Links inside paragraphs are underlined, so they are no longer told apart from the text around them by color alone (1.4.1, was 18 places, now none). The cyan we picked to make map pins stand out is no longer used as small heading text, where it measured 3.3:1 (25 of the 33 contrast failures). The “skip to main content” link now moves focus on all 36 pages — it did nothing on five, three because the thing it jumped to could not hold focus and two because the 403 page a signed-out visitor gets had nothing to jump to at all (2.4.1, now none). The show-password button has a name. The weekly brief’s lead item is inside a real list (1.3.1, now none).
We are not going to write “we are working on it” next to the three that remain, because no further repair work is scheduled yet. When a fix is queued, this page will say which one and stop saying it about the rest.
Color contrast — measured, every value
Recomputed from the actual color tokens using the WCAG 2.1 formula, checked first against an answer we already knew (black on white must come out at 21:1, and does). Ratios are against the page background:
| Text | Color | Ratio | Grade |
|---|---|---|---|
| Body and headings | #131C17 | 16.7:1 | AAA |
| Secondary text | #3D4A43 | 8.9:1 | AAA |
| Muted text | #5D6A62 | 5.4:1 | AA |
| Faint text (captions, dates) | #647169 | 4.9:1 | AA |
| Green links and actions | #3F6F5F | 5.5:1 | AA |
Every text color clears AA at any size, and two clear AAA. The three smaller-text colors do not reach AAA, and we are not going to describe that as anything other than what it is. Party affiliation is never carried by color anywhere on the site — every party gets identical treatment, which is a neutrality rule that happens to be an accessibility one too.
Windows High Contrast and forced colors
Re-audited on the date above across 8 screens and 309 controls: zero controls whose selected and unselected states are indistinguishable. When this audit was first written it found seven — on five screens the current page in the top nav rendered identically to every other destination. The cause was that selection was carried by a translucent white wash, and 8% white over a forced white background composites to plain white. Selection is now structural: an outline keyed to the control’s own ARIA state, so a control added later is covered without anyone having to remember to.
Still wrong, and measured rather than fixed: SVG icon colors are not forced by the operating system, and nine icons on the Civic Record page keep an author color in that mode.
Keyboard
A “skip to main content” link is on every page, and on all 36 of them activating it moves focus into the page body. It is the first thing you reach on 35 of the 36: the exception is Search, which puts your cursor in the search box as soon as it loads, so the skip link is sixteen Shift+Tab presses back up. That is the measured number, not an estimate, and it is a fair trade only if you came to Search to search. Search is fully keyboard-driven: arrow keys move through results, Enter opens one, and Escape closes the panel and returns focus to where you were rather than dropping it at the top of the document. Arrow navigation steps over rows that cannot take focus — on a real 51-row result set, 38 rows are focusable and the arrows skip all 13 that are not. That was a bug once: pressing End used to stall on row 2 of 51, silently.
Screen readers
Twenty-seven live regions across sixteen components announce the things that change without a page load — form errors, save confirmations, toasts, loading and empty states. Errors are announced as alerts; ordinary status changes are announced politely, so they do not interrupt what you are reading.
What is still wrong
43 form controls have no accessible name. A screen reader reaches them and has nothing useful to say. The count runs on every test run and is only allowed to fall. Where they are:
| Admin dashboard (staff only) | 16 |
| Admin meetings (staff only) | 15 |
| Bills | 7 |
| Letters | 2 |
| Sponsor | 2 |
| Password reset | 1 |
| Total | 43 |
31 of the 43 are on two staff-only admin screens no visitor can reach. That makes them lower priority; it does not make them acceptable, and it is not a reason to quote a smaller number. The 12 on pages you can actually reach — Bills, Letters, Sponsor, the district panel and password reset — are the ones being fixed first.
The map is a canvas, and nothing drawn on it can be read aloud. The interactive map draws to a <canvas> element. Tabbing does reach the canvas — it is announced as a region called “Map” — but the districts, boundaries and pins painted inside it are pixels, so no screen reader can read them and no keyboard can move between them. That is structural to every web mapping library, not something we chose. Corrected September 5, 2026: this page previously said the canvas could not be reached by keyboard at all, which was wrong — it is focusable. What is unreachable is its contents. It is tolerable only because everything the map shows is reachable without it: a “pins in view” panel sits beside the canvas as ordinary buttons and appears when you tab to it, the district panel lists the same officials, bills, events and news as keyboard-navigable rows, and the weekly calendar covers the same meetings and legislation without touching the map. Whether that is genuinely sufficient is a question we would rather hear answered by someone who relies on it than decide for ourselves.
There is no mobile bottom tab bar. Our own design spec calls for one and it has not been built, so small-screen navigation runs entirely through the top nav. Third-party embeds — map tiles, and the bill text and news articles we link out to — are outside our control and we make no claim about them. Some lower-traffic pages, including the admin screens above, have never had a full pass.
Tell us what we missed
The list above is what our own instruments can see, which is not the same as what is actually in your way. If you hit a barrier anywhere on Rallybase, write to support@rallybase.org — the contact page lists what helps us reproduce a problem fastest. Naming the page and the assistive technology you were using is usually enough. We have no response time we can honestly promise, so we will not print one; we read everything that arrives.