Accessibility
This page documents the specific decisions made in this build, not a generic policy. If something below stops being true, it's a bug — please report it.
Motion
The motion toggle in the header (Motion: on/off) is a real CSS state —
html[data-motion] — not a one-time sweep over running animations. It
defaults to your OS's prefers-reduced-motion setting and is remembered
across visits via localStorage.
Under reduced motion or the toggle set to off:
- The fridge door is already open on load. There is no swing animation to sit through.
- The pull-tab's idle "breathing" glow animation is disabled.
- The shelf-item physics nudge (hover-to-jostle neighbours) is a no-op.
-
The condensation effect's SVG
<animate>is explicitly paused viaSVGSVGElement.pauseAnimations()— CSS media queries cannot reach SMIL animations inside an SVG filter, so this one is paused with JavaScript, watching both the toggle and the OS setting. - View Transition morphs (shelf item → story panel) fall back to an instant swap.
Keyboard
- Opening the fridge door is drag-operable, but dragging is never the only way — Enter or Space on the pull-tab toggles it fully open or closed. This satisfies WCAG 2.5.7 Dragging Movements (AA): every dragging interaction on this page has a single-pointer, non-dragging equivalent.
- Shelf items are laid out as a real 2D grid widget: arrow keys move
focus row/column, Home/End jump to the first/last item, and
only the currently-focused item is in the tab sequence (roving
tabindex). - The jar-in-the-back puzzle in the freezer is two ordinary buttons — no drag, no timing requirement. Moving both reveals a third button; there's no pointer-only path through it.
- The story panel is a real
role="dialog": opening it moves focus to its close button, and Escape closes it and returns focus to the item that opened it.
Structure
Every "shelf" is a <section> with its own <h2>. The
page reads as a linear document top to bottom with CSS off — the dark kitchen and the
fridge light are entirely decorative layers on top of ordinary content, not a
replacement for it. Decorative elements (the door panel, the lightwell glow, the
condensation) all carry aria-hidden="true".
The fridge door's open/closed state is announced through a polite aria-live
region ("Fridge door open. Light spills into the kitchen.") — the light itself is a
visual effect, so the state is also available as text.
Contrast & the lit-kitchen mode
The default dark palette already clears 7:1 (AAA) at its worst text
pair — measured in sRGB, not eyeballed. "Turn on the kitchen light" isn't there to
rescue the contrast; it's for anyone who needs or prefers a light background.
"Turn on the kitchen light" flattens the entire page — background,
shelf cards, freezer, everything — to a token pair that also clears
7:1. This isn't a separate theme maintained on the side: it's the same
tokens, reassigned. prefers-contrast: more triggers that same authored
palette automatically. forced-colors: active (Windows Contrast Themes,
tested) is handled differently on purpose: the OS is going to override text,
background and link colors with its own system palette regardless of what we author, so
those tokens map to Canvas/CanvasText/LinkText
instead of literal colors the browser would ignore anyway — and the purely decorative
layers (the light glow, the condensation, the cast shadows) are hidden outright, since
they'd otherwise render unforced on top of a forced palette.
Palette values are authored in OKLCH for perceptually even steps, but contrast ratios were verified with an sRGB-based checker — OKLCH lightness is not a stand-in for WCAG's sRGB relative luminance.
What this page doesn't do
- No audio autoplays anywhere.
- No content relies on
DeviceMotionEventor device tilt. - Nothing requires hover alone — every hover-revealed state has a focus-visible equivalent.
- No interactive target is smaller than 24×24 CSS px (WCAG 2.5.8).
The closing line
The sentence at the end of the page is chosen from a small, hand-written set based on
what you actually did during this visit — which shelves you opened, whether you found
the jar pushed to the back of the freezer, whether you closed the fridge door and opened
it again, and whether you navigated only by keyboard. All of that is tracked in memory,
for this visit only. Nothing is sent anywhere, nothing is written to
localStorage, and none of it survives a reload. The paragraph's default
text, already present in the page's HTML, is what you see if JavaScript doesn't run at
all.