/*
 * The public floor plan.
 *
 * Like the forms stylesheet, this inherits the theme's typography and colour and
 * declares only what a theme cannot supply: the room's frame, what a place looks
 * like when it is free, taken, or yours, and the tab strip between floors.
 */

.floorplan {
	/*
	 * 14px on desktop, like the forms plugin, and the whole panel scales off it.
	 *
	 * An earlier version sized every control for a thumb at every width, which
	 * is right on a phone and enormous on a 27-inch monitor — a 48px button and
	 * a 16px input next to 14px body copy read as a different website. The
	 * touch sizes come back below the tablet breakpoint, where they are needed.
	 */
	--floorplan-font: 14px;
	--floorplan-control: 36px;
	--floorplan-pad: 0.45rem 0.6rem;
	--floorplan-radius: 8px;

	font-size: var(--floorplan-font);
	--floorplan-line: color-mix(in srgb, currentColor 18%, transparent);
	--floorplan-muted: color-mix(in srgb, currentColor 62%, transparent);
	--floorplan-surface: color-mix(in srgb, currentColor 3%, transparent);
	--floorplan-mine: #1a7f45;
	--floorplan-error: #b32d2e;
	/* The colour of going on: the book button, and the tray that stands in for
	   it on the drawing. One token, so the two never drift apart. */
	--floorplan-accent: #2f6fed;

	margin-block: 1.5rem;
}

/* -- Pages ----------------------------------------------------------------- */

/* See the note in jhlc-forms/assets/css/form.css: a `display` declaration beats
   the UA rule that implements the `hidden` attribute. The page tabs toggle it. */
.floorplan [hidden] {
	display: none !important;
}

.floorplan__tabs {
	display: flex;
	gap: 0.25rem;
	margin-bottom: 0.6rem;
	flex-wrap: wrap;
}

.floorplan__tab {
	font: inherit;
	font-size: 0.9em;
	padding: 0.35rem 0.8rem;
	border: 1px solid var(--floorplan-line);
	border-radius: 6px;
	background: none;
	color: inherit;
	cursor: pointer;
}

.floorplan__tab.is-current {
	background: var(--floorplan-surface);
	border-color: currentColor;
	font-weight: 600;
}

.floorplan__viewport {
	border: 1px solid var(--floorplan-line);
	border-radius: 8px;
	overflow: hidden;
	background: var(--floorplan-surface);
	line-height: 0;

	/*
	 * A fixed frame, not one the room's proportions decide.
	 *
	 * Letting the height follow the aspect ratio meant a wide terrace was a
	 * letterbox and a tall ballroom pushed everything below it off the screen —
	 * the seat list, the total, the button — so the page jumped by hundreds of
	 * pixels when somebody changed floor. 500px is a frame both fit inside, and
	 * `meet` scales the room down to sit in it whatever shape it is.
	 *
	 * A custom property, so a plan that genuinely needs a taller frame can set
	 * one without overriding the rule.
	 */
	height: var(--floorplan-canvas-height, 500px);
}

.floorplan__svg {
	display: block;
	width: 100%;
	/* Fills the fixed frame; preserveAspectRatio does the letterboxing. */
	height: 100%;
	/*
	 * One finger scrolls the page; two fingers belong to the room.
	 *
	 * `pan-y` leaves vertical scrolling to the browser — the frame is 500px of
	 * a phone screen and a reader swiping up through the page must not be
	 * trapped in it — while withdrawing everything else, which is what stops a
	 * pinch here from zooming the whole document. The runtime then takes the
	 * two-finger gesture itself and spends it on the viewBox, so the room is
	 * re-drawn at the new size rather than magnified as a picture.
	 *
	 * Safari needs the JavaScript as well as this: it treats page zoom as its
	 * own gesture and has never reliably honoured `touch-action` for it, so the
	 * runtime also calls preventDefault on the touches and on Safari's
	 * `gesturestart`.
	 */
	touch-action: pan-y;
	/*
	 * The room is a picture, not prose.
	 *
	 * Every number on every table is a <text> node, so dragging to pan was
	 * being read as dragging to SELECT: the labels went blue, the browser took
	 * the gesture, and the pan stuttered or stopped. Nothing here is meant to be
	 * selected, so nothing here is selectable.
	 */
	user-select: none;
	-webkit-user-select: none;
}

/* While a pan is live, nothing anywhere in the plan can start a selection. */
.floorplan__page.is-panning,
.floorplan__page.is-panning * {
	user-select: none;
	-webkit-user-select: none;
	cursor: grabbing;
}

.floorplan__page.is-zoomed .floorplan__svg {
	cursor: grab;
	/* Once zoomed in, a drag pans the room rather than scrolling the page —
	   otherwise there is no way to reach the far side of it on a phone. The
	   zoom controls include a "fit" button, which is the way back out. */
	touch-action: none;
}

/* -- Places ---------------------------------------------------------------- */

.floorplan__el {
	transition: opacity 0.12s ease;
}

.floorplan__el--seatable.is-pickable {
	cursor: pointer;
}

.floorplan__el--seatable.is-pickable:hover ellipse,
.floorplan__el--seatable.is-pickable:hover rect {
	/* A hairline in the ink colour rather than a colour change: the fill is
	   already saying whether the place is free, and a hover that recoloured it
	   would say something contradictory. */
	stroke: currentColor;
	stroke-width: 2;
}

.floorplan__el--seatable:focus-visible {
	outline: none;
}

.floorplan__el--seatable:focus-visible ellipse,
.floorplan__el--seatable:focus-visible rect {
	stroke: #2271b1;
	stroke-width: 3;
}

.floorplan__el.is-taken {
	/* Not `pointer-events: none`: a taken place must still be readable by a
	   screen reader and still say what it is when tapped. */
	cursor: not-allowed;
}

.floorplan__el.is-mine ellipse,
.floorplan__el.is-mine rect {
	stroke: var(--floorplan-mine);
	stroke-width: 4;
}

.floorplan.is-busy {
	opacity: 0.6;
	pointer-events: none;
}

/*
 * A zone's title on the public drawing.
 *
 * Its colour and size are attributes on the <text>, chosen per element by the
 * renderer — the panel is recolourable and the lettering has to stay legible on
 * whatever it was recoloured to. What belongs here is the one thing that is
 * true of every one of them: it is a label on the floor, and a visitor's click
 * is meant for whatever is standing on that floor.
 */
.floorplan__title {
	pointer-events: none;
	user-select: none;
}

/* -- Below the room -------------------------------------------------------- */

.floorplan__legend {
	display: flex;
	flex-wrap: wrap;
	gap: 0.4rem 1rem;
	list-style: none;
	margin: 0.75rem 0 0;
	padding: 0;
	font-size: 0.85em;
	color: var(--floorplan-muted);
}

.floorplan__legend li {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	margin: 0;
}

.floorplan__swatch {
	width: 0.85em;
	height: 0.85em;
	border-radius: 3px;
	display: inline-block;
	border: 1px solid var(--floorplan-line);
}

.floorplan__chosen {
	margin-top: 0.85rem;
	padding: 0.6rem 0.85rem;
	border-radius: 8px;
	background: var(--floorplan-surface);
	border-inline-start: 3px solid var(--floorplan-mine);
}

.floorplan__message:empty {
	display: none;
}

.floorplan__message {
	margin: 0.5rem 0 0;
	font-size: 0.9em;
}

.floorplan__message.is-error {
	color: var(--floorplan-error);
}

.floorplan__notice {
	padding: 0.9rem 1.1rem;
	border-radius: 8px;
	border-inline-start: 3px solid #dba617;
	background: var(--floorplan-surface);
}

/* -- Zoom controls --------------------------------------------------------- */

/*
 * In the viewport's own corner, in SCREEN pixels.
 *
 * Not inside the SVG: a control drawn in the room's coordinates would shrink as
 * the room is zoomed out, which is exactly when somebody needs to press it.
 */
.floorplan__viewport {
	position: relative;
}

.floorplan__zoom {
	position: absolute;
	right: 0.6rem;
	bottom: 0.6rem;
	display: flex;
	gap: 2px;
	padding: 2px;
	border-radius: 999px;
	background: color-mix(in srgb, Canvas 88%, transparent);
	backdrop-filter: blur(6px);
	border: 1px solid var(--floorplan-line);
	line-height: 1;
	z-index: 2;
}

.floorplan__zoom-btn {
	font: inherit;
	font-size: 1rem;
	font-weight: 600;
	/* 34px: small enough not to sit on the room, large enough for a thumb. */
	min-width: 2.1rem;
	height: 2.1rem;
	padding: 0 0.5rem;
	border: 0;
	border-radius: 999px;
	background: none;
	color: inherit;
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background-color 0.12s ease;
}

.floorplan__zoom-btn:hover:not(:disabled) {
	background: var(--floorplan-surface);
}

.floorplan__zoom-btn:disabled {
	opacity: 0.35;
	cursor: default;
}

.floorplan__zoom-btn--fit,
.floorplan__zoom-btn--legend {
	font-size: 0.78rem;
	font-weight: 500;
}

/* -- The basket ------------------------------------------------------------ */

.floorplan__basket {
	margin-top: 0.85rem;
	padding: 0.85rem 0.9rem 0.9rem;
	border: 1px solid var(--floorplan-line);
	border-radius: 12px;
	background: var(--floorplan-surface);
}

.floorplan__basket-title {
	margin: 0 0 0.6rem;
	font-size: 1.05em;
}

.floorplan__empty {
	margin: 0;
	color: var(--floorplan-muted);
	font-size: 0.92em;
}

.floorplan__seats {
	display: flex;
	flex-direction: column;
	gap: 0.6rem;
}

.floorplan__seats:empty {
	display: none;
}

.floorplan__seat {
	border: 1px solid var(--floorplan-line);
	border-radius: var(--floorplan-radius);
	padding: 0.55rem 0.7rem 0.7rem;
	background: color-mix(in srgb, Canvas 70%, transparent);
}

/* A place the server refused for want of a name says which one it was. */
.floorplan__seat.is-incomplete {
	border-color: var(--floorplan-error);
	box-shadow: 0 0 0 1px var(--floorplan-error);
}

.floorplan__seat-head {
	display: flex;
	align-items: center;
	gap: 0.6rem;
	margin-bottom: 0.6rem;
}

.floorplan__seat-name {
	font-weight: 700;
}

.floorplan__seat-price {
	margin-inline-start: auto;
	color: var(--floorplan-muted);
	font-variant-numeric: tabular-nums;
}

.floorplan__seat-drop {
	flex: none;
	width: 1.9rem;
	height: 1.9rem;
	border: 1px solid transparent;
	border-radius: 999px;
	background: none;
	color: var(--floorplan-muted);
	font-size: 1.1rem;
	line-height: 1;
	cursor: pointer;
}

.floorplan__seat-drop:hover {
	color: var(--floorplan-error);
	border-color: color-mix(in srgb, var(--floorplan-error) 30%, transparent);
}

/*
 * Three fields across on a roomy page, one column on a phone — a container
 * query, because this panel is as likely to be in a sidebar as full width.
 */
.floorplan__basket {
	container-type: inline-size;
}

.floorplan__seat-fields {
	display: grid;
	gap: 0.5rem;
}

@container (min-width: 30rem) {
	.floorplan__seat-fields {
		grid-template-columns: 1fr 1fr 1.3fr;
	}
}

.floorplan__seat-field {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	font-size: 0.85em;
	min-width: 0;
}

.floorplan__seat-field input {
	width: 100%;
	box-sizing: border-box;
	font: inherit;
	/* The label around it is 0.85em; the box people type in is not. */
	font-size: var(--floorplan-font);
	padding: var(--floorplan-pad);
	border: 1px solid var(--floorplan-line);
	border-radius: var(--floorplan-radius);
	background: Canvas;
	color: inherit;
	min-height: var(--floorplan-control);
}

.floorplan__seat-field input:focus-visible {
	outline: none;
	border-color: #2f6fed;
	box-shadow: 0 0 0 3px color-mix(in srgb, #2f6fed 25%, transparent);
}

.floorplan__req {
	color: var(--floorplan-error);
}

.floorplan__total {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	margin-top: 0.9rem;
	padding-top: 0.7rem;
	border-top: 1px solid var(--floorplan-line);
	font-size: 1.05em;
}

.floorplan__total strong {
	font-variant-numeric: tabular-nums;
	font-size: 1.15em;
}

.floorplan__book {
	margin-top: 0.85rem;
	width: 100%;
	font: inherit;
	font-size: 1em;
	font-weight: 600;
	padding: 0.6rem 1.4rem;
	min-height: var(--floorplan-control);
	border: 0;
	border-radius: 999px;
	background: var(--floorplan-accent);
	color: #fff;
	cursor: pointer;
	transition: filter 0.14s ease;
}

.floorplan__book:hover:not(:disabled) {
	filter: brightness(1.08);
}

.floorplan__book:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

/*
 * The mailing-list tick box.
 *
 * Laid out like a statement somebody is agreeing to rather than like another
 * field to fill in: the box beside the words, aligned to the first line of them
 * however many lines they run to.
 */
.floorplan__consent {
	display: flex;
	align-items: flex-start;
	gap: 0.55rem;
	margin-top: 0.9rem;
	font-size: 0.92em;
	line-height: 1.4;
	cursor: pointer;
}

.floorplan__consent input {
	/* Nudged down onto the first line's baseline, not the box's top edge. */
	margin-top: 0.15em;
	flex: 0 0 auto;
	width: 1rem;
	height: 1rem;
	accent-color: var(--floorplan-accent);
}

/*
 * Somebody else looking after the booking.
 *
 * The tick reads as a statement, like the mailing-list one above it; the fields
 * it opens are set apart with a rule and an indent so it is obvious they belong
 * to it and not to the person paying, whose boxes they sit directly under.
 */
.floorplan__contact {
	margin-top: 1rem;
}

.floorplan__contact-toggle {
	display: flex;
	align-items: flex-start;
	gap: 0.55rem;
	font-size: 0.92em;
	line-height: 1.4;
	cursor: pointer;
}

.floorplan__contact-toggle input {
	margin-top: 0.15em;
	flex: 0 0 auto;
	width: 1rem;
	height: 1rem;
	accent-color: var(--floorplan-accent);
}

.floorplan__contact-fields {
	margin-top: 0.9rem;
	padding-left: 1.55rem;
	border-left: 2px solid var(--floorplan-line);
}

.floorplan__note {
	margin: 0.75rem 0 0;
	font-size: 0.88em;
	color: var(--floorplan-muted);
}

@media (max-width: 600px) {
	.floorplan__basket {
		padding: 0.85rem;
	}

	.floorplan__zoom {
		right: 0.4rem;
		bottom: 0.4rem;
	}
}

/* -- The tray, on the drawing ----------------------------------------------- */

/*
 * How many seats are chosen, and the way on — pinned to the bottom of the room.
 *
 * Both used to be below the drawing: the count on a line under it, the button
 * to go on inside the basket under that. On a phone the plan is 500px, so while
 * somebody is choosing seats neither is on the screen — they could not see what
 * they had picked, and finishing meant scrolling away from the room to look for
 * a button. Here they are in the same glance as the tables being tapped.
 *
 * Absent from the layout entirely until something is chosen, so an untouched
 * plan is just the room.
 */
.floorplan__tray {
	position: absolute;
	left: 50%;
	bottom: 0.6rem;
	transform: translateX(-50%);
	z-index: 3;
	max-width: calc(100% - 1.2rem);
	/*
	 * The viewport sets `line-height: 0` so the SVG adds no descender space
	 * beneath it. That is right for a picture and wrong for the only words
	 * inside the frame: inherited, the count rendered as a line box of no
	 * height at all — legible on screen, and zero-by-zero to anything measuring
	 * it, including a screen reader's caret and a test.
	 */
	line-height: 1.3;
	animation: floorplan-tray-in 0.18s ease-out;
}

@keyframes floorplan-tray-in {
	from {
		opacity: 0;
		transform: translate(-50%, 0.5rem);
	}
}

@media (prefers-reduced-motion: reduce) {
	.floorplan__tray {
		animation: none;
	}
}

.floorplan__proceed {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.3rem;
	width: 100%;
	font: inherit;
	color: inherit;
	padding: 0.4rem 1rem 0.55rem;
	border: 1px solid var(--floorplan-line);
	border-radius: 1rem;
	background: color-mix(in srgb, Canvas 90%, transparent);
	backdrop-filter: blur(6px);
	box-shadow: 0 2px 10px color-mix(in srgb, CanvasText 12%, transparent);
	cursor: pointer;
	/*
	 * The gesture is the point: a drag down this handle is how somebody goes on
	 * to the reservation, so the browser must not read it as a page scroll
	 * first. Nothing here scrolls, so nothing here is handed over.
	 */
	touch-action: none;
	user-select: none;
	-webkit-user-select: none;
	transition: transform 0.16s ease, box-shadow 0.16s ease;
}

/*
 * The grabber: the one mark that says this can be pulled and not only pressed.
 *
 * Darker than `--floorplan-line`, which is the colour of a border nobody is
 * meant to look at. This is the affordance — at 3px and 18% it was there in the
 * markup and invisible on the screen, which is the same as not being there.
 */
.floorplan__proceed-grip {
	display: block;
	width: 2.25rem;
	height: 4px;
	border-radius: 999px;
	background: color-mix(in srgb, currentColor 32%, transparent);
}

.floorplan__proceed-go {
	display: flex;
	align-items: center;
	gap: 0.35rem;
	font-size: 0.9em;
	font-weight: 700;
	color: var(--floorplan-accent);
}

.floorplan__proceed-chevron {
	display: block;
	transition: transform 0.16s ease;
}

.floorplan__proceed:hover,
.floorplan__proceed:focus-visible {
	box-shadow: 0 4px 14px color-mix(in srgb, CanvasText 18%, transparent);
}

/*
 * While the handle is being pulled.
 *
 * The tray follows the finger — capped, and set from the runtime — so the
 * gesture answers before it is finished. Without that a swipe is a guess: you
 * find out whether the plan understood you only once you have let go.
 */
.floorplan__page.is-pulling .floorplan__proceed {
	transition: none;
}

.floorplan__proceed.is-armed {
	border-color: var(--floorplan-accent);
}

.floorplan__proceed.is-armed .floorplan__proceed-chevron {
	transform: translateY(2px);
}

/* -- Under the room -------------------------------------------------------- */

/*
 * The line directly beneath the plan: how many seats are chosen, and whatever
 * just happened.
 *
 * It lives here rather than only in the basket because on a long page the basket
 * is often most of a screen below the fold — so a refused click was answered
 * somewhere the reader was not looking, and the plan appeared to ignore them.
 */
.floorplan__under {
	display: flex;
	align-items: baseline;
	gap: 0.75rem;
	flex-wrap: wrap;
	margin-top: 0.5rem;
	min-height: 1.6em;
}

.floorplan__count {
	font-size: 0.85em;
	font-weight: 600;
	white-space: nowrap;
}

/* At the ceiling, the counter says so before the next click is refused. */
.floorplan__count.is-full {
	color: var(--floorplan-error);
}

.floorplan__flash:empty {
	display: none;
}

.floorplan__flash {
	margin: 0;
	font-size: 0.88em;
	color: var(--floorplan-muted);
}

.floorplan__flash.is-error {
	color: var(--floorplan-error);
	font-weight: 600;
}

/* -- Legend, behind its button --------------------------------------------- */

.floorplan__zoom-btn--legend.is-on {
	background: var(--floorplan-surface);
	box-shadow: inset 0 0 0 1px var(--floorplan-line);
}

/*
 * Directly under the room it describes, not at the bottom of the page. The
 * button that opens it is in the view cluster at the room's corner, so the two
 * are within a glance of each other.
 */
.floorplan__legend {
	margin: 0.6rem 0 0;
}

/*
 * The fill and the lettering of a taken seat.
 *
 * The server paints both when the page is rendered; these repaint them when the
 * runtime discovers a seat has gone while somebody was looking at the room.
 * Kept as CSS rather than as more attribute-writing in JavaScript, because the
 * classes are already being toggled and the two must not disagree.
 */
.floorplan__el--seatable.is-taken:not(.is-mine) > ellipse,
.floorplan__el--seatable.is-taken:not(.is-mine) > rect {
	fill: #e0c4bf;
}

.floorplan__el--seatable.is-taken:not(.is-mine) text {
	fill: #6d4b45;
}

/* -- Checkout: who is paying, and how -------------------------------------- */

.floorplan__checkout-title {
	margin: 0.9rem 0 0.2rem;
	font-size: 1em;
}

.floorplan__checkout-title:first-child {
	margin-top: 0;
}

.floorplan__checkout-hint {
	margin: 0 0 0.7rem;
	font-size: 0.85em;
	color: var(--floorplan-muted);
}

.floorplan__payer {
	display: grid;
	gap: 0.6rem;
}

@container (min-width: 30rem) {
	.floorplan__payer {
		grid-template-columns: 1fr 1fr;
	}

	/* An address line is one field, not half of two. */
	.floorplan__payer-field.is-wide {
		grid-column: 1 / -1;
	}
}

.floorplan__payer-field {
	display: flex;
	flex-direction: column;
	gap: 0.2rem;
	font-size: 0.85em;
	min-width: 0;
}

.floorplan__payer-field input,
.floorplan__payer-field select {
	width: 100%;
	box-sizing: border-box;
	font: inherit;
	/* The label around it is 0.85em; the box people type in is not. */
	font-size: var(--floorplan-font);
	padding: var(--floorplan-pad);
	border: 1px solid var(--floorplan-line);
	border-radius: var(--floorplan-radius);
	background: Canvas;
	color: inherit;
	min-height: var(--floorplan-control);
}

.floorplan__payer-field input:focus-visible,
.floorplan__payer-field select:focus-visible {
	outline: none;
	border-color: #2f6fed;
	box-shadow: 0 0 0 3px color-mix(in srgb, #2f6fed 25%, transparent);
}

.floorplan__payer-field input.is-invalid {
	border-color: var(--floorplan-error);
}

/* -- How to pay ------------------------------------------------------------ */

.floorplan__providers {
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem;
	margin-bottom: 0.9rem;
}

.floorplan__provider {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.5rem 0.8rem;
	border: 1px solid var(--floorplan-line);
	border-radius: var(--floorplan-radius);
	cursor: pointer;
	font-weight: 600;
	min-height: var(--floorplan-control);
	flex: 1 1 9rem;
}

.floorplan__provider:has(input:checked) {
	border-color: #2f6fed;
	box-shadow: inset 0 0 0 1px #2f6fed;
	background: color-mix(in srgb, #2f6fed 6%, transparent);
}

/*
 * A mark rather than a logo: shipping Stripe's and PayPal's brand assets means
 * shipping their trademarks and their usage rules, and a coloured dot beside the
 * word is honest about which is which without either.
 */
.floorplan__provider-mark {
	width: 1.2rem;
	height: 1.2rem;
	border-radius: 5px;
	flex: none;
}

.floorplan__provider-mark--stripe {
	background: linear-gradient(135deg, #635bff, #8b7dff);
}

.floorplan__provider-mark--paypal {
	background: linear-gradient(135deg, #003087, #009cde);
}

.floorplan__provider-mark--cash {
	background: linear-gradient(135deg, #2e7d32, #66bb6a);
}

.floorplan__pay {
	width: 100%;
	font: inherit;
	font-size: 1em;
	font-weight: 600;
	padding: 0.6rem 1.4rem;
	min-height: var(--floorplan-control);
	border: 0;
	border-radius: 999px;
	background: #2f6fed;
	color: #fff;
	cursor: pointer;
}

.floorplan__pay:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.floorplan__back {
	width: 100%;
	margin-top: 0.5rem;
	font: inherit;
	font-size: 0.9em;
	padding: 0.6rem;
	border: 0;
	background: none;
	color: var(--floorplan-muted);
	cursor: pointer;
	text-decoration: underline;
}

/* -- Coming back from a gateway -------------------------------------------- */

.floorplan__outcome {
	margin: 1rem 0;
	padding: 0.9rem 1.1rem;
	border-radius: 10px;
	border-inline-start: 3px solid var(--floorplan-line);
	background: var(--floorplan-surface);
}

.floorplan__outcome.is-paid {
	border-inline-start-color: var(--floorplan-mine);
	background: color-mix(in srgb, var(--floorplan-mine) 8%, transparent);
}

.floorplan__outcome.is-error,
.floorplan__outcome.is-cancelled {
	border-inline-start-color: var(--floorplan-error);
	background: color-mix(in srgb, var(--floorplan-error) 7%, transparent);
}

/* A seat nobody has been named for cannot be reserved, and says so. */
.floorplan__seat.is-incomplete::after {
	content: attr(data-incomplete-note);
	display: block;
	margin-top: 0.4rem;
	font-size: 0.8em;
	color: var(--floorplan-error);
	font-weight: 600;
}


/* -- Mobile ---------------------------------------------------------------- */

/*
 * Below the tablet breakpoint everything grows back.
 *
 * 16px on the CONTROLS is not a preference: iOS Safari zooms the whole page
 * whenever a focused input's font is under 16px, which throws the layout
 * sideways mid-typing. The larger targets go with it, because a finger is not a
 * pointer.
 */
@media (max-width: 782px) {
	.floorplan {
		--floorplan-control: 46px;
		--floorplan-pad: 0.6rem 0.75rem;
	}

	.floorplan__seat-field input,
	.floorplan__payer-field input,
	.floorplan__payer-field select {
		font-size: 16px;
	}

	.floorplan__book,
	.floorplan__pay {
		min-height: 48px;
	}

	/*
	 * The zoom cluster is the exception to "everything grows back".
	 *
	 * It floats OVER the room rather than sitting in the flow, so on a narrow
	 * screen the full-size buttons cover the corner of the very thing they are
	 * there to help you look at. Smaller, and still a 30px target — under the
	 * 44px guidance, which applies to controls you must hit, not to an aid for
	 * a picture you can also pinch.
	 */
	.floorplan__zoom {
		right: 0.4rem;
		bottom: 0.4rem;
		gap: 1px;
		padding: 1px;
	}

	/*
	 * The two of them want the same corner of a 328px frame.
	 *
	 * The tray is centred and the zoom cluster is right-aligned, which is room
	 * enough on a desktop and none at all on a phone — so while there is a tray
	 * the cluster steps up above it. Only here: moving it on a wide screen
	 * would be a jump with nothing behind it.
	 */
	.floorplan__page.has-tray .floorplan__zoom {
		bottom: auto;
		top: 0.4rem;
	}

	.floorplan__tray {
		bottom: 0.4rem;
		max-width: calc(100% - 0.8rem);
	}

	.floorplan__zoom-btn {
		font-size: 0.85rem;
		min-width: 1.9rem;
		height: 1.9rem;
		padding: 0 0.3rem;
	}
}
