/**
 * SLPH Plant Hire booking widget.
 *
 * Every colour, radius and font size is a custom property, so the theme can
 * rebrand the widget by redefining them on .slph-widget without touching
 * this file.
 */

.slph-widget {
	/* The surrounding page is styled to a brand, not to the visitor's OS, so
	   the form should not follow the browser's dark mode either. This also
	   stops Chrome re-tinting the parts it draws itself: form fields,
	   autofill, scrollbars and the dialog backdrop. */
	color-scheme: only light;

	--slph-accent: #c8511b;
	--slph-accent-ink: #ffffff;
	--slph-ink: #1d2327;
	--slph-ink-soft: #61686d;
	--slph-line: #d8dcdf;
	--slph-surface: #ffffff;
	--slph-surface-alt: #f4f6f7;
	--slph-taken: #eceff1;
	--slph-taken-ink: #a3abb1;
	--slph-error: #b3261e;
	--slph-success: #1c6b3f;
	--slph-radius: 6px;
	--slph-gap: 1rem;

	box-sizing: border-box;
	color: var(--slph-ink);
	background: var(--slph-surface);
	border: 1px solid var(--slph-line);
	border-radius: var(--slph-radius);
	padding: 1.25rem;
	max-width: 46rem;
}

.slph-widget *,
.slph-widget *::before,
.slph-widget *::after {
	box-sizing: inherit;
}

/* The item being hired. Set as a small kicker above the heading by default,
   because in a popup opened from a card the visitor needs telling which
   machine this is. Restyle freely: it has its own typography controls. */
.slph-widget__item {
	margin: 0 0 0.25rem;
	color: var(--slph-item-ink, var(--slph-ink-soft));
	font-size: 0.85rem;
	font-weight: 600;
	letter-spacing: 0.02em;
	line-height: 1.3;
}

.slph-widget__heading {
	margin: 0 0 0.75rem;
	font-size: 1.15rem;
	line-height: 1.3;
}

.slph-widget__prompt {
	margin: 0 0 0.75rem;
	color: var(--slph-ink-soft);
	font-size: 0.9rem;
}

.slph-widget__prompt.is-error {
	color: var(--slph-error);
}

/* Calendar ---------------------------------------------------------------- */

.slph-cal__nav {
	display: flex;
	justify-content: space-between;
	gap: 0.5rem;
	margin-bottom: 0.5rem;
}

.slph-cal__nav-btn {
	appearance: none;
	background: var(--slph-nav-bg, var(--slph-surface-alt));
	border: 1px solid var(--slph-line);
	border-radius: var(--slph-radius);
	color: var(--slph-nav-ink, var(--slph-ink));
	cursor: pointer;
	font-size: 1rem;
	line-height: 1;
	padding: 0.5rem 0.9rem;
}

.slph-widget .slph-cal__nav-btn:hover:not(:disabled) {
	background: var(--slph-nav-hover-bg, var(--slph-line));
	color: var(--slph-nav-hover-ink, var(--slph-ink));
}

.slph-cal__nav-btn:disabled {
	cursor: default;
	opacity: 0.4;
}

.slph-cal__months {
	display: grid;
	gap: var(--slph-gap);
	grid-template-columns: 1fr;
}

@media (min-width: 34rem) {
	.slph-cal__months {
		grid-template-columns: 1fr 1fr;
	}
}

.slph-cal__caption {
	font-weight: 600;
	text-align: center;
	padding: 0.25rem 0 0.5rem;
}

.slph-cal__weekdays,
.slph-cal__grid {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 2px;
}

.slph-cal__weekdays {
	font-size: 0.7rem;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--slph-ink-soft);
	text-align: center;
	padding-bottom: 0.25rem;
}

.slph-cal__day {
	appearance: none;
	aspect-ratio: 1 / 1;
	background: var(--slph-day-bg, var(--slph-surface-alt));
	border: 1px solid transparent;
	border-radius: 4px;
	color: var(--slph-ink);
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 0.85rem;
	font-variant-numeric: tabular-nums;
	padding: 0;
	width: 100%;
}

.slph-widget .slph-cal__day:not(:disabled) {
	color: var(--slph-day-ink, var(--slph-ink));
}

/* Every interactive state below declares its own colour, even where that
   colour is simply the inherited one. Leaving colour undeclared lets a theme's
   own button:hover rule paint the text, which is how a stray brand colour ends
   up on the calendar with nothing in this plugin to override it. */
.slph-widget .slph-cal__day:hover:not(:disabled) {
	background: var(--slph-day-hover-bg, var(--slph-surface-alt));
	border-color: var(--slph-day-hover-border, var(--slph-accent));
	color: var(--slph-day-hover-ink, var(--slph-ink));
}

.slph-cal__day:focus-visible {
	outline: 2px solid var(--slph-accent);
	outline-offset: 1px;
}

.slph-cal__day--empty {
	background: none;
	cursor: default;
}

.slph-widget .slph-cal__day--taken,
.slph-widget .slph-cal__day--closed,
.slph-widget .slph-cal__day--out-of-range {
	background: var(--slph-taken);
	color: var(--slph-taken-ink);
	cursor: not-allowed;
}

/* A diagonal hatch reads as "unavailable" even without colour. */
.slph-cal__day--taken {
	background-image: repeating-linear-gradient(
		45deg,
		transparent,
		transparent 3px,
		rgba(0, 0, 0, 0.07) 3px,
		rgba(0, 0, 0, 0.07) 6px
	);
}

/* Declared after the hover rule and at matching specificity, so hovering a day
   inside the chosen range cannot wash its text out. */
.slph-widget .slph-cal__day.is-within,
.slph-widget .slph-cal__day.is-within:hover {
	background: var(--slph-within-bg, color-mix(in srgb, var(--slph-accent) 16%, var(--slph-surface)));
	border-color: var(--slph-day-hover-border, var(--slph-accent));
	color: var(--slph-within-ink, var(--slph-ink));
}

.slph-widget .slph-cal__day.is-within:not(:hover) {
	border-color: transparent;
}

.slph-widget .slph-cal__day.is-selected,
.slph-widget .slph-cal__day.is-selected:hover {
	background: var(--slph-selected-bg, var(--slph-accent));
	color: var(--slph-selected-ink, var(--slph-accent-ink));
	font-weight: 600;
}

.slph-widget__key {
	display: flex;
	align-items: center;
	gap: 0.4rem;
	flex-wrap: wrap;
	margin: 0.75rem 0 0;
	font-size: 0.78rem;
	color: var(--slph-ink-soft);
}

.slph-key {
	display: inline-block;
	width: var(--slph-key-size, 0.85rem);
	height: var(--slph-key-size, 0.85rem);
	border: 1px solid var(--slph-key-border, var(--slph-line));
	border-radius: 3px;
	margin-left: 0.5rem;
}

.slph-key:first-child {
	margin-left: 0;
}

/* Each swatch defaults to the day colour it stands for, so the key stays true
   to the calendar unless it is deliberately overridden. */
.slph-key--free {
	background: var(--slph-key-free, var(--slph-day-bg, var(--slph-surface-alt)));
}

.slph-key--taken {
	background: var(--slph-key-taken, var(--slph-taken));
	/* The same hatch the unavailable days carry. Without it the two swatches
	   are near-identical greys and the key reads as a pair of empty boxes. */
	background-image: repeating-linear-gradient(
		45deg,
		transparent,
		transparent 2px,
		rgba(0, 0, 0, 0.16) 2px,
		rgba(0, 0, 0, 0.16) 4px
	);
}

/* The hidden attribute must win.
   .slph-widget__summary sets display:flex, which is a class selector and so
   outranks the browser's own [hidden] { display: none } rule. Without this the
   summary bar and the details form are both visible before any dates have been
   picked. Page builders set display on their descendants too, hence !important. */
.slph-widget [hidden],
.slph-widget[hidden] {
	display: none !important;
}

/* Reveal ------------------------------------------------------------------
   The summary and form grow open together when dates are picked.

   Height is animated with the grid 0fr -> 1fr technique rather than max-height,
   because it interpolates to the content's real height: no magic number to
   outgrow, and it stays correct when a validation message adds a line. */

.slph-widget__reveal {
	display: grid;
	grid-template-rows: 0fr;
	opacity: 0;
	visibility: hidden;
	transition-property: var(--slph-reveal-transition, grid-template-rows, opacity, visibility);
	transition-duration: var(--slph-reveal-duration, 300ms);
	transition-timing-function: var(--slph-reveal-easing, cubic-bezier(0.22, 0.61, 0.36, 1));
}

.slph-widget__reveal.is-open {
	grid-template-rows: 1fr;
	opacity: 1;
	visibility: visible;
}

/* The grid row cannot collapse below its content without both of these. */
.slph-widget__reveal-inner {
	min-height: 0;
	overflow: hidden;
}

/* visibility is deliberately in the transition list: it keeps the collapsed
   panel out of the tab order and away from screen readers, while still holding
   off until the closing animation has finished. */

@media (prefers-reduced-motion: reduce) {
	.slph-widget__reveal {
		transition-duration: 0.01ms !important;
	}
}

/* Summary ----------------------------------------------------------------- */

.slph-widget__summary {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--slph-gap);
	flex-wrap: wrap;
	margin-top: var(--slph-gap);
	padding: 0.75rem 0.9rem;
	background: var(--slph-surface-alt);
	border-radius: var(--slph-radius);
}

.slph-widget__summary-dates {
	font-weight: 600;
}

.slph-widget__link {
	appearance: none;
	background: none;
	border: 0;
	color: var(--slph-link, var(--slph-accent));
	cursor: pointer;
	font: inherit;
	padding: 0;
	text-decoration: underline;
}

.slph-widget .slph-widget__link:hover,
.slph-widget .slph-widget__link:focus {
	background: none;
	color: var(--slph-link-hover, var(--slph-link, var(--slph-accent)));
}

/* Price -------------------------------------------------------------------- */

.slph-widget__price {
	background: var(--slph-price-bg, var(--slph-surface-alt));
	border-radius: var(--slph-radius);
	margin-top: 0.5rem;
	padding: 0.75rem 0.9rem;
}

.slph-widget__price-line {
	align-items: baseline;
	display: flex;
	gap: var(--slph-gap);
	justify-content: space-between;
}

.slph-widget__price-line--deposit {
	border-top: 1px solid var(--slph-line);
	margin-top: 0.5rem;
	padding-top: 0.5rem;
}

.slph-widget__price-label {
	color: var(--slph-price-label-ink, var(--slph-ink-soft));
	font-size: 0.85rem;
}

.slph-widget__price-total {
	color: var(--slph-price-ink, var(--slph-ink));
	font-size: 1.3rem;
	font-weight: 700;
	font-variant-numeric: tabular-nums;
	line-height: 1.2;
}

.slph-widget__price-deposit {
	color: var(--slph-price-ink, var(--slph-ink));
	font-variant-numeric: tabular-nums;
	font-weight: 600;
}

.slph-widget__price-breakdown {
	color: var(--slph-ink-soft);
	font-size: 0.8rem;
	margin: 0.15rem 0 0;
}

.slph-widget__price-note {
	color: var(--slph-ink-soft);
	font-size: 0.75rem;
	line-height: 1.4;
	margin: 0.5rem 0 0;
}

/* Form -------------------------------------------------------------------- */

.slph-widget__form {
	margin-top: var(--slph-gap);
}

.slph-widget__grid {
	display: grid;
	gap: 0.85rem;
	grid-template-columns: 1fr;
}

@media (min-width: 34rem) {
	.slph-widget__grid {
		grid-template-columns: 1fr 1fr;
	}

	.slph-field--wide {
		grid-column: 1 / -1;
	}
}

.slph-field {
	margin: 0;
}

.slph-field label {
	display: block;
	font-size: 0.82rem;
	font-weight: 600;
	margin-bottom: 0.25rem;
}

.slph-field input,
.slph-field textarea {
	background: var(--slph-surface);
	border: 1px solid var(--slph-line);
	border-radius: 4px;
	color: var(--slph-ink);
	font: inherit;
	padding: 0.5rem 0.6rem;
	width: 100%;
}

.slph-field input:focus,
.slph-field textarea:focus {
	border-color: var(--slph-accent);
	outline: 2px solid color-mix(in srgb, var(--slph-accent) 35%, transparent);
	outline-offset: 0;
}

/* Off-screen rather than display:none, so bots that skip hidden fields still
   see it, while people and screen readers never meet it. */
.slph-widget__hp {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	clip-path: inset(50%);
	white-space: nowrap;
}

.slph-widget__actions {
	margin: var(--slph-gap) 0 0;
}

.slph-widget__submit {
	appearance: none;
	background: var(--slph-accent);
	border: 0;
	border-radius: var(--slph-radius);
	color: var(--slph-accent-ink);
	cursor: pointer;
	font: inherit;
	font-weight: 600;
	padding: 0.7rem 1.4rem;
}

.slph-widget .slph-widget__submit:hover:not(:disabled) {
	background: var(--slph-submit-hover-bg, var(--slph-accent));
	color: var(--slph-submit-hover-ink, var(--slph-accent-ink));
	filter: brightness(0.92);
}

.slph-widget__submit:disabled {
	cursor: default;
	opacity: 0.6;
}

.slph-widget__terms,
.slph-widget__note {
	color: var(--slph-ink-soft);
	font-size: 0.8rem;
	margin: 0.75rem 0 0;
}

/* Messages ---------------------------------------------------------------- */

.slph-widget__message {
	border-radius: var(--slph-radius);
	margin-top: var(--slph-gap);
	padding: 0.75rem 0.9rem;
}

.slph-widget__message.is-error {
	background: color-mix(in srgb, var(--slph-error) 10%, var(--slph-surface));
	border-left: 3px solid var(--slph-error);
	color: var(--slph-error);
}

.slph-widget__message.is-success {
	background: color-mix(in srgb, var(--slph-success) 10%, var(--slph-surface));
	border-left: 3px solid var(--slph-success);
	color: var(--slph-success);
}

.slph-widget__message:focus {
	outline: 2px solid var(--slph-accent);
	outline-offset: 2px;
}

/* Launch button and popup -------------------------------------------------
   The popup is a native <dialog>, so showModal() puts it in the top layer and
   no amount of overflow:hidden, transform or z-index on a surrounding card can
   clip it. That is the whole reason for using a dialog over a div. */

/* A grid wrapper, so one property covers left, centre, right and stretch.
   text-align cannot stretch a flex button; justify-items: stretch can. */
.slph-launch {
	color-scheme: only light;
	--slph-modal-width: 46rem;

	display: grid;
	justify-items: start;
}

.slph-launch__button {
	align-items: center;
	appearance: none;
	background: #c8511b;
	border: 0;
	border-radius: 6px;
	color: #fff;
	cursor: pointer;
	display: inline-flex;
	font: inherit;
	font-weight: 600;
	gap: 0.5rem;
	justify-content: center;
	line-height: 1.2;
	/* Flex items will not shrink below their min-content width unless told to,
	   which makes a long label push the button wider than its container
	   instead of wrapping inside it. */
	min-width: 0;
	max-width: 100%;
	padding: 0.75rem 1.5rem;
	text-align: center;
}

.slph-launch__label {
	min-width: 0;
	/* Break inside a long single word rather than let it overflow: yard items
	   have names like "Reversible Plate Compactor". */
	overflow-wrap: anywhere;
}

.slph-launch__button:hover {
	background: var(--slph-launch-hover-bg, #c8511b);
	color: var(--slph-launch-hover-ink, #fff);
	filter: brightness(0.92);
}

.slph-launch__icon {
	display: inline-flex;
	align-items: center;
}

.slph-launch__icon svg {
	width: 1em;
	height: 1em;
	fill: currentColor;
}

.slph-modal {
	color-scheme: only light;
	justify-self: stretch;
	background: #fff;
	border: 0;
	border-radius: 8px;
	box-shadow: 0 1.5rem 4rem rgba(0, 0, 0, 0.3);
	color: inherit;
	margin: auto;
	max-height: calc(100vh - 2rem);
	max-width: min(var(--slph-modal-width, 46rem), calc(100vw - 2rem));
	overflow: auto;
	padding: 0;
	width: 100%;
}

.slph-modal::backdrop {
	background: rgba(0, 0, 0, 0.55);
}

.slph-modal__inner {
	padding: 1.75rem;
	position: relative;
}

.slph-modal__close {
	align-items: center;
	appearance: none;
	background: transparent;
	border: 0;
	border-radius: 50%;
	color: #61686d;
	cursor: pointer;
	display: flex;
	height: 2rem;
	justify-content: center;
	padding: 0;
	position: absolute;
	right: 0.6rem;
	top: 0.6rem;
	width: 2rem;
	z-index: 1;
}

.slph-modal__close:hover {
	background: var(--slph-close-hover-bg, rgba(0, 0, 0, 0.07));
	color: var(--slph-close-hover-ink, #61686d);
}

.slph-modal__close svg {
	width: 60%;
	height: 60%;
	fill: currentColor;
}

/* Inside the popup the panel supplies the chrome, so the form sits flush. */
.slph-widget--in-modal {
	background: none;
	border: 0;
	border-radius: 0;
	max-width: none;
	padding: 0;
}

/* Popup animation ---------------------------------------------------------
   One pair of keyframes covers every style: each option only changes where the
   panel travels from, via --slph-anim-from. */

@keyframes slph-modal-in {
	from {
		opacity: 0;
		transform: var(--slph-anim-from, none);
	}
	to {
		opacity: 1;
		transform: none;
	}
}

@keyframes slph-modal-out {
	from {
		opacity: 1;
		transform: none;
	}
	to {
		opacity: 0;
		transform: var(--slph-anim-from, none);
	}
}

@keyframes slph-backdrop-in {
	from { opacity: 0; }
	to { opacity: 1; }
}

@keyframes slph-backdrop-out {
	from { opacity: 1; }
	to { opacity: 0; }
}

.slph-modal[data-slph-anim="fade"] { --slph-anim-from: none; }
.slph-modal[data-slph-anim="fade-up"] { --slph-anim-from: translateY(16px); }
.slph-modal[data-slph-anim="fade-down"] { --slph-anim-from: translateY(-16px); }
.slph-modal[data-slph-anim="zoom"] { --slph-anim-from: scale(0.94); }

/* :not(.is-closing) matters. The dialog keeps its open attribute for the whole
   of the exit animation, so without it this rule would still match and, being
   the more specific of the two, would keep the entrance animation applied and
   the exit would never play. */
.slph-modal[data-slph-anim]:not([data-slph-anim="none"]):not(.is-editor-open):not(.is-closing)[open] {
	animation: slph-modal-in var(--slph-anim-duration, 250ms) ease both;
}

.slph-modal[data-slph-anim]:not([data-slph-anim="none"]):not(.is-editor-open):not(.is-closing)[open]::backdrop {
	animation: slph-backdrop-in var(--slph-anim-duration, 250ms) ease both;
}

/* The closing class is added by script, which then waits for the animation to
   finish before calling close(). A dialog removed from the top layer mid
   animation would simply vanish. */
.slph-modal[data-slph-anim]:not([data-slph-anim="none"]).is-closing {
	animation: slph-modal-out var(--slph-anim-duration, 250ms) ease both;
}

.slph-modal[data-slph-anim]:not([data-slph-anim="none"]).is-closing::backdrop {
	animation: slph-backdrop-out var(--slph-anim-duration, 250ms) ease both;
}

/* Motion is decoration here, so honour the visitor's preference outright. */
@media (prefers-reduced-motion: reduce) {
	.slph-modal,
	.slph-modal::backdrop {
		animation-duration: 0.01ms !important;
	}
}

/* Shown open and in the flow while the page is being built, so the popup can
   be styled without fighting the editor for a click. */
.slph-modal.is-editor-open {
	display: block;
	margin: 1rem 0 0;
	max-height: none;
	max-width: none;
	position: static;
}
/* Editor placeholder ------------------------------------------------------ */

.slph-widget--placeholder,
.slph-widget--closed {
	border-style: dashed;
	color: var(--slph-ink-soft);
	text-align: center;
}

.slph-widget--placeholder p,
.slph-widget--closed p {
	margin: 0;
}

/* Hire details list -------------------------------------------------------
   Standalone from the booking panel, so it carries its own tokens and can sit
   anywhere on a page. */

.slph-details {
	color-scheme: only light;
	--slph-ink: #1d2327;
	--slph-ink-soft: #61686d;
	--slph-line: #d8dcdf;

	list-style: none;
	margin: 0;
	padding: 0;
}

.slph-details__row {
	border-bottom: 1px solid var(--slph-line);
	display: flex;
	gap: 1rem;
	padding: 0.5rem 0;
}

.slph-details__row:last-child {
	border-bottom: 0;
}

.slph-details--rows .slph-details__row {
	align-items: baseline;
	justify-content: space-between;
}

.slph-details--stacked .slph-details__row {
	flex-direction: column;
	gap: 0.15rem;
}

.slph-details__label {
	color: var(--slph-ink-soft);
	font-size: 0.85rem;
}

.slph-details__value {
	color: var(--slph-ink);
	font-weight: 600;
	text-align: right;
}

.slph-details--stacked .slph-details__value {
	text-align: left;
}
