# Number Formatting Component

## Objective

Format every count, percentage, and total the same way, without rounding away meaning.

One shared path for displaying numeric values, covering precision, abbreviation, locale separators, and the values that are not numbers.

## 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 numeric value the app renders — counts, totals, percentages, durations, file sizes, ratios — and give each a declared type so the display rules follow from what the number is rather than from where it appears.
2. Set precision per type and never abbreviate a value the user must act on. A summary tile can say 1.2k, but a quantity someone is about to reconcile or pay must show in full.
3. Keep the exact value available even where a shortened one is displayed, on hover and to assistive technology, so a rounded figure can always be checked.
4. Format separators, decimal marks, and percentage placement from the viewer's locale rather than hardcoding a convention, and align numeric columns on the decimal so magnitudes can be compared down a column.
5. Do not sort or filter on the formatted string. An abbreviated or separated value sorts as text, which puts 9 after 1.2k; keep the raw number for every comparison and use the formatted form only for display.

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

- Rounding must not change what the number means. A 99.6 per cent success rate displayed as 100 per cent hides every failure, so round toward the honest side for values where the difference matters.
- The value used for sorting, filtering, and thresholds must be the raw number, never the rendered string.
- Separators and decimal marks differ by locale — the same characters mean opposite things in different regions — so they must come from the viewer's locale rather than the developer's.
- Null, infinity, not-a-number, and negative zero each need a defined rendering. A missing value shown as 0 is a false statement about the data, and negative zero must display as zero.
- Very large and very small values need a defined ceiling and floor rather than an unbounded string that breaks the column width.
- A percentage must be unambiguous about whether it is already scaled; a ratio of 0.5 rendered as 0.5 per cent is a hundredfold error.
- Dates, times, and durations expressed as timestamps belong to Date and Time Display Component; this component owns quantities only.

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

- [ ] Every numeric display in the app goes through the shared formatting path with a declared value type.
- [ ] Precision and abbreviation rules are defined per type and applied consistently.
- [ ] Sorting, filtering, and comparison always use the raw value, never the formatted string.
- [ ] Separators and decimal marks follow the viewer's locale.
- [ ] Null, infinity, not-a-number, and negative zero each render a defined state.
- [ ] The exact value is reachable wherever an abbreviated or rounded one is shown.
- [ ] Numeric columns align on the decimal point.
- [ ] 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.
