/*
Theme Name: Cellar Door
Theme URI: https://gridwerkthemes.com/themes/cellar-door/
Author: Gridwerk Themes
Author URI: https://gridwerkthemes.com/
Description: A block theme for family estate wineries, with a wine shop for bottles and cases, the vineyard and cellar story, vintages and tastings.
Requires at least: 6.9
Tested up to: 7.1
Requires PHP: 7.4
Version: 1.0.1
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: cellar-door
Tags: full-site-editing, block-patterns, block-styles, style-variations, wide-blocks, editor-style, translation-ready, e-commerce
*/

/* 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;
}

/* 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;
}

/* 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. */
.cellar-door-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;
}

.cellar-door-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"] > .cellar-door-video-toggle__pause,
[aria-pressed="false"] > .cellar-door-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(.cellar-door-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.cellar-door-loader::before {
	content: "";
	position: static;
	min-width: 0;
	min-height: 0;
}

body:not(.editor-styles-wrapper) .cellar-door-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: cellar-door-loader-lift;
}

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

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

.wp-block-spacer.cellar-door-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: cellar-door-loader-spin;
}

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

.wp-block-spacer.cellar-door-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: cellar-door-loader-dots;
}

@keyframes cellar-door-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. */
.cellar-door-loader-bar {
	place-items: start stretch;
}

.wp-block-spacer.cellar-door-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: cellar-door-loader-bar;
}

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

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

@keyframes cellar-door-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) .cellar-door-loader {
		display: none;
	}
}

/* WooCommerce hard-codes its sale badge colors; the theme's style.css loads after it. */
.woocommerce span.onsale {
	background-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
}

/* Product facts (the product-specifications block) as facts on hairlines in the text color, not a boxed table. */
.wp-block-woocommerce-product-specifications :is(th, td) {
	padding-block: var(--wp--preset--spacing--20);
	padding-inline: 0 var(--wp--preset--spacing--30);
	border: 0;
	border-bottom: 1px solid color-mix(in srgb, currentcolor 25%, transparent);
	text-align: start;
	vertical-align: top;
}

.wp-block-woocommerce-product-specifications td p {
	margin: 0;
}

/* WooCommerce leaves the closed mini-cart drawer focusable while aria-hidden; take it out of the tab order. */
.wc-block-mini-cart__drawer[aria-hidden="true"] {
	visibility: hidden;
}

/* Prices line up in their columns. */
.wc-block-components-product-price,
.wp-block-woocommerce-product-price {
	font-variant-numeric: tabular-nums;
}

/* A variable product's choices (WooCommerce's variation chips) on the tokens: the chosen one in accent-1, the
   colour of the buy action. Set through WooCommerce's own variables, so the block's colour controls still apply. */
.wp-block-woocommerce-add-to-cart-with-options {
	--wc-product-filter-chips-selected-background: var(
		--wp--preset--color--accent-1
	);
	--wc-product-filter-chips-selected-border: var(
		--wp--preset--color--accent-1
	);
	--wc-product-filter-chips-selected-text: var(--wp--preset--color--base);
}

/* The price beside quantity and Add to cart (parts/*-product-add-to-cart-with-options.html): it follows the
   chosen variation, so it keeps one width and the buttons stay put. */
.add-to-cart-price {
	min-width: 6.5ch;
	margin: 0;
	text-align: end;
	font-size: var(--wp--preset--font-size--large);
}

/* WooCommerce gives a variation chip a 1px focus line in its own text colour, which vanishes on the chosen chip:
   every chip shows a 2px focus outline in the text colour, clear of the chip, on paper and on the accent alike. */
.wp-block-woocommerce-add-to-cart-with-options
	.wc-block-product-filter-chips__item:focus-visible {
	outline: 2px solid var(--wp--preset--color--contrast);
	outline-offset: 2px;
}

/* On a touch screen a variation chip is a full 44px target (WooCommerce draws it about 37px tall). */
@media (pointer: coarse) {
	.wp-block-woocommerce-add-to-cart-with-options
		.wc-block-product-filter-chips
		.wc-block-product-filter-chips__item {
		min-height: 44px;
	}
}

/* WooCommerce's quantity stepper drops the focus outline for a faint inset ring: the whole stepper shows the
   theme's focus outline while focus is inside it. */
.wc-block-components-quantity-selector:has(:focus-visible) {
	outline: 2px solid var(--wp--preset--color--accent-1);
	outline-offset: 2px;
}

/* WooCommerce's notices (added to the cart, a checkout error) on the theme's highlight surface in its text colour,
   not WooCommerce's mint, pink and grey; the round icon keeps the colour that says success, error or warning. Its
   links set their grey with !important, so only !important lets them follow the text. */
.wc-block-components-notice-banner,
.wc-block-components-notice-banner:is(
	.is-success,
	.is-error,
	.is-info,
	.is-warning
) {
	border-color: currentcolor;
	background-color: var(--wp--preset--color--accent-3);
	color: var(--wp--preset--color--contrast);
}

.wc-block-components-notice-banner
	> .wc-block-components-notice-banner__content
	.wc-forward {
	color: inherit !important;
	opacity: 1;
}

/* Cellar Door ---------------------------------------------------------------------------------------------- */

/* The browser's own surfaces in the list's inks. */
::selection {
	background: var(--wp--preset--color--accent-1);
	color: var(--wp--preset--color--base);
}

:root {
	accent-color: var(--wp--preset--color--accent-1);
}

/* Packs (bottle, case of 6, case of 12) are square, like everything on the list. */
.wp-block-woocommerce-add-to-cart-with-options
	.wc-block-product-filter-chips
	.wc-block-product-filter-chips__item {
	border-radius: 0;
	padding: 0.55em 0.9em;
	font-size: var(--wp--preset--font-size--small);
}

/* The List: the estate's numbered wine list (a Product Collection in the "Estate list" style). Each row: the
   number, the wine and its note, the price, then the packs and Add to basket. */
.is-style-estate-list .wc-block-product-template {
	counter-reset: wine;
	gap: 0;
	border-top: 2px solid currentcolor;
}

.is-style-estate-list .wc-block-product {
	counter-increment: wine;
	display: grid;
	grid-template-columns: 3.25rem minmax(14rem, 1fr) auto;
	grid-template-areas: "no wine buy";
	column-gap: var(--wp--preset--spacing--30);
	align-items: start;
	padding-block: var(--wp--preset--spacing--30);
	border-bottom: 1px solid color-mix(in srgb, currentcolor 22%, transparent);
}

.is-style-estate-list .wc-block-product::before {
	content: counter(wine);
	grid-area: no;
	line-height: 1.08; /* The headings' (theme.json), so the number sits level with the wine's name. */
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--large);
	font-variant-numeric: tabular-nums;
	color: var(--wp--preset--color--accent-1);
}

.is-style-estate-list .estate-row__wine {
	position: relative; /* The cellar stamp sits in its corner. */
	grid-area: wine;
}

.is-style-estate-list .estate-row__wine > * {
	margin-block: 0;
}

.is-style-estate-list .estate-row__wine .wp-block-post-title a {
	text-decoration: none;
}

.is-style-estate-list .estate-row__wine .wp-block-post-title a:hover {
	text-decoration: underline;
}

.is-style-estate-list .estate-row__wine .wp-block-post-excerpt {
	margin-top: 0.25rem;
	color: color-mix(in srgb, currentcolor 72%, transparent);
}

/* WooCommerce wraps the form in its notices container, so that wrapper takes the grid cell. */
.is-style-estate-list
	.wc-block-product
	> :has(> .wp-block-woocommerce-add-to-cart-with-options) {
	grid-area: buy;
	align-self: center;
	margin: 0;
}

.is-style-estate-list .wp-block-woocommerce-add-to-cart-with-options {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: end;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
}

.is-style-estate-list .wp-block-woocommerce-add-to-cart-with-options > *,
.is-style-estate-list
	.wp-block-woocommerce-add-to-cart-with-options-variation-selector-attribute
	> .wp-block-group {
	margin: 0;
}

/* On the list the pack buttons speak for themselves: their attribute name stays for screen readers only, and the
   stock line and variation description belong to the wine's own page. */
.is-style-estate-list
	.wp-block-woocommerce-add-to-cart-with-options-variation-selector-attribute-name {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.is-style-estate-list
	:is(
		.wp-block-woocommerce-product-stock-indicator,
		.wp-block-woocommerce-add-to-cart-with-options-variation-description
	) {
	display: none;
}

@media (max-width: 47.99rem) {
	.is-style-estate-list .wc-block-product {
		grid-template-columns: 2.25rem minmax(0, 1fr);
		grid-template-areas: "no wine" ". buy";
		row-gap: var(--wp--preset--spacing--20);
	}

	.is-style-estate-list .wp-block-woocommerce-add-to-cart-with-options {
		justify-content: start;
	}
}

/* The front page's header sits over the hero's photograph ("Over the hero" style on its group); never sticky. */
.wp-site-blocks > header:has(> .is-style-over-hero) {
	position: absolute;
	inset-inline: 0;
	z-index: 10;
}

/* Its own scrim in the ink colour, so the name and menu read over any sky. */
.is-style-over-hero {
	background-image: linear-gradient(
		color-mix(in srgb, var(--wp--preset--color--contrast) 70%, transparent),
		transparent
	);
}

.admin-bar .wp-site-blocks > header:has(> .is-style-over-hero) {
	top: var(--wp-admin--admin-bar--height, 0);
}

/* The regular header rules itself off from the page, as the list's head does. */
.wp-site-blocks > header > .wp-block-group:not(.is-style-over-hero) {
	border-bottom: 1px solid color-mix(in srgb, currentcolor 22%, transparent);
}

/* Hero over a photograph: the overlay is deepest on the side the words sit and lightens toward the photograph's
   own light, so the headline holds large-text contrast over a bright sky and the sunset still glows. */
.estate-hero .wp-block-cover__background {
	mask-image: linear-gradient(to right, #000 45%, rgb(0 0 0 / 0.45) 85%);
}

.estate-hero h1 {
	max-width: 14ch;
}

.estate-hero .wp-block-cover__inner-container p,
.wp-block-cover .wp-block-cover__inner-container p {
	max-width: 38rem;
}

/* The list's head: the season's heading and its note on one line, ruled off by the list's top rule. */
.estate-list__head {
	padding-bottom: var(--wp--preset--spacing--30);
}

.estate-list .estate-list__head p {
	max-width: 30rem;
	margin: 0;
}

/* The label card lifts off the paper. */
.estate-label img,
.wp-block-woocommerce-product-image-gallery img {
	box-shadow:
		0 1px 2px
			color-mix(
				in srgb,
				var(--wp--preset--color--contrast) 8%,
				transparent
			),
		0 18px 40px -18px
			color-mix(
				in srgb,
				var(--wp--preset--color--contrast) 35%,
				transparent
			);
}

/* The signature: the list row opens into the wine. A cross-document view transition between a page with the List
   and the wine's page; assets/js/list.js names the clicked row's title, the wine page names its own here. Browsers
   without it (Firefox) and reduced motion get an ordinary page load. */
@view-transition {
	navigation: auto;
}

/* The wine's own title only: a second element with the name (a related product's) would cancel the transition. */
.single-product h1.wp-block-post-title:not(.wc-block-product *) {
	view-transition-name: wine-name;
}

::view-transition-group(*) {
	animation-duration: 520ms;
	animation-timing-function: cubic-bezier(0.2, 0.75, 0, 1);
}

::view-transition-old(root),
::view-transition-new(root) {
	animation-duration: 260ms;
}

@media (prefers-reduced-motion: reduce) {
	@view-transition {
		navigation: none;
	}
}

/* Photo covers carry their words at the foot, where the overlay is deepest, across the wide column. */
.wp-block-cover.estate-foot {
	align-items: flex-end;
}

/* The cellar stamp on a wine that is in the basket (inc/woocommerce.php on every page load, assets/js/list.js the
   moment it goes in): the accent (rust in the default palette) on paper over the end of the wine's note, never its
   name. Only the List shows it. The press plays when it is added live; reduced motion shows it unpressed. */
.estate-stamp {
	display: none;
}

.is-style-estate-list .estate-stamp {
	position: absolute;
	inset-inline-end: 0;
	bottom: 0;
	display: block;
	padding: 0.3rem 0.7rem;
	border: 2px solid var(--wp--preset--color--accent-1);
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--accent-1);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	line-height: 1;
	opacity: 0.9;
	rotate: -4deg;
	pointer-events: none;
}

.is-style-estate-list .estate-stamp.is-pressed {
	animation: cellar-door-press 380ms cubic-bezier(0.2, 0.9, 0.1, 1);
}

@keyframes cellar-door-press {
	from {
		opacity: 0;
		scale: 1.6;
		rotate: -9deg;
	}
}

@media (prefers-reduced-motion: reduce) {
	.is-style-estate-list .estate-stamp.is-pressed {
		animation: none;
	}
}

/* Vintages read like the list: each year opens a ruled row. */
.estate-vintages > .wp-block-heading {
	margin-block-start: var(--wp--preset--spacing--40);
	padding-block-start: var(--wp--preset--spacing--30);
	border-top: 1px solid color-mix(in srgb, currentcolor 22%, transparent);
	font-variant-numeric: tabular-nums;
}

.estate-vintages > .wp-block-heading:first-child {
	margin-block-start: 0;
	border-top: 2px solid currentcolor;
}

/* The hero ends in vineyard hills instead of a straight cut: assets/images/hills.svg as a mask in the page's own
   colour, so the photograph runs into the next section in every palette. Decoration only, no motion. */
.estate-hero::after {
	content: "";
	position: absolute;
	inset: auto 0 -1px;
	z-index: 1;
	height: clamp(3rem, 9vw, 8.5rem);
	background-color: var(--wp--preset--color--base);
	mask: url(assets/images/hills.svg) bottom / 100% 100% no-repeat;
	pointer-events: none;
}

/* The words and buttons stay clear of the hills; the Cover's own padding stays the buyer's. */
.estate-hero .wp-block-cover__inner-container {
	margin-bottom: clamp(3rem, 9vw, 8.5rem);
}

/* Tastings and visits read like the list: one ruled row each, the price set off to the right. */
.estate-tastings {
	border-top: 2px solid currentcolor;
}

.estate-tasting {
	padding-block: var(--wp--preset--spacing--30);
	border-bottom: 1px solid color-mix(in srgb, currentcolor 22%, transparent);
}

.estate-tasting__what {
	flex: 1 1 24rem;
	max-width: 40rem;
}

.estate-tastings .estate-tasting .wp-block-heading,
.estate-tastings .estate-tasting p {
	margin-block: 0;
}

.estate-tastings .estate-tasting > p {
	font-variant-numeric: tabular-nums;
}

/* A wine's page: the tab already names the description, so its repeated heading goes; the text keeps a measure. */
.wp-block-woocommerce-product-details [role="tabpanel"] > h2:first-child {
	display: none;
}

.wp-block-woocommerce-product-details [role="tabpanel"] p {
	max-width: 65ch;
}

/* The list's Add to cart keeps its width when it turns into "1 in cart", so the row doesn't shift. */
.is-style-estate-list .wc-block-components-product-button__button {
	min-width: min(9rem, 100%);
	justify-content: center;
}

/* Checkout's order summary is square, like everything else on the list. */
.wp-block-woocommerce-checkout-order-summary-block,
.wc-block-components-sidebar-layout .wc-block-components-panel {
	border-radius: 0;
}

/* Photo covers keep a dark overlay with light words in every palette: a variation whose ink is light (Cellar) names
   its own through settings.custom.photo. A buyer's own overlay colour on a cover still wins (other classes). */
.wp-block-cover > .wp-block-cover__background.has-contrast-background-color {
	background-color: var(
		--wp--custom--photo--overlay,
		var(--wp--preset--color--contrast)
	);
}

.wp-block-cover.has-base-color {
	color: var(--wp--custom--photo--text, var(--wp--preset--color--base));
}
