# Email Preference Center

## Objective

Let people choose which emails they get without cutting off account-critical mail.

A preference page covering delivery channels and message categories, with unsubscribe links that work without signing in.

## 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. Extend the existing notification preference model rather than forking a second one — this feature adds channels and consent on top of the per-type preferences already there, and two competing sources of truth will drift.
2. Split messages into required transactional, optional product notifications, and marketing. Only the last two may be switched off, and the page must say plainly which mail keeps arriving regardless.
3. Give every optional email a one-click unsubscribe link that is signed, works with no session, and needs no confirmation step.
4. Send List-Unsubscribe and List-Unsubscribe-Post headers on optional mail so mailbox providers can honour a single click, and process those requests the same way as the link.
5. Do NOT build the digest schedule here. This owns whether and how a message is delivered; frequency and batching belong to Notification Digests.

## 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

- Messages already queued when someone opts out must be re-checked against preferences at send time, not at enqueue time.
- An unsubscribe link that is forwarded still works. Scope its token to one recipient and one category so it cannot mute someone else's mail.
- Turning off every optional channel must not silently disable password resets, receipts, or security alerts.
- Users in more than one workspace need per-workspace settings plus a global off switch, and the global one wins.
- Record consent changes with a timestamp, source, and IP where regulations require proof.
- The preference page must render correctly for a signed-out visitor arriving from an email link.

## 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

- [ ] Preferences extend the existing notification preference model rather than a parallel one.
- [ ] Required transactional mail is clearly separated and cannot be disabled.
- [ ] Every optional email has a signed one-click unsubscribe that works without a session.
- [ ] List-Unsubscribe headers are sent and honoured identically to the link.
- [ ] Preferences are evaluated at send time, so queued mail respects a recent opt-out.
- [ ] Consent changes are recorded with timestamp and source.
- [ ] 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.
