# Shopping Cart

## Objective

A cart that holds its contents, prices them correctly, and survives leaving the site.

A persistent cart holding line items with quantities, priced at load time and carried across sessions and sign-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. Give a signed-out visitor a cart tied to a long-lived browser token, and give a signed-in user a cart stored against their account. On sign-in, merge the two by product and variant so a line the visitor already had gains quantity rather than appearing twice.
2. Price the cart from the catalogue every time it is displayed, not from the numbers captured when the item was added. Store the quantity and the product reference on the line; treat price, tax, and availability as derived.
3. Show the cart contents and total in a place the user can reach from every page, and make the totals break down into subtotal, discounts, shipping, and tax rather than a single opaque number.
4. If the app already has Coupon and Promotion Codes, Tax and VAT Collection, or a hosted checkout, the cart must feed those rather than recomputing discounts and tax on its own. Extend the existing pricing path; do not add a second one.
5. Do not treat the cart as an order. Nothing in the cart reserves inventory, and the authoritative price and stock check happens again at checkout, because a cart can sit untouched for weeks.

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

- A visitor who fills a cart and then signs in must end up with one cart containing everything. Merging by product and variant, and summing quantities against the per-order cap, prevents the same item appearing on two lines.
- Prices change while a cart sits idle. Reprice on load, and if a line has gone up or down since it was last seen, say so plainly next to that line rather than silently charging the new amount.
- An item can go out of stock or be delisted while in the cart. Keep the line visible but mark it unavailable, exclude it from the total, and block checkout until the user removes it or reduces the quantity.
- Quantity must be capped against both available inventory and any per-order limit. Clamp the value server-side and tell the user why it was reduced; a client-only limit is trivially bypassed.
- Totals must stay correct across currency, rounding, and discounts that apply to more than one line. Compute in minor units, apply multi-line discounts before rounding the total, and never let the sum of the displayed lines disagree with the charged amount.
- Two tabs open on the same cart must not overwrite each other. Apply quantity changes as operations against the stored cart rather than saving a whole client-side snapshot.
- Removing a line should be undoable for a short window. People remove the wrong row and re-adding it from scratch loses the configured options.
- An abandoned cart still holds a browser token. Decide how long guest carts are retained and delete them on schedule rather than accumulating them forever.

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

- [ ] The cart survives a page reload, a closed browser, and a sign-in without losing or duplicating lines.
- [ ] Prices, discounts, and tax are recalculated on every render from the current catalogue.
- [ ] Unavailable or delisted items are visibly flagged and excluded from the total, and block checkout.
- [ ] Quantity limits are enforced server-side against inventory and per-order caps.
- [ ] The displayed total matches the amount the payment step charges, to the minor unit.
- [ ] Discounts and tax come from the app's existing promotion and tax logic, not a parallel implementation.
- [ ] 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.
