# Free Shipping Progress Bar

## Objective

Show shoppers exactly how much more they need to add to earn free shipping.

A progress indicator in the cart and mini-cart showing the remaining amount to a free shipping threshold.

## 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. Put the indicator wherever the cart total is already shown: the mini-cart, the cart page, and the first checkout step. A message that appears in only one of those reads as a bug.
2. Base the remaining amount on the qualifying subtotal, which is what the threshold rule actually measures, not the grand total with tax and shipping already added.
3. Write the copy as a single plain sentence naming the amount left, and switch it to an unambiguous qualified message once the threshold is met.
4. Update it from the same cart state that renders the totals, so the bar and the subtotal can never disagree after a quantity change.
5. Do not show the bar when the shopper cannot possibly qualify, such as a region the offer excludes or a cart made entirely of excluded items. A goal the shopper cannot reach is worse than no goal.

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

- The bar has to recalculate after every change to the money: quantity edits, discount codes, removed items, and refunds applied to the cart. A stale bar promising free shipping the shopper does not get is a support ticket.
- Carts often mix qualifying and excluded items. Count only the qualifying portion toward the threshold and say plainly that some items do not count, rather than quietly using a smaller number the shopper cannot reconcile.
- Once the threshold is met the bar must show a distinct completed state. A bar sitting at full with the same wording as before looks stuck and gets ignored.
- In regions where the offer does not apply, suppress the component entirely rather than rendering it at zero progress or with an unreachable target.
- Screen reader users need to hear progress change without hearing it on every keystroke. Announce politely and only when the remaining amount meaningfully changes or the threshold is crossed.
- A discount code applied after the fact can drop the subtotal back below the threshold. Handle the downgrade as explicitly as the upgrade and tell the shopper what happened.
- Currency and thresholds vary by store or region. Format the amount in the shopper's currency and never hardcode the threshold in the view.

## 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 remaining amount is correct after quantity changes, discounts, and removals.
- [ ] Excluded items are not counted toward the threshold and the shopper is told so.
- [ ] Meeting the threshold produces a distinct completed message, not a full bar with the same copy.
- [ ] The component is absent for regions and carts where the offer cannot apply.
- [ ] Progress changes are announced to assistive technology without repeating on every interaction.
- [ ] The bar and the cart subtotal never disagree.
- [ ] 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.
