# Unsplash Image Search

## Objective

Let users search and place Unsplash photography without leaving the screen.

An in-app image search that returns licensed photos with the identifier and attribution needed to use them.

## 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. Add image search where users currently paste a URL or hunt for a stock photo — cover images, avatars, banners — and keep the existing upload path beside it.
2. Proxy every provider request through the server so the application credential never reaches the browser, and cache popular queries briefly to stay inside the rate limit.
3. Debounce typing and cancel the request for a query the user has moved past, so results cannot arrive out of order and replace a newer search.
4. On selection, store the provider's stable image identifier, the photographer's name and profile link, and the source link, alongside whatever the app caches locally. A raw image URL alone cannot be attributed or re-resolved later.
5. Honour the provider's attribution and download-tracking requirements: show the photographer and source wherever the image appears, and trigger the download event when a user actually selects an image rather than on every result that renders.

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

- Attribution is a licence condition, not a nicety. An image shown without a visible credit and a working link back puts the app out of compliance.
- Results for an abandoned query must be discarded. Without cancellation a slow early request can land after a fast later one and show photos for a query the user has already replaced.
- The provider credential must stay server-side. Putting it in front-end code hands the app's entire quota to anyone who reads the page.
- An image can be removed by its author or by the provider after it was chosen. Detect the broken reference, fall back to a placeholder, and prompt for a replacement rather than leaving a dead image in place.
- Store the identifier and author metadata at the moment of selection so attribution survives even when the provider is later unreachable.
- Development and production rate limits differ by an order of magnitude. Handle exhaustion with a clear message and keep the upload path available, rather than an empty grid that reads as no matches.
- A search with no results, an empty query, and a failed request must each look different from one another.
- Results are unmoderated for any particular context. If the app serves a sensitive audience, apply the provider's content filtering and say in the interface that it is applied.

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

- [ ] Users can search and insert an image without leaving the screen they are working on.
- [ ] No provider credential is present in client code; all requests pass through the server.
- [ ] Typing is debounced and responses for superseded queries are discarded.
- [ ] Each selected image stores a stable identifier, photographer, and source link.
- [ ] Attribution is displayed wherever the image appears and links back correctly.
- [ ] Download tracking fires on selection only, not on search result rendering.
- [ ] A removed image or an exhausted rate limit degrades to a clear message with upload still available.
- [ ] 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.
