/* =========================================================================
   Voley PLT — single product page

   White from top to bottom: the product photography and the orange accents do
   the work, and nothing competes with them. Two columns at the top, then full
   width bands for tabs, reviews and related products.

   WooCommerce's own markup (cart form, variation table, tabs, reviews) is kept
   and restyled rather than rebuilt, so stock, variations and tax display all
   keep working.
   ========================================================================= */

.voley-single {
	padding-block: 34px 90px;
	background: var(--v-white);
}

.voley-single__crumb {
	margin-bottom: 26px;
}

/* Product page extras: warranty tab and specification video. */
.voley-single .voley-warranty ul {
	list-style: disc;
	padding-left: 22px;
	margin: 0 0 14px;
}

.voley-single .voley-spec-video {
	margin-top: 22px;
	max-width: 760px;
}

.voley-single .voley-spec-video video,
.voley-single .voley-spec-video .wp-video {
	width: 100% !important;
	height: auto;
	border-radius: var(--v-r-card, 14px);
	overflow: hidden;
	background: #000;
}

/* Layout ------------------------------------------------------------------
   div.product stays plain block flow: the top two columns live in their own
   .voley-single__top wrapper (added by includes/single-product.php), and the
   tabs, reviews and related grids follow it as normal blocks.

   The wrapper is not cosmetic. It is what bounds the sticky gallery — without
   it, sticky has no containing block that ends, and the gallery follows the
   scroll over every section below it. */
.voley-single div.product {
	margin: 0;
}

.voley-single__top {
	display: grid;
	grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
	gap: 20px 58px;
	align-items: start;
}

.voley-single__top > * {
	min-width: 0;
}

.voley-single div.product .summary {
	margin: 0;
}

/* Gallery -----------------------------------------------------------------
   Sticky is applied in the two-column media query further down, not here — it
   depends on there being a second column to scroll past. */
.voley-pgallery {
	display: flex;
	flex-direction: column;
	gap: 10px;
}

.voley-pgallery__main {
	position: relative;
	aspect-ratio: 1;
	/*
	 * `flex: none` is the point. As the only shrinkable child of the column
	 * this used to absorb every shortfall in the pinned strip, and since
	 * `object-fit: cover` fills whatever box it is given, the product was
	 * quietly delivered cropped instead of square. Nothing here gives way now;
	 * the sticky block further down bounds the gallery's width instead.
	 */
	flex: none;
	border-radius: var(--v-r-card);
	overflow: hidden;
	background: var(--v-white);
}

/* `contain`, to match the tiles: the paddle is a cut-out and cropping it to
   fill the square would cut the handle off. */
.voley-root .voley-pgallery__main img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* The arrows are positioned against this, so the track can keep scrolling
   underneath them. */
.voley-pgallery__strip {
	position: relative;
	flex: none;
	min-width: 0;
}

.voley-pgallery__thumbs {
	display: grid;
	/*
	 * One row, whatever the image count. Five fit; the rest scroll.
	 *
	 * `repeat(5, 1fr)` was right for a five-image product and turned hostile at
	 * twelve: the extra rows tripled the strip's height, and everything they
	 * took came out of the photo above. A single row keeps the gallery's height
	 * a known multiple of its width, which is what lets the sticky block below
	 * size it without ever touching the photo's shape.
	 */
	grid-auto-flow: column;
	grid-auto-columns: calc((100% - 40px) / 5);
	gap: 10px;
	overflow-x: auto;
	overscroll-behavior-x: contain;
	scroll-snap-type: x mandatory;
	/*
	 * No scrollbar. On macOS the overlay bar is invisible until something is
	 * already scrolling, which is exactly why a nine-image product read as a
	 * five-image one — so it was never carrying the "there is more" message
	 * anyway. The arrows carry it now, and dropping the gutter keeps the
	 * strip's height equal to one thumbnail on every platform, which is what
	 * the sticky block's height ratio below is derived from.
	 */
	scrollbar-width: none;
	scroll-behavior: smooth;
}

.voley-pgallery__thumbs::-webkit-scrollbar {
	display: none;
}

.voley-pgallery__thumbs > li {
	scroll-snap-align: start;
}

@media (prefers-reduced-motion: reduce) {
	.voley-pgallery__thumbs {
		scroll-behavior: auto;
	}
}

/* Arrows ------------------------------------------------------------------
   Overlaid on the first and last visible thumbnail rather than placed outside
   the strip: the gallery column is flush with the page edge on the left and
   owns no spare room on either side, so an outside arrow would either overflow
   the page or steal width from every thumbnail to buy space it only needs at
   the two ends. */
.voley-root .voley-pgallery__nav {
	position: absolute;
	top: 50%;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 32px;
	height: 32px;
	margin: 0;
	padding: 0;
	transform: translateY(-50%);
	border: 0;
	border-radius: 50%;
	background: var(--v-white);
	box-shadow: 0 2px 10px rgba(17, 18, 19, 0.18);
	color: var(--v-ink);
	cursor: pointer;
	transition: background-color 0.2s var(--v-ease), color 0.2s var(--v-ease);
}

/* `display: flex` above outranks the UA sheet's `[hidden] { display: none }`,
   so the attribute has to be honoured explicitly or a hidden arrow still
   paints. */
.voley-root .voley-pgallery__nav[hidden] {
	display: none;
}

.voley-root .voley-pgallery__nav:hover,
.voley-root .voley-pgallery__nav:focus-visible {
	background: var(--v-accent);
	color: var(--v-white);
}

.voley-pgallery__nav.is-prev {
	left: 3px;
}

.voley-pgallery__nav.is-next {
	right: 3px;
}

/* Thumbnails beside the photo ----------------------------------------------
   Only where there is width to spare. Below this the strip stays a row under
   the photo, which is the only shape that fits a phone. */
@media (min-width: 861px) {
	.voley-pgallery {
		flex-direction: row;
		align-items: flex-start;
	}

	.voley-pgallery__strip {
		order: -1;
		width: 84px;
		flex: none;
	}

	.voley-pgallery__main {
		flex: 1;
		min-width: 0;
	}

	/* One column instead of one row: the same scroll-and-arrow mechanics as the
	   horizontal strip, turned ninety degrees. */
	.voley-pgallery__thumbs {
		grid-auto-flow: row;
		grid-auto-columns: auto;
		grid-auto-rows: 84px;
		max-height: calc((84px * 5) + (10px * 4));
		overflow-x: hidden;
		overflow-y: auto;
		scroll-snap-type: y mandatory;
	}

	.voley-pgallery__nav.is-prev,
	.voley-pgallery__nav.is-next {
		left: 50%;
		right: auto;
		transform: translateX(-50%);
	}

	.voley-pgallery__nav.is-prev {
		top: 3px;
	}

	.voley-pgallery__nav.is-next {
		top: auto;
		bottom: 3px;
	}

	.voley-pgallery__nav svg {
		transform: rotate(90deg);
	}
}

.voley-pthumb {
	display: block;
	width: 100%;
	aspect-ratio: 1;
	border-radius: 10px;
	overflow: hidden;
	background: var(--v-grey-50);
	/* Inset ring, so the selected state costs no layout shift. */
	box-shadow: inset 0 0 0 1px var(--v-line-soft);
	opacity: 0.62;
	transition: opacity 0.25s var(--v-ease), box-shadow 0.25s var(--v-ease);
}

.voley-root .voley-pthumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.voley-pthumb:hover {
	opacity: 1;
}

.voley-pthumb.is-active {
	opacity: 1;
	box-shadow: inset 0 0 0 2px var(--v-accent);
}

/* Summary ----------------------------------------------------------------- */
.voley-single__brand {
	display: block;
	margin-bottom: 12px;
	font-size: var(--v-fs-eyebrow);
	font-weight: 700;
	letter-spacing: 0.18em;
	line-height: 1;
	text-transform: uppercase;
	color: var(--v-accent);
}

.voley-root.voley-root .voley-single__title {
	margin-bottom: 16px;
	font-family: var(--v-font-display);
	font-size: 28px;
	font-style: italic;
	font-weight: 800;
	line-height: 1.1;
	letter-spacing: -0.005em;
	text-transform: uppercase;
	color: var(--v-ink);
}

.voley-single__rating {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-bottom: 18px;
}

/* Nothing has been reviewed yet: the stars stay as an outline so the row keeps
   its shape, and the invitation beside them is what carries the colour. */
.voley-single__rating.is-empty .voley-stars__fill {
	display: none;
}

.voley-single__rating.is-empty .voley-stars__base {
	opacity: 0.45;
}

.voley-single__reviews {
	font-size: var(--v-fs-sm);
	font-weight: 600;
	color: var(--v-grey-600);
	border-bottom: 1px solid var(--v-line);
	transition: color 0.2s var(--v-ease), border-color 0.2s var(--v-ease);
}

.voley-single__reviews:hover {
	color: var(--v-accent);
	border-color: var(--v-accent);
}

/* Price — WooCommerce's own markup, so ranges and sale prices still work. */
.voley-single div.product .summary p.price,
.voley-single div.product .summary span.price {
	display: flex;
	align-items: baseline;
	flex-wrap: wrap;
	gap: 6px 12px;
	margin: 0 0 20px;
	padding-bottom: 20px;
	border-bottom: 1px solid var(--v-line-soft);
	font-family: var(--v-font-display);
	font-size: 26px;
	font-style: italic;
	font-weight: 800;
	color: var(--v-ink);
}

/* Same three-part price as the product tiles: current price, the markdown
   beside it, and the old price on its own line underneath. */
.voley-single div.product .summary .price ins {
	order: 1;
	text-decoration: none;
}

.voley-single div.product .summary .price .voley-product__off {
	order: 2;
	align-self: center;
	font-family: var(--v-font-body);
	font-style: normal;
	font-size: var(--v-fs-sm);
}

.voley-single div.product .summary .price del {
	order: 3;
	flex-basis: 100%;
	font-family: var(--v-font-body);
	font-size: var(--v-fs-body);
	font-style: normal;
	font-weight: 500;
	opacity: 1;
	color: var(--v-sale);
}

.voley-single .woocommerce-product-details__short-description {
	margin-bottom: 24px;
	font-size: var(--v-fs-body);
	line-height: 1.7;
	color: var(--v-grey-600);
}

.voley-single .woocommerce-product-details__short-description p {
	margin: 0 0 10px;
}

.voley-single .woocommerce-product-details__short-description p:last-child {
	margin-bottom: 0;
}

/* Cart form --------------------------------------------------------------- */
.voley-single form.cart {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	margin: 0 0 24px;
}

/* The pill is the stepper wrapper, which holds all three controls. `.quantity`
   is only the input's own box inside it, so it carries no border of its own —
   two nested pills is what that produced. */
.voley-single form.cart .voley-qtystep {
	display: flex;
	align-items: center;
	height: 52px;
	padding: 0 6px;
	border: 1px solid var(--v-line);
	border-radius: var(--v-r-pill);
	background: var(--v-grey-100);
}

.voley-single form.cart .voley-qtystep .quantity {
	display: flex;
	align-items: center;
	height: 100%;
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
}

/* Named apart from the cart drawer's `.voley-qty__btn`, which is white-on-dark
   and was reached by the shared class name — these are dark-on-light. */
.voley-single form.cart .voley-qtystep__btn {
	display: grid;
	place-items: center;
	width: 38px;
	height: 38px;
	flex: none;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background: none;
	color: var(--v-grey-700);
	font-size: 20px;
	font-weight: 600;
	line-height: 1;
	cursor: pointer;
	transition: background-color 0.2s var(--v-ease), color 0.2s var(--v-ease);
}

.voley-single form.cart .voley-qtystep__btn:hover {
	background: var(--v-white);
	color: var(--v-ink);
}

.voley-single form.cart .quantity input.qty,
.voley-single form.cart input[type="number"] {
	width: 62px;
	height: 100%;
	padding: 0;
	border: 0;
	background: none;
	font-size: var(--v-fs-body);
	font-weight: 700;
	text-align: center;
	color: var(--v-ink);
	appearance: textfield;
}

.voley-single form.cart input[type="number"]:focus {
	outline: none;
}

/*
 * `div.product form.cart` for the same reason as the tabs — two rules outrank
 * the short form, and between them they made the button invisible.
 *
 * The background came from the theme:
 *
 *     .lqd-woo-single-layout-3 div.product form.cart button.button
 *         { background-color: var(--color-primary) }
 *
 * at (0,4,3). `--color-primary` is defined from the theme's own options, and on
 * an unactivated theme those never load, so it resolved to transparent — white
 * text on nothing. The button was there and clickable the whole time; it simply
 * could not be seen.
 *
 * The padding came from WooCommerce itself, whose `.disabled` / `:disabled`
 * branch sits at (0,3,1) and is answered separately below.
 *
 * `button.button` is carried as well as the long ancestor path so this lands at
 * (0,5,3) and beats the theme outright, rather than tying with it and winning
 * only because the theme's stylesheet happens to be dequeued.
 */
/* Full width, on its own line under the quantity — the one action the column
   is built around should not be sharing a row with a number box. */
.voley-single div.product form.cart button.button.single_add_to_cart_button {
	flex: 1 1 0;
	min-width: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	height: 58px;
	padding: 0 30px;
	border: 0;
	border-radius: var(--v-r-sm);
	background: var(--v-accent);
	color: var(--v-white);
	font-family: var(--v-font-display);
	font-size: var(--v-fs-h3);
	font-style: normal;
	font-weight: 800;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	white-space: nowrap;
	cursor: pointer;
	transition: background-color 0.25s var(--v-ease), transform 0.25s var(--v-ease);
}

.voley-single div.product form.cart button.button.single_add_to_cart_button:hover {
	background: var(--v-accent-ink);
	transform: translateY(-1px);
}

/* Restates padding and colour, because WooCommerce's disabled rule sets both. */
.voley-single div.product form.cart button.button.single_add_to_cart_button:disabled {
	padding: 0 30px;
	background: var(--v-grey-300);
	color: var(--v-white);
	transform: none;
	cursor: not-allowed;
}

/*
 * A variable product buries the quantity and the button two levels deeper than a
 * simple one — inside `.single_variation_wrap > .woocommerce-variation-add-to-cart`
 * — so `form.cart`'s flex layout never reached them and the row shrank to its
 * content: a 90px pill and a 160px button adrift in a 628px column. These two
 * rules hand that pair back to the same layout a simple product gets.
 *
 * `float: none` because woocommerce.css floats the button left, which collapsed
 * its container to zero height.
 */
.voley-single form.cart .single_variation_wrap {
	flex: 1 1 100%;
	width: 100%;
}

.voley-single form.cart .woocommerce-variation-add-to-cart {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 12px;
	width: 100%;
}

.voley-single form.cart .woocommerce-variation-add-to-cart .quantity {
	margin: 0;
	float: none;
}

.voley-single div.product form.cart .woocommerce-variation-add-to-cart button.button.single_add_to_cart_button {
	float: none;
}

/* Variations ---------------------------------------------------------------
   Unpicked from a table into stacked rows: the swatches need the column's full
   width, which a 132px label cell beside them was taking a third of. */
.voley-single table.variations {
	display: block;
	width: 100%;
	margin: 0 0 18px;
	border: 0;
}

.voley-single table.variations tbody,
.voley-single table.variations tr {
	display: block;
	width: 100%;
}

.voley-single table.variations th,
.voley-single table.variations td {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	text-align: left;
}

.voley-single table.variations tr + tr {
	margin-top: 16px;
}

.voley-single table.variations td {
	position: relative;
}

.voley-single table.variations th {
	margin-bottom: 8px;
	font-size: var(--v-fs-sm);
	font-weight: 700;
	color: var(--v-ink);
}

/* "Color" becomes "Color:", so the chosen value reads as its continuation. */
.voley-single table.variations th label::after {
	content: ":";
}

.voley-swatch__value {
	margin-left: 6px;
	font-weight: 500;
	color: var(--v-grey-600);
}

/* The select stays in the markup and keeps driving WooCommerce; it is only
   hidden once the script that replaces it is known to be running.

   The long path is deliberate. WooCommerce ships

       .woocommerce div.product form.cart .variations select { display: inline-block }

   which lands at (0,4,2) — exactly what the short form of this rule scored, and
   woocommerce.css is enqueued after product.css, so the tie went to WooCommerce
   and the dropdown stayed on screen under the swatches. Carrying `div.product`
   and `form.cart` too puts this at (0,5,4) and settles it outright. */
.voley-root.js .voley-single div.product form.cart table.variations select {
	display: none;
}

/* Swatches ---------------------------------------------------------------- */
.voley-swatches {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
}

.voley-swatch {
	position: relative;
	border: 1px solid var(--v-grey-200);
	background: var(--v-white);
	cursor: pointer;
	transition: border-color 0.2s var(--v-ease), color 0.2s var(--v-ease), background-color 0.2s var(--v-ease);
}

.voley-swatch:hover:not(:disabled) {
	border-color: var(--v-grey-500);
}

/* Two pixels of ink, drawn inside: a thicker outer border would nudge the row
   every time the selection moved. */
.voley-swatch.is-active {
	border-color: var(--v-ink);
	box-shadow: inset 0 0 0 1px var(--v-ink);
}

/* Ruled out by the rest of the selection — still shown, because which colours
   exist should not change as you pick a size. */
.voley-swatch.is-off {
	opacity: 0.35;
	cursor: not-allowed;
}

.voley-swatch--image {
	width: 74px;
	aspect-ratio: 1;
	padding: 0;
	border-radius: 10px;
	overflow: hidden;
}

.voley-root .voley-swatch--image img {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

.voley-swatch--text {
	min-width: 64px;
	height: 40px;
	padding: 0 16px;
	border-radius: var(--v-r-sm);
	background: var(--v-grey-100);
	font-size: var(--v-fs-sm);
	font-weight: 700;
	text-transform: uppercase;
	color: var(--v-ink);
}

.voley-swatch--text.is-active {
	background: var(--v-white);
}

/* The gap belongs to the select, not the swatches above it: carried this way it
   goes away with the select when scripting hides it, instead of leaving a hole
   between the swatch row and the next attribute. */
.voley-single table.variations select {
	margin-top: 14px;
	width: 100%;
	height: 46px;
	padding: 0 38px 0 16px;
	border: 1px solid var(--v-line);
	border-radius: var(--v-r-pill);
	background-color: var(--v-white);
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%23111213' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right 14px center;
	font-size: var(--v-fs-sm);
	font-weight: 600;
	color: var(--v-ink);
	appearance: none;
	cursor: pointer;
}

/*
 * Taken out of flow on purpose.
 *
 * WooCommerce shows and hides this link with `visibility`, never `display`, so
 * in normal flow it reserves its height whether or not anyone can see it. The
 * select above it is full width, so the link wrapped to a line of its own and
 * held 34px of blank space open under every colour picker, before a shopper had
 * chosen anything. Absolute keeps the link exactly where it reads — under the
 * select, left aligned — and costs the row nothing when it is invisible.
 */
.voley-single .reset_variations {
	position: absolute;
	top: 100%;
	left: 0;
	margin-top: 4px;
	font-size: var(--v-fs-xs);
	line-height: 1;
	color: var(--v-grey-500);
}

.voley-single .woocommerce-variation-price {
	margin-bottom: 14px;
}

/* Stock and meta ---------------------------------------------------------- */
.voley-single .stock {
	margin: 0 0 16px;
	font-size: var(--v-fs-sm);
	font-weight: 600;
}

.voley-single .stock.in-stock {
	color: #1f7a45;
}

.voley-single .stock.out-of-stock {
	color: #b3261e;
}

.voley-single .product_meta {
	padding-top: 20px;
	border-top: 1px solid var(--v-line-soft);
	font-size: var(--v-fs-sm);
	color: var(--v-grey-600);
}

.voley-single .product_meta > span {
	display: block;
	margin-bottom: 6px;
}

.voley-single .product_meta a:hover {
	color: var(--v-accent);
}

/* Tabs -------------------------------------------------------------------- */
.voley-single .woocommerce-tabs {
	margin-top: 76px;
	padding-top: 42px;
	border-top: 1px solid var(--v-line-soft);
}

.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	margin: 0 0 30px;
	padding: 0;
	border: 0;
	/* WooCommerce clips this list to hide the tails of its folder tabs. */
	overflow: visible;
	list-style: none;
}

.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs::before,
.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs::after,
.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs li::before,
.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs li::after {
	content: none;
	display: none;
}

.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs li {
	margin: 0;
	padding: 0;
	border: 0;
	background: none;
	border-radius: 0;
	box-shadow: none;
}

/*
 * These three carry `div.product` and `.wc-tabs` for one reason: WooCommerce's
 * own stylesheet says
 *
 *     .woocommerce div.product .woocommerce-tabs ul.tabs li a { padding: .5em 0 }
 *     .woocommerce div.product .woocommerce-tabs ul.tabs li.active a { color: inherit }
 *
 * at (0,4,4) and (0,5,4). Written the short way these rules sit at (0,3,3) and
 * lose, which left the pill with no horizontal padding — so its rounded ends
 * closed over the first and last letters of the label. Nothing to do with the
 * theme; this was WooCommerce all along.
 *
 * The list and its items are qualified the same way, against
 *
 *     ul.tabs    { padding: 0 0 0 1em; margin: 0 0 1.618em; overflow: hidden }
 *     ul.tabs li { border: 1px solid #cfc8d8; border-radius: 4px 4px 0 0;
 *                  margin: 0 -5px; padding: 0 1em }
 *
 * which is WooCommerce's folder-tab look — the grey boxes behind the pills.
 */
.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs li a {
	display: inline-block;
	padding: 10px 20px;
	border: 1px solid var(--v-line);
	border-radius: var(--v-r-pill);
	font-size: var(--v-fs-sm);
	font-weight: 600;
	color: var(--v-ink);
	transition: border-color 0.2s var(--v-ease), background-color 0.2s var(--v-ease), color 0.2s var(--v-ease);
}

.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs li a:hover {
	border-color: var(--v-ink);
}

.voley-single div.product .woocommerce-tabs ul.tabs.wc-tabs li.active a {
	border-color: var(--v-accent);
	background: var(--v-accent);
	color: var(--v-white);
}

.voley-single .woocommerce-Tabs-panel {
	max-width: 74ch;
	font-size: var(--v-fs-body);
	line-height: 1.75;
	color: var(--v-grey-600);
}

.voley-single .woocommerce-Tabs-panel > h2 {
	display: none;
}

.voley-single .woocommerce-Tabs-panel p {
	margin: 0 0 14px;
}

/*
 * Description tab: shop-owner content, not our chrome.
 *
 * base.css strips list markers and indentation from every ul/ol under
 * .voley-root, which is right for a nav or a grid of tiles and wrong for a
 * description someone wrote in the editor — their numbered list arrived as
 * six unmarked lines flush against the margin. The reset is undone for the
 * tab panels only, so everything the plugin draws itself keeps it.
 */
.voley-single .woocommerce-Tabs-panel :where(ul, ol) {
	margin: 0 0 14px;
	padding-left: 22px;
}

.voley-single .woocommerce-Tabs-panel :where(ul) {
	list-style: disc;
}

.voley-single .woocommerce-Tabs-panel :where(ol) {
	list-style: decimal;
}

.voley-single .woocommerce-Tabs-panel :where(li) {
	margin-bottom: 4px;
}

.voley-single .shop_attributes {
	width: 100%;
	margin: 6px 0 0;
	border-collapse: collapse;
}

.voley-single .shop_attributes th {
	width: 190px;
	padding: 12px 0;
	border-bottom: 1px solid var(--v-line-soft);
	font-size: var(--v-fs-sm);
	font-weight: 600;
	text-align: left;
	color: var(--v-ink);
}

.voley-single .shop_attributes td {
	padding: 12px 0;
	border-bottom: 1px solid var(--v-line-soft);
	font-size: var(--v-fs-sm);
}

.voley-single .shop_attributes td p {
	margin: 0;
}

/* Related and upsells ------------------------------------------------------ */
.voley-single .related,
.voley-single .upsells {
	margin-top: 76px;
	padding-top: 54px;
	border-top: 1px solid var(--v-line-soft);
}

.voley-root.voley-root .voley-single .related > h2,
.voley-root.voley-root .voley-single .upsells > h2 {
	margin-bottom: 30px;
	font-size: var(--v-fs-h2);
}

/* Reviews -----------------------------------------------------------------
   Its own section under the tabs, so it is spaced like the other sections that
   follow it rather than like a tab panel. */
.voley-reviews {
	margin-top: 76px;
	padding-top: 54px;
	border-top: 1px solid var(--v-line-soft);
}

.voley-reviews__head {
	margin-bottom: 30px;
}

/* WooCommerce's own "Reviews" / "Be the first to review" heading, now that the
   section above it already carries the title. */
.voley-reviews #reviews > h2,
.voley-reviews #reviews #comments > h2 {
	display: none;
}

.voley-single #reviews .commentlist {
	margin: 0 0 30px;
	padding: 0;
	list-style: none;
}

.voley-single #reviews .comment_container {
	display: flex;
	gap: 16px;
	padding: 20px 0;
	border-bottom: 1px solid var(--v-line-soft);
}

.voley-root .voley-single #reviews .comment_container img.avatar {
	width: 44px;
	height: 44px;
	border-radius: 50%;
	flex: none;
}

.voley-single #reviews .comment-text p.meta {
	margin: 0 0 6px;
	font-size: var(--v-fs-sm);
	color: var(--v-grey-500);
}

.voley-single #reviews .comment-text strong {
	color: var(--v-ink);
}

/* Review form -------------------------------------------------------------
   The star selector itself is left to woocommerce.css, which ships the glyphs
   and the hover states for `p.stars` — theme-compat.php keeps that file for
   exactly this kind of component. Only the layout around it is ours. */
.voley-single #review_form_wrapper {
	margin-top: 36px;
	padding-top: 30px;
	border-top: 1px solid var(--v-line-soft);
}

.voley-root.voley-root .voley-single #reply-title {
	display: block;
	margin-bottom: 6px;
	font-family: var(--v-font-display);
	font-size: var(--v-fs-h3);
	font-weight: 800;
	text-transform: uppercase;
	color: var(--v-ink);
}

.voley-single #review_form .comment-notes {
	margin: 0 0 20px;
	font-size: var(--v-fs-sm);
	color: var(--v-grey-600);
}

.voley-single #review_form .comment-form > p,
.voley-single #review_form .comment-form-rating {
	margin: 0 0 16px;
}

.voley-single #review_form .comment-form label {
	display: block;
	margin-bottom: 6px;
	font-size: var(--v-fs-sm);
	font-weight: 600;
	color: var(--v-ink);
}

.voley-single #review_form .required {
	color: var(--v-sale);
}

/* Name and email side by side — they are short, and stacking them pushes the
   submit button a screenful down on a phone. */
@media (min-width: 601px) {
	.voley-single #review_form .comment-form-author,
	.voley-single #review_form .comment-form-email {
		display: inline-block;
		width: calc(50% - 8px);
		vertical-align: top;
	}

	.voley-single #review_form .comment-form-author {
		margin-right: 12px;
	}
}

.voley-single #review_form .comment-form input[type="text"],
.voley-single #review_form .comment-form input[type="email"],
.voley-single #review_form .comment-form textarea {
	width: 100%;
	padding: 12px 16px;
	border: 1px solid var(--v-line);
	border-radius: var(--v-r-sm);
	background: var(--v-white);
	font-family: var(--v-font-body);
	font-size: var(--v-fs-sm);
	color: var(--v-ink);
}

.voley-single #review_form .comment-form textarea:focus,
.voley-single #review_form .comment-form input:focus {
	outline: none;
	border-color: var(--v-accent);
}

.voley-single #review_form .form-submit input[type="submit"] {
	height: 46px;
	padding: 0 26px;
	border: 0;
	border-radius: var(--v-r-pill);
	background: var(--v-ink);
	color: var(--v-white);
	font-family: var(--v-font-display);
	font-size: var(--v-fs-sm);
	font-style: italic;
	font-weight: 800;
	text-transform: uppercase;
	cursor: pointer;
}

/* Sticky gallery ----------------------------------------------------------
   Only while there are two columns, and only when the window is tall enough to
   show the whole gallery at once. Pinning something taller than the viewport
   puts its lower half — here, the thumbnails — permanently out of reach.

   The max-height is the safety net: it caps the gallery to the visible strip so
   the thumbnails stay clickable however tall the photo wants to be. */
@media (min-width: 1001px) and (min-height: 680px) {
	.voley-pgallery {
		position: sticky;
		top: calc(var(--v-chrome-h) + 20px);
		/*
		 * Bound the width, not the height.
		 *
		 * Capping the height only decided which child would be sacrificed, and
		 * it was always the photo. Bounding the width scales the whole gallery
		 * down together, so a short window gets a smaller square rather than a
		 * cropped rectangle.
		 *
		 * 1.2 is the gallery's own height-to-width: a square photo, a 10px gap,
		 * and one row of five thumbs at (W - 40) / 5 — so 1.2W + 2 — solved for
		 * W against the height the pinned strip has to spend. A product with a
		 * single image renders no thumbnail row at all and is left a little
		 * smaller than it needed to be, which costs it nothing but size.
		 */
		/*
		 * The thumbnails sit beside the photo at this width, not under it, so
		 * the gallery is as tall as the square photo and no taller — the 1.2
		 * that used to account for a row of thumbs below would now shrink it
		 * for clearance it no longer needs.
		 */
		width: min(100%, calc(100vh - var(--v-chrome-h) - 42px));
		margin-inline-end: auto;
	}
}

/* Responsive -------------------------------------------------------------- */
@media (max-width: 1000px) {
	.voley-single__top {
		grid-template-columns: minmax(0, 1fr);
		gap: 34px;
	}
}

@media (max-width: 900px) {
	.voley-single {
		padding-block: 24px 60px;
	}

	.voley-root.voley-root .voley-single__title {
		font-size: 23px;
	}

	.voley-single .woocommerce-tabs,
	.voley-reviews,
	.voley-single .related,
	.voley-single .upsells {
		margin-top: 52px;
		padding-top: 36px;
	}
}

@media (max-width: 560px) {
	.voley-single form.cart {
		gap: 10px;
	}


	/* Four across on a phone. Stated as an auto-column width, not a
	   `grid-template-columns`, because `grid-auto-flow: column` above places
	   every thumbnail in its own column — an explicit four-column template
	   would size only the first four and leave the rest at the desktop
	   width. */
	.voley-pgallery__thumbs {
		grid-auto-columns: calc((100% - 30px) / 4);
	}
}


/* =========================================================================
   v1.25.2 adjustments
   ========================================================================= */

/* Bigger stars beside the "Review" link in the summary. */
.voley-single__rating .voley-stars svg {
	width: 18px;
	height: 18px;
}

.voley-single__rating .voley-stars__base,
.voley-single__rating .voley-stars__fill {
	gap: 3px;
}

/* Variation picker: no theme zebra background, no row rule. */
.voley-single table.variations,
.voley-single table.variations tbody,
.voley-single table.variations tr,
.voley-single table.variations th,
.voley-single table.variations td {
	background: transparent !important;
	border: 0 !important;
}

/* Quantity and Add to cart share one row (simple and variable products). */
.voley-single form.cart .woocommerce-variation-add-to-cart {
	flex-wrap: nowrap;
}

.voley-single form.cart .voley-qtystep {
	flex: none;
}

.voley-single div.product form.cart button.button.single_add_to_cart_button {
	height: 52px;
}

@media (max-width: 560px) {
	.voley-single form.cart .voley-qtystep__btn {
		width: 32px;
	}

	.voley-single form.cart .quantity input.qty,
	.voley-single form.cart input[type="number"] {
		width: 40px;
	}
}

/* Tab panel links: brand colour, no focus box after a click. */
.voley-single .woocommerce-Tabs-panel a {
	font-weight: 600;
	color: var(--v-accent-ink);
}

.voley-single .woocommerce-Tabs-panel a:focus,
.voley-single .woocommerce-tabs ul.tabs li a:focus {
	outline: none;
	box-shadow: none;
}

/* Review form --------------------------------------------------------------
   The theme wraps every field in a Bootstrap `.row` (a flex row), which put the
   stars, the comment box and the button side by side. Back to a stack. */
.voley-single #review_form #commentform .row {
	display: block;
	margin: 0;
}

.voley-single #review_form #commentform .row > * {
	width: 100%;
	max-width: none;
	flex: none;
	margin: 0 0 16px;
	padding: 0;
}

@media (min-width: 601px) {
	.voley-single #review_form #commentform .row {
		display: grid;
		grid-template-columns: 1fr 1fr;
		column-gap: 16px;
	}

	.voley-single #review_form #commentform .row > * {
		grid-column: 1 / -1;
	}

	.voley-single #review_form #commentform .row > .comment-form-author {
		grid-column: 1;
	}

	.voley-single #review_form #commentform .row > .comment-form-email {
		grid-column: 2;
	}
}

.voley-root.voley-root .voley-single #reply-title {
	margin-bottom: 18px;
	font-size: var(--v-fs-h2);
	font-style: italic;
}

.voley-single #review_form .comment-form-rating {
	display: flex;
	align-items: center;
	gap: 14px;
}

.voley-single #review_form .comment-form-rating::before {
	content: "Your rating";
	font-size: var(--v-fs-sm);
	font-weight: 700;
	color: var(--v-ink);
}

.voley-single #review_form .comment-form-rating p.stars {
	margin: 0;
	line-height: 1;
}

.voley-single #review_form .comment-form-rating p.stars a {
	width: 28px;
	height: 28px;
	font-size: 26px;
	color: var(--v-accent);
}

.voley-single #review_form .comment-form-rating p.stars a::before {
	color: var(--v-accent);
}

.voley-single #review_form #commentform textarea {
	min-height: 140px;
	padding: 14px 16px;
	border: 1px solid var(--v-line);
	border-radius: var(--v-r-card);
	resize: vertical;
}

.voley-single #review_form #commentform input[type="text"],
.voley-single #review_form #commentform input[type="email"] {
	height: 48px;
	border-radius: var(--v-r-pill);
	padding: 0 20px;
}

.voley-single #review_form .comment-form-cookies-consent {
	display: flex;
	align-items: center;
	gap: 8px;
	font-size: var(--v-fs-sm);
	color: var(--v-grey-600);
}

.voley-single #review_form .comment-form-cookies-consent label {
	margin: 0;
	font-weight: 500;
}

/* woocommerce.css styles `#respond input#submit` with two ids; three here. */
.voley-single #review_form #respond input#submit {
	height: 50px;
	padding: 0 34px;
	border: 0;
	border-radius: var(--v-r-pill);
	background: var(--v-accent);
	font-family: var(--v-font-display);
	font-size: var(--v-fs-sm);
	font-style: italic;
	font-weight: 800;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--v-white);
	cursor: pointer;
	transition: background-color 0.2s var(--v-ease);
}

.voley-single #review_form #respond input#submit:hover {
	background: var(--v-ink);
}

.voley-single__rating.is-empty .voley-stars__base {
	opacity: 1;
	color: var(--v-grey-300);
}

/* A thumbnail was clicked and its photo is still on the way: dim the old one so
   the click is seen to have landed. product.js clears it on load. */
.voley-pgallery__main img {
	transition: opacity 0.2s var(--v-ease);
}

.voley-pgallery__main img.is-loading {
	opacity: 0.5;
}
