components/appointment/ had every colour hard-coded, so the flow rendered
identically in either theme even after the wiring was fixed. It now reads from
CSS custom properties.
These are not new colours. The :root values are byte-for-byte the hex codes
that were already in the components — twenty-one files, mapped one to one — so
light mode is unchanged. The dark values are derived from those same colours:
surfaces and borders darkened, text inverted, and the two brand colours (the
indigo and the orange) lightened rather than replaced, because both lose
contrast against a dark surface at their original values.
Verified in a headless browser with prefers-color-scheme forced dark:
data-theme lands on <html> and --ap-surface resolves to #1b1b20 rather than
white. Six one-off colours remain hard-coded — a success green, an error red
and similar — each used exactly once and none of them a surface.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A doctor now has one booking schedule per context — the personal practice plus
one per clinic — and every booking endpoint takes an optional clinic_uuid where
omitting it means the personal practice, not a wildcard. This site sent none, so
a clinic-only doctor showed no availability at all and a doctor working in both
places silently booked into the wrong one.
- services/response.js: getBookingLocations + clinic_uuid on slots,
service-slots, booking-services and month-availability. The manual query
building is kept so the service_item_uuids[] serialisation does not change.
- AppointmentPage owns the selected location; booking_mode and services are
derived from it instead of a separate getBookingServices call, which drops a
request. Changing location clears the selected service, slot and date, since
a service from one location cannot be booked into another.
- New LocationSelect step, shown only when there is more than one location.
The list arrives sorted by earliest free slot, so the first item is the
default and is not re-sorted here.
- DatePicker drops its month cache when the location changes; otherwise the
previous location's disabled days stayed on the calendar.
- The slot address now comes from the selected location rather than
doctor.address, which does not contain clinic addresses.
- clinic_uuid rides through to the appointment payload, and
/appointment/[doctorId]?clinic_uuid=… preselects a location.
- Doctor page JSON-LD gains availableService from the bookable services.
openingHoursSpecification still needs a public weekly-hours endpoint.
Removed the dead locateVisit state, which was initialised true and never unset.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>