# Live Region Manager

## Objective

Announce the things that change on their own, once each, at the right urgency.

A single managed channel through which asynchronous status — saves, errors, filter results, background jobs — reaches screen reader users.

## Before You Begin

This feature is being added to an application that already exists and already
works. Do not scaffold a new project, and do not assume a blank slate.

Inspect the codebase first and establish:

- The existing application structure and where code of this kind already lives.
- The framework and version in use.
- The existing design system — colours, spacing, typography, and component conventions.
- Existing UI components you can reuse instead of writing new ones.
- The existing database structure, if this feature needs to persist anything.
- The existing authentication and authorization system, if this feature is user-scoped.
- Dependencies already installed, so you don't add a library that duplicates one.
- The existing test setup and conventions.

Only start writing code once you understand the above. If the application
already implements part of this feature, extend it rather than replacing it.

## Implementation Instructions

1. Find every place the app changes the screen without a user action immediately preceding it: autosave, polling, validation on blur, filter result counts, upload progress, toast notifications, and background job completion.
2. Route all of those through one manager with two channels — polite for status the user can absorb when they pause, assertive for errors and anything that interrupts what they were about to do — and default everything to polite.
3. Keep the live regions themselves mounted and empty in the shell from first paint, and change only their text content. A region inserted at the moment of the announcement is frequently missed entirely.
4. Collapse repeated and superseded messages: an identical message within a short window is dropped, and a progress or count message replaces the previous one rather than queueing behind it.
5. Do not announce anything the user has just caused directly and can already perceive — a button label changing under their own click, or a field they just typed into. Duplicating that turns the channel into noise and trains people to ignore the announcements that matter; visually hidden text used by these messages should come from Screen Reader Only Utility rather than being styled here.

## UI and UX Requirements

Match the application's existing design system exactly. Reuse its components,
spacing, and typography. This feature should look like it was always there.

## Responsive Requirements

Works on mobile, tablet, and desktop. Touch targets are large enough to hit on a
phone, and nothing overflows horizontally at 320px.

## Accessibility Requirements

- Fully keyboard navigable.
- Correct semantic elements and ARIA roles.
- Visible focus states.
- Meets WCAG AA contrast.
- Dynamic changes are announced to screen readers.
- Respects prefers-reduced-motion.

## Edge Cases

- Polite and assertive must stay in separate regions, because mixing them means an error waits behind a queue of routine status, and routine status interrupts the user mid-sentence.
- The same message posted twice in quick succession is read twice; deduplicate on message text within a short window, and expose an explicit override for the rare case where a repeat genuinely carries information.
- Superseded content must be replaced predictably — a filter count or an upload percentage should overwrite the region rather than append, or the user hears every intermediate value in order and the current one last.
- Announcing every minor event makes the channel useless. Set a threshold for what qualifies as status worth interrupting for, and let ordinary rendering carry the rest.
- Rapid successive changes need throttling with a trailing announcement so the final state is spoken, not merely the first of a burst.
- A route change should reset the regions, otherwise a stale message from the previous screen is read against the new one.
- Emptying and refilling a region in the same frame is often coalesced and never announced; separate the clear and the set.

## Testing

Exercise the feature end to end in the running application. Cover every edge case
above, then run the existing test suite and confirm nothing regressed.

## Acceptance Criteria

- [ ] All asynchronous status in the app is announced through one manager rather than per-component regions.
- [ ] Polite and assertive messages occupy separate persistent regions present from first paint.
- [ ] Identical messages within the deduplication window are announced once.
- [ ] Progress and count messages replace their predecessor instead of queueing.
- [ ] Announcements do not duplicate feedback the user's own action already conveys.
- [ ] Regions are cleared on route change and no stale message carries across screens.
- [ ] The feature matches the existing design system.
- [ ] No existing functionality is broken.

## Adaptation Rules

- Match the existing design system. Do not introduce a new colour palette,
  spacing scale, or component library.
- Reuse existing components and utilities wherever they fit.
- Follow the naming, file layout, and code style already present.
- Do not upgrade, replace, or remove existing dependencies to make this
  feature fit. Adapt the feature to the app, not the app to the feature.
- Do not break existing functionality. If a change is genuinely required in
  existing code, make the smallest one that works and say so.
- If something in these instructions conflicts with how the application is
  built, follow the application and explain the deviation.

## Final Verification

Before you report the work as done:

1. Re-read the acceptance criteria above and check each one against what you
   actually built.
2. Run the application and exercise the feature end to end.
3. Run the existing test suite and confirm you have broken nothing.
4. Check the feature on mobile, tablet, and desktop widths.
5. Check keyboard navigation and focus handling.
6. Summarize what changed: files added, files modified, and anything you
   deliberately did differently because of how this application is built.

If any acceptance criterion is unmet, fix it before reporting completion.
