# Accessibility

Contrast, focus, touch targets and reduced motion are built into the tokens and components, so they hold for every theme. Labels, alt text and the meaning of your screens are still yours.

## Contrast is checked for every theme

The theme generator checks every text and boundary pair in both modes, with WCAG 2 ratios and APCA, and refuses to build a theme that fails. Some of the minimums:

| Foreground | On | Minimum |
| --- | --- | --- |
| `color-text-primary` | `color-background-surface` | 7:1 |
| `color-text-secondary` | `color-background-surface` | 4.5:1 |
| `color-text-tertiary` | `color-background-surface` | 3:1 |
| `color-text-on-accent` | `color-accent` | 4.5:1 |
| `color-accent`, `color-focus-ring` | `color-background-page` | 3:1 |
| `color-border-control` | Page, surface, raised and sunken | 3:1 |

`color-text-tertiary` meets AA only for large text. Use it for placeholders and timestamps, never for information someone needs to finish a task. The full list is on [Colors](https://www.werewolf-ui.dev/docs/foundations/colors.md).

## Visible focus

Every interactive component shows a 2px ring in `color-focus-ring`, 2px away from its edge, on keyboard focus only. For your own focusable elements use `focus-visible:focus-ring`, and never `transition-colors` or `transition-all`, which fade the ring in.

```tsx
<a href="/settings" className="rounded-element transition-control duration-fast ease-standard focus-visible:focus-ring">
  Settings
</a>
```

## Touch targets

On touch screens controls reach a 44px target: `md`, `lg` and `xl` grow, and `sm` controls, checkboxes and icon buttons keep their look but extend their hit area. Text inputs cannot extend theirs, so use Input `lg` or `xl` on touch-first screens. Input text is 16px on touch so iOS Safari does not zoom the page.

## Never color alone

- A status needs a word or an icon, not just a red or green fill.
- Links are always underlined, because the accent can match the text color.
- Charts with more than four series need direct labels or patterns.
- Disabled controls are also non-interactive (`disabled` or `aria-disabled`), not only gray.

## Reduced motion

Movement sits behind `motion-safe:`. When someone asks for reduced motion, slides and press scaling stop and only fades and color changes remain. Loops such as the Skeleton pulse do not run at all.

```tsx
<button className="transition-control duration-fast ease-standard motion-safe:active:scale-pressed">
```

## Keyboard and screen readers

Overlays, menus, selects, tabs and the other interactive components follow the expected keyboard patterns. Dialogs and sheets move focus inside when they open and return it when they close. Each component spec lists its role and accessibility notes on the component page.

## Your part

- Give every field a visible label, with Field and FieldLabel or Label.
- Give every icon-only button an `aria-label` (the Button type requires it) and mark decorative icons `aria-hidden`.
- Write alt text for meaningful images and an empty `alt` for decorative ones.
- Never make text lighter with opacity; use the secondary or tertiary text tokens.
- Keep one `h1` per page and headings in order.

```tsx
<Button iconOnly aria-label="Close" variant="ghost">
  <IconX size={16} aria-hidden />
</Button>
```
