/*
 * Single product page.
 *
 * The first screen follows the concept the owner picked on 17.09.2026
 * («Знайомий GSL», concept 2): the heading and the article first, the photo
 * in a white card, then a vertical deal — price, the pack box, the fact
 * chips, the colours, quantity with its running total, and a full-width
 * gold button with the wishlist heart beside it. Denser than the concept
 * on purpose (the owner's second variant): a 200px photo on the phone keeps
 * the button inside a 390×844 first screen. On the desktop the trust tiles
 * and the consultant stand under the photo, where the deal column used to
 * leave half a metre of white (owner, 23.09.2026); on the phone they keep
 * their old place after the deal. Below the fold the page stands in two
 * columns on the desktop.
 *
 * Small on purpose: the gallery, the price and the add-to-cart form are
 * WooCommerce blocks styled through theme.json, the plugin's blocks carry
 * their own CSS, and this file owns only the page chrome and the form's
 * WooCommerce classes (the quantity field, the button).
 */

/* ---------------------------------------------------------------- ground ---- */
/* The page stands on the same ground as the rest of the storefront (owner,
   17.09.2026) — the theme's surface — and the white cards (photo, chips,
   the consultant) read as cards on it. The warm paper of August («Тепла
   майстерня») is gone with the layout it belonged to. */

/* Room for the sticky buy bar so the footer's last lines stay reachable. */
@media (max-width: 782px) {
	.gsl-product {
		padding-bottom: 84px;
	}
}

/* One quiet line of trail, never a paragraph: the crumb is a map. The
   product-name crumb itself is trimmed server-side (Catalog\Breadcrumbs). */
.gsl-product .gsl-crumbs {
	white-space: nowrap;
	overflow-x: auto;
	scrollbar-width: none;
	padding-block: var(--wp--preset--spacing--20);
}

.gsl-pd__top {
	margin-block: var(--wp--preset--spacing--30) 0;
}

/* --------------------------------------------------------------- heading ---- */
/* The name first, the article right under it: what the shopper reads out
   on the phone and what the order is checked against. The heading is the
   short display name (Catalog\DisplayName); the numbers it used to carry
   live a finger below. */
.gsl-pd__heading {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--10);
	margin: 0 0 var(--wp--preset--spacing--30);
}

.gsl-pd__heading > * {
	margin: 0;
}

.gsl-product .wp-block-post-title {
	font-family: var(--wp--preset--font-family--fixel-display);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.2;
	letter-spacing: 0.005em;
	text-wrap: balance;
	margin: 0;
}

.gsl-pd__skurow {
	gap: var(--wp--preset--spacing--20);
	align-items: baseline;
}

.gsl-pd__sku {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	margin: 0;
}

/* ----------------------------------------------------------------- photo ---- */
/* A white card with a hairline, the photo whole inside it — never cropped:
   the photo is the contract, and the owner already sent the cream card away
   (18.08) because a tinted ground fought the merchandise. */
.gsl-pd__photo {
	position: relative;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--medium);
	padding: var(--wp--preset--spacing--30);
}

.gsl-pd__photo .woocommerce-product-gallery {
	position: relative;
	margin: 0;
}

.gsl-pd__photo .gsl-pd__count,
.gsl-pd__photo .gsl-pd__dots {
	display: none;
}

.gsl-pd__photo .woocommerce-product-gallery__image img {
	display: block;
	width: 100%;
	height: auto;
	max-height: 480px;
	object-fit: contain;
	border-radius: 0;
	background: var(--wp--preset--color--base);
}

/* Several photos: WooCommerce's slider (theme support in functions.php)
   turns the stack into swipeable slides with a strip of thumbnails under
   them; the active one wears the brand ring. The slider's own inline
   styles do the sliding, this only dresses the strip — with selectors
   heavy enough (0,5,1) to outweigh WooCommerce's classic «25% and float»
   rules for the same list, which weigh (0,4,3). */
.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
	margin: var(--wp--preset--spacing--20) 0 0;
	padding: 0;
	overflow: visible;
}

.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs li {
	flex: none;
	width: 56px;
	height: 56px;
	margin: 0;
	padding: 0;
	float: none;
	list-style: none;
}

.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs img {
	display: block;
	width: 100%;
	height: 100%;
	margin: 0;
	object-fit: cover;
	border: 2px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
	cursor: pointer;
	opacity: 0.85;
}

.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs img:hover,
.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs img.flex-active {
	border-color: var(--wp--preset--color--brand-action);
	opacity: 1;
}

/* ----------------------------------------------------------------- trust ---- */
/* The assurance tiles and the consultant share one column of rhythm; the
   group exists so the template can carry them together (under the photo on
   the desktop, after the deal on the phone) and the blocks keep their own
   chrome. */
.gsl-pd .gsl-pd__trust {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
	/* Core's flow layout hands every non-first child of a group a top
	   margin; the left column's gap already spaces this one. */
	margin-block: 0;
}

/* Two classes: the tiles' own block margin weighs one, and order between
   the theme's file and the block's is not a contract. */
.gsl-pd .gsl-pd__trust > * {
	margin-block: 0;
}

/* The article on the left, availability on the right, one line under the
   name — the concept's «Артикул … / Готово до відправки» folded into the
   space the phone can spare. */
.gsl-pd__meta {
	gap: var(--wp--preset--spacing--30);
	align-items: baseline;
}

.gsl-pd__meta .gsl-pd__stock {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

/* A sold-out product already says so under its name; the purchase form
   said it a second time in plain text between the chips and the lead
   (design review, 28.09.2026). */
.gsl-product .gsl-pd .wc-block-add-to-cart-form > .stock.out-of-stock {
	display: none;
}

/* ------------------------------------------------------------------ deal ---- */
/* The info column deals one rhythm to its children. */
.gsl-pd__info {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--30);
}

.gsl-pd__info > * {
	margin-block: 0;
}

/* The price and the unit line share one row, on one baseline (owner,
   24.09.2026: under the price the line «з'їдає місце»). When the line
   does not fit beside the price it drops to the next row whole — a
   wrapping flex container places an item on a new line before it
   shrinks one — so the phone shows «34 ₴  за упаковку · 25 г · ≈95 шт ·
   ≈0,36 ₴/шт» on one line where it fits and on two where it does not. */
.gsl-pd__pricebox {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	gap: var(--wp--preset--spacing--10) var(--wp--preset--spacing--30);
}

.gsl-pd__pricebox > * {
	margin: 0;
}

.gsl-pd__price {
	font-size: var(--wp--preset--font-size--price-large);
	font-weight: 700;
	letter-spacing: -0.03em;
	line-height: 1.05;
	color: var(--wp--preset--color--ink);
}

/* The form as a small grid: the quantity label, the stepper with the
   running total beside it, and the button on its own row with the heart
   (Catalog\PdpQuantity prints the label and the total, Catalog\Wishlist
   appends the heart; the classes without the shop prefix are WooCommerce
   form chrome and are styled here, ADR 0018).

   The selectors are deliberately heavy: WooCommerce's own block stylesheet
   lays form.cart out as a grid of its own — «min-content auto auto», the
   button in column 2, everything else spanning — at (0,3,1), and only a
   heavier selector takes the layout back. */
.gsl-product .gsl-pd .gsl-pd__form form.cart {
	display: grid;
	grid-auto-flow: row;
	grid-template-columns: auto minmax(0, 1fr) auto;
	grid-template-areas:
		"label qty total"
		"buy buy heart";
	column-gap: var(--wp--preset--spacing--30);
	row-gap: var(--wp--preset--spacing--20);
	align-items: center;
	margin: 0;
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .qty-label {
	grid-area: label;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	white-space: nowrap;
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .quantity {
	grid-area: qty;
	display: flex;
	align-items: stretch;
	height: 48px;
	width: max-content;
	margin: 0;
	border: 1px solid var(--wp--preset--color--border-strong);
	border-radius: var(--wp--custom--radius--small);
	overflow: hidden;
	background: var(--wp--preset--color--base);
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .quantity .qty {
	box-sizing: border-box;
	width: 48px;
	margin: 0;
	padding: 0;
	text-align: center;
	border: 0;
	font: inherit;
	font-weight: 600;
	appearance: textfield;
}

.gsl-pd__form .quantity .qty::-webkit-outer-spin-button,
.gsl-pd__form .quantity .qty::-webkit-inner-spin-button {
	appearance: none;
	margin: 0;
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .quantity .qty-step {
	width: 40px;
	border: 0;
	background: var(--wp--preset--color--surface-soft);
	color: var(--wp--preset--color--brand-text);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	cursor: pointer;
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .quantity .qty-step:hover {
	background: var(--wp--preset--color--brand-wash);
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .qty-total {
	grid-area: total;
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.2;
	color: var(--wp--preset--color--muted);
}

/* One pack costs what the price says; the total only appears once there
   is something to add up (owner, 17.09.2026). */
.gsl-product .gsl-pd .gsl-pd__form form.cart > .qty-total[hidden] {
	display: none;
}

.gsl-pd__form .qty-total__sum {
	font-size: var(--wp--preset--font-size--price);
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--wp--preset--color--ink);
}

/* The buy button wears the storefront's gold (owner, 19.08.2026): every
   primary «купить» on this site is gold. Full width, the row's reason
   to exist; the wishlist heart — the one other button in the form — takes
   the cell beside it. */
.gsl-product .gsl-pd .gsl-pd__form form.cart > .single_add_to_cart_button {
	grid-area: buy;
	justify-self: stretch;
	width: 100%;
	min-height: 50px;
	margin: 0;
	padding-inline: var(--wp--preset--spacing--40);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	white-space: nowrap;
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > .single_add_to_cart_button:hover {
	background: var(--wp--preset--color--gold-hover);
	color: var(--wp--preset--color--ink);
}

.gsl-product .gsl-pd .gsl-pd__form form.cart > button:not(.single_add_to_cart_button) {
	grid-area: heart;
	justify-self: end;
}

/* --------------------------------------------------------------- desktop ---- */
/* The concept's desktop: the heading top right, the photo card on the left
   spanning down, the deal under the heading. The two WordPress columns
   become one grid; the gallery column dissolves so the heading can take the
   right-hand cell while the left column — the photo card with the trust
   tiles and the consultant under it — takes the left.

   Three rows, the last one flexible: core's columns stylesheet pins
   «align-items: normal !important» on the container, and a left column
   taller than heading + deal would otherwise hand its excess to both rows
   and push the deal 140px down from the heading. A flexible third row
   swallows the excess instead. */
@media (min-width: 782px) {
	.wp-block-columns.gsl-pd__top {
		display: grid;
		grid-template-columns: minmax(0, 46%) minmax(0, 1fr);
		grid-template-rows: auto auto 1fr;
		column-gap: var(--wp--preset--spacing--70);
		align-items: start;
	}

	.gsl-pd__top > .gsl-pd__gallery {
		display: contents;
	}

	.gsl-pd__heading {
		grid-column: 2;
		grid-row: 1;
	}

	.gsl-pd__left {
		grid-column: 1;
		grid-row: 1 / span 3;
		align-self: start;
		display: flex;
		flex-direction: column;
		gap: var(--wp--preset--spacing--40);
	}

	.gsl-pd__top > .gsl-pd__info {
		grid-column: 2;
		grid-row: 2;
	}
}

/* ----------------------------------------------------------------- phone ---- */
/* The first screen is dense on purpose (owner, 18.08.2026, kept on
   17.09.2026): name, article, photo, price, pack, facts, colours, quantity
   and the button must share one 844px viewport — the ad visitor decides
   here. 210px of photo with the quantity label inline is what fits. */
@media (max-width: 781px) {
	.gsl-pd__top {
		margin-block: var(--wp--preset--spacing--20) 0;
	}

	.gsl-product .wp-block-post-title {
		font-size: var(--wp--preset--font-size--price);
		line-height: 1.3;
	}

	/* Both wrappers dissolve into the columns' own flex flow, so the trust
	   group can step behind the deal with «order» while the markup keeps the
	   desktop's grouping. The row gap of the columns block spaces the four
	   items; the heading's own margin would double it. */
	.gsl-pd__top > .gsl-pd__gallery,
	.gsl-pd__gallery > .gsl-pd__left {
		display: contents;
	}

	.gsl-pd__gallery .gsl-pd__heading,
	.gsl-pd__gallery .gsl-pd__photo,
	.gsl-pd__gallery .gsl-pd__trust {
		flex: 0 0 100%;
		min-width: 0;
	}

	.gsl-pd__gallery .gsl-pd__trust {
		order: 1;
		gap: var(--wp--preset--spacing--20);
	}

	.gsl-pd__heading {
		margin-bottom: 0;
	}

	/* Edge to edge, as Rozetka, Kasta and AliExpress show a phone the photo:
	   the card's hairline and cushion go, the photo takes the whole 390 and
	   grows from 342×210 to 390×260 (sizes research, owner 24.09.2026). The
	   photo is a flex item of the columns row, so the width must be said
	   twice: the basis grows by two gutters and the margins pull it out. */
	.gsl-pd__gallery .gsl-pd__photo {
		flex-basis: calc(100% + 2 * var(--wp--custom--gutter));
		max-width: none;
		margin-inline: calc(-1 * var(--wp--custom--gutter));
		padding: 0 0 var(--wp--preset--spacing--20);
		border: 0;
		border-radius: 0;
	}

	.gsl-pd__photo .woocommerce-product-gallery__image img {
		max-height: 260px;
	}

	/* One scrollable row on the phone: ten photos must not cost two rows
	   of the first screen. */
	.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs {
		flex-wrap: nowrap;
		overflow-x: auto;
		scrollbar-width: none;
		padding: 0 var(--wp--custom--gutter) 2px;
	}

	.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs li {
		width: 44px;
		height: 44px;
	}

	/* No strip at all on the phone (owner, 29.09.2026): it cost ~110px and
	   pushed the buy button under the first screen for every product with
	   more than one photo. The photo says «1 / 10» and shows dots instead
	   (assets/js/gallery-count.js); swiping does the rest. */
	.gsl-product .gsl-pd .gsl-pd__gallery .gsl-pd__photo .flex-control-thumbs {
		display: none;
	}

	.gsl-pd__photo .gsl-pd__count {
		position: absolute;
		left: var(--wp--custom--gutter);
		bottom: var(--wp--preset--spacing--20);
		z-index: 2;
		display: block;
		padding: 4px 10px;
		border-radius: 999px;
		background: var(--wp--preset--color--contrast);
		color: var(--wp--preset--color--base);
		font-size: var(--wp--preset--font-size--small);
		font-weight: 600;
		line-height: 1.3;
		font-variant-numeric: tabular-nums;
		opacity: 0.85;
		pointer-events: none;
	}

	.gsl-pd__photo .gsl-pd__dots {
		position: absolute;
		left: 0;
		right: 0;
		bottom: calc(var(--wp--preset--spacing--20) + 9px);
		z-index: 1;
		display: flex;
		justify-content: center;
		gap: 6px;
		pointer-events: none;
	}

	.gsl-pd__photo .gsl-pd__dots[hidden] {
		display: none;
	}

	.gsl-pd__photo .gsl-pd__dots > span {
		width: 6px;
		height: 6px;
		border-radius: 50%;
		background: var(--wp--preset--color--border);
	}

	.gsl-pd__photo .gsl-pd__dots > .is-on {
		background: var(--wp--preset--color--contrast);
	}

	.gsl-product .gsl-crumbs {
		padding-block: var(--wp--preset--spacing--10);
		margin: 0;
	}

	.gsl-pd__info {
		margin-top: var(--wp--preset--spacing--30);
		gap: var(--wp--preset--spacing--20);
	}

	.gsl-pd__price {
		font-size: var(--wp--preset--font-size--large);
	}
}

/* ------------------------------ below the fold: two columns (14.09.2026) ---- */

/* Reviews, specifications and the story on the left; «Схожі товари» — the
   second chance for the shopper whose landing product missed — and the
   service accordions on the right, where half the desktop screen used to
   stand empty and the similar rows waited two screens down. The phone
   keeps one column in the same order; the blocks carry their own
   modifiers (gsl-sections--lower, gsl-similar--aside, gsl-service--aside)
   so each side styles only its own classes. */
.gsl-pd__lower {
	margin-top: var(--wp--preset--spacing--60);
	padding-top: var(--wp--preset--spacing--50);
	border-top: 1px solid var(--wp--preset--color--border);
}

@media (max-width: 781px) {
	.gsl-pd__lower {
		gap: var(--wp--preset--spacing--40);
	}
}
