/* ==========================================================================
   Contact page
   Stacked on phones: intro, form, contact details.
   Desktop: intro and form on the left, details on the right, both columns
   starting level with the top of the form.

   The form is Contact Form 7's (see inc/contact.php). Its template uses the
   theme's class names (.field, .field__label, .field__input,
   .contact-form__submit), and the rules below also style Contact Form 7's
   own elements: error tips, the notice box and the sending state.

   All motion for this page lives in section 7 at the bottom.
   ========================================================================== */

/* 1. Section and brand keyhole
   ========================================================================== */

.contact {
	--keyhole-size: clamp(20rem, 48vw, 43.75rem); /* 320px on phones, up to 700px */

	position: relative;
	isolation: isolate;
	overflow: clip;
	padding-block: var(--space-section);
	background-color: var(--surface);
}

/* The keyhole outline: large, brand blue, behind the contact card and bleeding
   off the right edge of the window. It sits inside the card's column and is
   placed from the card's bottom, so the mark's lower half, including the
   speech-bubble tail at its bottom left, is always hidden behind the card.
   The right offset reaches the window edge: the gutter, plus the margin either
   side of the 1280px container on wide screens, plus 30% of the mark. */
.contact__keyhole {
	position: absolute;
	z-index: -1;
	right: calc(-1 * (var(--gutter) + max(0px, (100vw - var(--container-max)) / 2)) - var(--keyhole-size) * 0.3);
	bottom: 45%;
	width: var(--keyhole-size);
	height: auto;
	max-width: none;
	pointer-events: none;
}

.contact__keyhole path {
	fill: none;
	stroke: var(--brand-blue);
	stroke-width: 2;
	stroke-linejoin: round;
	vector-effect: non-scaling-stroke;
}

.contact__inner {
	display: grid;
	gap: var(--space-6);
}

.contact__title {
	color: var(--brand-blue);
}

.contact__lede {
	max-width: var(--measure);
	margin-top: var(--space-4);
	font-size: var(--text-lg);
}

/* 2. Right column: contact details and the keyhole
   ========================================================================== */

/* Phones and tablets: the keyhole rises about a third of its height above the
   card, so the extra top margin keeps it clear of the booking link above. */
.contact__aside {
	position: relative;
	margin-top: var(--space-9);
}

.contact__details {
	padding: var(--space-6) var(--space-5);
	background-color: var(--surface-100);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-md);
}

/* An h2 for the outline, sized as a label so it does not compete with the h1. */
.contact__details-title {
	font-size: var(--text-lg);
	color: var(--brand-blue);
}

.contact__list dl {
	display: grid;
	gap: var(--space-5);
	margin-top: var(--space-5);
}

.contact__item dt {
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--ink-muted);
}

.contact__item dd {
	margin: var(--space-1) 0 0;
	font-weight: var(--weight-semibold);
	overflow-wrap: anywhere;
}

.contact__item a {
	text-decoration-thickness: 1px;
}

.contact__item a:hover {
	text-decoration-color: var(--accent-yellow);
	text-decoration-thickness: 2px;
}

/* 3. Form fields
   ========================================================================== */

.contact-form__grid {
	display: grid;
	gap: var(--space-5);
}

.field__label {
	display: block;
	font-weight: var(--weight-semibold);
	line-height: var(--leading-snug);
}

.field__optional {
	font-size: var(--text-sm);
	font-weight: var(--weight-regular);
	color: var(--ink-muted);
}

/* Border at 8.9:1 against white, well above the 3:1 needed to see a field's edge. */
.field__input {
	display: block;
	width: 100%;
	min-height: 3rem;
	margin-top: var(--space-2);
	padding: var(--space-3) var(--space-4);
	line-height: var(--leading-snug);
	background-color: var(--surface);
	border: 1px solid var(--ink-muted);
	border-radius: var(--radius-md);
}

textarea.field__input {
	min-height: 10rem;
	line-height: var(--leading-body);
	resize: vertical;
}

.field__input:hover {
	border-color: var(--ink);
}

/* Focus: the site-wide blue ring (style.css), plus a blue border so the field
   itself changes too. Shown on every focus, since typing needs it. */
.field__input:focus {
	border-color: var(--brand-blue);
	outline: var(--focus-width) solid var(--focus-color);
	outline-offset: 0;
}

/* Contact Form 7 wraps each input in an inline span; make it a block so the
   input keeps its own spacing. */
.field .wpcf7-form-control-wrap {
	display: block;
}

/* Invalid: red border and a message underneath. The message, not only the
   colour, tells the visitor what is wrong. Contact Form 7 adds .wpcf7-not-valid
   to the input and prints the message as .wpcf7-not-valid-tip. */
.field__input.wpcf7-not-valid {
	border-color: var(--error);
	box-shadow: inset 0 0 0 1px var(--error);
}

.field__input.wpcf7-not-valid:focus {
	outline-color: var(--error);
}

.field .wpcf7-not-valid-tip {
	margin-top: var(--space-2);
	font-size: var(--text-sm);
	font-weight: var(--weight-semibold);
	line-height: var(--leading-snug);
	color: var(--error);
}

/* 4. Submit, booking link and notices
   ========================================================================== */

.contact-form__submit {
	width: 100%;
	margin-top: var(--space-6);
}

/* Hover darkens the yellow a touch, mixed from the brand tokens rather than a new hex.
   Ink on it stays above 11:1. */
.contact-form__submit:hover {
	color: var(--ink);
	background-color: color-mix(in srgb, var(--accent-yellow) 88%, var(--ink));
}

.contact-form__alt {
	margin-top: var(--space-4);
	color: var(--ink-muted);
}

.contact-form__alt a {
	font-weight: var(--weight-semibold);
}

/* Sending: the button dims and shows a small spinning ring. Contact Form 7 also
   makes the form inert while it sends, so it cannot be sent twice. */
.contact-form.submitting .contact-form__submit {
	cursor: progress;
	opacity: 0.7;
}

.contact-form.submitting .contact-form__submit::after {
	content: "";
	display: inline-block;
	width: 1em;
	height: 1em;
	margin-left: var(--space-3);
	vertical-align: -0.125em;
	border: 2px solid currentcolor;
	border-right-color: transparent;
	border-radius: 50%;
}

/* Contact Form 7 dims the whole form while it sends; the button already shows it. */
.wpcf7 .contact-form[inert] {
	opacity: 1;
}

/* Notices: the unavailable message, and Contact Form 7's response box, shown
   at the top of the form when a send fails. Field errors show under each
   field instead, so the box stays hidden for them (screen readers still hear
   Contact Form 7's summary). The long selector outranks the plugin's own,
   including its per-state border colours. */
.form-notice,
.contact__form-wrap .wpcf7 form.contact-form .wpcf7-response-output {
	margin: 0 0 var(--space-6);
	padding: var(--space-4) var(--space-5);
	font-weight: var(--weight-semibold);
	color: var(--error);
	background-color: var(--surface-100);
	border: 0;
	border-left: var(--space-1) solid var(--error);
	border-radius: var(--radius-sm);
}

.wpcf7 .contact-form.init .wpcf7-response-output,
.wpcf7 .contact-form.invalid .wpcf7-response-output,
.wpcf7 .contact-form.sent .wpcf7-response-output {
	display: none;
}

/* 5. Success state
   .is-sent on .contact__form-wrap swaps the form for this confirmation.
   ========================================================================== */

.form-success {
	display: none;
	padding: var(--space-7) var(--space-5);
	background-color: var(--surface-100);
	border: 1px solid var(--border-subtle);
	border-radius: var(--radius-md);
}

.is-sent .contact-form,
.is-sent .contact-form__alt {
	display: none;
}

.is-sent .form-success {
	display: block;
}

/* The panel takes focus only so screen readers announce it (contact-form.js).
   It is not interactive, so it shows no focus ring. */
.form-success:focus-visible {
	outline: none;
}

.form-success__icon {
	width: var(--space-8);
	height: var(--space-8);
}

.form-success__ring,
.form-success__tick {
	fill: none;
	stroke-linecap: round;
	stroke-linejoin: round;
}

.form-success__ring {
	stroke: var(--brand-blue);
	stroke-width: 2;
}

.form-success__tick {
	stroke: var(--brand-blue);
	stroke-width: 3;
}

.form-success__title {
	margin-top: var(--space-5);
	font-size: var(--text-2xl);
	color: var(--brand-blue);
}

.form-success__text {
	max-width: var(--measure);
	margin-top: var(--space-3);
	font-size: var(--text-lg);
}

/* 6. Proof strip: the homepage logo partial, compact
   ========================================================================== */

.logos--slim {
	padding-block: var(--space-7);
	border-top: 1px solid var(--border-subtle);
}

.logos--slim .logos__title {
	max-width: none;
	font-size: var(--text-sm);
	font-weight: var(--weight-bold);
	letter-spacing: 0.08em;
	text-align: center;
	color: var(--ink-muted);
}

.logos--slim .logos__list {
	margin-top: var(--space-5);
}

/* Tablet and up
   ========================================================================== */

@media (min-width: 40em) {
	.contact-form__grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}

	.field--message {
		grid-column: 1 / -1;
	}

	.contact-form__submit {
		width: auto;
	}

	.contact__details {
		padding: var(--space-6);
	}
}

@media (min-width: 48em) {
	.logos--slim .logos__list {
		margin-top: var(--space-6);
	}
}

/* Desktop
   ========================================================================== */

@media (min-width: 64em) {
	.contact__inner {
		grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
		column-gap: var(--space-9);
		row-gap: var(--space-7);
	}

	.contact__intro,
	.contact__form-wrap {
		grid-column: 1;
	}

	/* Starts level with the top of the form. */
	.contact__aside {
		grid-column: 2;
		grid-row: 2;
		align-self: start;
		margin-top: 0;
	}

	/* Taller mark beside a shorter card: its bottom sits just inside the card's
	   bottom edge, and the top rises into the space beside the heading. */
	.contact__keyhole {
		bottom: var(--space-6);
	}
}

/* 7. Motion
   Only when the visitor allows it. With reduced motion everything is simply
   there: the keyhole fully drawn, the tick shown, no transitions, no lift.
   ========================================================================== */

@media (prefers-reduced-motion: no-preference) {
	/* The keyhole outline draws on once on load. pathLength="1" on the path makes
	   the whole outline one unit long, so no measuring is needed. */
	.contact__keyhole path {
		stroke-dasharray: 1;
		stroke-dashoffset: 1;
		animation: contact-draw 1.2s ease-out 0.15s forwards;
	}

	.field__input {
		transition:
			border-color 0.2s ease-out,
			box-shadow 0.2s ease-out;
	}

	/* Hover lifts the button 2px. Plain ease-out, no overshoot. */
	.contact-form__submit {
		transition:
			background-color 0.2s ease-out,
			transform 0.2s ease-out;
	}

	.contact-form__submit:hover {
		transform: translateY(-2px);
	}

	.contact-form.submitting .contact-form__submit:hover {
		transform: none;
	}

	.contact-form.submitting .contact-form__submit::after {
		animation: contact-spin 0.8s linear infinite;
	}

	/* Success: the ring draws, then the tick, then the text fades up.
	   Restarts whenever .is-sent is added, since the block goes from hidden to shown. */
	.is-sent .form-success__ring,
	.is-sent .form-success__tick {
		stroke-dasharray: 1;
		stroke-dashoffset: 1;
	}

	.is-sent .form-success__ring {
		animation: contact-draw 0.6s ease-out forwards;
	}

	.is-sent .form-success__tick {
		animation: contact-draw 0.35s ease-out 0.5s forwards;
	}

	.is-sent .form-success__title,
	.is-sent .form-success__text {
		opacity: 0;
		animation: contact-rise 0.5s ease-out 0.6s forwards;
	}
}

@keyframes contact-draw {
	to {
		stroke-dashoffset: 0;
	}
}

@keyframes contact-spin {
	to {
		transform: rotate(360deg);
	}
}

@keyframes contact-rise {
	from {
		opacity: 0;
		transform: translateY(0.5rem);
	}

	to {
		opacity: 1;
		transform: none;
	}
}
