/*
Theme Name: Turndown
Theme URI: 
Author: Gridwerk Themes
Author URI: https://gridwerkthemes.com/
Description: A quiet, assured block theme for owner-run boutique hotels: rooms with their facts, the practical details and one clear Book a stay button.
Requires at least: 6.9
Tested up to: 7.1
Requires PHP: 7.4
Version: 1.0.0
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: turndown
Tags: full-site-editing, block-patterns, block-styles, style-variations, wide-blocks, editor-style, translation-ready
*/

/* Base layer shared by every theme (from starter/). Theme-specific CSS goes below it. Rules on html, body and
   .wp-site-blocks sit in :where(), so a theme's own rule on the same element always wins and is no duplicate. */

/* Visible keyboard focus (WordPress.org requirement). */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 2px solid currentcolor;
	outline-offset: 2px;
}

/* Buttons draw the ring inside, in their text color: outside, it would sit on a section background of the
   same color as the button (a gilded button on a gilded band). */
.wp-element-button:focus-visible {
	outline-offset: -5px;
}

/* Form fields follow the palette, so a dark theme never shows white boxes. */
:where(
	input:not(
		[type="checkbox"],
		[type="radio"],
		[type="submit"],
		[type="button"]
	),
	textarea,
	select
) {
	border: 1px solid currentcolor;
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
}

/* Content made with core's default palette (another theme's posts, the test data) sets a background but no text
   colour, so it would inherit this theme's text colour. Each default background takes black or white, whichever
   contrasts more, and its headings and links follow. */
:is(
	.has-cyan-bluish-gray-background-color,
	.has-white-background-color,
	.has-pale-pink-background-color,
	.has-luminous-vivid-orange-background-color,
	.has-luminous-vivid-amber-background-color,
	.has-light-green-cyan-background-color,
	.has-vivid-green-cyan-background-color,
	.has-pale-cyan-blue-background-color,
	.has-vivid-cyan-blue-background-color,
	.has-vivid-purple-background-color
):not(.has-text-color) {
	color: var(--wp--preset--color--black);
}

:is(.has-black-background-color, .has-vivid-red-background-color):not(
	.has-text-color
) {
	color: var(--wp--preset--color--white);
}

:is(
		.has-black-background-color,
		.has-cyan-bluish-gray-background-color,
		.has-white-background-color,
		.has-pale-pink-background-color,
		.has-vivid-red-background-color,
		.has-luminous-vivid-orange-background-color,
		.has-luminous-vivid-amber-background-color,
		.has-light-green-cyan-background-color,
		.has-vivid-green-cyan-background-color,
		.has-pale-cyan-blue-background-color,
		.has-vivid-cyan-blue-background-color,
		.has-vivid-purple-background-color
	):not(.has-text-color)
	:is(h1, h2, h3, h4, h5, h6, a:not(.wp-element-button)) {
	color: inherit;
}

/* The byline reads "By Name" on one line, not as a tiny label above the name. */
.wp-block-post-author__content {
	display: flex;
	flex-wrap: wrap;
	gap: 0 0.3em;
	align-items: baseline;
}

.wp-block-post-author__byline {
	width: auto;
	font-size: inherit;
}

/* The comment beside its avatar may shrink below its longest word, so a long word wraps instead of widening the page. */
:where(.wp-block-comment-template li > .is-layout-flex) > .wp-block-group {
	flex: 1;
	min-width: 0;
}

/* The post author's own replies are marked, so readers can tell them from a guest's. */
:where(.wp-block-comment-template .bypostauthor) > .wp-block-group {
	border-inline-start: 2px solid var(--wp--preset--color--accent-1);
	padding-inline-start: var(--wp--preset--spacing--30);
}

/* One long word in a large heading (a name, a URL) wraps instead of widening the page. */
:where(h1, h2, h3, h4, h5, h6) {
	overflow-wrap: break-word;
}

/* Links inside running text stay recognizable without color. */
.wp-block-post-content
	:where(p, li:not(.wp-block-post))
	a:where(:not(.wp-element-button)) {
	text-decoration: underline;
}

/* Classic and comment content (captions, sized images, preformatted text) must not widen the page;
   :is() outranks the layout's content-size cap. */
:is(.wp-block-post-content, .wp-block-comment-content)
	:is(img, .wp-caption, embed, iframe, video) {
	max-width: 100%;
}

:where(.wp-block-post-content, .wp-block-comment-content) :where(img, video) {
	height: auto;
}

:where(.wp-block-post-content, .wp-block-comment-content) pre {
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}

/* Logo-only social icons take the text color, not each brand's; the block's icon color (inline) still wins. */
.wp-block-social-links.is-style-logos-only .wp-social-link {
	color: currentcolor;
}

/* The mobile menu's open and close buttons are touch targets, however short their label (WCAG 2.5.8). */
.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
	min-width: 2.75rem;
	min-height: 2.75rem;
	justify-content: center;
	align-items: center;
}

/* Core's Sticky position on a header Group sticks only inside the template part's <header>, which is just as tall,
   so the header scrolled away. The <header> sticks instead, below the admin bar the way core offsets sticky blocks
   (core sets the offset only on .is-position-sticky, and to 0 where the admin bar scrolls away on phones). */
.wp-site-blocks > .wp-block-template-part:has(> .is-position-sticky) {
	--wp-admin--admin-bar--position-offset: var(
		--wp-admin--admin-bar--height,
		0px
	);
	position: sticky;
	top: var(--wp-admin--admin-bar--position-offset);
	z-index: 10;
}

@media screen and (max-width: 600px) {
	.wp-site-blocks > .wp-block-template-part:has(> .is-position-sticky) {
		--wp-admin--admin-bar--position-offset: 0px;
	}
}

/* Keyboard focus and anchor links scroll to just below a sticky header, never under it (WCAG 2.4.11). All of it
   inside :where(), since :has() weighs as much as its argument and a theme's own scroll-padding-top must win. */
:where(
	html:has(.wp-site-blocks > .wp-block-template-part > .is-position-sticky)
) {
	scroll-padding-top: calc(var(--wp-admin--admin-bar--height, 0px) + 8rem);
}

/* On a very short screen (a phone held sideways) a sticky header would take most of it; it scrolls away there. */
@media (max-height: 30rem) {
	.wp-site-blocks > .wp-block-template-part:has(> .is-position-sticky) {
		position: static;
	}
}

/* A page built from full-width sections shows the template's title on the sections' wide edge, not on the text
   column centred above them (the page patterns' own title bands sit there too). */
.page:has(.wp-block-post-content > .alignfull:first-child)
	.wp-block-post-title {
	max-width: var(--wp--style--global--wide-size);
}

/* A page whose content opens with its own title band (a page pattern's full-width group with an h1) shows that
   title; the template's smaller one steps aside, so the page never says its name twice. */
.wp-site-blocks:has(.wp-block-post-content > .alignfull:first-child h1)
	.wp-block-post-title {
	display: none;
}

/* That title band starts right under the header, without a strip of page background above it (a photo page head
   runs up to the header). The template's padding on <main> is inline, so only !important outranks it. */
.wp-site-blocks
	> main:has(> .wp-block-post-content > .alignfull:first-child h1) {
	margin-block-start: 0;
	padding-top: 0 !important;
}

.wp-site-blocks
	> main
	> .wp-block-post-content:has(> .alignfull:first-child h1) {
	margin-block-start: 0;
}

/* Short pages end with the footer, not with a strip of page background below it. */
:where(.wp-site-blocks) {
	display: flex;
	flex-direction: column;
	min-height: calc(100svh - var(--wp-admin--admin-bar--height, 0px));
}

:where(.wp-site-blocks > main) {
	flex-grow: 1;
}

/* A page that ends in a full-width band (a call to action, a photo) runs it into the footer, without a strip of
   page background between them. The template's padding on <main> is inline, so only !important outranks it. */
:where(.wp-site-blocks) > footer {
	margin-block-start: 0;
}

.wp-site-blocks
	> main:is(
		:has(> .alignfull:last-child),
		:has(> .wp-block-post-content:last-child > .alignfull:last-child)
	) {
	padding-bottom: 0 !important;
}

/* Inside a page, full-width bands follow each other without the content's block gap between them, a strip of page
   background that shows wherever two band colours meet or a photo runs down to the next band. */
:where(.wp-block-post-content) > .alignfull + .alignfull {
	margin-block-start: 0;
}

/* The menu marks the page you are on; a theme restyles it to match its own hover. */
.wp-block-navigation .wp-block-navigation-item__content[aria-current="page"] {
	text-decoration-line: underline;
	text-decoration-thickness: max(1px, 0.08em);
	text-underline-offset: 0.3em;
}

/* Details (the FAQ component) open with a chevron drawn in the text colour instead of the browser's triangle.
   A block style of Details (a booking card, say) keeps its own summary. */
.wp-block-details:not([class*="is-style-"]) > summary {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 1em;
	cursor: pointer;
	list-style: none;
}

.wp-block-details:not([class*="is-style-"]) > summary::-webkit-details-marker {
	display: none;
}

.wp-block-details:not([class*="is-style-"]) > summary::after {
	flex: none;
	width: 0.5em;
	height: 0.5em;
	border-right: 1.5px solid currentcolor;
	border-bottom: 1.5px solid currentcolor;
	content: "";
	transform: translateY(-0.15em) rotate(45deg);
	transition: transform 0.2s ease-out;
}

.wp-block-details:not([class*="is-style-"])[open] > summary::after {
	transform: translateY(0.1em) rotate(-135deg);
}

/* A face without an italic stays upright rather than slanted by the browser; themes bundle the italics they use. */
:where(body) {
	font-synthesis-style: none;
}

/* A full-height Cover means the visible screen: on phones 100vh runs under the browser's toolbar. */
@supports (min-height: 100svh) {
	.wp-block-cover[style*="min-height:100vh"] {
		min-height: 100svh !important;
	}
}

/* Pause button on Cover background videos (inc/cover-video.php), above the overlay and the content. */
.turndown-video-toggle {
	position: absolute;
	z-index: 2;
	inset-inline-end: var(--wp--preset--spacing--40);
	bottom: var(--wp--preset--spacing--40);
	display: grid;
	place-items: center;
	width: 2.75rem;
	height: 2.75rem;
	padding: 0;
	border: 2px solid currentcolor;
	border-radius: 50%;
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--contrast);
	cursor: pointer;
}

.turndown-video-toggle svg {
	width: 1rem;
	height: 1rem;
	fill: currentcolor;
}

/* The slug once per selector, so a long slug still fits Prettier's line. */
[aria-pressed="true"] > .turndown-video-toggle__pause,
[aria-pressed="false"] > .turndown-video-toggle__play {
	display: none;
}

/* Complianz's cookie banner on the theme's tokens, so it follows the palette, the style variations and the type.
   Complianz sets these properties on :root; set on the banner itself, they win without !important. Deny looks
   exactly like Accept: rejecting must be as easy as accepting. A hairline frame keeps it apart from a page of
   the same colour. A theme's own section sets position and shape. */
.cmplz-cookiebanner {
	--cmplz_banner_background_color: var(--wp--preset--color--base);
	--cmplz_banner_border_color: var(--wp--preset--color--contrast);
	--cmplz_banner_border_width: 1px;
	--cmplz_banner_border_radius: 0;
	--cmplz_text_color: var(--wp--preset--color--contrast);
	--cmplz_hyperlink_color: var(--wp--preset--color--contrast);
	--cmplz_title_font_size: var(--wp--preset--font-size--medium);
	--cmplz_text_font_size: var(--wp--preset--font-size--small);
	--cmplz_link_font_size: var(--wp--preset--font-size--small);
	--cmplz_category_body_font_size: var(--wp--preset--font-size--small);
	--cmplz_category_header_title_font_size: var(
		--wp--preset--font-size--small
	);
	--cmplz_category_header_active_font_size: var(
		--wp--preset--font-size--small
	);
	--cmplz_category_header_always_active_color: var(
		--wp--preset--color--contrast
	);
	--cmplz_button_font_size: var(--wp--preset--font-size--small);
	--cmplz_button_border_radius: 0;
	--cmplz_button_accept_background_color: var(--wp--preset--color--accent-1);
	--cmplz_button_accept_border_color: var(--wp--preset--color--accent-1);
	--cmplz_button_accept_text_color: var(--wp--preset--color--base);
	--cmplz_button_deny_background_color: var(--wp--preset--color--accent-1);
	--cmplz_button_deny_border_color: var(--wp--preset--color--accent-1);
	--cmplz_button_deny_text_color: var(--wp--preset--color--base);
	--cmplz_button_settings_background_color: var(--wp--preset--color--base);
	--cmplz_button_settings_border_color: var(--wp--preset--color--contrast);
	--cmplz_button_settings_text_color: var(--wp--preset--color--contrast);
	--cmplz_slider_active_color: var(--wp--preset--color--accent-1);
	--cmplz_slider_inactive_color: var(--wp--preset--color--contrast);
	--cmplz_slider_bullet_color: var(--wp--preset--color--base);

	font-family: var(--wp--preset--font-family--body);
}

/* Complianz's stylesheet loads after this one, so these start from its container's id. The focus ring sits
   inside the buttons: outside, Accept's base-colored ring would vanish on the base-colored banner. */
#cmplz-cookiebanner-container .cmplz-cookiebanner .cmplz-btn:focus-visible {
	outline: 2px solid currentcolor;
	outline-offset: -5px;
}

#cmplz-cookiebanner-container .cmplz-cookiebanner .cmplz-category {
	background-color: var(--wp--preset--color--accent-2);
}

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		scroll-behavior: auto !important;
		transition-duration: 0.01ms !important;
	}
}

/* Opening hours (inc/hours.php): one ruled row per day, and today's row (assets/js/hours.js) set stronger. */
.wp-block-table.is-style-hours :is(th, td) {
	padding: 0.5em 0;
	border: 0;
	border-bottom: 1px solid color-mix(in srgb, currentcolor 25%, transparent);
}

.wp-block-table.is-style-hours td:last-child {
	text-align: end;
}

.wp-block-table.is-style-hours tr.is-today td {
	font-weight: 700;
}

/* Page loader (inc/loader.php): in the editor a box showing its spinner, so the buyer sees and can delete it;
   on the page a cover until assets/js/loader.js lifts it, or until the cap lifts it if the script never runs. */
:where(.turndown-loader) {
	display: grid;
	place-items: center;
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--accent-1);
}

/* The editor draws a spacer's ::before as an absolute box filling it (a selector of the same weight as these), so
   every loader rule on it names the spacer and sets its size outright. */
.wp-block-spacer.turndown-loader::before {
	content: "";
	position: static;
	min-width: 0;
	min-height: 0;
}

body:not(.editor-styles-wrapper) .turndown-loader {
	position: fixed;
	z-index: 100000;
	inset: 0;
	max-width: none;

	/* The spacer's inline height is only for the editor. */
	height: auto !important;
	margin: 0;

	/* The name on a line of its own, so a long slug never changes how Prettier wraps the rest. */
	animation: 0.3s 3s forwards;
	animation-name: turndown-loader-lift;
}

body:not(.editor-styles-wrapper) .turndown-loader.is-loaded {
	visibility: hidden;
	opacity: 0;
	transition:
		opacity 0.3s,
		visibility 0s 0.3s;
}

@keyframes turndown-loader-lift {
	to {
		visibility: hidden;
		opacity: 0;
	}
}

.wp-block-spacer.turndown-loader-ring::before {
	width: 2.5rem;
	height: 2.5rem;
	border: 3px solid color-mix(in srgb, currentcolor 20%, transparent);
	border-top-color: currentcolor;
	border-radius: 50%;
	animation: 0.8s linear infinite;
	animation-name: turndown-loader-spin;
}

@keyframes turndown-loader-spin {
	to {
		transform: rotate(1turn);
	}
}

.wp-block-spacer.turndown-loader-dots::before {
	width: 3.5rem;
	height: 0.875rem;
	background: radial-gradient(
			circle closest-side,
			currentcolor 90%,
			transparent
		)
		0 / calc(100% / 3) 100% space;
	clip-path: inset(0 100% 0 0);
	animation: 1s steps(4) infinite;
	animation-name: turndown-loader-dots;
}

@keyframes turndown-loader-dots {
	to {
		clip-path: inset(0 -34% 0 0);
	}
}

/* The bar runs along the top and covers nothing: the page shows beneath it as it loads. */
.turndown-loader-bar {
	place-items: start stretch;
}

.wp-block-spacer.turndown-loader-bar::before {
	width: 100%;
	height: 3px;
	background-color: currentcolor;
	transform-origin: left;
	animation: 3s cubic-bezier(0.1, 0.7, 0.3, 1) infinite;
	animation-name: turndown-loader-bar;
}

.rtl .wp-block-spacer.turndown-loader-bar::before {
	transform-origin: right;
}

body:not(.editor-styles-wrapper) .turndown-loader-bar {
	bottom: auto;
	background-color: transparent;
	pointer-events: none;
}

@keyframes turndown-loader-bar {
	from {
		transform: scaleX(0);
	}

	to {
		transform: scaleX(0.9);
	}
}

/* A spinner standing still reads as a frozen page, so reduced motion gets no loader. */
@media (prefers-reduced-motion: reduce) {
	body:not(.editor-styles-wrapper) .turndown-loader {
		display: none;
	}
}

/* Turndown: the hotel's limewashed wall. Theme-specific CSS from here on. */

/* The night palette (inc/turndown.php) is drawn from the active palette, so every variation and every colour a
   buyer picks turns down with it: the ink becomes the ground, the wall's colour becomes the type and the lamp. The
   swap sits on body, because :root already defines the presets these values read. */
:root {
	--turndown-night-base: var(--wp--preset--color--contrast);
	--turndown-night-contrast: color-mix(
		in oklab,
		var(--wp--preset--color--base) 80%,
		#fff
	);
	--turndown-night-accent-1: var(--wp--preset--color--base);
	--turndown-night-accent-2: color-mix(
		in oklab,
		var(--wp--preset--color--contrast) 88%,
		var(--wp--preset--color--base)
	);
	--turndown-night-accent-3: color-mix(
		in oklab,
		var(--wp--preset--color--contrast) 82%,
		var(--wp--preset--color--accent-3)
	);
}

/* At night the browser's own scrollbars and controls go dark with the page. */
html.is-turned-down {
	background-color: var(--turndown-night-base);
	color-scheme: dark;
}

html.is-turned-down body {
	--wp--preset--color--base: var(--turndown-night-base);
	--wp--preset--color--contrast: var(--turndown-night-contrast);
	--wp--preset--color--accent-1: var(--turndown-night-accent-1);
	--wp--preset--color--accent-2: var(--turndown-night-accent-2);
	--wp--preset--color--accent-3: var(--turndown-night-accent-3);
}

/* The first evening page dims once, slowly, like lamps being lowered: a view transition (inc/turndown.php)
   cross-fades the day page into the night one on the compositor, so the DOM holds its final colours at once. */
::view-transition-old(root),
::view-transition-new(root) {
	animation-duration: 2.4s;
	animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

/* Search is a utility, not a booking: Book stays the only filled button. */
.wp-block-search__button {
	border: 1px solid currentcolor;
	background-color: transparent;
	color: currentcolor;
}

::selection {
	background-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
}

:is(.wp-site-blocks, .editor-styles-wrapper) a {
	text-underline-offset: 0.28em;
	text-decoration-thickness: 1px;
}

/* Window in the wall: the photograph sits flat and crisp in the wall, cropped to its box; after turndown the
   hero's view dims. */
.wp-block-image.is-style-window {
	position: relative;
}

.wp-block-image.is-style-window img {
	display: block;
	width: 100%;
	object-fit: cover;
}

/* Full-height hero: copy beside a window that runs the hero's full height; the clock sits at the foot. A page
   head is the same wall and window on an inner page, shorter, so the page's own content starts in the first
   screen. */
.wp-block-columns.is-style-hero {
	min-height: min(calc(100svh - 7rem), 60rem);
}

.wp-block-columns.is-style-page-head {
	min-height: min(calc(78svh - 7rem), 38rem);
}

.wp-block-columns:is(.is-style-hero, .is-style-page-head) > .wp-block-column {
	display: flex;
	flex-direction: column;
}

.wp-block-columns:is(.is-style-hero, .is-style-page-head)
	> .wp-block-column
	> :first-child {
	margin-top: auto;
}

.wp-block-columns:is(.is-style-hero, .is-style-page-head)
	> .wp-block-column
	> .wp-block-template-part:last-child {
	margin-top: auto;
	padding-top: var(--wp--preset--spacing--60);
}

/* The window runs off the page's edge and down to the next band, so half the first screen is the house rather
   than a picture on the wall. The distance is the wide layout's gutter: root padding or the space beside the wide
   size, whichever is larger. */
.wp-block-columns:is(.is-style-hero, .is-style-page-head)
	.wp-block-image.is-style-window {
	flex: 1;
	min-height: 24rem;
	margin: 0
		calc(
			-1 *
				max(
					var(--wp--style--root--padding-right, 0px),
					(100vw - var(--wp--style--global--wide-size, 100vw)) / 2
				)
		)
		0 0;
}

.wp-block-columns:is(.is-style-hero, .is-style-page-head)
	.wp-block-image.is-style-window
	img {
	position: absolute;
	inset: 0;
	height: 100%;
}

/* The window and its light reach past the hero; clip them at the page wrapper (not on body, whose overflow
   passes to the viewport and still widens the page). */
.wp-site-blocks:has(.wp-block-columns:is(.is-style-hero, .is-style-page-head)) {
	overflow-x: clip;
}

/* A page head's light stays on its own band, even when the next section is the same wall without a background
   to cover it (the restaurant's menu). */
.wp-block-group:has(> .wp-block-columns.is-style-page-head) {
	overflow: clip;
}

@media (max-width: 781px) {
	.wp-block-columns:is(.is-style-hero, .is-style-page-head) {
		min-height: 0;
	}

	.wp-block-columns:is(.is-style-hero, .is-style-page-head)
		.wp-block-image.is-style-window {
		min-height: 0;
		margin-left: calc(-1 * var(--wp--style--root--padding-left, 0px));
		aspect-ratio: 4 / 4.4;
	}

	.wp-block-columns.is-style-page-head .wp-block-image.is-style-window {
		aspect-ratio: 4 / 3;
	}
}

/* Only the hero's view dims at night; the rooms keep their light, because evening is when people plan. */
html.is-turned-down .is-style-hero .wp-block-image.is-style-window img {
	filter: brightness(0.6) saturate(0.75);
}

/* The afternoon passes as the hero leaves: shutter light lies on the hero's wall, behind its words and window, and
   scrolls with the wall. It starts at the hotel's hour (--turndown-sun); as the hero scrolls away it lengthens,
   warms and fades. Its colour is the wall's own, lifted toward sunlight, so it follows every palette. */
html.has-shutter-light
	.wp-block-columns:is(.is-style-hero, .is-style-page-head) {
	position: relative;
	isolation: isolate;
}

html.has-shutter-light
	.wp-block-columns:is(.is-style-hero, .is-style-page-head)::before {
	position: absolute;
	z-index: -1;
	inset: -4rem -6vw 0;
	background-color: color-mix(
		in oklab,
		var(--wp--preset--color--base) 45%,
		#fff6dc
	);
	content: "";
	opacity: 0.55;
	pointer-events: none;
	transform: rotate(var(--turndown-sun, 0deg)) skewX(-18deg) scaleY(1.1);
	will-change: translate, opacity;
	transform-origin: 40% 20%;
	mask: url(assets/images/shutter-light.svg) no-repeat 30% 10% /
		min(95vw, 68rem) auto;
}

@supports (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) {
		html.has-shutter-light
			.wp-block-columns:is(.is-style-hero, .is-style-page-head)::before {
			animation: turndown-afternoon linear both;
			animation-timeline: view();
			animation-range: exit 0% exit 100%;
		}
	}
}

/* Only translate and opacity change, so the masked layer is composited, not repainted, on every frame. */
@keyframes turndown-afternoon {
	0% {
		opacity: 0.55;
		translate: 0 0;
	}

	100% {
		opacity: 0;
		translate: 10vw 14vh;
	}
}

/* After turndown a lamp inside the house throws a soft pool through the shutters: warm, out of focus, no stripes,
   at most 0.3 strong so night text keeps about 5:1. */
html.is-turned-down.has-shutter-light
	.wp-block-columns:is(.is-style-hero, .is-style-page-head)::before {
	background-color: color-mix(
		in oklab,
		var(--wp--preset--color--accent-1) 40%,
		#ff8a3d
	);
	opacity: 0.3;
	transform: rotate(var(--turndown-sun, 0deg)) skewX(10deg) scaleY(1.2);
	mask-image: url(assets/images/lamplight.svg);
}

@supports (animation-timeline: view()) {
	@media (prefers-reduced-motion: no-preference) {
		html.is-turned-down.has-shutter-light
			.wp-block-columns:is(.is-style-hero, .is-style-page-head)::before {
			animation-name: turndown-lamplight;
		}
	}
}

@keyframes turndown-lamplight {
	0% {
		opacity: 0.3;
		translate: 0 0;
	}

	100% {
		opacity: 0;
		translate: -8vw 10vh;
	}
}

/* A hover that never touches contrast: the label underlines, in any band and either palette. */
.wp-element-button:hover {
	text-decoration: underline;
	text-underline-offset: 0.25em;
}

/* Hotel clock: the hotel's time (assets/js/clock.js) and the line for this hour; the second line is the night's.
   The editor shows both, so the buyer can edit both. */
:is(.is-style-clock, .is-style-clock-turndown) {
	padding-top: var(--wp--preset--spacing--30);
	border-top: 1px solid color-mix(in oklab, currentcolor 35%, transparent);
	font-size: var(--wp--preset--font-size--small);
}

:is(.is-style-clock, .is-style-clock-turndown) > p {
	margin: 0;
}

html:not(.is-night)
	body:not(.editor-styles-wrapper)
	:is(.is-style-clock, .is-style-clock-turndown)
	> p:nth-of-type(2),
html.is-night
	body:not(.editor-styles-wrapper)
	:is(.is-style-clock, .is-style-clock-turndown)
	> p:first-of-type {
	display: none;
}

:is(.is-style-clock, .is-style-clock-turndown) time {
	margin-inline-end: 0.6em;
	font-weight: 500;
}

/* Room facts: the same ruled fields, in the same order, for every room. */
.wp-block-table.is-style-facts table {
	width: 100%;
	border-collapse: collapse;
}

.wp-block-table.is-style-facts thead {
	border: 0;
}

.wp-block-table.is-style-facts :is(th, td) {
	padding: 0.55em 1em 0.55em 0;
	border: 0;
	border-top: 1px solid color-mix(in oklab, currentcolor 35%, transparent);
	text-align: start;
	vertical-align: top;
}

.wp-block-table.is-style-facts th {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
}

/* Quantities are type: times, sizes and prices line up. */
:is(.wp-block-table, time) {
	font-variant-numeric: tabular-nums lining-nums;
}

/* Bands meet: the footer starts where the last band ends, with no strip of wall between them. */
.wp-site-blocks > footer {
	margin-block-start: 0;
}

/* Stacked on a phone, a window always comes before the words about it, whichever side it sat on. */
@media (max-width: 781px) {
	.wp-block-columns
		> .wp-block-column:has(> .wp-block-image.is-style-window) {
		order: -1;
	}
}

/* Motifs from the house, drawn as masks in the text colour, so they follow the block's colour and every palette:
   a run of shutter slats breaks a band in two, and a room's key tag hangs beside its number. */
.wp-block-separator.is-style-slats {
	width: 4.5rem;
	height: 1.5rem;
	margin-inline: 0 auto;
	border: 0;
	background-color: currentcolor;
	opacity: 1;
	mask: url(assets/images/slats.svg) no-repeat center / contain;
}

.wp-block-group.is-style-key-tag {
	gap: 0.6em;
	font-size: var(--wp--preset--font-size--small);
}

.wp-block-group.is-style-key-tag::before {
	flex: none;
	width: 1.1em;
	height: 2.2em;
	background-color: currentcolor;
	content: "";
	transform-origin: 50% 12%;
	mask: url(assets/images/key-tag.svg) no-repeat center / contain;
}

.wp-block-group.is-style-key-tag > * {
	margin: 0;
}

/* Motion that answers the visitor, never on its own: a room's key tag swings when its row is pointed at, a
   photo that is a link leans closer, a button gives under the press, and an answer unfolds. */
@media (prefers-reduced-motion: no-preference) {
	.wp-block-column:hover > .is-style-key-tag::before {
		animation: turndown-swing 0.9s cubic-bezier(0.22, 1, 0.36, 1);
	}

	.wp-block-image.is-style-window:has(> a) {
		overflow: hidden;
	}

	.wp-block-image.is-style-window > a img {
		transition: transform 0.4s cubic-bezier(0.22, 1, 0.36, 1);
	}

	.wp-block-image.is-style-window > a:is(:hover, :focus-visible) img {
		transform: scale(1.03);
	}

	.wp-element-button {
		transition: transform 0.15s ease-out;
	}

	.wp-element-button:active {
		transform: translateY(1px);
	}

	.wp-block-details > summary::after {
		transition: transform 0.25s ease-out;
	}

	.wp-block-details[open] > :not(summary) {
		animation: turndown-unfold 0.3s ease-out;
	}
}

@keyframes turndown-swing {
	0%,
	100% {
		rotate: 0deg;
	}

	30% {
		rotate: 9deg;
	}

	60% {
		rotate: -5deg;
	}

	85% {
		rotate: 2deg;
	}
}

@keyframes turndown-unfold {
	from {
		opacity: 0;
		translate: 0 -0.4em;
	}
}
