# Booking Page

## Objective

A shareable page where someone picks an open time and confirms it in a few clicks.

A public scheduling page listing open slots, taking a booking, and confirming it to both sides.

## 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. Build the visitor path first: pick a date, see open times in their own zone, fill a short form, confirm, and receive an email with the details and a cancellation link. That is the minimum coherent version.
2. Derive open slots from the owner's availability rules and existing bookings on the server at request time. Do not trust a slot list the browser has been holding since page load.
3. Reuse the app's existing Time Zone-Aware Scheduling for conversion and storage, store every time as an absolute instant, and display it converted to the visitor's detected zone with the zone named on screen.
4. If the app already has Calendly Booking Sync or Google Calendar Event Creation, write confirmed bookings through those so the owner's calendar stays the source of truth, rather than maintaining a second parallel calendar.
5. Defer payments, round-robin assignment across a team, recurring appointments, and group events. Ship single-person, single-slot booking that works, rather than half of a scheduling product.

## 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 filling in the form is not yet booked. Place a short expiring hold on the slot when they begin, release it if they abandon, and show a clear message if the hold lapses before they submit.
- Two visitors can confirm the same slot within the same second. Enforce the conflict as a uniqueness constraint at the database level, and when the second booking loses, tell that visitor and offer the nearest open times rather than showing a generic failure.
- Times must be shown in the visitor's local zone and stored as absolute instants. A booking rendered in the owner's zone will be attended an hour early or missed entirely.
- Minimum notice and maximum horizon both have to be enforced server-side. Without them a visitor books a slot ten minutes from now, or something eighteen months out that will never be honoured.
- A slot near a daylight saving transition can be ambiguous or nonexistent in local time. Resolve it against the absolute instant and never generate a slot that does not exist locally.
- A cancellation or reschedule link must be unguessable and scoped to one booking, since the person holding it is not signed in.
- The confirmation email can fail to send. The booking still exists, so surface the details on screen and retry delivery rather than leaving the visitor unsure.
- The public page is an unauthenticated form and will be scraped and spammed. Rate-limit by address and require email confirmation before the slot is held permanently.

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

- [ ] A visitor can pick a slot and confirm a booking without an account.
- [ ] Open slots are computed server-side from availability and existing bookings at request time.
- [ ] Two simultaneous confirmations for the same slot result in exactly one booking, and the loser is offered alternatives.
- [ ] Times display in the visitor's zone with the zone named, and are stored as absolute instants.
- [ ] Minimum notice and booking horizon are enforced on the server and cannot be bypassed from the client.
- [ ] Slots spanning a daylight saving change resolve to the correct instant, with no nonexistent local times offered.
- [ ] Both parties receive confirmation, and cancellation links work without sign-in.
- [ ] 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.
