# Reading Progress Bar

## Objective

A slim bar showing how far through an article the reader has scrolled.

A thin progress indicator pinned to the top of article pages, tracking scroll through the body text.

## 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. Measure progress against the article body element only. Take the top and bottom of the prose, not the height of the document.
2. Recalculate the body height when the page reflows: late-loading images, expanded sections, embeds, and font swaps all change the total after first paint.
3. Reuse the app's existing Progress Indicator System tokens for the bar's colour and height rather than introducing a new accent, and keep it visually distinct from Route Change Progress so the two are not confused.
4. Hide the bar entirely when the article fits within the viewport, and update it on a throttled scroll handler tied to the frame rather than on every scroll event.
5. Do not animate the fill with a transition. The bar should track the scroll position exactly, and a smoothed fill lags behind the reader and reads as broken.

## 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 short article that fits on one screen has no meaningful progress. The bar would sit at zero or jump straight to full, so it should not render at all.
- Progress must stop at the end of the article body. Counting the footer, the related posts block, and the comment thread means the bar reads half full when the reader has finished the piece.
- Images and embeds that load after first paint change the total height mid-read, so a reader who was at sixty percent suddenly drops to forty. Recompute the bounds on resize and on load, and reserve image dimensions so the shift is small.
- A moving bar is a motion effect. Under prefers-reduced-motion, either hide it or update it without any animated transition.
- A sticky site header and the bar compete for the same strip of screen. Decide which owns the top edge and offset the other, or the bar will disappear under the header on scroll.
- The bar is decoration for assistive technology and should be hidden from the accessibility tree rather than announced as a live percentage on every scroll.
- Returning to an article with a restored scroll position must show the correct fill immediately, not animate up from zero.
- In right-to-left layouts the bar must fill from the right edge.

## 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 bar reflects scroll position through the article body and reaches full at the end of the prose.
- [ ] Articles shorter than the viewport show no bar.
- [ ] Late-loading images and embeds do not leave the bar reporting a stale total.
- [ ] The bar respects prefers-reduced-motion and does not animate its fill.
- [ ] It coexists with the sticky header without overlap on any breakpoint.
- [ ] It is hidden from screen readers and does not emit scroll announcements.
- [ ] 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.
