Sulture WCAG 2.2 AA · August 2026
Design impact

Accessibility assessment for Queer East

19 of 86 audit findings alter rendered output. 10 require a design decision.

Standard
WCAG 2.2 Level AA
Scope
24 routes × 2 viewports — 1440×900, 390×844
States exercised
Nav drawer, filter popover, filter modal, search overlay, basket drawer
Method
axe-core 4.13 + Lighthouse, then 6 reviewers by hand and script
Sample
2,222 interactive elements measured
Conditions
Default · 200% zoom · 400% reflow · text-spacing · forced-colors · reduced-motion
Build under test
queer-east.vercel.app — not queereast.org.uk, which remains the previous site
Excluded
Screen-reader passes · browsers other than Chrome · Shopify checkout (password-gated)
Values
Computed from the live DOM. Contrast ratios calculated, not sampled
7 Tonal Colour and state; no reflow
9 Geometry Spacing and size; 1 unavoidable
3 New surfaces Do not exist; require design
10 Decision required Remaining 9 proceed unblocked
Index

All 19 changes

Ten items are blocked on a design decision; nine have a determined answer and are listed for visibility only. Item 01 gates five others — they resolve automatically once its token value is set.

#ChangeGroupDecision
01Muted grey gets darker, everywhereTonalToken value; site-wide
02Three form fields gain a focus ringTonalDetermined — ring or thickened underline
03Form field underlines become visibleTonalBorder token at 3:1
04Hover and focus stop dimming textTonalNone — resolved by 01
05Grid / list toggle needs a second cueTonalPressed-state treatment
06Map markers get darker and biggerTonalMap design pass
07Icons vanish in Windows High ContrastTonalSVG redraw or forced-colors border
08Footer gets ~150px taller on mobileGeometryAccept height or restructure
09Nav drawer links gain ~3px eachGeometryDetermined — minimum spacing
10Filter rows gain a few pixelsGeometryNone
11Card titles stop being truncatedGeometryNone
12/about emails stop being clippedGeometryDetermined — verify wrap
13Film Index must stack and scrollGeometryFull-bleed treatment below threshold
14Hover content needs a dismissGeometryDismiss handler or always-visible
15Carousel dots gain a bigger hit areaGeometryDetermined — inactive dot colour
16Type scale moves from px to remGeometryNone
17Venue and screening access infoNewTwo surfaces + tag taxonomy
18Country list beside the Film Index mapNewHidden list or visible list
19An accessibility statement pageNewNone — template exists
Group one

Tonal — visible, but nothing moves

Colour and state only. No reflow, no repositioning, no impact on approved layout. Item 01 gates items 02, 04, 05, 06 and 15 — all resolve once its value is set.

01

The muted grey gets darker, everywhere

Decision needed858 failures119 usages

--color-grey: #A2A2A2 is the site's only muted-text colour. It is used 119 times across 60 stylesheets and never reaches the 4.5:1 minimum on any surface it is painted on. Every one of the 858 contrast failures in the audit is this single value.

Changing it is a one-line fix that clears all of them, and it is the most visible change in the programme: category labels, screening times, author bylines, venue cities, footer fine print and the translated film titles all become noticeably more solid.

Aa
#A2A2A2
2.55 · 2.38 · 2.12
Current — fails
Aa
#767676
4.54 · 4.24 · 3.78
White only
Aa
#717171
4.88 · 4.56 · 4.06
Minimum
Aa
#6F6F6F
5.02 · 4.69 · 4.18
Recommended
Aa
#595959
7.00 · 6.54 · 5.82
Reaches AAA

Measured against #ffffff · #f7f7f7 card surface · #eaeaea chips.

Decision needed

Pick the value. Do not stop at #767676 — it is what most contrast checkers suggest, but 470 of the 858 failures sit on the #F7F7F7 card surface, where it still fails at 4.24:1. #6F6F6F is the safe pick. #595959 buys AAA for the same effort, at the cost of more of the pale register.

02

Three form fields gain a focus ring they do not currently have

Free — deleting CSS

The newsletter, donate and search inputs each set outline:none on :focus-visible with nothing in its place. Measured focus-indicator contrast: zero. The only feedback a keyboard user gets is the text caret.

The site's global focus ring is genuinely good — 2px blue at 8.59:1, clearing even the AAA standard. These three rules simply cancel it. Deleting them restores the ring already designed.

Minor design call

A hard blue ring may sit awkwardly on a bare underlined field. The alternative that keeps the aesthetic: move the underline to --color-blue and thicken it on focus. Either satisfies the criterion.

NewsletterForm.module.css:39DonateForm.module.css:40SearchOverlay.module.css:57 Footer — on every page
03

Form field underlines become visible

Decision needed

The only boundary marking the newsletter and donate fields is --b, a 0.75px #EAEAEA rule at 1.2:1 against white. The minimum for a control boundary is 3:1. The search input has no boundary at all.

Worth noting how these compound: the fields have a visually hidden label, a near-invisible border and no focus ring — so the placeholder is currently the field's only visible identity, and that sits at 2.55:1 too.

Decision needed

Introduce a separate boundary token. #8F8F8F gives 3.23:1 on white and 3.02:1 on cards. Keep --color-grey-mid for decorative rules — only the four that bound actual controls need to change.

globals.css:109Footer forms
04

Hover and focus currently make text harder to read

Free — fixed by 01

14 rules set text to the muted grey on hover and focus, so interacting with a link drops it from 8.59:1 to 2.55:1 — including the primary “Add to Basket” and “Book” buttons. Scanners never caught these because they only test the resting state.

Item 01 fixes them automatically. The pattern is worth a look though: a hover or focus state should raise contrast, not lower it. If the intent was to dim, something other than colour should carry it.

AddToBasketButton.module.css:14EventBookings.module.css:62+12 more /shop — Add to Basket
05

The grid / list toggle needs a non-colour pressed state

Decision needed

The inactive icon sits at 2.12:1, and the list glyph is a 0.75px rule at that contrast. More importantly the pressed state changes only the glyph's hue — the button chrome is identical in both states, so the selection does not survive greyscale or high-contrast mode.

The grid and list view toggle, with the inactive list icon barely visible against its light grey button.
Measured — active #0000FF, inactive #A2A2A2 at 2.12:1, both on #EAEAEA. Identical chrome.
Decision needed

Give the pressed button a second cue — a filled ground with an inverted glyph, or a border. Item 01 lifts the inactive icon to roughly 4.5:1 on its own, but the state ambiguity is a separate problem.

ArchiveViewToggle.module.css:13,34,54/whats-on/news
06

Map markers get darker and bigger

Decision neededAlso geometry

The Film Index country dots are #A2A2A2 at 2.18:1 on the land fill and need 3:1. They are also 12px across against a 24px minimum, so circle-radius goes from 6 to 12 — a visible change in the map's density.

Related: Hong Kong and Macau sit 5.5px apart and already render as one blob. Doubling the radius makes that worse, so they need a collision offset or a stroke.

The land, sea and border fills deserve a look independently — #ededed land against #f7f7f7 sea is 1.09:1, and the country borders are 1.16:1. The geography is effectively a flat field right now.

Film Index map at desktop width, with pale grey country markers on a near-white landmass.
Desktop — markers at 2.18:1
Film Index map at 390 pixels wide, with markers overlapping around Hong Kong and Macau.
390px — HK and Macau overlap, 5 countries off-screen
Decision needed

This is a map design pass, not a token swap: marker colour, marker size, collision handling, and whether land, sea and border separation should be readable at all. Selection is also a pure hue swap today — it needs a size or stroke change to read without colour.

FilmIndexMap.jsx:15,19-21,80-89/film-index
07

Icons disappear entirely in Windows High Contrast

Decision needed

Icons and indicators are drawn as background-coloured <span> elements rather than glyphs or SVG. Forced-colors mode strips backgrounds, so the view toggle, the event status dots and every chip fill vanish completely. Text is rescued correctly; the icons are not.

The What's On page rendered normally, with visible filter chips and view toggle.
Normal rendering
The same page in forced-colors mode, where chip fills and view toggle icons have disappeared.
Forced colors — toggle and chip fills gone
Decision needed

Redraw these as SVG with currentColor, or as text glyphs — the filter option list already does this correctly with ○ and ●. Alternatively add a forced-colors block giving each a CanvasText border.

ArchiveViewToggle.module.css:33-58EventStatusDot.module.css:9/whats-on
Group two

Geometry — things that move

578 target-size failures reads as a layout rewrite. It is not — WCAG 2.2 permits target size to be satisfied by spacing rather than padding, so most cases resolve by adding gap, not size. Only item 08 is genuinely unavoidable.

08

The footer gets about 150px taller on mobile

UnavoidableDecision needed288 failures

The social, contact and legal links are display:block; width:100% at the small type size, so 12 links stack one per line at 11.6px pitch with zero gap. The measured safe clickable diameter is 0.0px — adjacent targets touch exactly.

Reaching the 24px minimum costs about 12.4px per link, whether by padding or by gap. Twelve links, so roughly 150px of extra footer height on mobile and 107px on desktop. This is the one fix in the whole programme that cannot be made free.

Decision needed

Either accept the taller footer, or restructure. Two columns on mobile would absorb most of it, and the legal links in particular could sit inline rather than stacked.

Footer.module.css:56-64Any page — scroll to footer
09

Nav drawer links need about 3px more room each

288 failures

Drawer links are 22px tall at 20.9px pitch with no gap, so their target circles overlap. The audit proposed 12px of padding per link, which would add roughly 155px. The spacing route needs only about 3px per link — roughly 40px across the drawer.

The mobile navigation drawer at 390 pixels wide, with tightly stacked links and no vertical separation.
390×844 — 12 of 13 links fail. Pitch 20.9px, needs 24px.
Design call

3px is nearly invisible and clears the requirement. More generous spacing reads better but pushes the lower links further down — and at 400% zoom the drawer already shows only about 2.5 links at a time (item 13).

Nav.module.css:184-186Open the menu at mobile width
10

Filter option rows gain a few pixels each

Barely visible

Every checkbox and radio row is a zero-padding label at 20.9px pitch. The real <input> is clipped to 1×1px, so the label is the target. The calendar quick-range rows measure a safe diameter of 0.1px.

Adding around 3px per row inside a container that already scrolls is effectively unnoticeable — though with up to 98 options in the modal it adds roughly 300px of scroll length.

The mobile filter modal with the Role section expanded, showing densely stacked option rows.
Mobile modal — 98 rows at 20.9px
The desktop filter popover on What's On, with option rows 18.6 pixels tall.
Desktop popover — 18.6px tall
ArchiveOptionList.module.css:10-19/whats-on/venues
11

Card titles stop being silently truncated

Zero change at default

Card bodies use a fixed height: 157px with -webkit-line-clamp: 2. When a reader applies the standard text-spacing adjustment — a documented AA requirement — titles push out of the clamp and are cut off with no ellipsis. On the programme page one title loses 75px of content and renders as “The Spring Outside of”.

An event card title rendering fully inside its fixed-height box.
Before — fits, 28px of 28px
The same card with text spacing applied, its title cut off mid-phrase with no ellipsis.
Text spacing applied — 75px hidden, no ellipsis

The fix is nearly free. Swapping height for min-height produces zero visual change at default settings — the cards sit in a repeat(4, minmax(0,1fr)) grid, and grid already stretches row siblings to match. A row grows only when a title genuinely needs a third line, and the cards within it stay aligned.

EventCard.module.css:63-69, 310-312ArticleCard.module.css:35-41 /programme/queer-east-2026
12

Contact emails on /about stop being clipped

Fixes a live bug

The contact email links overflow their grid column and are cut off by overflow-x: clip at every viewport between 781px and 1338px — exactly where 200% zoom lands a normal desktop window. A maximised 1920px screen at 200% renders submissions@queereast.org.uk as “submissions@queerea”.

One of the two affected links is, with some irony, the Accessibility contact address.

The About page contact block at 960 pixels wide, with an email address cut off mid-word at the column edge.
960px — overflows by 94.5px, silently clipped

Adding overflow-wrap: anywhere fixes it — the grid already uses minmax(0, 1fr), so wrapping is all that is missing. A wrapped email address across two lines is a look worth checking though.

ContactBlock.module.css:24-30, 58-64/about — resize to ~960px
13

The Film Index has to be allowed to stack and scroll

Decision needed

The page locks itself to viewport height with overflow: hidden. At the 400% zoom condition the map collapses to 99px tall and the zoom-in control is clipped out of reach, with no scroll to recover it. Since the map is the page's only navigation, the page becomes inoperable.

The Film Index at 320 by 256 pixels, the map collapsed to a thin strip with its zoom control cut off.
320×256 — map is 99px, zoom-in clipped
The navigation drawer at 320 by 256 pixels, where the newsletter and donate forms fill most of the panel.
Drawer at the same size — forms take 64%
Decision needed

Below a height threshold, let the page stack normally instead of filling the viewport. That changes the Film Index's defining full-bleed treatment at small sizes — worth deciding deliberately rather than letting a media query decide it. Same question for the drawer, where the two forms should shrink or scroll with the links.

film-index/page.module.css:55-79Nav.module.css:147-186/film-index
14

Hover-revealed content needs a way to dismiss it

Decision needed

Two hover behaviours reveal content that overlays other content and cannot be dismissed without moving the pointer. Event card badges cover the bottom 26px of the card image. The archive row thumbnail is a 220×140px panel that follows the cursor, so it can never be hovered off either.

An event card at rest, its image unobstructed.
At rest
The same card on hover, badges overlaying the lower part of the image.
On hover — badges cover 26px of image
A homepage archive row with a large thumbnail panel floating over the list, following the cursor.
Homepage archive — 220×140px, tracks the cursor
Decision needed

Simplest fix is an Escape handler that hides them. For the card badges there is a cheaper option: they are already permanently visible on mobile, so making that universal removes both the problem and the interaction. That is a design preference, not a technical one.

EventCard.module.css:35-53ArchiveBlock.module.css:74-97 /whats-on — hover a cardHomepage archive rows
15

Carousel dots keep their size but gain a bigger hit area

Visually identical

The slide indicators are 8×8px dots 6px apart — a safe clickable diameter of 4px against a 24px minimum. Inactive dots are also #EAEAEA on white, which is 1.2:1 and so effectively invisible.

Transparent padding with background-clip: content-box keeps the painted dot at exactly 8px while the target grows to 24px. The visual stays identical — only the inactive colour needs a decision.

FeaturedProductGallery.module.css:70-89Homepage featured carousel
16

The type scale moves from px to rem

Zero change at default

Every font size is an absolute px token, so a reader's browser font-size preference currently has literally no effect on this site. Converting at 16px = 1rem renders identically at default settings — it changes behaviour only for someone who has asked for larger text.

Why it matters: with type doubled, clipped containers jump from 2 to 123 on /venues, because single-line text sits in line-height-height boxes with overflow: hidden. Those need min-height too.

The Venues page at 200 percent text size, row labels with descenders sliced off and the nav bar text overlapping.
Text at 200% — descenders sliced (“Cambridae”, “Enaland”), nav overlapping
globals.css:74-81, 145-154VenueRow.module.css:24-31/venues
Group three

New surfaces — things to design

Three surfaces that do not currently exist. Item 17 ranks highest in the audit by user impact — above every technical finding in this register.

17

Venue and screening access information

Highest valueDecision needed

The venue schema has four fields: name, url, city, country. There is nowhere to record step-free access, a hearing loop, an accessible toilet, wheelchair spaces or an access booking contact — so an editor cannot publish it even if they want to. Thirty venues are live with none of it.

A keyword sweep across /venues, /about and an event page for step-free, wheelchair, hearing loop, audio described, relaxed, lift, accessible toilet returned zero hits. BSL, Captioned and Subtitled tags do exist in the CMS — applied to zero events.

For an arts charity this typically carries as much weight as technical conformance. A screen-reader problem can be worked around; not knowing whether the building is enterable cannot.

Needs designing

Two surfaces: an access block on the venue row or venue detail, and per-screening access badges on the event page. Plus an “accessible screenings” filter, which the existing chip pattern can carry. Worth designing the taxonomy alongside — the current tag list mixes access (BSL, Captioned) with marketing (Opening Night, Free Entry) in one undifferentiated row.

sanity/schemas/venue.jssanity/schemas/event.js/venues/events/bunny
18

A country list beside the Film Index map

Decision needed

The map is currently the only way to select a country, and it is a GPU canvas layer with no DOM nodes — so it cannot be reached by keyboard at all. A full tab traversal is 31 stops and none reach a country. The entire visible text of the page is “Select a Country”.

The content already exists: deep-linking ?country=japan renders a correct heading and a working list. Rendering the countries as real links resolves four separate failures at once.

Decision needed

This can be a visually hidden list — costing nothing and changing nothing — or a visible list beside the map, which is better for everyone and arguably a better page. That is the call: minimum compliance, or an actual improvement.

19

An accessibility statement page

Template exists

The footer already links to /accessibility. That route returns 404, as does /imprint. The site advertises a statement that does not exist, which reads worse to a reviewer than having no link at all.

Minimal design work — the legal/[slug] template already handles privacy, cookies, terms and shipping. It needs content, not layout. One caveat: those legal pages currently render no heading at all, so the template needs an <h1> adding first.

Excluded from this register

No visual impact

The remaining 67 findings alter no rendered output. Listed by area for completeness; no design review required.

AreaWhat changesVisual impact
ARIA roles and structureGallery tab roles removed, calendar rows added, radiogroup moved off list elementsNone
Focus managementFocus moves into menus and popovers, returns to trigger on close, background made inertNone
Status messagesVisually hidden live region announcing result counts after filteringNone
Headingsh1 added per route, per-card headings on programme pagesNone if styled
Duplicate IDsFooter forms switched to generated IDsNone
Alt text261 gallery images backfilled, 8 schema fields made requiredNone
Languagelang added to CJK, Thai and Devanagari title translationsNone
KeyboardSpace key no longer swallowed, scroll padding added so focus clears sticky barsNone
Reduced motionCarousels respect the preference, three smooth-scroll calls gatedNone by default
FormsNewsletter wired to a real provider, donate amount parsing fixedNone