{ if (open) return; // ESC/overlay while a payment is in flight (the charge, or the // out-of-band SCA challenge the buyer must approve in their banking // app) must NOT close the modal — the charge may still land, and // closing mid-challenge strands it. Block close until it resolves. if (status === 'processing' || waitingForSCA) return; // ESC while the overflow-confirm prompt is showing must dismiss the // prompt (back to the amount-editing form) instead of closing the whole // modal — the payment was rejected by the guard and the user needs to // confirm or adjust, not lose the flow entirely. if (overflowConfirm) { cancelOverflowConfirmation(); return; } handleClose(); }} > Make a Payment {#if booking.id}
Booking ID: {booking.id}
{/if}
{#if overflowConfirm}

Secure payment powered by Square

{:else if status === 'idle' || status === 'processing' || status === 'error'}
{#if booking.status === 'pending_release' && lockAcquired && lockTimer > 0}
Slot re-secured for {formatTimer(lockTimer)} to ensure smooth payment processing
{:else if booking.status === 'pending_release' && (lockTimer === 0 || !lockAcquired)}
Slot no longer secured — please close and retry
{/if} {#if waitingForSCA}

Approve this payment in your banking app on your phone…

The payment is waiting for your approval. This may take a few moments.

{/if}
Services
{#each booking.services ?? [] as service, index (index)}
{service.service_name || 'Unknown Service'} {service.override_price ? formatCurrency(Math.round(service.override_price * 100)) : service.price ? formatCurrency(Math.round(service.price * 100)) : '-'}
{/each}
{#if loyaltyEligible}
Available Savings
{/if} {#if booking.discounts && booking.discounts.length > 0}
Applied Discounts
{#if servicesSubtotal > 0} {((discountSum / servicesSubtotal) * 100).toFixed(0)}% Off Total {/if}
{#each booking.discounts as d (d.id)}
{#if d.discount_source === 'loyalty'} Loyalty Stamp Card (10% Off) {:else if d.campaign_name} {d.campaign_name} {:else} Promo Campaign ({d.discount_percent}% Off) {/if}
-{formatCurrency(d.discount_amount)}
{/each}
{/if}
Total {formatCurrency(Math.round(booking.total_amount * 100))}
{#if discountPreview?.eligible} {#each discountPreview.discounts as d (d.name)}
{d.name} -{formatCurrency(Math.round(d.amount * 100))}
{/each} {/if}
Amount Paid {formatCurrency(totalPaid)}
{#if useLoyalty && loyaltyDiscount > 0}
Loyalty Stamp Card (10% Off) -{formatCurrency(loyaltyDiscount)}
{/if}
Amount Remaining {formatCurrency( Math.max( 0, remainingBalancePence - campaignDiscountPence(discountPreview) - loyaltyDiscount ) )}
{#if authStore.isAuthenticated} {#if savedCardsStore.loading}
Loading payment methods...
{:else} (cardSelectionValid = v)} /> {/if} {/if} {#if twoFactor.showInput && twoFactorEnabled} {/if} {#if depositPolicyWarning}

Cancellation & Deposit Policy

{depositPolicyWarning}

{#snippet trigger()} Full cancellation policy → {/snippet}
{/if} {#if isScenarioA}

Secure payment powered by Square

{/if} {#if isScenarioB}
{#if paymentType === 'partial'}
£
{#if partialValidationError}

{partialValidationError}

{/if}
{/if}

Secure payment powered by Square

{/if} {#if status === 'error' && error}

{error}

{/if}
{:else if status === 'success' && paymentResult}

Payment Successful

Amount {formatCurrency(paymentResult.amount / 100)}
Type {paymentResult.payment_type}
{#if paymentResult.card_brand}
Card {paymentResult.card_brand} ****{paymentResult.card_last4}
{/if}
Status Completed
{/if}