# Variant Class Generator

## Objective

Declare a component's variants once instead of scattering conditionals through its markup.

A declarative variant definition per component mapping size, tone, and state to the classes each combination produces.

## 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 the components whose markup is threaded with conditional class logic and replace that logic with a single declaration listing each variant, its options, and its default.
2. Support combinations that are more than the sum of their parts, so a specific pairing of size and tone can produce classes that neither produces alone, without reintroducing a conditional in the markup.
3. Make invalid combinations impossible to express rather than merely undesirable, and give the component a defined appearance when it receives a combination it does not recognise.
4. Publish the variant options as the component's contract for callers while keeping the class strings themselves private, so the classes can be changed without touching a single call site.
5. Hand the final composition of the generated classes with caller-supplied ones to Class Merge Helper rather than resolving precedence here. This feature decides which classes a variant produces; that one decides which classes win.

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

- Compound variants are the reason hand-written conditionals appear in the first place — the small size in the destructive tone needing a different border, and nothing else needing it. If the declaration cannot express that pairing, the conditional comes straight back into the markup.
- Combinations that are not meant to exist, such as a ghost tone with an elevated surface, must be rejected at authoring time. Left permitted, they will be used, and the component will be expected to support them forever.
- Generated output must not become one large object that pulls every component's variants into every bundle. Keep each component's definition independently removable so unused ones never ship.
- The types a caller sees must name the variants and their options and nothing else. Leaking the class strings into the public type makes them part of the contract and freezes them.
- Defaults must be explicit for every variant, because a component rendered with no props at all is the most common case in the app and must still look right.
- State that is not a variant — focus, hover, disabled, loading — should stay in the class definition rather than becoming a prop the caller has to pass.
- A variant added or renamed later must not silently change the appearance of existing call sites that relied on the previous default.

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

- [ ] Each converted component has one declaration covering its variants, options, and defaults.
- [ ] No conditional class logic remains in the markup of converted components.
- [ ] Compound combinations are expressible in the declaration itself.
- [ ] Invalid combinations are rejected at authoring time, and unknown values render a defined fallback.
- [ ] Unused component definitions are removed from the shipped bundle.
- [ ] Public types expose variant names and options but not the underlying class strings.
- [ ] Final class composition is delegated to Class Merge Helper.
- [ ] 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.
