/**
 * Toast (template-parts/components/toast.php).
 *
 * Bottom right on desktop, full width along the bottom below the layout
 * switch. Every offset is --container-pad, so the toast sits on the page's own
 * gutter line - 64px on desktop, 16px below 1024 - and follows it without a
 * second set of numbers.
 */

.toast-region {
	position: fixed;
	right: var(--container-pad);
	bottom: var(--container-pad);
	/* Above the page, below every header layer. The header shells are 90/100/
	   110 and the mobile navigation overlay is 95; a toast must never cover the
	   navigation, and at the bottom of the viewport it has no reason to. */
	z-index: 80;
	display: flex;
	flex-direction: column;
	gap: 16px;
	/* The region spans nothing when empty and never eats clicks meant for the
	   page. The toasts themselves take pointer events back. */
	pointer-events: none;
}

.toast {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	width: max-content;
	/* Wide enough to read, never wider than the container's own measure. */
	max-width: min(420px, calc(100vw - 2 * var(--container-pad)));
	padding: 32px;
	border-radius: 6px;
	background-color: var(--color-surface-darkest);
	color: var(--color-heading-text-on-dark);
	pointer-events: auto;
	/* The house reveal: 650ms on --motion-ease, matching every other enter on
	   the site. It slides in from the right, which is the edge it is docked to. */
	opacity: 0;
	transform: translateX(16px);
	transition: opacity 650ms var(--motion-ease), transform 650ms var(--motion-ease);
}

.toast.is-visible {
	opacity: 1;
	transform: translateX(0);
}

.toast[hidden] {
	display: none;
}

/* The accent is the only colour difference: the tick reads as confirmation,
   the error's rule reads as a stop. Orange stays under the 3% budget - this is
   a 24px glyph and a 2px edge. */
.toast--success .toast__icon {
	flex-shrink: 0;
	display: block;
	color: var(--color-accent);
}

.toast--error {
	border-left: 2px solid var(--color-accent);
}

.toast__message {
	margin: 0;
	flex: 1;
	min-width: 0; /* so a long word wraps instead of widening the box */
	font-size: var(--type-card-body-size);
	line-height: var(--type-body-line);
	color: var(--color-body-text-on-dark);
}

/* The rate-limit message carries a real mailto link, because that limit is
   per-network and a genuine enquirer can be blocked by a colleague behind the
   same address. A blocked lead is only recovered if it can act immediately. */
.toast__message a {
	color: var(--color-heading-text-on-dark);
	text-decoration: underline;
}

.toast__close {
	flex-shrink: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	/* 44px is the site's touch target, and this is the only way out of an
	   error toast. Margin pulls the optical edge back to the 32px padding. */
	width: 44px;
	height: 44px;
	margin: -10px -10px -10px 0;
	padding: 0;
	border: 0;
	background: none;
	color: var(--color-text-secondary-on-dark);
	cursor: pointer;
	transition: color 150ms ease; /* the interaction tier */
}

.toast__close:hover,
.toast__close:focus-visible {
	color: var(--color-heading-text-on-dark);
}

@media (max-width: 1024px) {
	/* Full width along the bottom, on the container inset - not a small box in
	   a corner, which at 390 would be neither readable nor easy to dismiss. */
	.toast-region {
		left: var(--container-pad);
	}

	.toast {
		width: auto;
		max-width: none;
	}
}

/* Fade, no slide. The transform is what a vestibular trigger reacts to; the
   opacity change carries the same information without it. */
@media (prefers-reduced-motion: reduce) {
	.toast {
		transform: none;
		transition: opacity 650ms var(--motion-ease);
	}

	.toast.is-visible {
		transform: none;
	}
}

/* --------------------------------------------------------------------
 * Room for the toast
 *
 * The toast is fixed to the bottom of the viewport, and on a form page the
 * primary action is the LAST thing in the document. Measured at 390 with the
 * submit button scrolled to the bottom edge - which is where someone is
 * standing when they press it - the toast covered it by 176px. An error toast
 * never dismisses itself, so the retry button would sit underneath the message
 * asking for a retry.
 *
 * The page therefore grows by exactly what the toast occupies while one is up:
 * its measured height plus the offset it sits at. Nothing on the page moves,
 * the scrollable area simply gets longer, and the button can be scrolled into
 * the clear. toast.js publishes the height it measured and releases it on hide.
 * -------------------------------------------------------------------- */

/* Its height, the offset it sits at, and one more gutter. Without the third
   term the reserved space is exactly what the toast occupies, so scrolling to
   the end lands the button flush against the toast's top edge - measured
   touching to the sub-pixel. The extra gutter is the same --container-pad the
   toast is already inset by, so the button clears it by the same distance the
   toast clears the viewport. */
body.has-toast {
	padding-bottom: calc(var(--toast-space, 0px) + 2 * var(--container-pad));
}
