/*
 * Product detail styles — the single package page.
 *
 * Enqueued only on is_product() (see functions.php), with kyrex-storefront
 * (style.css) as a dependency for the token variables, @font-face rules, the
 * shared .kyrex-card border treatment, and the shared layout primitives
 * (.kyrex-container, .kyrex-section, .kyrex-eyebrow, .kyrex-heading) this
 * file builds on. Those primitives used to be duplicated here verbatim from
 * assets/homepage.css; they now live once in style.css (see its "Shared
 * layout primitives" section) since this file already depends on style.css
 * — not on homepage.css, which is enqueued only on is_front_page() and never
 * loads for a shopper on /product/.... This file keeps only the small,
 * page-specific .kyrex-heading margin override below.
 *
 * Same brand rules as catalogue.css: no border-radius, no drop shadows, no
 * gradients, no filled/rounded "pill" button anywhere on this page — the
 * add-to-cart control is a flat, square-cornered outline, same visual
 * language as the catalogue's Add to Cart control.
 */

/* ── Shared primitives now live in style.css (see header comment) ───────
   Only this page's tighter bottom margin before the Inclusions body copy
   stays local — it's a genuine per-page difference, not a redefinition. */

.kyrex-heading {
	margin-bottom: 1.5rem;
}

/* Notices are styled globally in style.css — see the note there about why
   `ul.woocommerce-message` never matched. Only the spacing that is specific
   to this template stays here. */

.kyrex-product .woocommerce-notices-wrapper:not(:empty) {
	margin-bottom: 2rem;
}

/* ── Layout — media + summary, single column under 900px ────────────── */

.kyrex-product__section {
	background-color: var(--kyrex-ivory);
}

.kyrex-product__layout {
	display: grid;
	grid-template-columns: 1fr;
	gap: 2.5rem;
}

@media (min-width: 900px) {
	.kyrex-product__layout {
		/*
		 * Two even columns.
		 *
		 * This was 26rem of gallery against whatever was left, which put a
		 * 416px photograph beside a 632px calendar — the photograph, the thing
		 * being sold, was the smaller half. Even columns give the product its
		 * weight back and the calendar still has room for seven day cells.
		 */
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 3rem;
		align-items: start;
	}

	/*
	 * The photograph stays put while the content scrolls past it.
	 *
	 * `align-items: start` above is what makes this possible — a stretched
	 * grid item is as tall as the row, and a sticky element can never move
	 * within its own box, so the whole thing would simply sit still and do
	 * nothing. `top` clears the sticky site header plus the occasion chips.
	 */
	.kyrex-product__media {
		position: sticky;
		top: 7.5rem;
	}
}

/*
 * Below 900px the columns stack and stickiness is switched off explicitly.
 * A sticky gallery on a phone pins the photograph over the content somebody
 * is trying to read, which is the opposite of the intent.
 */
@media (max-width: 899px) {
	.kyrex-product__media {
		position: static;
	}
}

/* ── Media — gallery when present, an intentional placeholder when not ── */

.kyrex-product__media {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
}

.kyrex-product__image-frame {
	display: block;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	border: 1px solid var(--kyrex-border);
}

.kyrex-product__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.kyrex-product__thumbnails {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: 0.75rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.kyrex-product__thumbnail {
	display: block;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	border: 1px solid var(--kyrex-border);
}

.kyrex-product__thumbnail img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/*
 * The no-image placeholder. Every demo package lacks a photo, so this is the
 * NORMAL state, not an error fallback — an ivory block with a centered gold
 * mark, the same device used on the catalogue cards, scaled up. No new
 * colors: ivory fill and gold mark are both existing tokens.
 */
.kyrex-product__placeholder {
	position: relative;
	display: block;
	aspect-ratio: 1 / 1;
	background-color: var(--kyrex-ivory);
	border: 1px solid var(--kyrex-border);
}

.kyrex-product__placeholder::before,
.kyrex-product__placeholder::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 50%;
	background-color: var(--kyrex-gold);
}

.kyrex-product__placeholder::before {
	width: 3rem;
	height: 1px;
	transform: translate(-50%, -50%);
}

.kyrex-product__placeholder::after {
	width: 1px;
	height: 3rem;
	transform: translate(-50%, -50%);
}

/* ── Summary — title, price, description, add-ons, add to cart ──────── */

.kyrex-product__title {
	margin-bottom: 1rem;
}

.kyrex-product__price {
	font-family: var(--kyrex-font-body);
	font-size: 1.375rem;
	font-weight: 600;
	color: var(--kyrex-charcoal);
	margin: 0 0 1.5rem;
}

.kyrex-product__price .woocommerce-Price-amount {
	color: inherit;
}

.kyrex-product__short-description {
	font-size: 0.9375rem;
	line-height: 1.6;
	color: var(--kyrex-charcoal-muted);
	margin-bottom: 2rem;
}

.kyrex-product__short-description p {
	margin: 0 0 1rem;
}

.kyrex-product__short-description p:last-child {
	margin-bottom: 0;
}

/* ── Slot picker — date & time selection ─────────────────────────────
   Rendered client-side by assets/slot-picker.js; the container ships empty
   in the HTML (see single-product.php's header comment for why). Chips use
   the same flat, square-cornered language as everything else on this page —
   the selected state is the only place the occasion accent (--kyrex-accent,
   set per-category on .kyrex-product__section) fills a background. ──────── */

.kyrex-slot-picker {
	margin: 0 0 2rem;
	padding-bottom: 1.75rem;
	border-bottom: 1px solid var(--kyrex-border);
}

.kyrex-slot-picker__legend {
	font-family: var(--kyrex-font-body);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal-muted);
	margin: 0 0 1rem;
}

.kyrex-slot-picker__status {
	font-size: 0.9375rem;
	color: var(--kyrex-charcoal-muted);
	margin: 0 0 1rem;
}

.kyrex-slot-picker__status[hidden] {
	display: none;
}

/* Block, not flex. These were a flex row when dates were chips; left as flex,
   the calendar's month header laid out BESIDE the grid instead of above it. */
.kyrex-slot-picker__dates,
.kyrex-slot-picker__times {
	display: block;
}

.kyrex-slot-picker__times:not(:empty) {
	margin-top: 1rem;
}

.kyrex-slot-picker__empty {
	font-size: 0.9375rem;
	color: var(--kyrex-charcoal-muted);
	margin: 0;
}

/* ── Add to cart — disabled state before a slot is chosen ────────────── */

.kyrex-product__submit[disabled] {
	cursor: not-allowed;
	opacity: 0.5;
}

.kyrex-product__submit[disabled]:hover {
	background-color: transparent;
	color: var(--kyrex-charcoal);
}

.kyrex-product__slot-hint {
	font-size: 0.8125rem;
	color: var(--kyrex-charcoal-muted);
	margin: 0.75rem 0 0;
}

.kyrex-product__slot-hint[hidden] {
	display: none;
}

/* ── Add-ons — checkbox rows, flat hairline dividers ─────────────────── */

.kyrex-product__addons {
	border: none;
	margin: 0 0 2rem;
	padding: 1.25rem 0 0.25rem;
	border-top: 1px solid var(--kyrex-border);
}

.kyrex-product__addons-legend {
	font-family: var(--kyrex-font-body);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal-muted);
	padding: 0;
	margin: 0 0 1rem;
}

.kyrex-product__addon {
	display: flex;
	align-items: baseline;
	gap: 0.75rem;
	padding: 0.75rem 0;
	border-bottom: 1px solid var(--kyrex-border);
	cursor: pointer;
}

.kyrex-product__addon:first-of-type {
	padding-top: 0;
}

.kyrex-product__addon-input {
	flex-shrink: 0;
	width: 1rem;
	height: 1rem;
	margin: 0.1875rem 0 0;
	accent-color: var(--kyrex-charcoal);
}

.kyrex-product__addon-label {
	flex: 1 1 auto;
	font-size: 0.9375rem;
	color: var(--kyrex-charcoal);
}

.kyrex-product__addon-price {
	flex-shrink: 0;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--kyrex-charcoal-muted);
}

/* ── Add to cart — flat, square-cornered; explicitly never a pill ───── */

/*
 * The quantity stepper and the button are one control group and have to read
 * as one. They did not: the stepper was 40px tall with an 8px radius and a
 * cream border, the button 49px tall, square, and outlined in charcoal. Two
 * unrelated controls that happened to sit next to each other.
 *
 * Both are now the same height and both square — square because the button is
 * deliberately never a pill, and a rounded stepper beside a square button is
 * the mismatch itself. The stepper keeps the lighter border: it is the
 * secondary control, and the eye should land on Add to Cart.
 */

.kyrex-product__actions {
	margin-top: 0.5rem;
	display: flex;
	flex-wrap: wrap;
	align-items: stretch;
	gap: 0.75rem;
}

.kyrex-product__actions .quantity,
.kyrex-product__actions .kyrex-qty {
	border-radius: 0;
	height: 3rem;
	flex: 0 0 auto;
	align-items: stretch;
}

.kyrex-product__actions .kyrex-qty__input,
.kyrex-product__actions .kyrex-qty__step {
	height: auto;
	align-self: stretch;
}

.kyrex-product__submit {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 3rem;
	flex: 1 1 auto;
	min-width: 11rem;
	max-width: 20rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.8125rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	text-align: center;
	color: var(--kyrex-charcoal);
	background-color: transparent;
	border: 1px solid var(--kyrex-charcoal);
	border-radius: 0;
	padding: 0 2rem;
	cursor: pointer;
	transition: background-color 150ms ease, color 150ms ease;
}

.kyrex-product__submit:hover,
.kyrex-product__submit:focus-visible {
	background-color: var(--kyrex-charcoal);
	color: var(--kyrex-ivory);
}

.kyrex-product__unavailable {
	font-size: 0.9375rem;
	color: var(--kyrex-charcoal-muted);
}

/* ── Inclusions — the long description, styled as a checklist section ── */

.kyrex-product__inclusions {
	background-color: var(--kyrex-surface);
	border-top: 1px solid var(--kyrex-border);
}

.kyrex-product__inclusions-body {
	font-size: 0.9375rem;
	line-height: 1.7;
	color: var(--kyrex-charcoal-muted);
	max-width: 42rem;
}

.kyrex-product__inclusions-body p {
	margin: 0 0 1rem;
}

.kyrex-product__inclusions-body ul,
.kyrex-product__inclusions-body ol {
	margin: 0 0 1rem;
	padding-left: 1.25rem;
}

.kyrex-product__inclusions-body li {
	margin-bottom: 0.5rem;
}

.kyrex-product__inclusions-body > :last-child {
	margin-bottom: 0;
}

/* ── Gallery ───────────────────────────────────────────────────────
   WooCommerce's gallery markup, styled to the brand. See
   woocommerce/single-product/product-image.php for why the structure is
   kept intact rather than hand-rolled. */

.kyrex-product__gallery {
	position: relative;
}

/*
 * WooCommerce normally ships this element with inline `opacity: 0` and fades
 * it in from its own script, which means a JS failure hides the product image
 * for good. The override drops the inline style, so the default here is
 * VISIBLE and the fade is added back only when script is available.
 */
html.js .kyrex-product__gallery {
	opacity: 0;
	transition: opacity 250ms ease-in-out;
}

html.js .kyrex-product__gallery.kyrex-gallery-ready,
html.js .kyrex-product__gallery.woocommerce-product-gallery--with-images.flexslider,
html.no-js .kyrex-product__gallery {
	opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
	html.js .kyrex-product__gallery {
		transition: none;
	}
}

.kyrex-product__gallery .woocommerce-product-gallery__wrapper {
	margin: 0;
	padding: 0;
	list-style: none;
}

.kyrex-product__gallery .woocommerce-product-gallery__image,
.kyrex-product__gallery .woocommerce-product-gallery__image--placeholder {
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
}

.kyrex-product__gallery .woocommerce-product-gallery__image a {
	display: block;
}

.kyrex-product__gallery img {
	display: block;
	width: 100%;
	height: auto;
}

/* Thumbnail strip. WooCommerce lays these out as floated columns; a grid is
   steadier and needs no clearfix. */
.kyrex-product__gallery .flex-control-thumbs {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 0.5rem;
	margin: 0.75rem 0 0;
	padding: 0;
	list-style: none;
	float: none;
}

.kyrex-product__gallery .flex-control-thumbs li {
	width: auto;
	float: none;
	margin: 0;
}

.kyrex-product__gallery .flex-control-thumbs img {
	border: 1px solid var(--kyrex-border);
	cursor: pointer;
	opacity: 0.65;
	transition: opacity 150ms ease, border-color 150ms ease;
}

.kyrex-product__gallery .flex-control-thumbs img.flex-active,
.kyrex-product__gallery .flex-control-thumbs img:hover {
	opacity: 1;
	border-color: var(--kyrex-accent);
}

/* ── The zoom / lightbox trigger ───────────────────────────────────
 *
 * WooCommerce injects this button from JavaScript as
 * `<a …><span aria-hidden="true">🔍</span></a>` — a colour-emoji glyph. It
 * renders differently on every platform, sits off-centre in its own em box,
 * and cannot take the brand colour, which is exactly why it looked wrong.
 *
 * The emoji is decorative (the accessible name lives on the anchor's
 * aria-label, which WooCommerce sets), so hiding it costs nothing and the
 * button is still announced as "View full-screen image gallery". The lens is
 * drawn instead from two pseudo-elements: a ringed circle and a handle. Drawn
 * rather than an SVG data-URI so it inherits `currentColor` and stays crisp at
 * any zoom, with no encoding to get wrong.
 *
 * Sized 2.75rem — 44px, the minimum touch target — where it was 36px before.
 */
.kyrex-product__gallery .woocommerce-product-gallery__trigger {
	position: absolute;
	top: 0.75rem;
	right: 0.75rem;
	z-index: 2;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	background-color: rgb(255 255 255 / 92%);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-pill);
	color: var(--kyrex-charcoal);
	text-decoration: none;
	line-height: 1;
	/* The gallery photograph behind it can be any colour, so the button needs
	   to lift off it rather than rely on the border alone. */
	box-shadow: 0 2px 8px rgb(0 0 0 / 12%);
	transition: background-color 150ms ease, box-shadow 150ms ease, transform 150ms ease;
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
}

/* The emoji itself. WooCommerce wraps it in a span; older versions put it
   straight in the anchor, so the font-size rule covers both. */
.kyrex-product__gallery .woocommerce-product-gallery__trigger {
	font-size: 0;
}

.kyrex-product__gallery .woocommerce-product-gallery__trigger > * {
	display: none;
}

/*
 * The magnifier, as one masked shape rather than two positioned pieces.
 *
 * It was a circle from ::before and a rotated bar from ::after, each placed
 * with absolute pixel offsets. Getting the ink optically centred that way
 * means hand-balancing the lens against a handle that sticks out diagonally,
 * and it was measurably off — ink centred at (23.2, 22.7) in a button whose
 * centre is (22, 22), which reads as the glyph sitting high and left of the
 * pill that contains it.
 *
 * Drawn in a 24x24 viewBox that is centred by construction and applied as a
 * mask, so the browser's own flex centring places it — no magic numbers to
 * drift. `background-color: currentColor` through the mask keeps it taking
 * the button's colour, which is why this is a mask rather than a background
 * image of a coloured SVG.
 */
.kyrex-product__gallery .woocommerce-product-gallery__trigger::before {
	content: '';
	width: 1.25rem;
	height: 1.25rem;
	background-color: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='6.5'/%3E%3Cline%20x1='15.8'%20y1='15.8'%20x2='19.5'%20y2='19.5'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='black'%20stroke-width='2'%20stroke-linecap='round'%3E%3Ccircle%20cx='11'%20cy='11'%20r='6.5'/%3E%3Cline%20x1='15.8'%20y1='15.8'%20x2='19.5'%20y2='19.5'/%3E%3C/svg%3E") center / contain no-repeat;
}

.kyrex-product__gallery .woocommerce-product-gallery__trigger:hover {
	background-color: var(--kyrex-ivory);
	color: var(--kyrex-gold-deep);
	box-shadow: 0 4px 14px rgb(0 0 0 / 18%);
	transform: translateY(-1px);
}

.kyrex-product__gallery .woocommerce-product-gallery__trigger:active {
	transform: translateY(0);
}

.kyrex-product__gallery .woocommerce-product-gallery__trigger:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.kyrex-product__gallery .woocommerce-product-gallery__trigger {
		transition: none;
	}

	.kyrex-product__gallery .woocommerce-product-gallery__trigger:hover {
		transform: none;
	}
}

/* ── Rating, SKU, availability ─────────────────────────────────────
   Directly under the title and above the fold — audit baseline 12.10. */

.kyrex-product__summary .woocommerce-product-rating {
	display: flex;
	align-items: center;
	gap: 0.625rem;
	margin: 0 0 0.75rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.8125rem;
}

.kyrex-product__summary .star-rating {
	color: var(--kyrex-gold-deep);
}

.kyrex-product__summary .woocommerce-review-link {
	color: var(--kyrex-charcoal-muted);
	text-decoration: none;
	border-bottom: 1px solid var(--kyrex-border);
}

.kyrex-product__summary .woocommerce-review-link:hover {
	color: var(--kyrex-charcoal);
	border-bottom-color: var(--kyrex-gold);
}

.kyrex-product__meta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem 1rem;
	margin: 0 0 1.25rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.75rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal-muted);
}

.kyrex-product__meta-label {
	font-weight: 600;
	margin-right: 0.25rem;
}

/* Availability is stated in words, not only by colour. */
.kyrex-product__stock--instock {
	color: var(--kyrex-emerald);
	font-weight: 600;
}

.kyrex-product__stock--outofstock {
	color: var(--kyrex-wine);
	font-weight: 600;
}

/* ── Tabs ──────────────────────────────────────────────────────────*/

.kyrex-product__tabs-section {
	background-color: var(--kyrex-surface);
	border-top: 1px solid var(--kyrex-border);
}

.woocommerce-tabs .wc-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 0.25rem;
	list-style: none;
	margin: 0 0 1.5rem;
	padding: 0;
	border-bottom: 1px solid var(--kyrex-border);
}

.woocommerce-tabs .wc-tabs li {
	margin: 0;
}

.woocommerce-tabs .wc-tabs li a {
	display: block;
	padding: 0.75rem 1.125rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal-muted);
	text-decoration: none;
	border-bottom: 2px solid transparent;
}

.woocommerce-tabs .wc-tabs li.active a {
	color: var(--kyrex-charcoal);
	border-bottom-color: var(--kyrex-accent);
}

.woocommerce-tabs .wc-tabs li a:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: -2px;
}

.woocommerce-tabs .woocommerce-Tabs-panel {
	font-family: var(--kyrex-font-body);
	color: var(--kyrex-charcoal);
}

.woocommerce-tabs .woocommerce-Tabs-panel h2 {
	font-family: var(--kyrex-font-display);
	font-size: 1.25rem;
	margin: 0 0 1rem;
}

/* ── Reviews ───────────────────────────────────────────────────────*/

.woocommerce-tabs .commentlist {
	list-style: none;
	margin: 0 0 2rem;
	padding: 0;
	display: grid;
	gap: 1.25rem;
}

.woocommerce-tabs .commentlist .review {
	background-color: var(--kyrex-ivory);
	border: 1px solid var(--kyrex-border);
	padding: 1.25rem;
}

.woocommerce-tabs .comment-text .star-rating {
	color: var(--kyrex-gold-deep);
	margin-bottom: 0.5rem;
}

.woocommerce-tabs .woocommerce-review__author {
	font-weight: 600;
}

.woocommerce-tabs .woocommerce-review__published-date {
	color: var(--kyrex-charcoal-muted);
	font-size: 0.8125rem;
}

.woocommerce-tabs #review_form_wrapper {
	background-color: var(--kyrex-ivory);
	border: 1px solid var(--kyrex-border);
	border-top: 3px solid var(--kyrex-accent);
	padding: 1.5rem;
}

.woocommerce-tabs .comment-form label {
	display: block;
	font-size: 0.8125rem;
	font-weight: 500;
	margin-bottom: 0.375rem;
}

.woocommerce-tabs .comment-form input[type="text"],
.woocommerce-tabs .comment-form input[type="email"],
.woocommerce-tabs .comment-form textarea {
	width: 100%;
	box-sizing: border-box;
	padding: 0.75rem 0.875rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.9375rem;
	color: var(--kyrex-charcoal);
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-sm);
}

.woocommerce-tabs .comment-form input:focus-visible,
.woocommerce-tabs .comment-form textarea:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 1px;
}

.woocommerce-tabs .comment-form-rating .stars a {
	color: var(--kyrex-gold-deep);
}

.woocommerce-tabs .comment-form p {
	margin: 0 0 1rem;
}

/* ── Related packages ──────────────────────────────────────────────*/

.kyrex-product__related-section .related > h2 {
	font-family: var(--kyrex-font-display);
	font-size: 1.5rem;
	margin: 0 0 1.5rem;
}

.kyrex-product__related-section ul.products {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 1.5rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

/*
 * Kill WooCommerce's clearfix pseudo-elements.
 *
 * WooCommerce sets `content: " "; display: table` on ul.products::before and
 * ::after to clear its floated layout. On a GRID container those are not
 * clearfixes — they are grid items. ::before took the first cell, every
 * package shifted one column right, and the last one wrapped onto a row of
 * its own. The row-one-is-empty, last-card-alone layout was entirely this.
 *
 * `content: none` removes the box altogether; `display: none` alone would
 * not, because a grid container blockifies its children regardless.
 */
.kyrex-product__related-section ul.products::before,
.kyrex-product__related-section ul.products::after {
	content: none;
}

@media (min-width: 768px) {
	.kyrex-product__related-section ul.products {
		grid-template-columns: repeat(4, minmax(0, 1fr));
	}
}

/*
 * Let the grid size the cards.
 *
 * WooCommerce ships `li.product { width: 48% }` inside its own mobile media
 * query, aimed at its float layout. Against a grid it does nothing useful and
 * a great deal of harm: each card shrank to 48% of its column — 76px inside a
 * 159px cell on a phone — leaving a narrow strip of card with the title
 * wrapping a word per line.
 *
 * The `[class*="columns-"]` attribute selector is deliberate: it is the shape
 * WooCommerce's own rule uses, and matching it raises specificity above theirs
 * without reaching for !important.
 */
.kyrex-product__related-section ul.products[class*="columns-"] li.product,
.kyrex-product__related-section ul.products li.product {
	width: auto;
	max-width: none;
	margin: 0;
	float: none;
	clear: none;
}

.kyrex-product__related-section ul.products li.product {
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-top: 3px solid var(--kyrex-accent);
	padding: 1rem;
	width: auto;
	float: none;
	margin: 0;
	text-align: left;
}

.kyrex-product__related-section ul.products li.product .woocommerce-loop-product__title {
	font-family: var(--kyrex-font-display);
	font-size: 1rem;
	font-weight: 600;
	color: var(--kyrex-charcoal);
	margin: 0.75rem 0 0.375rem;
	padding: 0;
}

.kyrex-product__related-section ul.products li.product a {
	text-decoration: none;
	color: var(--kyrex-charcoal);
}

.kyrex-product__related-section ul.products li.product .price {
	color: var(--kyrex-charcoal);
	font-weight: 600;
	font-size: 0.9375rem;
}

/* The loop add-to-cart button cannot work for a slot-bearing package — same
   reason the catalogue cards link through instead. Hidden so no dead control
   ships here either. */
.kyrex-product__related-section ul.products li.product .add_to_cart_button {
	display: none;
}

/* ── Sticky buy bar (mobile) ───────────────────────────────────────
   Appears once the real buy box scrolls away. Desktop never shows it —
   the buy box is beside the gallery there and rarely leaves the viewport. */

.kyrex-buybar {
	display: none;
}

@media (max-width: 899px) {
	.kyrex-buybar:not([hidden]) {
		display: flex;
		align-items: center;
		justify-content: space-between;
		gap: 1rem;
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 350;
		padding: 0.75rem 1rem;
		/* Clear of the iOS home indicator and Android gesture bar. */
		padding-bottom: calc(0.75rem + env(safe-area-inset-bottom, 0px));
		background-color: var(--kyrex-surface);
		border-top: 1px solid var(--kyrex-border);
		box-shadow: 0 -2px 12px rgb(42 38 34 / 8%);
		animation: kyrex-buybar-in 200ms ease-out;
	}

	/*
	 * The footer must stay reachable. A fixed bar overlays the end of the
	 * document, so the last screen needs padding equal to the bar's height
	 * or the footer links sit permanently underneath it.
	 */
	body.single-product .kyrex-footer {
		padding-bottom: calc(4.5rem + env(safe-area-inset-bottom, 0px));
	}
}

@keyframes kyrex-buybar-in {
	from { transform: translateY(100%); }
	to   { transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
	.kyrex-buybar:not([hidden]) {
		animation: none;
	}
}

.kyrex-buybar__info {
	display: flex;
	flex-direction: column;
	gap: 0.125rem;
	min-width: 0;
}

.kyrex-buybar__price {
	font-family: var(--kyrex-font-body);
	font-size: 1rem;
	font-weight: 600;
	color: var(--kyrex-charcoal);
	line-height: 1.2;
}

.kyrex-buybar__price .amount {
	font-weight: 600;
}

.kyrex-buybar__slot {
	font-family: var(--kyrex-font-body);
	font-size: 0.75rem;
	color: var(--kyrex-charcoal-muted);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* Says why the button cannot be pressed, rather than leaving it inert. */
.kyrex-buybar__slot--empty {
	color: var(--kyrex-wine);
}

.kyrex-buybar__submit {
	flex: none;
	padding: 0.875rem 1.5rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal);
	background-color: var(--kyrex-gold);
	border: 1px solid var(--kyrex-gold);
	border-radius: var(--kyrex-radius-sm);
	cursor: pointer;
}

.kyrex-buybar__submit:disabled {
	opacity: 0.5;
	cursor: not-allowed;
}

.kyrex-buybar__submit:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
}


/* ── Slot picker: month calendar ───────────────────────────────────
   Replaces the date chip row. A chip row could not distinguish "closed"
   from "too soon"; a grid shows every day and marks each one. */

.kyrex-cal__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
	margin-bottom: 0.75rem;
}

.kyrex-cal__title {
	font-family: var(--kyrex-font-body);
	font-size: 0.875rem;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal);
	margin: 0;
}

.kyrex-cal__nav {
	width: 2rem;
	height: 2rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-size: 1.125rem;
	line-height: 1;
	color: var(--kyrex-charcoal);
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-sm);
	cursor: pointer;
}

.kyrex-cal__nav:disabled {
	opacity: 0.35;
	cursor: not-allowed;
}

.kyrex-cal__nav:focus-visible,
.kyrex-cal__day:focus-visible,
.kyrex-slot-picker__retry:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
}

.kyrex-cal__grid {
	display: grid;
	gap: 0.25rem;
}

.kyrex-cal__row {
	display: grid;
	grid-template-columns: repeat(7, 1fr);
	gap: 0.25rem;
}

.kyrex-cal__dow {
	text-align: center;
	font-family: var(--kyrex-font-body);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	color: var(--kyrex-charcoal-muted);
	padding-bottom: 0.25rem;
}

.kyrex-cal__day {
	aspect-ratio: 1;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	font-family: var(--kyrex-font-body);
	font-size: 0.875rem;
	color: var(--kyrex-charcoal);
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-sm);
	cursor: pointer;
	transition: background-color 120ms ease, border-color 120ms ease;
}

.kyrex-cal__day--available:hover {
	border-color: var(--kyrex-accent);
}

.kyrex-cal__day.is-selected {
	background-color: var(--kyrex-emerald);
	border-color: var(--kyrex-emerald);
	color: var(--kyrex-ivory);
	font-weight: 600;
}

/*
 * Unavailable days. Each state is visually distinct AND carries its reason in
 * the accessible name, so the distinction never depends on colour alone:
 *
 *   closed / past — faded, plain
 *   lead_time     — faded with a dashed edge, "too soon to book"
 *   blackout      — struck through, "we are not taking bookings that day"
 */
.kyrex-cal__day--closed,
.kyrex-cal__day--past,
.kyrex-cal__day--lead_time,
.kyrex-cal__day--blackout {
	color: var(--kyrex-charcoal-muted);
	background-color: transparent;
	cursor: not-allowed;
}

.kyrex-cal__day--past,
.kyrex-cal__day--closed {
	opacity: 0.45;
	border-color: transparent;
}

.kyrex-cal__day--lead_time {
	opacity: 0.7;
	border-style: dashed;
	border-color: var(--kyrex-border);
}

.kyrex-cal__day--blackout {
	opacity: 0.8;
	border-color: var(--kyrex-border);
	text-decoration: line-through;
	text-decoration-color: var(--kyrex-wine);
	text-decoration-thickness: 2px;
}

.kyrex-cal__day--outside {
	visibility: hidden;
}

.kyrex-cal__none {
	margin: 0.75rem 0 0;
	font-family: var(--kyrex-font-body);
	font-size: 0.8125rem;
	color: var(--kyrex-charcoal-muted);
}

@media (prefers-reduced-motion: reduce) {
	.kyrex-cal__day {
		transition: none;
	}
}

/* ── Times for the chosen day ──────────────────────────────────────*/

.kyrex-slot-picker__times-title {
	font-family: var(--kyrex-font-body);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal-muted);
	margin: 1.25rem 0 0.625rem;
}

.kyrex-slot-picker__time-list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(6rem, 1fr));
	gap: 0.5rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.kyrex-slot-picker__time {
	width: 100%;
	padding: 0.625rem 0.5rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.8125rem;
	color: var(--kyrex-charcoal);
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-sm);
	cursor: pointer;
}

.kyrex-slot-picker__time:hover {
	border-color: var(--kyrex-accent);
}

.kyrex-slot-picker__time.is-selected,
.kyrex-slot-picker__time[aria-pressed="true"] {
	background-color: var(--kyrex-emerald);
	border-color: var(--kyrex-emerald);
	color: var(--kyrex-ivory);
	font-weight: 600;
}

.kyrex-slot-picker__time:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
}

/* ── Failure state ─────────────────────────────────────────────────
   A failed request must never look like "fully booked". */

.kyrex-slot-picker__error {
	padding: 1rem;
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-left: 3px solid var(--kyrex-wine);
	border-radius: var(--kyrex-radius-sm);
}

.kyrex-slot-picker__error-text {
	margin: 0 0 0.75rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.875rem;
	color: var(--kyrex-charcoal);
}

.kyrex-slot-picker__retry {
	padding: 0.5rem 1rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--kyrex-charcoal);
	background-color: transparent;
	border: 1px solid var(--kyrex-charcoal);
	border-radius: var(--kyrex-radius-sm);
	cursor: pointer;
}

/* Structured inclusions.
   Ticks rather than bullets: this is a list of things the customer gets,
   and the mark should read as confirmation. Drawn with a pseudo-element
   so the list stays a plain <ul> for a screen reader, which announces the
   item count — the thing a shopper actually wants to know. */

.kyrex-product__inclusions-list {
	list-style: none;
	margin: 1.25rem 0 0;
	padding: 0;
	display: grid;
	gap: 0.625rem;
}

@media (min-width: 48rem) {
	.kyrex-product__inclusions-list {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 0.625rem 2rem;
	}
}

.kyrex-product__inclusions-list li {
	position: relative;
	padding-left: 1.75rem;
	font-family: var(--kyrex-font-body);
	line-height: 1.55;
	color: var(--kyrex-charcoal);
}

.kyrex-product__inclusions-list li::before {
	content: '';
	position: absolute;
	left: 0.25rem;
	top: 0.45em;
	width: 0.5rem;
	height: 0.28rem;
	border-left: 1.5px solid var(--kyrex-gold-deep);
	border-bottom: 1.5px solid var(--kyrex-gold-deep);
	transform: rotate(-45deg);
}


/* ── Content cards ─────────────────────────────────────────────────
   Inclusions, the description, and the blocks from Package Content, down
   the right of the package page. Cards rather than plain sections: each
   one answers a different question, and a hairline card makes that
   separation without the heavy borders the reference design uses. */

.kyrex-pcard {
	background-color: var(--kyrex-surface);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-lg);
	padding: 1.5rem;
	margin-top: 1.5rem;
}

.kyrex-pcard__title {
	font-family: var(--kyrex-font-display);
	font-size: 1.25rem;
	font-weight: 600;
	color: var(--kyrex-charcoal);
	margin: 0 0 1rem;
	padding-bottom: 0.75rem;
	border-bottom: 1px solid var(--kyrex-border);
}

.kyrex-pcard__text,
.kyrex-pcard__prose {
	font-family: var(--kyrex-font-body);
	font-size: 0.9375rem;
	line-height: 1.65;
	color: var(--kyrex-charcoal);
	margin: 0;
}

.kyrex-pcard__prose p {
	margin: 0 0 0.875rem;
}

.kyrex-pcard__prose p:last-child {
	margin-bottom: 0;
}

/* ── Tick list ─────────────────────────────────────────────────────
   A drawn tick rather than a character, so it inherits the brand colour
   and never falls back to an emoji font. The list stays a plain <ul> so a
   screen reader still announces how many items are in it — which is the
   thing a shopper most wants to know. */

.kyrex-pcard__ticks {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.75rem;
}

.kyrex-pcard__ticks li {
	position: relative;
	padding-left: 1.75rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.9375rem;
	line-height: 1.5;
}

.kyrex-pcard__ticks li::before {
	content: '';
	position: absolute;
	left: 0.25rem;
	top: 0.4em;
	width: 0.5rem;
	height: 0.28rem;
	border-left: 1.5px solid var(--kyrex-emerald);
	border-bottom: 1.5px solid var(--kyrex-emerald);
	transform: rotate(-45deg);
}

/* ── Plain lists (need to know, cancellation) ──────────────────────*/

.kyrex-pcard__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.625rem;
}

.kyrex-pcard__list li {
	position: relative;
	padding-left: 1.25rem;
	font-family: var(--kyrex-font-body);
	font-size: 0.9375rem;
	line-height: 1.55;
}

.kyrex-pcard__list li::before {
	content: '';
	position: absolute;
	left: 0.25rem;
	top: 0.6em;
	width: 0.3125rem;
	height: 0.3125rem;
	border-radius: 50%;
	background-color: var(--kyrex-gold);
}

/* Need-to-know carries practical warnings, so it gets the accent rather
   than the decorative gold — these are the lines somebody regrets not
   reading. */
.kyrex-pcard__list--need_to_know li::before {
	background-color: var(--kyrex-accent, var(--kyrex-gold));
}

/* ── Reason pairs (why book with us) ───────────────────────────────*/

.kyrex-pcard__pairs {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 0.875rem;
}

.kyrex-pcard__pairs li {
	font-family: var(--kyrex-font-body);
	font-size: 0.9375rem;
	line-height: 1.55;
}

.kyrex-pcard__pairs strong {
	display: block;
	color: var(--kyrex-charcoal);
}

.kyrex-pcard__pairs span {
	color: var(--kyrex-charcoal-muted);
}

/* ── Read more ─────────────────────────────────────────────────────
   The prose is clamped, not truncated: the full text is in the DOM once,
   so a screen reader and a search engine both get all of it. The button
   is `hidden` in the markup and revealed by product.js only when the text
   actually overflows — offering "Read more" on three lines that are
   already fully visible is worse than not offering it. */

.kyrex-pcard__prose[data-kyrex-clamp] {
	display: -webkit-box;
	-webkit-line-clamp: 5;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

.kyrex-pcard__prose[data-kyrex-clamp].is-expanded {
	display: block;
	-webkit-line-clamp: none;
	overflow: visible;
}

/* No script, no clamp. Nothing is ever hidden behind a file that failed
   to load. */
html.no-js .kyrex-pcard__prose[data-kyrex-clamp] {
	display: block;
	overflow: visible;
}

html.no-js .kyrex-pcard__more {
	display: none;
}

.kyrex-pcard__more {
	margin-top: 0.875rem;
	padding: 0;
	background: none;
	border: 0;
	font-family: var(--kyrex-font-body);
	font-size: 0.875rem;
	font-weight: 600;
	color: var(--kyrex-gold-deep);
	cursor: pointer;
	text-decoration: underline;
	text-underline-offset: 0.15em;
}

.kyrex-pcard__more:hover {
	color: var(--kyrex-charcoal);
}

.kyrex-pcard__more:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
	border-radius: var(--kyrex-radius-sm);
}

.kyrex-pcard__more .kyrex-pcard__more-close,
.kyrex-pcard__more[aria-expanded="true"] .kyrex-pcard__more-open {
	display: none;
}

.kyrex-pcard__more[aria-expanded="true"] .kyrex-pcard__more-close {
	display: inline;
}

/* ── The slot confirmation chip ────────────────────────────────────
 *
 * Floats near the bottom of the viewport when a date and time are chosen.
 *
 * Shown and hidden with opacity and transform ONLY. `display: none`,
 * `visibility: hidden` and the `hidden` attribute all remove an element from
 * the accessibility tree, which would stop this live region announcing the
 * very thing it exists to announce. Opacity leaves it in the tree.
 *
 * `pointer-events: none` throughout, so an invisible chip can never swallow a
 * tap meant for the add-to-cart bar underneath it — and neither can a visible
 * one, since there is nothing here to press.
 */

.kyrex-slot-chip {
	position: fixed;
	left: 50%;
	/* Cleared by the sticky mobile buybar, whose real height product.js
	   measures into this property. The fallback covers the moment before
	   that runs, and every case where there is no buybar at all. */
	bottom: var(--kyrex-chip-bottom, 1.5rem);
	z-index: 340;
	margin: 0;
	max-width: min(22rem, calc(100vw - 2rem));
	display: flex;
	align-items: center;
	gap: 0.5rem;
	padding: 0.6875rem 1.125rem;
	background-color: var(--kyrex-charcoal);
	color: var(--kyrex-ivory);
	border-radius: var(--kyrex-radius-pill);
	box-shadow: 0 6px 24px rgb(0 0 0 / 22%);
	font-family: var(--kyrex-font-body);
	font-size: 0.875rem;
	line-height: 1.35;
	text-align: left;
	pointer-events: none;
	/*
	 * Hidden by opacity, revealed by the class — with NO transition on
	 * opacity.
	 *
	 * A fade was the first attempt and it failed in a way worth recording:
	 * the chip has never been painted before the first selection, so the
	 * browser had no rendered starting value to transition from, declined to
	 * run the transition, and left the element on its pre-transition value.
	 * The chip stayed invisible permanently. Confirmed by measurement —
	 * `transition: none` made the very same code compute `opacity: 1` — and
	 * deferring the class by two animation frames did not help.
	 *
	 * So opacity switches instantly and only the slide is animated. The
	 * movement still reads as an entrance, and appearing immediately is the
	 * right behaviour for a confirmation anyway.
	 */
	opacity: 0;
	transform: translate(-50%, 0.75rem);
	transition: transform 220ms ease;
}

.kyrex-slot-chip.is-visible {
	opacity: 1;
	transform: translate(-50%, 0);
}

/* The tick. Drawn rather than a character so it takes the chip's own colour
   and never falls back to an emoji font. */
.kyrex-slot-chip::before {
	content: '';
	flex: none;
	width: 0.5rem;
	height: 0.28rem;
	margin-top: -0.2em;
	border-left: 1.75px solid var(--kyrex-gold);
	border-bottom: 1.75px solid var(--kyrex-gold);
	transform: rotate(-45deg);
}

/*
 * Note there is deliberately no `:empty { display: none }` here, tempting as
 * it is. It would take the live region out of the accessibility tree while
 * empty and put it back in the same frame its text arrives — the classic way
 * to build a toast that never announces. Opacity already makes an empty chip
 * invisible, and the tick below is drawn on the chip itself, so an empty one
 * renders nothing regardless.
 */

@media (prefers-reduced-motion: reduce) {
	.kyrex-slot-chip,
	.kyrex-slot-chip.is-visible {
		transition: none;
		transform: translate(-50%, 0);
	}
}

/* ── Gallery previous / next ───────────────────────────────────────
 *
 * FlexSlider's own arrows, enabled in functions.php. It ships them as
 * anchors carrying text ("Previous"/"Next") which most themes hide with
 * `text-indent: -9999px` — that moves the text off-screen but leaves it in
 * the accessibility tree, which is what we want; the chevron is drawn.
 *
 * Deliberately matched to the zoom control: same size, same white pill, same
 * shadow. They sit on the same photograph and should look like one set of
 * controls rather than three different designers' work.
 */

/*
 * The hover magnifier, switched off.
 *
 * jquery.zoom paints a full-resolution copy of the photograph over the frame
 * on hover — 2000x2000 inside a 528px box, absolutely positioned and clipped
 * by nothing, so it spilled straight out across the page. See functions.php
 * for why the feature flag cannot simply be turned off: it also controls the
 * lightbox button and its click handler.
 *
 * pointer-events as well as display, so the element can never intercept a
 * click meant for the photograph beneath it.
 */
.kyrex-product__gallery .zoomImg {
	display: none !important;
	pointer-events: none;
}

/*
 * The frame clips its own contents.
 *
 * Belt and braces after hover-magnify was removed: WooCommerce's gallery
 * scripts paint absolutely-positioned children into this box (the magnifier
 * did, at full resolution), and nothing here was clipping them, so a
 * 2000x2000 image spilled straight out over the page. Whatever a future
 * gallery script draws, it stays inside the frame now.
 *
 * Applied to the slide wrapper rather than the gallery root, because the
 * arrows and the zoom button are positioned against the root and must not be
 * clipped by it.
 */
.kyrex-product__gallery .woocommerce-product-gallery__wrapper {
	overflow: hidden;
}

.kyrex-product__gallery .flex-direction-nav {
	list-style: none;
	margin: 0;
	padding: 0;
}

.kyrex-product__gallery .flex-direction-nav a {
	position: absolute;
	top: 50%;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2.75rem;
	height: 2.75rem;
	margin-top: -1.375rem;
	background-color: rgb(255 255 255 / 92%);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-pill);
	box-shadow: 0 2px 8px rgb(0 0 0 / 12%);
	color: var(--kyrex-charcoal);
	/* The label stays for screen readers; the glyph below is the visual. */
	font-size: 0;
	text-decoration: none;
	overflow: hidden;
	/*
	 * Always visible, not revealed on hover.
	 *
	 * Hover-reveal is the fashionable choice and it was the wrong one here:
	 * the complaint that started this was "there is no left/right option", and
	 * a control you have to already suspect exists before you can see it does
	 * not answer that. It also does not exist at all on a touch device, where
	 * :hover never fires.
	 */
	opacity: 1;
	transition: background-color 150ms ease, box-shadow 150ms ease, color 150ms ease;
	-webkit-backdrop-filter: blur(4px);
	backdrop-filter: blur(4px);
}

.kyrex-product__gallery .flex-direction-nav .flex-prev { left: 0.75rem; }
.kyrex-product__gallery .flex-direction-nav .flex-next { right: 0.75rem; }

/* The chevron, drawn from a rotated corner so it takes currentColor and needs
   no icon font. */
.kyrex-product__gallery .flex-direction-nav a::before {
	content: '';
	width: 0.5rem;
	height: 0.5rem;
	border-top: 2px solid currentColor;
	border-right: 2px solid currentColor;
}

.kyrex-product__gallery .flex-direction-nav .flex-prev::before {
	transform: rotate(-135deg);
	margin-left: 3px;
}

.kyrex-product__gallery .flex-direction-nav .flex-next::before {
	transform: rotate(45deg);
	margin-right: 3px;
}

.kyrex-product__gallery .flex-direction-nav a:hover {
	background-color: var(--kyrex-ivory);
	color: var(--kyrex-gold-deep);
	box-shadow: 0 4px 14px rgb(0 0 0 / 18%);
}

.kyrex-product__gallery .flex-direction-nav a:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
}

/* FlexSlider marks an end-of-list arrow with .flex-disabled. Hidden rather
   than dimmed: animationLoop is off, so a disabled arrow does nothing at all
   and offering it is a small lie. */
.kyrex-product__gallery .flex-direction-nav a.flex-disabled {
	opacity: 0;
	pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {
	.kyrex-product__gallery .flex-direction-nav a {
		transition: none;
	}
}

/* ── The thumbnail strip ───────────────────────────────────────────
 *
 * FlexSlider renders the thumbnails as a plain list, so with more
 * photographs than fit they simply wrapped into a second row and pushed the
 * page around. It now scrolls horizontally, with its own arrows that JS
 * reveals ONLY when there is something off-screen to scroll to — arrows on a
 * strip of three thumbnails that already fit are noise.
 */

.kyrex-product__thumbs {
	position: relative;
}

.kyrex-product__gallery .flex-control-thumbs {
	display: flex;
	flex-wrap: nowrap;
	gap: 0.5rem;
	overflow-x: auto;
	scroll-behavior: smooth;
	scrollbar-width: none;
	padding: 0;
	margin: 0.75rem 0 0;
	list-style: none;
}

.kyrex-product__gallery .flex-control-thumbs::-webkit-scrollbar {
	display: none;
}

.kyrex-product__gallery .flex-control-thumbs li {
	flex: 0 0 auto;
	margin: 0;
	width: auto;
}

.kyrex-product__gallery .flex-control-thumbs img {
	width: 5rem;
	height: 5rem;
	object-fit: cover;
	cursor: pointer;
}

/* Scroll buttons, hidden until product.js finds the strip overflowing. */
.kyrex-thumbnav {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 2rem;
	height: 2rem;
	padding: 0;
	background-color: rgb(255 255 255 / 94%);
	border: 1px solid var(--kyrex-border);
	border-radius: var(--kyrex-radius-pill);
	box-shadow: 0 2px 8px rgb(0 0 0 / 12%);
	color: var(--kyrex-charcoal);
	cursor: pointer;
}

.kyrex-thumbnav[hidden] {
	display: none;
}

.kyrex-thumbnav--prev { left: -0.5rem; }
.kyrex-thumbnav--next { right: -0.5rem; }

.kyrex-thumbnav::before {
	content: '';
	width: 0.4375rem;
	height: 0.4375rem;
	border-top: 2px solid currentColor;
	border-right: 2px solid currentColor;
}

.kyrex-thumbnav--prev::before { transform: rotate(-135deg); margin-left: 3px; }
.kyrex-thumbnav--next::before { transform: rotate(45deg); margin-right: 3px; }

.kyrex-thumbnav:hover {
	background-color: var(--kyrex-ivory);
	color: var(--kyrex-gold-deep);
}

.kyrex-thumbnav:focus-visible {
	outline: 2px solid var(--kyrex-charcoal);
	outline-offset: 2px;
}
