{modalTitle()}
{#if editMode === 'select'}

What would you like to change?

{#if noticePeriodBlocked}

Cannot Reschedule Online

{noticeBlockedMessage}

Contact us to discuss options, or and rebook — note that cancellation fees may apply based on our {#snippet trigger()} deposit policy {/snippet} .

{:else if noticePeriodWarning}

Rescheduling Within 24h

Rescheduling within 24h counts as a no-show towards your deposit obligations. Two no-shows within 6 months will require deposits on future bookings. {#snippet trigger()} Full policy {/snippet}

{/if} {#if booking.discounts && booking.discounts.length > 0}

Discounts Applied to This Booking

Your booking has £{discountTotal.toFixed(2)} in savings from loyalty stamps or promotional offers. A time change requires admin approval. If denied, you can cancel (standard refund policy applies) and rebook at full price.

{/if} {#if hasOverrides}
This booking has custom pricing. To change services, please contact the salon. You can still request a time change.
{/if}
{:else if editMode === 'time' || editMode === 'both-time'} {#if loadingHours && !workingHours}

Loading available dates...

{:else}
{ newDate = d; newTime = ''; }} onPlaceholderChange={(p) => { userNavigatedCalendar = true; placeholderDate = p; fetchHoursForMonth(p); }} />
{/if} {#if newDate} {#if loadingHours}

Loading times...

{:else}
{newDate.toDate(getLocalTimeZone()).toLocaleDateString('en-GB', { weekday: 'long', day: 'numeric', month: 'short' })}
{#if workingHours && !workingHours[newDate.toString()]?.isOpen}

We're closed on this day

{:else} {@const grouped = generateGroupedTimeSlots( slotDuration, newDate, lunchProtection() )} {#if grouped.length > 0}
{#each grouped as slot (slot.type + '-' + slot.startTime + '-' + slot.endTime)} {#if slot.type === 'available'} {:else} {/if} {/each}
{:else}

No available slots

{/if} {/if}
{/if} {/if}
Reason (optional)
{:else if editMode === 'services'} {#if hasOverrides}
This booking has custom pricing. To change services, please contact the salon.
{:else if loadingServices}

Loading services...

{:else} {@const remaining = calculateRemainingTime()}

Current Services {#if selectedServices.length > 0} (tap to remove) {/if}

{#if selectedServices.length === 0}

No services selected

{:else}
{#each selectedServices as service (service.id)} {/each}
{/if}
{#if remaining > 0} {@const fittingServices = availableAdditionalServices()} {#if fittingServices.length > 0}

Add Services ({remaining} min remaining)

{#each fittingServices as service (service.id)} {/each}
{:else}
No additional services can fit in the remaining time.
{/if} {:else}
No remaining time available. Remove a service to free up time for additions.
{/if} {#if selectedServices.length === 0}

Select at least one service to continue.

{/if}
{/if}
Special Requests {#if notesChanged} changed {/if}
{#if originalNotes}
Original: {originalNotes}
{/if}
{:else if editMode === 'both-services'} {#if hasOverrides}
This booking has custom pricing. To change services, please contact the salon.
{:else if loadingServices}

Loading services...

{:else} {@const unselected = availableServices.filter( (avail) => !selectedServices.some((selected) => selected.id === avail.id) )}

Selected Services {#if selectedServices.length > 0} (tap to remove) {/if}

{#if selectedServices.length === 0}

No services selected

{:else}
{#each selectedServices as service (service.id)} {/each}
{/if}
{#if unselected.length > 0}

Add Services

{#each unselected as service (service.id)} {/each}
{/if} {#if selectedServices.length === 0}

Select at least one service to continue.

{/if}
Special Requests {#if notesChanged} changed {/if}
{#if originalNotes}
Original: {originalNotes}
{/if}
{/if} {/if}
{#if editMode === 'select'} {:else if editMode === 'time' || editMode === 'services'} {:else if editMode === 'both-services'} {:else if editMode === 'both-time'} {/if}