/*
Theme Name: GSL
Theme URI: https://gsl.com.ua/
Author: GSL
Description: Блочная тема витрины gsl.com.ua. Палитра снята измерением с действующего сайта, раскладка — по образцу onlymoms.com.ua. Шрифт — Fixel самохостингом (см. docs/decisions/0024; правило «без вебшрифтов» отменено). См. docs/decisions/0011 и docs/design/tokens.md.
Version: 0.1.0
Requires at least: 6.7
Tested up to: 7.0
Requires PHP: 8.3
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: gsl
Tags: block-theme, e-commerce, full-site-editing
*/

/*
 * Base layer: everything that is on the page whatever the page is — utility bar,
 * header, USP strip, breadcrumbs, product card, pagination, footer.
 *
 * The rest of the storefront is split by context into assets/css — home,
 * catalog and product — of which functions.php enqueues exactly one. Two per
 * page, same as before the split; a category page simply stops carrying the hero
 * and the product page stops carrying the filter rail.
 *
 * Every colour, size, radius and gap below is a `--wp--preset--*` or
 * `--wp--custom--*` variable that theme.json defines. No literal hex, no literal
 * font size. tokens.md is the provenance table for all of them.
 */

/* Keyboard focus must always be visible — check 1 of the delivery list. */
:where(a, button, input, select, textarea, summary, [tabindex]):focus-visible {
	outline: 3px solid var(--wp--preset--color--brand-hover);
	outline-offset: 2px;
	border-radius: 4px;
}

/* No pointer means no hover, so nothing important may hide behind it, and every
   target has to reach 44 px. */
@media (hover: none) {
	:where(.wp-block-button__link, button, [role="button"]) {
		min-height: 44px;
	}
}

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

/* Prices and counts keep Fixel's own figures. Its tabular set is a different
   drawing — a barred 7 and a slashed 0 — and «278 ₴» read as a struck-out old
   price on every page (cart review, 29.09.2026). Proportional figures in a
   right-aligned column still end on the same edge. */
.gsl-num,
.wp-block-woocommerce-product-price,
.woocommerce-Price-amount {
	font-variant-numeric: normal;
}

/* Reserve the box before the image arrives. CLS is on the blocker list, and a
   catalogue page is mostly images. */
.gsl-thumb {
	aspect-ratio: 1;
	background: var(--wp--preset--color--surface);
}

.gsl-thumb img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* Wide content scrolls inside itself rather than dragging the page sideways. */
.gsl-scroll-x {
	overflow-x: auto;
	max-width: 100%;
}

/* ---------------------------------------------------------------- shared ---- */
.gsl-wrap {
	max-width: var(--wp--style--global--content-size, 1240px);
	margin-inline: auto;
	padding-inline: var(--wp--preset--spacing--50);
}

.gsl-icon {
	flex-shrink: 0;
}

.gsl-main {
	padding-block: var(--wp--preset--spacing--50) var(--wp--preset--spacing--60);
}

/* The page's bottom padding and the footer's top margin added up to 162 px
   of grey before the footer; the home page lost it on 23.09, every other
   page on 29.09. The footer's shadow marks the edge by itself. */
main.gsl-main + footer .gsl-foot {
	margin-top: 0;
}

/* The gutter is one dial, and the phone turns it down. 24px between the
   screen edge and the first card cost a tenth of the card's width on a
   390px screen; 16px is what the platforms ask for and what the market
   holds (owner, 19.09). Root padding, the full-bleed negative margins
   WordPress derives from it, and the rail all read this one token. */
@media (max-width: 640px) {
	:root {
		--wp--custom--gutter: 16px;
	}
}

/* --------------------------------------------------------------- 404 ------
 *
 * The one page nobody designs and everybody sees. It carries three offers, in
 * the order they are useful after an address stops working: the search — because
 * the article number survived the migration and is the thing a customer already
 * has written down — a way back, and the sections of the catalogue.
 *
 * The sections are `gsl/category-tiles`, the same block the front page uses, and
 * not `woocommerce/product-categories`: that one prints every one of the 194
 * terms as a flat bulleted list with counts in brackets, which on this catalogue
 * is a screen and a half of links under a heading that says something went
 * wrong.
 */
.gsl-404__lead {
	max-width: 60ch;
	color: var(--wp--preset--color--muted);
}

.gsl-404__go {
	margin-bottom: var(--wp--preset--spacing--70);
	gap: var(--wp--preset--spacing--30);
}

.gsl-404__head {
	margin-bottom: var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--ink);
}

/* ----------------------------------------------------------- utility bar ---- */
.gsl-util {
	color: var(--wp--preset--color--brand-light);
	font-size: var(--wp--preset--font-size--small);
}

.gsl-util > .wp-block-group {
	min-height: 38px;
	align-items: center;
}

.gsl-util p {
	margin: 0;
}

.gsl-util a {
	color: inherit;
	text-decoration: none;
}

.gsl-util a:hover {
	color: var(--wp--preset--color--base);
}

.gsl-util__links {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--40);
	margin-left: auto;
}

/* ---------------------------------------------------------------- header ---- */
.gsl-head {
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.gsl-head__row {
	gap: var(--wp--preset--spacing--40);
	min-height: 78px;
	align-items: center;
}

.gsl-logo {
	gap: var(--wp--preset--spacing--30);
	flex-shrink: 0;
	flex-direction: column;
	align-items: flex-start !important;
	row-gap: 0;
}

/* The wordmark is inside the image, so the site title is not printed a second
   time next to it. It still exists as the `alt`, which is what a screen reader
   and a search engine read — and it is set on the attachment rather than taken
   from the site name, because on the stand that name carries «(staging)». */
.gsl-logo__mark {
	line-height: 0;
}

.gsl-logo__mark img {
	display: block;
	height: auto;
	max-width: 100%;
}

.gsl-logo__tagline {
	color: var(--wp--preset--color--muted);
	letter-spacing: 0.04em;
	margin: 0;
}

/* Search sits between the catalogue button and the cart, and takes what is left.
   It was not taking it: `.gsl-head__acts` carried `margin-left: auto`, and an
   auto margin absorbs the row's free space *before* `flex-grow` gets to divide
   it — so the field stayed at its 220 px floor with 500 px of blank header to
   its right. The actions are pushed over by this `flex: 1` alone. */
.gsl-search {
	flex: 1;
	min-width: 320px;
	margin: 0;
}

/* Three nested boxes, and each one has to be told to grow. The block renders
   `div.gsl-search > form > div.__fields > input + button`, and the middle
   wrapper defaults to `flex: 0 1 auto`: the outer div stretched across the
   header while the field inside stayed at its 250 px content width, which is why
   widening the search looked like it had done nothing. */
.gsl-search .wc-block-product-search__fields,
.gsl-search form {
	display: flex;
	/* No fixed height: the 44px box was 2px shorter than the bordered pill
	   inside it, and the mobile overflow clip shaved the pill bottom border
	   off - the «нижня смужка» the owner kept photographing (14.08). The
	   input still sets the pace; the wrapper follows it. */
	height: auto;
}

.gsl-search .wc-block-product-search__fields {
	flex: 1;
	min-width: 0;
}

.gsl-search input[type="search"] {
	flex: 1;
	min-width: 0;
	height: 44px;
	border: 1.5px solid var(--wp--preset--color--border-strong);
	border-right: 0;
	border-radius: var(--wp--custom--radius--pill) 0 0 var(--wp--custom--radius--pill);
	padding-inline: var(--wp--preset--spacing--40);
	font: inherit;
	background: var(--wp--preset--color--base);
}

.gsl-search input[type="search"]::placeholder {
	color: var(--wp--preset--color--muted);
}

.gsl-search input[type="search"]:focus {
	border-color: var(--wp--preset--color--brand);
}

/* `form > button`, not `button`. The bare selector meant «every button that
   ever lands inside the search block», and one did: the plugin's suggestion
   panel prints «Показати все за запитом …» at the foot of its list. It came out
   52 px wide with a brand-coloured background, one word per line, because
   `.gsl-search button` (0,1,1) outranks `.gsl-suggest__all` (0,1,0).
   The rule means the magnifier, so it says the magnifier — the panel is a
   sibling of the form, not a child of it. */
.gsl-search form > button,
.gsl-search .wc-block-product-search__fields > button {
	/* Variant В of the search study (owner, 14.08): the button wears the
	   same gold as «Додати в кошик» - the header starts speaking the
	   storefront's language, and the magnifier says «find» where the old
	   chevron said «go». */
	width: 58px;
	border: 0;
	border-radius: 0 var(--wp--custom--radius--pill) var(--wp--custom--radius--pill) 0;
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--ink);
	cursor: pointer;
	display: grid;
	place-items: center;
	transition: background-color 0.12s;
}

.gsl-search form > button:hover,
.gsl-search .wc-block-product-search__fields > button:hover {
	background: var(--wp--preset--color--gold-hover);
	color: var(--wp--preset--color--ink);
}

/* Whatever holds this may not be a constrained layout. WordPress gives every
   direct child of one `margin-left: auto !important; margin-right: auto
   !important`, so a capped width centres itself and lands out of line with the
   heading above — and `!important` there means no declaration of ours can talk
   it out of it. The 404 wraps this in a flow group for exactly that reason. */
.gsl-search.is-standalone {
	max-width: 520px;
	margin-block: var(--wp--preset--spacing--50);
}

.gsl-head__acts {
	gap: var(--wp--preset--spacing--20);
	flex-shrink: 0;
}

.gsl-head__acts a,
.gsl-head__acts button {
	color: var(--wp--preset--color--contrast);
}

/* The two header actions are deliberately not the same shape. Account is a bare
   46 px icon target that only fills in on hover; the cart is a filled pill,
   because it is the one control that carries a number and has to be findable
   without reading. Giving both a border and a background made them read as two
   boxes of mismatched width — the same control, drawn twice, badly.
   The account half of that pair now lives in the plugin, with the block that
   prints it: blocks/account-panel/style.css. */
.gsl-cart .wc-block-mini-cart__button {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--20);
	height: 46px;
	padding-inline: var(--wp--preset--spacing--40) var(--wp--preset--spacing--30);
	border: 0;
	border-radius: var(--wp--custom--radius--medium);
	background: var(--wp--preset--color--surface);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

.gsl-cart .wc-block-mini-cart__button:hover {
	background: var(--wp--preset--color--hairline);
}

.gsl-cart .wc-block-mini-cart__quantity-badge {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--contrast);
}

/* ------------------------------------------------------------ cart drawer ---
 *
 * The cart that slides in from the right, dressed. It stays a drawer rather than
 * becoming a centred window like the login panel, and that is on purpose: this
 * one is a list that can run to twenty rows and needs the full height of the
 * screen, and on a phone a full-height sheet is the shape that works. The login
 * panel is four controls and would look lost in it.
 *
 * These rules live in the base stylesheet, not in assets/css/cart.css, because
 * the drawer opens from the header — that is, on every page — and cart.css is
 * only enqueued where `is_cart()`. A stepper that is styled on the cart page and
 * bare in the drawer is the kind of defect that only shows up after the second
 * click.
 */
.wc-block-components-drawer__screen-overlay {
	background: color-mix(in srgb, var(--wp--preset--color--ink) 50%, transparent);
}

.wc-block-components-drawer__screen-overlay .wc-block-components-drawer {
	border-left: 0;
	background: var(--wp--preset--color--base);
	box-shadow: -30px 0 60px -30px color-mix(in srgb, var(--wp--preset--color--ink) 60%, transparent);
}

.wc-block-mini-cart__title {
	align-items: baseline;
	gap: var(--wp--preset--spacing--20);
	padding-bottom: var(--wp--preset--spacing--40);
	border-bottom: 1px solid var(--wp--preset--color--hairline);
	color: var(--wp--preset--color--ink);
}

/* The count is context, not a heading. WooCommerce's Ukrainian catalogue renders
   it as «(елементи: 2)», which is theirs to translate and ours to stop shouting. */
.wp-block-woocommerce-mini-cart-title-items-counter-block {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
	color: var(--wp--preset--color--muted);
}

/* Four classes and an element to clear WooCommerce's own
   `table.wc-block-cart-items .wc-block-cart-items__row .X` at (0,3,1), and
   scoped to `.wc-block-mini-cart-items` so the cart page keeps its own layout. */
table.wc-block-cart-items.wc-block-mini-cart-items .wc-block-cart-items__row {
	border-bottom: 1px solid var(--wp--preset--color--hairline);
}

table.wc-block-cart-items.wc-block-mini-cart-items .wc-block-cart-items__row .wc-block-cart-item__image img {
	aspect-ratio: 1;
	object-fit: contain;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--surface);
}

table.wc-block-cart-items.wc-block-mini-cart-items .wc-block-cart-items__row .wc-block-components-product-name {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* The short description of a product is a paragraph, and a paragraph per row
   turns a four-item cart into a wall of text — the name and the price are what
   a person checks here. The line under it stays: that is the plugin's article
   number and per-piece price, which is the one thing this catalogue is bought by. */
.wc-block-mini-cart-items .wc-block-components-product-metadata__description {
	display: none;
}

.wc-block-mini-cart-items .wc-block-components-product-metadata {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

/* Two prices per row: the pack price under the name and the line total on the
   right. At one item they are the same number twice, which reads as a mistake —
   so the left one is muted into what it actually is, the price of one pack, and
   the right one carries the weight. Removing it instead would leave a row of
   «202,82 ₴» with nothing saying what a single pack costs. */
table.wc-block-cart-items.wc-block-mini-cart-items .wc-block-cart-items__row .wc-block-cart-item__prices {
	color: var(--wp--preset--color--muted);
}

table.wc-block-cart-items.wc-block-mini-cart-items .wc-block-cart-items__row .wc-block-cart-item__total {
	font-weight: 700;
	color: var(--wp--preset--color--ink);
}

/* Quantity stepper. Shared with the cart page on purpose — same control, one
   description of it, and the drawer would otherwise be the only place it is
   drawn bare. 38 px with a pointer, 44 where there is none: check 2 of the
   delivery list in tokens.md. */
.wc-block-components-quantity-selector {
	border: 1px solid var(--wp--preset--color--border-strong);
	border-radius: var(--wp--custom--radius--small);
	height: 38px;
}

.wc-block-components-quantity-selector input {
	color: var(--wp--preset--color--contrast);
}

.wc-block-mini-cart__footer {
	padding-top: var(--wp--preset--spacing--40);
	border-top: 1px solid var(--wp--preset--color--hairline);
}

.wc-block-mini-cart__footer-subtotal .wc-block-components-totals-item__label {
	color: var(--wp--preset--color--muted);
}

.wc-block-mini-cart__footer-subtotal .wc-block-components-totals-item__value {
	font-size: var(--wp--preset--font-size--price);
	font-weight: 700;
	letter-spacing: -0.028em;
	color: var(--wp--preset--color--ink);
}

/* Two buttons, one row, equal width — «переглянути» and «оформити» are a pair,
   and the checkout half is the one that carries the shop's action colour from
   theme.json. Stacked below 380 px, where two of them side by side leave four
   characters each. */
.wc-block-mini-cart__footer-actions {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
	gap: var(--wp--preset--spacing--30);
}

.wc-block-mini-cart__footer-cart,
.wc-block-mini-cart__footer-checkout {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 48px;
	border-radius: var(--wp--custom--radius--small);
	text-align: center;
}

@media (hover: none) {
	.wc-block-components-quantity-selector {
		height: 44px;
	}
}

.gsl-crumbs {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	padding-block: var(--wp--preset--spacing--40);
}

/* ---------------------------------------------------------- product card ---- */
.gsl-grid {
	gap: var(--wp--preset--spacing--30) !important;
}

.gsl-grid > li,
.gsl-grid > .wc-block-product {
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--medium);
	overflow: hidden;
	display: flex;
	flex-direction: column;
	transition: border-color 0.12s, box-shadow 0.12s;
}

.gsl-grid > li:hover,
.gsl-grid > .wc-block-product:hover {
	border-color: var(--wp--preset--color--brand-light);
	box-shadow: 0 10px 24px -18px color-mix(in srgb, var(--wp--preset--color--ink) 50%, transparent);
}

/* The square is a promise, not a preference. `aspect-ratio` alone only sets the
   preferred size: this is a flex item in a column card, so its `min-height: auto`
   lets anything inside push it taller, and the product image block puts an `<a>`
   between the box and the `<img>` — a link with no height of its own, against
   which the image's `height: 100%` resolves to `auto` and the image falls back to
   its intrinsic size. A portrait photograph then made one card several times
   taller than the one beside it, which is what the catalogue looked like on a
   phone once real photographs replaced the 300x300 placeholder. Three
   declarations close it: the floor, the link, and the clip. */
.gsl-card__img {
	position: relative;
	aspect-ratio: 1;
	min-height: 0;
	overflow: hidden;
	background: var(--wp--preset--color--surface);
	border-bottom: 1px solid var(--wp--preset--color--hairline);
	display: grid;
	place-items: center;
	margin: 0;
}

.gsl-card__img a,
.gsl-card__img .wc-block-components-product-image {
	display: block;
	width: 100%;
	height: 100%;
}

.gsl-card__img img {
	width: 100%;
	height: 100%;
	object-fit: contain;
}

.gsl-card__body {
	padding: var(--wp--preset--spacing--30);
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	flex: 1;
}

/* Article number and availability share one line under the name. They are the
   two facts a buyer checks second, and stacking them cost two rows of card
   height that the photograph wants more. */
.gsl-card__meta {
	gap: var(--wp--preset--spacing--20) !important;
	min-height: 20px;
}

.gsl-card__sku {
	font-family: var(--wp--preset--font-family--mono);
	color: var(--wp--preset--color--muted);
	letter-spacing: 0.02em;
	margin: 0;
}

/* Name first, and clamped to three lines.

   First, because the article number read above it — «ДК0015в15» — answers a
   question nobody asks before knowing what the thing is; it stays on the card
   because reorders are placed by it, just not in the position of a headline.

   Clamped, because names in this catalogue run to six words of attributes and
   an unclamped card grew a row taller than the one beside it. Three lines is
   where the longest names in the export stop needing a fourth. `min-height`
   reserves the space whether or not the name uses it, which is what puts every
   price and every button in a row on the same line. */
.gsl-card__name {
	line-height: 1.35;
	font-weight: 500;
	margin: 0;
	/* The reserve, so a short name holds the same space as a long one and the
	   cards of a row end level. The clamp itself lives on the link below. */
	min-height: calc(3 * 1.35em);
}

/* The clamp cannot sit on the heading: the heading is a flex item of the card's
   column, and a flex item's `display` is blockified — `-webkit-box` computed to
   `flow-root` and the limit did nothing, which is why names ran to six lines on
   the live site while the stylesheet said three. The link inside is an ordinary
   inline box and clamps as asked. */
.gsl-card__name a {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
}

.gsl-card__name a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.gsl-card__name a:hover {
	color: var(--wp--preset--color--brand-text);
}

.gsl-card__stock {
	font-weight: 600;
	margin: 0;
	margin-left: auto;
	white-space: nowrap;
}

.gsl-card__stock .wc-block-components-product-stock-indicator--in-stock,
.gsl-card__stock.wc-block-components-product-stock-indicator--in-stock {
	color: var(--wp--preset--color--in-stock);
}

.gsl-card__stock.wc-block-components-product-stock-indicator--low-stock {
	color: var(--wp--preset--color--gold-text);
}

.gsl-card__stock.wc-block-components-product-stock-indicator--out-of-stock {
	color: var(--wp--preset--color--muted);
}

/* The price row: the price, and beside it the plugin's quiet «≈0,43/шт»
   (owner, 21.09.2026). The row is what carries the auto margin now, and the
   price sits at its baseline — before this the price itself was pushed to the
   bottom of the card, so a card without a per-piece line had its price sink
   while its neighbour's stayed put. */
.gsl-card__pricerow {
	gap: 0 6px !important;
	align-items: baseline;
	margin-top: auto;
}

.gsl-card__price {
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--wp--preset--color--ink);
}

.gsl-card__price del {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
	font-weight: 400;
}

/* The sale price WooCommerce wraps in <ins>. The browser default underline
   reads as a link on a price; the colour is what actually says «reduced». */
.gsl-card__price ins {
	text-decoration: none;
	color: var(--wp--preset--color--sale);
}

/* The stepper printed by `Catalog\CardQuantity` lands inside this wrapper, so
   the wrapper becomes the row that holds both. WooCommerce's own rule is
   `flex-direction: column` at (0,2,0); three classes here outrank it.

   `flex-wrap` matters on a 145 px phone card, where a labelled button will not
   fit beside the stepper and drops to its own line instead of squeezing the
   label to one character per row. */
.wp-block-button.wc-block-components-product-button.gsl-card__buy {
	flex-direction: row;
	flex-wrap: nowrap;
	align-items: stretch;
	gap: var(--wp--preset--spacing--20);
	margin-top: var(--wp--preset--spacing--20);
}

/* Selector shaped to beat WooCommerce's own, not by accident. Its
   `.wp-block-button.wc-block-components-product-button .wp-block-button__link`
   is (0,3,0) and sets `width: auto`, so a plain `.gsl-card__buy button` (0,1,1)
   lost the width and kept the `padding: 0` — which is how the label ended up
   touching both edges of a button shrink-wrapped around it. Four classes puts
   this at (0,4,0) and the two properties stop disagreeing.

   `flex: 1` rather than `width: 100%`: the button now shares its line with the
   stepper, and a hard 100% would push the stepper out of the card.

   Padding stays even though the button fills its share: it is what the label
   wraps against on a 145 px phone card, and `white-space: normal` there is
   theirs. */
.wp-block-button.wc-block-components-product-button.gsl-card__buy a,
.wp-block-button.wc-block-components-product-button.gsl-card__buy button,
.wp-block-button.wc-block-components-product-button.gsl-card__buy .wp-block-button__link {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: 1 1 0;
	min-width: 0;
	min-height: 40px;
	padding-block: 0;
	padding-inline: var(--wp--preset--spacing--20);
	border-radius: var(--wp--custom--radius--small);
	line-height: 1.2;
}

/* «Переглянути кошик» appears after a successful add. It is a sibling of the
   button inside the same row, so without this it would try to sit beside the
   stepper on a line with no space left. */
.wp-block-button.wc-block-components-product-button.gsl-card__buy > span,
.wp-block-button.wc-block-components-product-button.gsl-card__buy .added_to_cart {
	flex: 1 0 100%;
	text-align: center;
	font-size: var(--wp--preset--font-size--small);
}

.gsl-stk {
	position: absolute;
	top: var(--wp--preset--spacing--20);
	left: var(--wp--preset--spacing--20);
	z-index: 2;
	background: var(--wp--preset--color--sale);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	padding: 3px 8px;
	border-radius: 4px;
}

/* ------------------------------------------------------------ pagination ---- */
.gsl-pager {
	gap: var(--wp--preset--spacing--20);
	padding-top: var(--wp--preset--spacing--70);
}

/* The numbered links come wrapped in their own div
   (`.wp-block-query-pagination-numbers`), a sibling of prev/next inside
   `.gsl-pager`. That div is not itself a flex container, so without this its
   `display: grid` children below stack one per line instead of running
   alongside prev/next. */
.gsl-pager .wp-block-query-pagination-numbers {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--20);
}

.gsl-pager a,
.gsl-pager span {
	min-width: 38px;
	height: 38px;
	padding-inline: var(--wp--preset--spacing--30);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--small);
	display: grid;
	place-items: center;
	text-decoration: none;
	font-weight: 500;
}

.gsl-pager a:hover {
	border-color: var(--wp--preset--color--brand);
	color: var(--wp--preset--color--brand-text);
}

.gsl-pager .page-numbers.current {
	background: var(--wp--preset--color--ink);
	border-color: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
	font-weight: 700;
}

/* ---------------------------------------------------------------- footer ---- */
/* The footer casts upward, so the page above it reads as a sheet the content
   scrolls under rather than as a block that simply ends. The shadow is drawn
   outside the element, onto the white above it — an inset one would be invisible,
   because a dark shadow on the ink background has nothing to darken. */
.gsl-foot {
	color: var(--wp--preset--color--brand-light);
	margin-top: var(--wp--preset--spacing--80);
	padding-block: var(--wp--preset--spacing--80) 0;
	font-size: var(--wp--preset--font-size--base);
	box-shadow: 0 -4px 20px -4px color-mix(in srgb, var(--wp--preset--color--ink) 42%, transparent);
	position: relative;
	z-index: 1;
}

.gsl-foot__grid {
	gap: var(--wp--preset--spacing--70);
	padding-bottom: var(--wp--preset--spacing--70);
}

.gsl-foot a {
	color: inherit;
	text-decoration: none;
}

.gsl-foot a:hover {
	color: var(--wp--preset--color--base);
	text-decoration: underline;
}

.gsl-foot__name a,
.gsl-foot__name {
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--price);
	font-weight: 700;
	text-decoration: none;
}

.gsl-foot__head {
	color: var(--wp--preset--color--base) !important;
	font-size: var(--wp--preset--font-size--base) !important;
	margin: 0 0 var(--wp--preset--spacing--30);
}

.gsl-foot__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
}

.gsl-foot__addr,
.gsl-foot__contacts {
	margin-block: var(--wp--preset--spacing--30) 0;
	line-height: 1.6;
}

.gsl-foot__phone {
	margin-block: var(--wp--preset--spacing--30) 0;
	font-weight: 600;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--base);
}

/* The working hours are three lines, not the seven of the old shop's table: five
   of those seven said 10:00–18:00, and repeating the same value five times is how
   a reader stops reading the column. Thursday and the weekend are the whole
   content, so they are what the eye has to land on. */
.gsl-foot__hours {
	gap: var(--wp--preset--spacing--20) var(--wp--preset--spacing--60);
	align-items: baseline;
	padding-bottom: var(--wp--preset--spacing--60);
}

.gsl-foot__hours .gsl-foot__head {
	margin: 0;
	flex-basis: 100%;
}

.gsl-foot__hours p {
	margin: 0;
}

.gsl-foot__bottom {
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--base) 12%, transparent);
	padding-block: var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--brand);
}

.gsl-foot__bottom p {
	margin: 0;
}

/* ------------------------------------------------------------- to the top --- */

/* Fixed rather than sticky at the end of the footer: it is worth having halfway
   down a category of 2 410 products, not only once the visitor has already
   reached the bottom. `hidden` is the resting state and JavaScript removes it, so
   without scripts there is no button rather than a dead one. */
.gsl-totop {
	position: fixed;
	right: var(--wp--preset--spacing--50);
	bottom: var(--wp--preset--spacing--50);
	z-index: 30;
	width: 46px;
	height: 46px;
	display: grid;
	place-items: center;
	border: 0;
	border-radius: 50%;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 82%, transparent);
	color: var(--wp--preset--color--base);
	cursor: pointer;
	box-shadow: 0 6px 18px -6px color-mix(in srgb, var(--wp--preset--color--ink) 60%, transparent);
	transition: background-color 0.14s, transform 0.14s;
}

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

.gsl-totop:hover {
	background: var(--wp--preset--color--ink);
	transform: translateY(-2px);
}

@media (max-width: 860px) {
	.gsl-foot__grid {
		grid-template-columns: 1fr 1fr;
	}

	.gsl-util > .wp-block-group {
		overflow-x: auto;
	}
}

@media (max-width: 640px) {
	.gsl-head__row {
		min-height: 0;
		padding-block: var(--wp--preset--spacing--30);
	}

	/* Full width on its own line, so the 320 px floor that keeps the field usable
	   on a desktop header has nothing left to do — and on a 320 px phone it would
	   be the one thing pushing the page wider than the screen. */
	.gsl-search {
		order: 9;
		flex-basis: 100%;
		min-width: 0;
	}

	/* A phone shows two cards side by side at about 165 px each, and at that width
	   the card is mostly chrome: the same padding, the same gaps and the same
	   40 px button as a 285 px card, stacked into a column that scrolls forever.
	   The picture keeps its square — it is what the product is recognised by —
	   and everything under it tightens. */
	.gsl-card__body {
		padding: var(--wp--preset--spacing--20);
		gap: var(--wp--preset--spacing--10);
	}

	/* Two lines, then an ellipsis. Names here run to eight words, and one card
	   wrapping to four lines sets the height of every card in its row. The
	   reserved height comes down with the clamp — left at the desktop's three
	   lines it would hold open a row the name no longer fills. */
	/* Four lines on a phone, not two (owner, 21.09.2026). The names here carry
	   the size and the colour at the end — «…19х3 мм 1 пара Платина» — and a
	   two-line limit hid that tail on nine names out of ten: only 9% of the
	   catalogue fits two lines, 94% fits four. */
	.gsl-card__name {
		min-height: calc(4 * 1.35em);
	}

	.gsl-card__name a {
		-webkit-line-clamp: 4;
		line-clamp: 4;
	}

	/* The button keeps its height: 44 px is the touch target from the delivery
	   list, and a card that scrolls a little longer is cheaper than one nobody can
	   hit. Only the side padding narrows, which is all this needs — the label is
	   14 px here and cannot be talked out of it from a stylesheet, because the
	   block carries `has-base-font-size` and WordPress prints every preset
	   font-size class with `!important`. Changing it means changing the block's
	   `fontSize` attribute in the template, on every viewport at once. */
	.wp-block-button.wc-block-components-product-button.gsl-card__buy a,
	.wp-block-button.wc-block-components-product-button.gsl-card__buy button,
	.wp-block-button.wc-block-components-product-button.gsl-card__buy .wp-block-button__link {
		padding-inline: var(--wp--preset--spacing--20);
		min-height: 44px;
	}

	/* The stepper claims the whole line at this width (its own stylesheet says
	   so), so the row has to be allowed to break. Without this the button would
	   be squeezed to nothing beside a 100% sibling that cannot shrink. */
	.wp-block-button.wc-block-components-product-button.gsl-card__buy {
		flex-wrap: wrap;
	}

	.gsl-grid {
		gap: var(--wp--preset--spacing--20) !important;
	}
}

/* Touch: no hover exists, so nothing may hide behind it and every target has to
   reach 44 px. Check 2 of the delivery list in tokens.md. */
@media (hover: none) {
	.gsl-pager a,
	.gsl-pager span {
		min-width: 44px;
		height: 44px;
	}

	/* Same four-class shape as the base rule above, and for a second reason: at
	   (0,1,1) this would now lose to our own (0,4,0) declaration and the touch
	   target would silently go back to 40 px. */
	.wp-block-button.wc-block-components-product-button.gsl-card__buy a,
	.wp-block-button.wc-block-components-product-button.gsl-card__buy button,
	.wp-block-button.wc-block-components-product-button.gsl-card__buy .wp-block-button__link {
		height: 46px;
	}
}

/* ------------------------------------------------- compact mobile header ----
   One icon row and one slim search line, six stacked rows before it. The
   reference is the owner's green-circled screenshot of onlymoms: burger,
   logo, then the actions, all on a single 56 px line. */

.gsl-head__phone {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: var(--wp--custom--radius--small);
	color: var(--wp--preset--color--ink);
}

.gsl-head__phone:hover {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--brand-text);
}

@media (max-width: 640px) {
	/* The schedule is contacts-page material; on a phone the top strip keeps
	   only what gets tapped: the delivery links and the language. */
	.gsl-util__item {
		display: none;
	}

	.gsl-util > .wp-block-group {
		flex-wrap: nowrap;
	}

	/* Burger before logo — the order of the reference, not of the markup. The
	   child is addressed by position, not by the plugin's class name: the
	   theme does not get to know it (ADR 0018), but it owns this container
	   and may seat its children. */
	.gsl-head__row {
		flex-wrap: wrap;
		column-gap: var(--wp--preset--spacing--10);
	}

	.gsl-head__row > :nth-child(2) {
		order: -1;
	}

	.gsl-logo__mark img {
		max-width: 84px;
		height: auto;
	}

	.gsl-logo__tagline {
		display: none;
	}

	.gsl-head__acts {
		gap: var(--wp--preset--spacing--10);
	}
}

/* Second pass after the 390 px screenshot: the links strip was wrapping
   internally, and the cart's running total was the 50 px that pushed the
   actions off the icon row. The total belongs to the drawer; the badge with
   the count stays. */
@media (max-width: 640px) {
	.gsl-util__links {
		white-space: nowrap;
	}

	.gsl-cart .wc-block-mini-cart__amount {
		display: none;
	}

	.gsl-logo__mark img {
		max-width: 84px;
	}
}

/* The links strip is a wrapping flex of its own (base rule above) — nowrap
   there was the missing half of keeping the top strip to one line. */
@media (max-width: 640px) {
	.gsl-util__links {
		flex-wrap: nowrap;
		gap: var(--wp--preset--spacing--30);
	}
}
/* ================================================================ v2 ====
   The owner's prototype (gsldesignv2.html), applied as a cascade layer at
   the end of the file: same selectors, later position, so these rules win
   without touching the originals. The prototype's palette is this theme's
   own tokens retuned in theme.json — nothing here names a colour.

   The shift in one sentence: the page ground goes grey, the cards go white
   and drop their borders for shadows, and everything clickable becomes a
   pill. */

body {
	background: var(--wp--preset--color--surface);
}

/* Header: white card on the grey page. */
.gsl-head {
	box-shadow: 0 2px 10px color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
	position: relative;
	z-index: 40;
}

/* Variant B of the search study (owner, 14.08): the ring quiets to a
   hairline, the cap turns the storefront gold and says «find» with a
   magnifier; focus brings the teal back on the ring. */
.gsl-search .wc-block-product-search__fields {
	border: 1.5px solid var(--wp--preset--color--border-strong);
	border-radius: var(--wp--custom--radius--pill);
	/* Visible, and it is load-bearing: this row is the positioned ancestor of
	   the plugin's suggestion panel, and `hidden` left the panel «open» in the
	   DOM but clipped to the 46px pill (CDP-геометрия, 24.08). The clip was
	   only ever for the gold cap's corners, and the cap rounds itself. */
	overflow: visible;
	background: var(--wp--preset--color--base);
	transition: border-color 0.12s;
}

.gsl-search .wc-block-product-search__fields:focus-within {
	border-color: var(--wp--preset--color--brand);
}

.gsl-search input[type="search"] {
	border: 0;
	border-radius: 0;
	background: transparent;
}

.gsl-search input[type="search"]:focus {
	outline: none;
	box-shadow: none;
}

/* The cap rounds itself since the wrapper stopped clipping (24.08, the
   suggestion panel). With a bare 0 here the gold block showed two square
   corners inside the pill — the owner circled them on a phone (17.09). The
   radius is the pill minus the wrapper border, so the curve nests inside the
   ring instead of poking past it. */
.gsl-search form > button,
.gsl-search .wc-block-product-search__fields > button {
	border-radius: 0 calc(var(--wp--custom--radius--pill) - 1.5px) calc(var(--wp--custom--radius--pill) - 1.5px) 0;
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--ink);
}

.gsl-search form > button:hover,
.gsl-search .wc-block-product-search__fields > button:hover {
	background: var(--wp--preset--color--gold-hover);
}

/* Round icon buttons on a teal wash — cart, account, phone. */
.gsl-head__phone,
.gsl-head__acts a,
.gsl-head__acts button,
.gsl-cart .wc-block-mini-cart__button {
	border-radius: 50%;
	background: var(--wp--preset--color--brand-wash);
	color: var(--wp--preset--color--ink);
}

/* Product card: shadow instead of border, and a lift on hover. */
.gsl-grid > li,
.gsl-grid > .wc-block-product {
	border: 0;
	border-radius: var(--wp--custom--radius--medium);
	background: var(--wp--preset--color--base);
	box-shadow: 0 2px 10px color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
	transition: box-shadow 0.15s, transform 0.15s;
}

.gsl-grid > li:hover,
.gsl-grid > .wc-block-product:hover {
	border: 0;
	box-shadow: 0 8px 22px color-mix(in srgb, var(--wp--preset--color--ink) 15%, transparent);
	transform: translateY(-3px);
}

.gsl-card__img {
	background: var(--wp--preset--color--base);
	border-bottom: 0;
}

/* The buy button becomes the gold pill. */
.wp-block-button.wc-block-components-product-button.gsl-card__buy a,
.wp-block-button.wc-block-components-product-button.gsl-card__buy button,
.wp-block-button.wc-block-components-product-button.gsl-card__buy .wp-block-button__link {
	border-radius: var(--wp--custom--radius--pill);
	font-weight: 700;
	/* No browser double-tap zoom on the buy control (owner hit it live). */
	touch-action: manipulation;
}

/* Badges: pill-shaped, as in the prototype's flags row. */
.gsl-stk {
	border-radius: var(--wp--custom--radius--pill);
	padding: 3px 10px;
}

/* Toolbar controls join the pill family. */
.gsl-toolbar {
	border-block: 0;
}

.gsl-toolbar__sort select {
	border-radius: var(--wp--custom--radius--pill);
	background-color: var(--wp--preset--color--base);
}

/* Pagination: white shadow tiles, the current page in deep teal. */
.gsl-pager a,
.gsl-pager span {
	background: var(--wp--preset--color--base);
	box-shadow: 0 2px 10px color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
	border-radius: var(--wp--custom--radius--small);
	border: 0;
}

.gsl-pager .current {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--base);
}

/* Filters rail: one white card holding the groups. Desktop only — on the
   phone the column holds just the filter bar, and a card around two pills
   was the tallest empty thing on the page (owner's red pen, 19.08). */
@media (min-width: 641px) {
	.gsl-aside {
		background: var(--wp--preset--color--base);
		border-radius: var(--wp--custom--radius--medium);
		box-shadow: 0 2px 10px color-mix(in srgb, var(--wp--preset--color--ink) 8%, transparent);
		padding: var(--wp--preset--spacing--40);
	}
}
/* ---------------------------------------------------------------- v2b ----
   The prototype's remaining chrome: the phone block beside the search, the
   teal category bar under the header, the pictogram squares on the tiles,
   the cart glyph on the buy pill, and the fixed bottom bar on phones. */

/* Phone block: two lines, right-aligned, desktop only. It takes the auto
   margin the actions group used to hold, so the pair sit together at the
   right edge of the row. */
.gsl-hphone {
	margin-left: auto;
	text-align: right;
	text-decoration: none;
	line-height: 1.35;
}

.gsl-hphone span {
	display: block;
	font-size: var(--wp--preset--font-size--label);
	color: var(--wp--preset--color--muted);
}

.gsl-hphone b {
	color: var(--wp--preset--color--contrast);
	white-space: nowrap;
}

.gsl-head__row .gsl-head__acts {
	margin-left: 0;
}

@media (max-width: 1024px) {
	.gsl-hphone {
		display: none;
	}

	.gsl-head__row .gsl-head__acts {
		margin-left: auto;
	}
}

/* The round phone icon is the mobile stand-in for the block above. */
@media (min-width: 641px) {
	.gsl-head__phone {
		display: none;
	}
}

/* Category bar: the prototype's teal nav strip. */
.gsl-mainnav {
	background: var(--wp--preset--color--brand-action);
}

.gsl-mainnav__in {
	max-width: var(--wp--style--global--wide-size, 1200px);
	margin: 0 auto;
	display: flex;
	flex-wrap: wrap;
}

.gsl-mainnav a {
	display: block;
	color: var(--wp--preset--color--base);
	padding: 12px 15px;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	text-decoration: none;
}

.gsl-mainnav a:hover {
	background: var(--wp--preset--color--ink);
}

@media (max-width: 640px) {
	.gsl-mainnav {
		display: none;
	}
}

/* The cart glyph on the buy pill, drawn with a mask so it inherits the
   label's colour in every state without a second asset. */
.gsl-card__buy .add_to_cart_button::before {
	content: "";
	width: 15px;
	height: 15px;
	flex-shrink: 0;
	margin-right: 7px;
	background: currentColor;
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 18a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm10 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zM3 2h2l3.6 11.59A2 2 0 0 0 10.5 15h9a2 2 0 0 0 1.93-1.5L23.5 6H6.2l-.9-3H3z'/%3E%3C/svg%3E") center / contain no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 18a2 2 0 1 0 0 4 2 2 0 0 0 0-4zm10 0a2 2 0 1 0 0 4 2 2 0 0 0 0-4zM3 2h2l3.6 11.59A2 2 0 0 0 10.5 15h9a2 2 0 0 0 1.93-1.5L23.5 6H6.2l-.9-3H3z'/%3E%3C/svg%3E") center / contain no-repeat;
}

/* Out of stock: the grey «повідомити» pill of the prototype, and no cart
   glyph on a button that does not add to a cart. */
.gsl-grid > li.outofstock .gsl-card__buy a,
.gsl-grid > li.outofstock .gsl-card__buy button {
	background: var(--wp--preset--color--hairline);
	color: var(--wp--preset--color--muted);
}

.gsl-grid > li.outofstock .gsl-card__buy a::before,
.gsl-grid > li.outofstock .gsl-card__buy button::before {
	display: none;
}

/* Bottom navigation: phones only, over the page, under the thumb. */
.gsl-bnav {
	display: none;
}

@media (max-width: 640px) {
	.gsl-bnav {
		display: flex;
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		background: var(--wp--preset--color--base);
		box-shadow: 0 -3px 14px color-mix(in srgb, var(--wp--preset--color--ink) 18%, transparent);
		z-index: 60;
	}

	.gsl-bnav a {
		flex: 1;
		text-align: center;
		padding: 7px 0 9px;
		color: var(--wp--preset--color--muted);
		font-size: var(--wp--preset--font-size--label);
		text-decoration: none;
	}

	.gsl-bnav svg {
		display: block;
		margin: 0 auto 2px;
	}
}

/* v2c — the owner's red/green screens of 11.08: on a phone the top strip and
   the USP belt go, so the header is two rows and the banner comes right
   after. Their contents survive elsewhere — the links in the footer, the
   promises in the hero cards, the language switcher moved to the footer. */
@media (max-width: 640px) {
	.gsl-util {
		display: none;
	}
}

/* v2d — the three header circles, take two (owner, 11.08): the grounds go
   back to one wash and one size, and the glyph lines carry the difference.
   Colours follow what each action means on this site: gold buys, teal talks,
   ink is the person. */
.gsl-head__phone {
	color: var(--wp--preset--color--brand-text);
}

.gsl-head__acts a {
	color: var(--wp--preset--color--ink);
}

.gsl-cart .wc-block-mini-cart__button svg {
	color: var(--wp--preset--color--ink);
}

/* v2e — one size for the circles the theme owns. The account button is
   sized the same way in its own block stylesheet: the first cut of this rule
   sized every <a> in the group and surfaced the block's hidden fallback
   link as a twin icon. */
@media (max-width: 640px) {
	.gsl-head__phone {
		width: 44px;
		height: 44px;
	}

	.gsl-cart .wc-block-mini-cart__button {
		width: 44px;
		height: 44px;
		min-width: 44px;
		padding: 0;
	}
}

/* v2f — the header the onlymoms way (owner, 11.08): no coloured discs, just
   thin dark line glyphs at one size. The 44px tap target survives as an
   invisible boundary; only the paint goes. */
@media (max-width: 640px) {
	.gsl-head__acts .gsl-head__phone,
	.gsl-cart .wc-block-mini-cart__button {
		background: transparent;
		border: 0;
		color: var(--wp--preset--color--contrast);
	}

	.gsl-head__acts .gsl-head__phone svg,
	.gsl-cart .wc-block-mini-cart__button svg {
		width: 25px;
		height: 25px;
		color: var(--wp--preset--color--contrast);
	}

	.gsl-head__acts {
		gap: var(--wp--preset--spacing--20);
	}
}

/* v2g — the row closes up to onlymoms density: Instagram joins the set, the
   invisible tap boxes narrow so the glyphs sit as tight as the reference. */
.gsl-head__ig {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: var(--wp--preset--color--brand-wash);
	color: var(--wp--preset--color--ink);
}

@media (max-width: 640px) {
	.gsl-head__acts .gsl-head__ig,
	.gsl-head__acts .gsl-head__phone {
		width: 34px;
		height: 44px;
		background: transparent;
		border: 0;
		color: var(--wp--preset--color--contrast);
	}

	.gsl-cart .wc-block-mini-cart__button {
		width: 34px;
		min-width: 34px;
	}

	.gsl-head__acts {
		gap: 2px;
		transform: translateY(3px);
	}
}

/* v2h — the search hides behind the loupe on phones (owner, 11.08): tap the
   glyph and the field drops in under the icon row; tap again and it goes.
   The row itself also breathes out to the screen edges, the reference's
   density. */
.gsl-search-toggle {
	display: none;
	background: transparent;
	border: 0;
	color: var(--wp--preset--color--contrast);
	align-items: center;
	justify-content: center;
}

@media (max-width: 640px) {
	.gsl-head__acts .gsl-search-toggle {
		display: inline-flex;
		width: 34px;
		height: 44px;
		background: transparent;
		border-radius: 0;
		margin-right: 6px;
	}

	/* 16px keeps iOS from zooming the page when the field takes focus. */
	.gsl-head .gsl-search input[type="search"] {
		font-size: var(--wp--preset--font-size--medium);
	}

	.gsl-head__row {
		margin-inline: -14px;
	}

	/* Пошук — постійний рядок (власник, 12.08): видно завжди, а при
	   прокрутці вниз ховається, лишаючи тонку шапку; перший рух угору
	   повертає його — патерн Rozetka/WB. */
	.gsl-head .gsl-search {
		display: block;
		/* Headroom over the tallest the pill gets on iOS - the clip must
		   only ever cut air, never the pill. */
		max-height: 72px;
		overflow: hidden;
		transition: max-height 0.22s ease;
	}

	/* The clip above exists for the slide-away animation and for it alone —
	   left on while typing, it swallows the suggestion panel whole: open in
	   the DOM, невидима на екрані (CDP-геометрия, 24.08). While the shopper
	   is actually in the field the row cannot be collapsing anyway — and an
	   open panel keeps it lifted through the blur a tap causes, or the row
	   under the finger clips away between touch and click. */
	.gsl-head .gsl-search:focus-within,
	.gsl-head.is-search-open .gsl-search,
	.gsl-head .gsl-search:has(.gsl-suggest:not([hidden])) {
		overflow: visible;
	}

	/* The pill leaves by sliding up behind the logo row, in step with the
	   row closing — the old max-height-only collapse guillotined it in
	   place: a half-pill sitting on the banner (owner photographed exactly
	   that frame, 14.08). Movement keeps the bottom edge whole. */
	.gsl-head .gsl-search form {
		transition: transform 0.22s ease, opacity 0.18s ease;
	}

	.gsl-head.is-scrolled .gsl-search {
		max-height: 0;
	}

	.gsl-head.is-scrolled .gsl-search form {
		transform: translateY(-110%);
		opacity: 0;
	}

	@media (prefers-reduced-motion: reduce) {
		.gsl-head .gsl-search,
		.gsl-head .gsl-search form {
			transition: none;
		}
	}

	.gsl-head__acts .gsl-search-toggle {
		display: none;
	}
}

@keyframes gsl-search-in {
	from {
		opacity: 0;
		transform: translateY(-6px);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* v2i — the white bar slims down and the banner docks against it (owner,
   11.08, «как на onlymoms»): the bar keeps just enough breath for the 44px
   targets, and the hero's top margin collapses to a seam. */
@media (max-width: 640px) {
	.gsl-head__row {
		padding-block: 2px;
		min-height: 0;
	}

	.gsl-head__acts .gsl-head__ig,
	.gsl-head__acts .gsl-head__phone,
	.gsl-head__acts .gsl-search-toggle,
	.gsl-cart .wc-block-mini-cart__button {
		height: 44px;
	}

	.gsl-head {
		padding-block: 0;
	}

	.gsl-main {
		margin-block-start: 0;
	}

	.gsl-main {
		padding-block-start: 0;
	}

	.gsl-main > :first-child,
	.gsl-hero {
		margin-block-start: 0;
	}

	/* The white shelf: the header keeps a breath of its own white under the
	   icons, so the top of the page reads white and the banner starts right
	   where the white ends. */
	.gsl-head {
		/* One step more shelf than before: the owner asked the pill lifted
		   clear of the banner (14.08) - the white below it is the lift. */
		padding-block-end: var(--wp--preset--spacing--50);
		transition: padding 0.22s ease;
	}

	/* The shelf is the pill breathing room, so it folds away with the
	   pill: with the search hidden the thin bar keeps only a hair of
	   white, not the full shelf (owner, 14.08 - «большая белая полоса»). */
	.gsl-head.is-scrolled {
		padding-block-end: var(--wp--preset--spacing--20);
	}

	/* A hair thinner, per the owner's eye. Only stroke-drawn glyphs listen
	   to this; the burger is a mask with its own thinner bars. */
	.gsl-head__acts svg,
	.gsl-head__phone svg,
	.gsl-search-toggle svg {
		stroke-width: 1.5;
		width: 27px;
		height: 27px;
	}

}

/* v2j — the cream promise panel from the owner's mock (11.08): a 2x2 grid
   between the header and the banner, phones only. The desktop keeps its
   running belt; the hero side cards bow out on phones so nothing repeats. */
.gsl-usp2 {
	display: none;
}

@media (max-width: 640px) {
	/* One quiet band, not four islands: near full width, a hair of a gap,
	   every cell the same height. */
	.gsl-usp2 {
		display: grid;
		grid-template-columns: 1fr 1fr;
		grid-auto-rows: 1fr;
		gap: 6px;
		position: relative;
		left: 50%;
		width: 100vw;
		max-width: none !important;
		margin-left: -50vw !important;
		margin-block: 12px 0 !important;
	}

	.gsl-usp2__item {
		display: flex;
		gap: var(--wp--preset--spacing--30);
		align-items: flex-start;
		background: var(--wp--preset--color--cream);
		border-radius: 0;
		padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
	}

	.gsl-usp2__item svg {
		width: 26px;
		height: 26px;
	}

	.gsl-usp2__item svg {
		flex-shrink: 0;
		color: var(--wp--preset--color--gold-icon);
		margin-top: 2px;
	}

	.gsl-usp2__item b {
		display: block;
		font-size: var(--wp--preset--font-size--base);
		font-weight: 700;
		line-height: 1.3;
		letter-spacing: -0.01em;
		color: var(--wp--preset--color--ink);
		text-wrap: balance;
	}

	.gsl-usp2__item span {
		display: block;
		font-size: var(--wp--preset--font-size--small);
		line-height: 1.4;
		color: var(--wp--preset--color--muted);
		margin-top: 3px;
	}

	/* Same promises now live above the banner, so the side cards would say
	   everything twice on a phone. */
	.gsl-hero__side {
		display: none;
	}

	/* Icons ride the middle of the whole white area, shelf included. */
	.gsl-head__row {
		transform: translateY(6px);
	}
}


/* v2k — the wishlist heart in the header and the gold counters (owner,
   11.08): one yellow disc language for «how many» on both the heart and
   the cart. */
.gsl-head__fav {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	background: var(--wp--preset--color--brand-wash);
	color: var(--wp--preset--color--ink);
}

/* The flex above would beat the hidden attribute (the stepper stepped on
   this same rake): with the wishlist empty the badge said «0». */
.gsl-fav-count[hidden] {
	display: none;
}

.gsl-fav-count {
	position: absolute;
	top: 1px;
	right: -2px;
	min-width: 17px;
	height: 17px;
	padding: 0 3px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 9px;
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	line-height: 1;
}

/* The badge mirrors the heart's: the same small gold disc in the same
   top corner, and nothing else on the cart is yellow. */
.gsl-cart .wc-block-mini-cart__button {
	position: relative;
}

/* WooCommerce's «quantity-badge» is the wrapper around the whole icon, so
   it stays unpainted; the inner __badge is the number, and that is the only
   gold. */
.gsl-cart .wc-block-mini-cart__quantity-badge {
	background: transparent;
	border: 0;
}

.gsl-cart .wc-block-mini-cart__badge {
	position: absolute;
	top: 1px;
	right: -2px;
	min-width: 17px;
	height: 17px;
	padding: 0 3px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 9px;
	/* !important against the block's own inline colours, which the
	   interactivity runtime writes onto the element after hydration. */
	background: var(--wp--preset--color--gold) !important;
	color: var(--wp--preset--color--ink) !important;
	font-size: var(--wp--preset--font-size--label);
	font-weight: 700;
	line-height: 1;
}

.gsl-cart .wc-block-mini-cart__badge:empty,
.gsl-cart .wc-block-mini-cart__badge[hidden] {
	display: none;
}

@media (max-width: 640px) {
	.gsl-cart .wc-block-mini-cart__badge {
		top: 4px;
	}
}

@media (max-width: 640px) {
	.gsl-head__acts .gsl-head__fav {
		width: 34px;
		height: 44px;
		background: transparent;
		border-radius: 0;
		color: var(--wp--preset--color--contrast);
	}

	.gsl-head__acts .gsl-head__fav svg {
		width: 27px;
		height: 27px;
	}

	.gsl-fav-count {
		top: 4px;
	}
}

/* v2l — the bar rides along (owner, 11.08): on phones the header sticks to
   the top of the screen so the cart and the heart are always in reach, and
   the page is clipped sideways so the full-bleed strips cannot rock it. */
@media (max-width: 640px) {
	/* The clip sits on the site wrapper, not on html/body (17.09). Woo's
	   product-filters script writes an inline overflow:auto onto body at
	   load; with html clipped that value could not propagate to the
	   viewport, so body itself became the scroll container — and the sticky
	   header stuck to a box that scrolls away with the page. The owner saw
	   the filter bar hanging 133px below an empty top edge on an iPhone.
	   `clip` is not a scroll container, so the header sticks through it. */
	.wp-site-blocks {
		overflow-x: clip;
	}

	.wp-site-blocks > header {
		position: sticky;
		top: 0;
		z-index: 70;
		background: var(--wp--preset--color--base);
	}
}


/* --------------------------------------------------- card scheme B ----
   Owner's pick after the stepper-vs-popup research (13.08): one labelled
   full-width button per card; once the product is in the cart the plugin
   hides the button and shows its stepper in the same spot (both via
   `hidden` on markup the plugin owns). Here: make sure `hidden` beats our
   own display:flex on the button, and keep the post-add «Переглянути
   кошик» span on its own line. */
.wp-block-button.wc-block-components-product-button.gsl-card__buy .add_to_cart_button[hidden] {
	display: none;
}

.wp-block-button.wc-block-components-product-button.gsl-card__buy > span,
.wp-block-button.wc-block-components-product-button.gsl-card__buy .added_to_cart {
	flex: 1 0 100%;
	text-align: center;
	font-size: var(--wp--preset--font-size--small);
}

/* Design pass on the buy row (owner, 13.08): the card button borrows the
   hero CTA silhouette - pill, bold - so the stepper it turns into can keep
   the same shape and read as one control changing state, not two controls
   trading places. */
.wp-block-button.wc-block-components-product-button.gsl-card__buy a,
.wp-block-button.wc-block-components-product-button.gsl-card__buy button,
.wp-block-button.wc-block-components-product-button.gsl-card__buy .wp-block-button__link {
	border-radius: var(--wp--custom--radius--pill);
	font-weight: 700;
}

/* ------------------------------------------- PLP wave 2: phone bar ----
   The owner's second pass (19.08, phone screens): a compact «Фільтри»
   trigger on the left and the gsl/facet-chips quick-filter row filling the
   rest of the line. Sorting left the bar for the sheet itself (.gsl-dsort,
   first thing inside the overlay); the toolbar sort and per-page still hide
   on the phone, where the sheet owns them. */
.gsl-dsort {
	display: none;
}

/* The loupe of the bar exists only for the fixed phone bar; the desktop
   rail must never see it, so the hide lives outside the media block. */
.gsl-mbar__search {
	display: none;
}

@media (max-width: 640px) {
	/* Transparent in the flow — the pills carry their own chrome, a white
	   band behind them was pure height. The fixed state paints itself back
	   in, or the page would scroll through it. */
	.gsl-mbar {
		display: flex;
		align-items: center;
		gap: 6px;
		padding-block: 2px;
	}

	.gsl-mbar.is-fixed {
		background: var(--wp--preset--color--surface);
	}

	/* Fixed rather than sticky: the bar's own column is exactly bar-tall,
	   so sticky has no track to run on. JS seats it under the header's
	   live lower edge. Since 17.09 (variant Б of the scroll study) it no
	   longer hides on the way down — no transition either, the script
	   follows the header frame by frame while its search folds. */
	.gsl-mbar.is-fixed {
		position: fixed;
		left: 0;
		right: 0;
		z-index: 40;
		padding-inline: 14px;
		box-shadow: 0 8px 18px -14px color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
	}

	/* The filter sheet lives inside the bar, so it can climb no higher than
	   the bar does: stuck under the header at z 40, the sheet slid its top —
	   «Фільтри · Скинути все · Закрити» — under the header (z 70), and a tap
	   on «Закрити» opened the login window instead (QA sweep, 25.09.2026).
	   While the sheet is open the bar rises over everything. */
	.gsl-mbar:has(.wc-block-product-filters.is-overlay-opened) {
		z-index: 10000;
	}

	/* The loupe joins the fixed bar once the header has folded its search:
	   the same 40px ring as the consult buttons, brand-teal glyph. In the
	   flow, and with the search on screen, it stays away. */
	.gsl-mbar__search {
		position: relative;
		flex: 0 0 36px;
		width: 36px;
		height: 36px;
		min-height: 0;
		aspect-ratio: 1;
		box-sizing: border-box;
		padding: 0;
		border: 1px solid var(--wp--preset--color--border-strong);
		border-radius: 50%;
		background: var(--wp--preset--color--base);
		color: var(--wp--preset--color--brand-text);
		cursor: pointer;
		place-items: center;
		line-height: 0;
	}

	/* 36px to sit level with the chips; the 44px touch floor is an
	   invisible halo, as on the consult buttons. */
	.gsl-mbar__search::after {
		content: "";
		position: absolute;
		inset: -4px;
	}

	.gsl-mbar.is-fixed.has-search .gsl-mbar__search {
		display: grid;
	}

	/* The trigger is a button now, not a banner: the chips need the line. */
	.gsl-mbar .wc-block-product-filters {
		flex: none;
	}

	/* The trigger has no ring of its own, so its right cushion read as a
	   hole before the first chip (owner, 17.09): 4px there, the icon keeps
	   its 12px from the edge. */
	.gsl-mbar .wc-block-product-filters__open-overlay {
		min-height: 40px;
		padding-inline: 12px 4px;
		font-size: var(--wp--preset--font-size--base);
	}

	/* Sorting inside the sheet: the first control the overlay shows. */
	.gsl-dsort {
		display: block;
		margin: 0 0 var(--wp--preset--spacing--30);
	}

	/* Woo floats its ordering form right; in the sheet it is a full row. */
	.gsl-dsort form {
		float: none;
		width: 100%;
		margin: 0;
	}

	.gsl-dsort select {
		width: 100%;
		min-height: 44px;
		border: 1px solid var(--wp--preset--color--border-strong);
		border-radius: var(--wp--custom--radius--medium);
		background: var(--wp--preset--color--base);
		font-size: var(--wp--preset--font-size--small);
	}

	/* Per-page hides on the phone; the sort stays and becomes a pill (see the «Б» block). */
	.gsl-toolbar .gsl-perpage {
		display: none;
	}
}

/* ------------------------------------------- PLP: the rail rides with the page ----
   The rail used to stick under the header and scroll inside its own column
   (owner's ask of 19.08). On a Windows desktop that box wears a system
   scrollbar with arrows inside the white card, and the owner asked for the
   scroll to go (17.09). The rail is a plain column again: it scrolls with
   the page, and the card hugs its own content instead of stretching to the
   height of the product grid. */
@media (min-width: 641px) {
	.gsl-cat .gsl-cat__cols > .gsl-aside {
		align-self: flex-start;
	}
}

/* --------------------------------------- PLP density: variant 1 (19.08) ----
   The owner's pick: the same structure, minus the air. Scoped to the
   category page so the front page keeps its breath; the card itself is
   untouched - «один в один» with the front page stands. */
.gsl-cat .wp-block-query-title {
	margin-block: var(--wp--preset--spacing--20) var(--wp--preset--spacing--20);
}

.gsl-cat .gsl-crumbs {
	margin-block-end: var(--wp--preset--spacing--10);
}

.gsl-cat .gsl-toolbar {
	margin-block: var(--wp--preset--spacing--20);
}

@media (min-width: 641px) {
	.gsl-cat .gsl-grid {
		gap: var(--wp--preset--spacing--20) !important;
	}

	.gsl-cat .gsl-cat__cols {
		gap: var(--wp--preset--spacing--40);
	}
}

/* The phone pass (owner, 19.08, red pen): every gap between the crumbs and
   the first card row goes to its floor. Each block above the grid keeps one
   small breath, no block keeps two. */
@media (max-width: 640px) {
	.gsl-main.gsl-cat {
		padding-block-start: var(--wp--preset--spacing--20);
	}

	.gsl-cat .gsl-crumbs {
		margin-block: 0;
	}

	.gsl-cat .wp-block-query-title {
		margin-block: var(--wp--preset--spacing--20) var(--wp--preset--spacing--10);
	}

	.gsl-cat .gsl-cat__cols {
		gap: 0;
	}

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

/* Facet groups fold behind their titles; the chevron says which way. */
.gsl-facet__title {
	cursor: pointer;
	user-select: none;
	display: flex;
	align-items: center;
	justify-content: space-between;
}

.gsl-facet__title::after {
	content: "";
	width: 8px;
	height: 8px;
	border-right: 1.5px solid var(--wp--preset--color--muted);
	border-bottom: 1.5px solid var(--wp--preset--color--muted);
	transform: rotate(45deg);
	transition: transform 0.14s;
	flex: 0 0 auto;
	/* The rotation pokes ~2px past the box; the rail clips overflow now, and
	   a clipped chevron reads as a stray slash. */
	margin-right: 3px;
}

.gsl-facet.is-closed .gsl-facet__title::after {
	transform: rotate(-45deg);
}

.gsl-facet.is-closed > :not(.gsl-facet__title) {
	display: none;
}

/* --------------------------------------------- PLP: filter controls polish ----
 *
 * The price fields are Woo's bare system inputs, floated left and right.
 * Inside the 230px rail the right one overflowed the white card and gifted
 * the whole sidebar a horizontal scrollbar with arrows — the ugliest control
 * on the page and not even ours. The floats become a grid row under the
 * slider, and the fields dress like every other input on the site.
 *
 * One set of rules covers rail and sheet alike: the markup is the same
 * overlay, shown inline on desktop. */

.gsl-facet .wc-block-product-filter-price-slider__content {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 8px 10px;
	align-items: center;
}

.gsl-facet .wc-block-product-filter-price-slider__range {
	grid-column: 1 / -1;
}

/* «.text» is a wrapper div around the field, not the field: the input inside
   carries only «min»/«max» and its browser-default size, which is what was
   poking out of the rail. The wrapper takes the grid cell, the input fills
   the wrapper. */
.gsl-facet .wc-block-product-filter-price-slider__content > .text {
	min-width: 0;
	float: none;
	margin: 0;
}

.gsl-facet .wc-block-product-filter-price-slider__content > .text input {
	float: none;
	/* border-box, or width:100% plus the padding below overflows the cell by
	   exactly padding+border — the browser default here is content-box. */
	box-sizing: border-box;
	width: 100%;
	min-width: 0;
	margin: 0;
	min-height: 36px;
	padding: 4px 10px;
	border: 1px solid var(--wp--preset--color--border-strong);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast);
}

.gsl-facet .wc-block-product-filter-price-slider__right input {
	text-align: right;
}

/* Facet groups read as one instrument when a hairline separates them. Both
 * columns ran on raw block gaps, and the emptiness between groups was the
 * tallest thing in them — the owner's ruling on sparseness (19.08) applies
 * to the rail as much as to the grid. The general sibling leaves the first
 * facet clean without counting the sort block that tops the sheet. */

.wc-block-product-filters__overlay-content {
	gap: 4px;
}

.wc-block-product-filters .gsl-facet {
	margin-block: 0;
	padding-block: 12px;
}

.wc-block-product-filters .gsl-facet ~ .gsl-facet {
	border-top: 1px solid var(--wp--preset--color--border);
}

@media (max-width: 640px) {
	/* The sheet introduces itself: a title on the left, «Закрити» on the
	   right. Before, the header was a lone close button on an empty band. */
	.wc-block-product-filters__overlay-header {
		display: flex;
		/* Woo lays the header out right-to-left; said plainly so the title
		   reads first and «Закрити» keeps the corner people close from. */
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
	}

	.wc-block-product-filters__overlay-header::before {
		content: "Фільтри";
		font-weight: 600;
		font-size: var(--wp--preset--font-size--medium);
		color: var(--wp--preset--color--contrast);
	}

	html[lang^="ru"] .wc-block-product-filters__overlay-header::before {
		content: "Фильтры";
	}
}

/* -------------------------------------------------------------- Cart page ----
 *
 * The owner's reference is the old Prom cart: a tight row per product — photo,
 * two-line name, a stepper and the line total on one line, a bin in the corner
 * — and one honest summary under the list. Everything below is scoped to
 * `.wp-block-woocommerce-cart`, which only the cart page prints; the mini-cart
 * drawer never enters this cascade.
 *
 * The column split is ours on purpose: WooCommerce sizes main and sidebar at
 * 65% + 35% of a wrapping flexbox, and inside our constrained wrapper the pair
 * always wrapped, sidebar under list. Two explicit baskets with flex-basis do
 * what the percentages promised. */

.wp-block-woocommerce-cart .wc-block-components-sidebar-layout {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--50);
}

.wp-block-woocommerce-cart .wc-block-cart__main {
	flex: 999 1 460px;
	min-width: 0;
	width: auto;
	padding: 0;
}

.wp-block-woocommerce-cart .wc-block-cart__sidebar {
	flex: 1 1 330px;
	width: auto;
	min-width: 0;
	padding: 0;
}

@media (min-width: 900px) {
	.wp-block-woocommerce-cart .wc-block-cart__sidebar {
		position: sticky;
		top: var(--wp--preset--spacing--50);
		max-width: 430px;
	}
}

/* The list drops its table costume and takes the shape Prom gives it: one
   white card on the grey page, a rounded edge around the whole basket, and a
   hairline between neighbours. The border does the grouping, the rule does the
   separating — on a grey background with no card at all, four items read as
   one long ribbon and the owner could not tell where a product ended
   (owner, 21.09). */
.wp-block-woocommerce-cart table.wc-block-cart-items,
.wp-block-woocommerce-cart table.wc-block-cart-items tbody {
	display: block;
	width: 100%;
	border: none;
	margin: 0;
}

.wp-block-woocommerce-cart table.wc-block-cart-items {
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--hairline);
	border-radius: var(--wp--custom--radius--medium);
	overflow: hidden;
}

.wp-block-woocommerce-cart .wc-block-cart-items thead {
	display: none;
}

/* One row: photo on the left, everything else in a column beside it, the line
   total sharing a baseline with the stepper, the bin in the top corner.
   Built in August a size too large — 170px a row, so three items filled a
   phone screen on their own. Prom, which the owner's customers have used for
   years, spends about 112px on the same four facts, and that is the size
   here now (owner, 21.09). */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row {
	display: grid;
	grid-template-columns: 80px minmax(0, 1fr) auto;
	grid-template-rows: auto auto;
	column-gap: var(--wp--preset--spacing--30);
	row-gap: var(--wp--preset--spacing--10);
	position: relative;
	padding-block: var(--wp--preset--spacing--30);
	padding-inline: var(--wp--preset--spacing--30);
	border-bottom: 1px solid var(--wp--preset--color--hairline);
}

/* The rule belongs between two products, not under the last one, where it
   would draw a second line a hair above the card's own edge. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row:last-child {
	border-bottom: 0;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__image {
	grid-column: 1;
	grid-row: 1 / span 2;
	width: 80px;
	padding: 0;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__image img {
	border-radius: var(--wp--custom--radius--small);
	border: 1px solid var(--wp--preset--color--hairline);
	width: 80px;
	height: 80px;
	max-width: 80px;
	object-fit: cover;
}

/* The stepper lives INSIDE this cell (Woo nests it in the product column), so
   the cell spans both rows and the line total answers it from the third
   column, bottom-aligned to sit on the stepper's line. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__product {
	grid-column: 2 / 3;
	grid-row: 1 / span 2;
	padding: 0;
	min-width: 0;
	/* Room for the absolutely-parked bin so a long name never runs under it. */
	padding-right: calc(var(--wp--preset--spacing--60) + var(--wp--preset--spacing--20));
	display: block;
}

/* Woo wraps the cell's content once more, as a flex column. That wrap becomes
   a small grid: the name on its own line, the pack price and the per-piece
   facts on one — «34 ₴ · ≈6,80 ₴/шт · 5 в упаковці» — and the stepper last,
   so every row in the list stands the same height (23.09). A grid rather than
   a wrapping row because Woo's metadata box is itself a flex column, and a
   separator drawn into it stacked above the facts. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap {
	display: grid;
	grid-template-columns: auto minmax(0, 1fr);
	grid-template-areas: "name name" "badge badge" "price meta" "qty qty";
	align-items: baseline;
	column-gap: var(--wp--preset--spacing--20);
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap > .wc-block-components-product-name {
	grid-area: name;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap > .wc-block-components-product-badge {
	grid-area: badge;
	justify-self: start;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap > .wc-block-cart-item__prices {
	grid-area: price;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap > .wc-block-cart-item__quantity {
	grid-area: qty;
}

/* The per-piece facts follow the pack price with a middle dot; their
   «Ціна за штуку:» key is redundant next to «₴/шт» and stays in the markup
   for the checkout summary, where the line stands alone. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap > .wc-block-components-product-metadata {
	grid-area: meta;
	display: block;
	min-width: 0;
	margin: 0;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-components-product-details,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-components-product-details li {
	display: inline;
	margin: 0;
	padding: 0;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-components-product-details::before {
	content: "· ";
	color: var(--wp--preset--color--muted);
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-product-details__name {
	display: none;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__product .wc-block-cart-item__quantity {
	padding-top: var(--wp--preset--spacing--10);
}

/* A stepper the size of a thumb: 44px is Apple's minimum and what Prom's
   customers are used to; the market's 32–34 read as fiddly next to an 80 px
   photo (sizes research, 24.09.2026). */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__input {
	height: 44px;
	min-height: 44px;
}

/* The stepper keeps its own width. The name column of a phone row is 123 px
   and the stepper needs 134: shrunk to fit, it left the plus 13 px outside the
   box at «1» and 29 px at «12» — and big quantities are what wholesale buys.
   It may run into the bin's gutter; the line total has its own column. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector {
	width: max-content;
	min-width: max-content;
	flex-shrink: 0;
}

/* Prom draws the stepper as one quiet outlined box; ours came out as three
   gold pills, which shouted louder than the price beside them. Inside the cart
   list it goes neutral: one hairline box, plain glyphs, no fills. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector {
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--small);
	background: var(--wp--preset--color--base);
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button--plus,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button--minus {
	border: 0;
	border-radius: 0;
	background: transparent;
	box-shadow: none;
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
}

/* The plus kept a box of its own — not a border but a tofu: WooCommerce
   labels the button with U+FF0B, the fullwidth plus, and Fixel does not draw
   it, so the browser printed the empty square it falls back to. The label is
   pushed out of sight and the glyph redrawn in characters the font has. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button {
	position: relative;
	overflow: hidden;
	text-indent: 110%;
	white-space: nowrap;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button::before {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	text-indent: 0;
	color: var(--wp--preset--color--contrast);
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button--minus::before {
	content: "−";
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button--plus::before {
	content: "+";
}

/* The per-piece note is a footnote, not a paragraph: one line, then an
   ellipsis, so every row in the list keeps the same height. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-product-metadata {
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__button:hover {
	background: var(--wp--preset--color--surface);
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-components-quantity-selector__input {
	border: 0;
	background: transparent;
}

/* Woo walks the selector to the right edge with an auto margin on narrow
   containers; the stepper belongs under the name. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__product .wc-block-components-quantity-selector {
	margin: 0;
}

.wp-block-woocommerce-cart .wc-block-components-product-name {
	font-size: var(--wp--preset--font-size--base);
	line-height: 1.3;
	font-weight: 500;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

/* Two lines, then an ellipsis: the full name is one tap away on the product
   page, and a four-line name turned the row into a paragraph. The selector
   carries the table because WooCommerce sets `display: block` from
   `table.wc-block-cart-items .wc-block-cart-items__row .…product-name`, and a
   clamp without `-webkit-box` does nothing at all. The same overflow rule
   clipped the plus off the stepper, which is why the box above no longer
   hides its own overflow. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-components-product-name {
	/* Woo pins the line name to the small size at (0,3,1); this selector outranks it. */
	font-size: var(--wp--preset--font-size--base);
	display: -webkit-box;
	-webkit-line-clamp: 2;
	-webkit-box-orient: vertical;
	overflow: hidden;
}

/* The row's own white, so the card reads as a card on the grey page even
   where WooCommerce keeps the table transparent. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row {
	background: var(--wp--preset--color--base);
}

/* The short description is PDP material; in a working list it is noise. */
.wp-block-woocommerce-cart .wc-block-components-product-metadata__description {
	display: none;
}

/* The pack price under the name is what one unit of the row costs — quiet,
   small and grey next to the bold line total (same reasoning as the drawer).
   The price component insists on its own colour and weight, hence the deep
   selectors. */
.wp-block-woocommerce-cart .wc-block-cart-item__prices {
	margin-top: var(--wp--preset--spacing--10);
	flex: 0 0 auto;
}

.wp-block-woocommerce-cart .wc-block-cart-item__prices .wc-block-components-product-price,
.wp-block-woocommerce-cart .wc-block-cart-item__prices .wc-block-components-product-price__value,
.wp-block-woocommerce-cart .wc-block-cart-item__prices .wc-block-formatted-money-amount {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
	color: var(--wp--preset--color--muted);
}

.wp-block-woocommerce-cart .wc-block-components-product-metadata {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--muted);
}

/* Sale badges and low-stock notes keep their seat but drop to a whisper. */
.wp-block-woocommerce-cart .wc-block-components-product-badge {
	font-size: var(--wp--preset--font-size--label);
}

/* The reference stepper: two outlined gold squares with a bare number between.
   The drawer keeps its boxed selector; only the cart page dresses it up. */
.wp-block-woocommerce-cart .wc-block-components-quantity-selector {
	border: none;
	height: auto;
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	margin: 0;
	/* Woo stretches the selector across the column on small screens; pinned to
	   its content the line total keeps its own corner. */
	width: max-content;
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector::after {
	display: none;
}

/* Woo prints fullwidth ＋/－ glyphs (U+FF0B/FF0D) that thin font stacks miss;
   the buttons hide their own text and wear ASCII glyphs drawn by ::before,
   which every font on earth carries. */
.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button {
	position: relative;
	width: 42px;
	height: 42px;
	flex: 0 0 42px;
	border: 1px solid var(--wp--preset--color--gold);
	border-radius: var(--wp--custom--radius--medium);
	color: transparent;
	background: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1;
	opacity: 1;
	cursor: pointer;
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button::before {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	color: var(--wp--preset--color--gold-text);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button--minus::before {
	content: "−";
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button--plus::before {
	content: "+";
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button:hover {
	border-color: var(--wp--preset--color--gold-hover);
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button:hover::before {
	color: var(--wp--preset--color--ink);
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button--minus {
	order: 1;
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector input.wc-block-components-quantity-selector__input {
	order: 2;
	flex: 0 0 auto;
	width: 2.6em;
	min-width: 2.6em;
	border: none;
	background: none;
	text-align: center;
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

.wp-block-woocommerce-cart .wc-block-components-quantity-selector .wc-block-components-quantity-selector__button--plus {
	order: 3;
}

/* Line total: the one loud number of the row, on the stepper's line. The
   bottom margin centres its text against the 42px stepper buttons. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__total {
	grid-column: 3;
	grid-row: 1 / span 2;
	align-self: end;
	justify-self: end;
	padding: 0;
	margin-bottom: 9px;
	font-size: var(--wp--preset--font-size--price);
	font-weight: 700;
	color: var(--wp--preset--color--ink);
	white-space: nowrap;
}

.wp-block-woocommerce-cart .wc-block-cart-item__total .wc-block-components-product-price {
	font-weight: 700;
}

/* The bin waits in the corner, grey until meant. */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__remove-link {
	position: absolute;
	top: var(--wp--preset--spacing--30);
	right: 0;
	padding: var(--wp--preset--spacing--10);
	border: none;
	background: none;
	color: var(--wp--preset--color--muted);
	cursor: pointer;
	line-height: 0;
}

.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__remove-link:hover {
	color: var(--wp--preset--color--sale);
}

/* ---- Summary card ---- */

.wp-block-woocommerce-cart .wc-block-cart__sidebar .wp-block-woocommerce-cart-order-summary-block {
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--hairline);
	border-radius: var(--wp--custom--radius--large);
	padding: var(--wp--preset--spacing--40) var(--wp--preset--spacing--40) var(--wp--preset--spacing--20);
}

/* One card, not a card per line: the theme wrapper borders go. */
.wp-block-woocommerce-cart .wc-block-cart__sidebar .wc-block-components-totals-wrapper {
	border: none;
	padding: 0;
	margin: 0;
	background: none;
	border-radius: 0;
}

.wp-block-woocommerce-cart .wc-block-cart__sidebar .wc-block-cart__totals-title {
	font-size: var(--wp--preset--font-size--label);
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	border: none;
	padding: 0;
	margin-bottom: var(--wp--preset--spacing--30);
	text-align: left;
}

.wp-block-woocommerce-cart .wc-block-components-totals-item {
	font-size: var(--wp--preset--font-size--base);
	padding: 0;
	margin-bottom: var(--wp--preset--spacing--20);
}

/* The cart's shipping line says «Доставка» and nothing more (the label is
   rewritten by Cart\CartPage): the carrier is chosen later and may be
   Укрпошта as well as Нова Пошта, and the zero WooCommerce would print as
   «Безкоштовно» is not the point (owner, 23.09). The <strong> is what
   WooCommerce uses for that zero; a real price keeps its seat. */
.wp-block-woocommerce-cart .wc-block-components-totals-shipping .wc-block-components-totals-item__value > strong {
	display: none;
}

.wp-block-woocommerce-cart .wp-block-woocommerce-cart-order-summary-shipping-block .wc-block-components-totals-item__label {
	color: var(--wp--preset--color--contrast);
}

.wp-block-woocommerce-cart .wc-block-components-totals-item__label {
	color: var(--wp--preset--color--muted);
	font-weight: 400;
}

.wp-block-woocommerce-cart .wc-block-components-totals-item__value {
	color: var(--wp--preset--color--contrast);
}

.wp-block-woocommerce-cart .wc-block-components-totals-footer-item {
	border-top: 1px solid var(--wp--preset--color--hairline);
	padding-top: var(--wp--preset--spacing--30);
	margin-top: var(--wp--preset--spacing--20);
}

.wp-block-woocommerce-cart .wc-block-components-totals-footer-item .wc-block-components-totals-item__label {
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
}

.wp-block-woocommerce-cart .wc-block-components-totals-footer-item .wc-block-components-totals-item__value {
	font-size: var(--wp--preset--font-size--price);
	font-weight: 700;
	color: var(--wp--preset--color--ink);
}

/* The checkout button carries the site's primary gold. */
.wp-block-woocommerce-cart .wc-block-cart__submit-container a,
.wp-block-woocommerce-cart .wc-block-cart__submit-button {
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--ink);
	border: none;
	border-radius: var(--wp--custom--radius--medium);
	min-height: 52px;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	width: 100%;
}

.wp-block-woocommerce-cart .wc-block-cart__submit-container a:hover,
.wp-block-woocommerce-cart .wc-block-cart__submit-button:hover {
	background: var(--wp--preset--color--gold-hover);
	color: var(--wp--preset--color--ink);
}

/* ---- Empty cart ---- */

/* One white card: what happened, the way back, and the way to past
   orders — the cart is a shopper's external memory (NN/g), and the empty
   one says so rather than apologising. */
.gsl-cart-empty {
	margin-top: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--50) var(--wp--preset--spacing--40);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--hairline);
	border-radius: var(--wp--custom--radius--large);
}

.gsl-cart-empty__title {
	margin: 0 0 var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--large);
}

.gsl-cart-empty__note {
	max-width: 34em;
	margin: 0 auto var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

.gsl-cart-empty__actions {
	margin-bottom: var(--wp--preset--spacing--30);
}

.gsl-cart-empty__orders {
	margin: 0;
	font-size: var(--wp--preset--font-size--small);
}

.gsl-cart-empty__cta .wp-block-button__link {
	background: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--ink);
	border-radius: var(--wp--custom--radius--medium);
	font-weight: 700;
	min-height: 48px;
	padding-inline: var(--wp--preset--spacing--60);
}

.gsl-cart-empty__cta .wp-block-button__link:hover {
	background: var(--wp--preset--color--gold-hover);
}

/* ---- In the totals column, under the button: the way back, where the
   coupon went, and a phone for questions (ADR 0027) ---- */

.wp-block-woocommerce-cart .gsl-cart-continue {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-size: var(--wp--preset--font-size--base);
	font-weight: 600;
}

.wp-block-woocommerce-cart .gsl-cart-continue a {
	display: inline-block;
	min-height: 44px;
	line-height: 44px;
	color: var(--wp--preset--color--brand-text);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.wp-block-woocommerce-cart .gsl-cart-continue a:hover {
	color: var(--wp--preset--color--ink);
}

.wp-block-woocommerce-cart .gsl-cart-promo-note {
	margin: 0;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--label);
}

.wp-block-woocommerce-cart .gsl-cart-help {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-size: var(--wp--preset--font-size--label);
	line-height: 1.4;
	color: var(--wp--preset--color--muted);
}

.wp-block-woocommerce-cart .gsl-cart-help a {
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	white-space: nowrap;
}

/* The totals column's own blocks keep a breath between them on every width. */
.wp-block-woocommerce-cart .wc-block-cart__sidebar .wp-block-woocommerce-cart-totals-block > .wp-block-gsl-order-hours,
.wp-block-woocommerce-cart .wc-block-cart__sidebar .wp-block-woocommerce-cart-totals-block > .wp-block-gsl-cart-fillers,
.wp-block-woocommerce-cart .wc-block-cart__sidebar .wp-block-woocommerce-cart-totals-block > .wp-block-gsl-assurances {
	margin-top: var(--wp--preset--spacing--40);
}

/* Beside an 80 px photo the unit line does not fit after the pack price on a
   phone. Wrapped, it hung from the price like a stair and rows with facts
   stood 18 px taller than rows without (cart review, 29.09.2026); on its own
   line under the price it is one even line — «6,80 ₴/шт. · 5 в уп.». */
@media (max-width: 640px) {
	.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__wrap {
		grid-template-areas: "name name" "badge badge" "price price" "meta meta" "qty qty";
	}

	.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-components-product-details::before {
		content: none;
	}
}

@media (max-width: 480px) {
	.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row {
		grid-template-columns: 80px minmax(0, 1fr) auto;
	}

	.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__image,
	.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-item__image img {
		width: 80px;
		max-width: 80px;
	}
}

/* WooCommerce draws its own top border on the row's cells and on the totals
   list. Under our hairline between rows they came out as a second line over
   every name, a short stroke over every line total and a rule over «Товари»
   on a phone (cart review, 29.09.2026). */
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__image,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__product,
.wp-block-woocommerce-cart table.wc-block-cart-items .wc-block-cart-items__row .wc-block-cart-item__total,
.wp-block-woocommerce-cart .wc-block-cart__sidebar .wp-block-woocommerce-cart-order-summary-totals-block {
	border-top: 0;
}

/* WooCommerce ends the cart with 24 + 16 px of its own bottom margins; with
   the page padding under them the footer stood 92 px below the last line. */
.wp-block-woocommerce-cart .wc-block-cart.wc-block-components-sidebar-layout,
.wp-block-woocommerce-cart .wc-block-cart__sidebar {
	margin-bottom: 0;
}

/* ------------------------------------------- PLP: filter redesign «Б» (17.09) ----
 *
 * The owner picked direction «Б» of the filter canvas: the list anatomy stays
 * for most facets but wears the brand, the colour facet becomes a swatch grid
 * (blocks/facet-title/style.css), the size facet grows chips
 * (blocks/numeric-facet/style.css). What follows is the theme's share — the
 * rules on WooCommerce's own list, status and price markup, which no plugin
 * class owns: rows at 32 px, an 18 px box with the brand tick, a muted count,
 * one availability switch instead of two boxes, «від/до» inside the price
 * fields. Tokens only (docs/design/tokens.md). */

.gsl-facet .wc-block-product-filter-checkbox-list__label {
	min-height: 32px;
	padding: 0;
	gap: 8px;
	align-items: center;
}

.gsl-facet .wc-block-product-filter-checkbox-list__label input[type="checkbox"].wc-block-product-filter-checkbox-list__input {
	width: 18px;
	height: 18px;
	border-radius: calc(var(--wp--custom--radius--small) - 2px);
	border: 1px solid var(--wp--preset--color--border-strong);
}

.gsl-facet .wc-block-product-filter-checkbox-list__label input[type="checkbox"].wc-block-product-filter-checkbox-list__input:checked {
	background: var(--wp--preset--color--brand-action);
	border-color: var(--wp--preset--color--brand-action);
}

.gsl-facet .wc-block-product-filter-checkbox-list__input-wrapper .wc-block-product-filter-checkbox-list__mark {
	width: 18px;
	height: 18px;
}

.gsl-facet .wc-block-product-filter-checkbox-list__count {
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--small);
}

.gsl-facet .wc-block-product-filter-checkbox-list__show-more-button {
	min-height: 32px;
	padding: 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	color: var(--wp--preset--color--brand-action);
}

/* Availability is one question, «only what is in stock?», so it is one
   switch. The out-of-stock row goes (the whole assortment is the default
   view anyway); the box's wrapper becomes the track, the box itself the
   knob. Browsers without :has() keep a plain list — still a working filter. */
.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__item:has(input[value="outofstock"]),
.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__item:has(input[value="onbackorder"]) {
	display: none;
}

.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__label {
	min-height: 36px;
	gap: 10px;
}

.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__input-wrapper {
	position: relative;
	display: inline-block;
	flex: 0 0 auto;
	width: 36px;
	height: 20px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--border-strong);
	transition: background-color 0.15s;
}

.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__input-wrapper:has(input:checked) {
	background: var(--wp--preset--color--brand-action);
}

.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__label input[type="checkbox"].wc-block-product-filter-checkbox-list__input {
	appearance: none;
	-webkit-appearance: none;
	position: absolute;
	top: 2px;
	left: 2px;
	width: 16px;
	height: 16px;
	margin: 0;
	border: 0;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	box-shadow: 0 1px 2px color-mix(in srgb, var(--wp--preset--color--ink) 25%, transparent);
	transition: left 0.15s;
	cursor: pointer;
}

.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__label input[type="checkbox"].wc-block-product-filter-checkbox-list__input:checked {
	left: 18px;
	border: 0;
	background: var(--wp--preset--color--base);
}

.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__mark,
.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__input-wrapper::before,
.gsl-facet.wp-block-woocommerce-product-filter-status .wc-block-product-filter-checkbox-list__input-wrapper::after {
	display: none;
}

/* The price fields say what they are: «від» and «до» sit inside as quiet
   prefixes, the way the numeric facet's own fields do. */
.gsl-facet .wc-block-product-filter-price-slider__content > .text {
	position: relative;
}

.gsl-facet .wc-block-product-filter-price-slider__content > .text::before {
	position: absolute;
	left: 10px;
	top: 50%;
	transform: translateY(-50%);
	font-size: var(--wp--preset--font-size--label);
	color: var(--wp--preset--color--muted);
	pointer-events: none;
}

.gsl-facet .wc-block-product-filter-price-slider__left::before {
	content: "від";
}

html[lang^="ru"] .gsl-facet .wc-block-product-filter-price-slider__left::before {
	content: "от";
}

.gsl-facet .wc-block-product-filter-price-slider__right::before {
	content: "до";
}

.gsl-facet .wc-block-product-filter-price-slider__content > .wc-block-product-filter-price-slider__left input[type="text"] {
	padding-left: 34px;
}

.gsl-facet .wc-block-product-filter-price-slider__content > .wc-block-product-filter-price-slider__right input[type="text"] {
	padding-left: 30px;
	text-align: left;
}

/* «Скинути все» in the sheet header, between the title and «Закрити». Built
   by the template script: with filters applied it leads to the clean view
   (the address the rail head prints), otherwise it unticks what is pending. */
@media (max-width: 640px) {
	.gsl-sheet-reset {
		margin-inline-start: auto;
		margin-inline-end: var(--wp--preset--spacing--30);
		min-height: 44px;
		display: inline-flex;
		align-items: center;
		font-size: var(--wp--preset--font-size--small);
		font-weight: 600;
		color: var(--wp--preset--color--brand-text);
		text-decoration: none;
	}
}

/* The rail is a column again on the desktop: the filter group is a flex
   row by its block layout (that is what the phone bar needs), and the head
   block would otherwise sit beside the facets instead of above them. */
@media (min-width: 641px) {
	.gsl-cat .gsl-mbar {
		flex-direction: column;
		align-items: stretch;
	}
}

/* The phone head, tightened (owner, 19.09, red pen on the crumbs-to-title
   and chips-to-bar gaps; «is the results line needed at all?»). Crumbs sit
   on the title, the title on the category chips, the chips on the filter
   bar - one small breath each - and the results line goes: the count is on
   the «Усі» chip and on the sheet's button, and sorting shrinks to one «⇅»
   glyph at the end of the filter bar. Desktop keeps its line. */
@media (max-width: 640px) {
	.gsl-cat .gsl-crumbs {
		padding-block: var(--wp--preset--spacing--20) 0;
	}

	.gsl-cat .wp-block-query-title {
		margin-block: var(--wp--preset--spacing--10) 0;
	}

	.gsl-cat .gsl-chips {
		margin-block-start: var(--wp--preset--spacing--20);
	}

	.gsl-cat > .wp-block-template-part {
		margin-block-start: var(--wp--preset--spacing--20);
	}

	.gsl-cat .gsl-cat__cols {
		margin-block-start: 0;
	}

	.gsl-cat .gsl-toolbar {
		display: none;
	}
}

/* Sorting on the phone is one small glyph at the end of the filter bar -
   «Фільтри (2) · chips … ⇅». The control is WooCommerce's own sorting
   block (a second instance, in the bar), laid transparent over the glyph:
   a tap opens the system picker, a change navigates the way the desktop
   select does. A sort other than the default tints the glyph so the state
   still reads. Desktop never shows this one. */
.gsl-msort {
	display: none;
}

@media (max-width: 640px) {
	.gsl-msort {
		position: relative;
		display: block;
		flex: none;
		width: 30px;
		height: 36px;
		margin-inline-start: 2px;
		border: 0;
		border-radius: var(--wp--custom--radius--pill);
		background-color: transparent;
		background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%23333333' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 4v16M4 17l3 3 3-3M17 20V4M14 7l3-3 3 3'/%3E%3C/svg%3E");
		background-repeat: no-repeat;
		background-position: center;
		background-size: 18px 18px;
	}

	.gsl-msort:has(option:checked:not([value="menu_order"])) {
		background-color: var(--wp--preset--color--brand-wash);
		background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%2314494F' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 4v16M4 17l3 3 3-3M17 20V4M14 7l3-3 3 3'/%3E%3C/svg%3E");
	}

	.gsl-msort .wc-block-catalog-sorting,
	.gsl-msort form {
		position: absolute;
		inset: 0;
		float: none;
		margin: 0;
		width: 100%;
		height: 100%;
	}

	.gsl-msort select {
		position: absolute;
		inset: 0;
		width: 100%;
		height: 100%;
		margin: 0;
		padding: 0;
		border: 0;
		opacity: 0;
		cursor: pointer;
		/* 16 px keeps iOS from zooming the page when the picker opens. */
		font-size: var(--wp--preset--font-size--medium);
	}
}

/* The bar's width goes to the chips (owner, 19.09, red pen): the trigger
   sits flush on the content edge with no left padding, the empty no-JS form
   that WooCommerce's block carries no longer costs a flex gap, and the
   scroll arrow and the sort glyph hold the right edge. */
@media (max-width: 640px) {
	.gsl-mbar {
		gap: 0;
	}

	.gsl-mbar .wc-block-product-filters {
		margin-inline-end: 6px;
	}

	.gsl-mbar .wc-block-product-filters__open-overlay {
		padding-inline: 0 4px;
	}
}

/* The fixed bar paints itself across the screen, so its own padding is the
   page gutter — one token, not a number that used to be close to it. */
@media (max-width: 640px) {
	.gsl-cat .gsl-mbar.is-fixed {
		padding-inline: var(--wp--custom--gutter);
	}
}



/* ---------------------------------------------- folded footer on phones ----
   Owner, 23.09 (home design pass): the footer ran 968px on a phone in two
   cramped columns. One column, and the three link columns fold behind their
   headings the way Rozetka and Prom do it; contacts and the hours stay in
   view. The fold exists only where a script can undo it — without scripting
   every link is visible — and assets/js/footer.js is the script. The heading
   is a real <button> inside the <h4>, so on a wide screen it is only a
   heading and nothing here applies. */
.gsl-foot__toggle {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	font: inherit;
	color: inherit;
	text-align: left;
}

@media (max-width: 640px) and (scripting: enabled) {
	.gsl-foot__grid {
		grid-template-columns: 1fr;
		gap: 0;
		padding-bottom: var(--wp--preset--spacing--30);
	}

	.gsl-foot__grid > :first-child {
		padding-bottom: var(--wp--preset--spacing--50);
	}

	.gsl-foot__col {
		border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--base) 12%, transparent);
	}

	.gsl-foot__col .gsl-foot__head {
		margin: 0 !important;
	}

	.gsl-foot__toggle {
		display: flex;
		align-items: center;
		justify-content: space-between;
		min-height: 48px;
		cursor: pointer;
	}

	.gsl-foot__toggle::after {
		content: "";
		width: 8px;
		height: 8px;
		margin-right: 4px;
		border-right: 2px solid var(--wp--preset--color--brand-light);
		border-bottom: 2px solid var(--wp--preset--color--brand-light);
		transform: rotate(45deg);
		transition: transform 0.2s ease;
	}

	.gsl-foot__col.is-open .gsl-foot__toggle::after {
		transform: rotate(-135deg);
	}

	/* Closed: only the heading. Open: the links, with room under them. */
	.gsl-foot__col:not(.is-open) > :not(.gsl-foot__head) {
		display: none;
	}

	.gsl-foot__col.is-open > :not(.gsl-foot__head) {
		padding-bottom: var(--wp--preset--spacing--40);
	}
}

@media (prefers-reduced-motion: reduce) {
	.gsl-foot__toggle::after {
		transition: none;
	}
}
