# Accessibility

> The reduced-motion policy every component follows, and the details screen readers care about.

## Reduced motion

Every component has a `prefers-reduced-motion: reduce` branch, and the test
suite refuses a component without one. The policy is **cross-fade instead of
movement, never a hard cut, never nothing**:

- Reveal and SplitText keep a fast opacity fade and drop translate, scale, blur
  and stagger.
- RotatingText crossfades in place instead of rising.
- Typewriter shows the full text at once; the caret stops blinking.
- Marquee stops, hides its duplicate copies, and becomes a scrollable strip
  so every item is reachable.
- Aurora becomes a static gradient.

Scripts read the preference through the runtime's `prefersReducedMotion()` and
shorten motion to near-zero rather than skipping the code path, so end states
still apply.

## Previewing reduced motion

The header of this site has a **motion** switch. It sets
`data-ma-motion="reduce"` on `<html>`, and every reduced-motion rule on the
page (the components', Tailwind's `motion-reduce:` utilities, the site's own)
also applies under that attribute, so the switch shows what the media query
does without changing an OS setting. The exception is motion that only a
`(prefers-reduced-motion: no-preference)` block turns on: the attribute does
not stop it. Nothing is duplicated by hand: the
integration's `motionAttribute` option mirrors the `@media
(prefers-reduced-motion: reduce)` blocks at build time, and
`prefersReducedMotion()` in the runtime reads the attribute as well as the
media query. Turn it on in your own project with

```js
moonarc({ motionAttribute: true })
```

and stamp the attribute from a toggle of your own. It costs a few percent of
CSS and no JavaScript.

## Content is never hidden by default

Server HTML is the end state. Entrance effects hide content only behind
`html[data-ma-js]`, which the integration sets just before first paint. If
JavaScript fails or is disabled, the page is simply visible.

## Text components

SplitText and Typewriter keep the whole string in a visually hidden copy
(`.ma-sr`) and mark the animated parts `aria-hidden`, so assistive tech reads
one string rather than a stream of letters. RotatingText's hidden copy lists
every word once. Marquee's duplicate copies are `aria-hidden` and `inert`,
so their links are not reached twice. Aurora is `aria-hidden` outright.

## Pointer gating

Hover effects are gated on `(hover: hover) and (pointer: fine)` so touch
devices never trigger them on tap.