/*
 * Catalogue menu: the header button and the two-pane drawer it opens.
 *
 * Ships with the block rather than with the theme: the render callback emits
 * these class names, so a theme that does not know them would leave the block
 * unstyled. Colours and sizes are theme.json tokens — the contract is written
 * down in docs/design/block-css-contract.md.
 *
 * The two-pane shape is the 14.08 study's verdict: a family-grouped rail on
 * the left, the hovered branch's subcategories on the right; on the phone the
 * same markup plays drill-down — the rail is screen one, the pane screen two.
 */

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

.gsl-catalog__toggle {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	height: 44px;
	padding-inline: var(--wp--preset--spacing--40);
	border: 0;
	border-radius: var(--wp--custom--radius--medium);
	background: var(--wp--preset--color--brand-action);
	color: var(--wp--preset--color--base);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

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

.gsl-catalog__toggle[aria-expanded="true"] .gsl-catalog__chevron {
	transform: rotate(180deg);
}

.gsl-catalog__chevron {
	transition: transform 0.14s;
}

.gsl-catalog__panel {
	position: absolute;
	left: 0;
	right: 0;
	z-index: 20;
	background: var(--wp--preset--color--surface-soft);
	border-bottom: 1px solid var(--wp--preset--color--border);
	box-shadow: 0 18px 30px -26px color-mix(in srgb, var(--wp--preset--color--ink) 55%, transparent);
	padding-block: var(--wp--preset--spacing--40);
}

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

/* ------------------------------------------------------------ two panes ---- */

.gsl-catalog__flyout {
	display: flex;
	align-items: stretch;
}

.gsl-catalog__rail {
	flex: 0 0 270px;
	padding-block: var(--wp--preset--spacing--20);
	border-right: 1px solid var(--wp--preset--color--border);
}

.gsl-catalog__family {
	display: block;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--40) var(--wp--preset--spacing--10);
	font-size: var(--wp--preset--font-size--label);
	letter-spacing: 0.09em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.gsl-catalog__branch {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	padding: 6px var(--wp--preset--spacing--40);
	border-left: 3px solid transparent;
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
}

.gsl-catalog__branch:hover,
.gsl-catalog__branch.is-active {
	background: var(--wp--preset--color--base);
	border-left-color: var(--wp--preset--color--gold);
	color: var(--wp--preset--color--brand-text);
}

/* The category glyphs: strokes ride the row colour (muted rest, brand on
   hover via currentColor), the strung-bead signature takes the gold token,
   bead bodies take base so the thread passes behind them. */
.gsl-catalog__ic {
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	color: var(--wp--preset--color--muted);
}

.gsl-catalog__ic svg {
	display: block;
	width: 100%;
	height: 100%;
}

.gsl-catalog__branch:hover .gsl-catalog__ic,
.gsl-catalog__branch.is-active .gsl-catalog__ic {
	color: var(--wp--preset--color--brand-text);
}

.gsl-catalog__ic-g {
	fill: var(--wp--preset--color--gold-icon);
	stroke: none;
}

/* «Фурнітура з позолотою» — єдиний розділ, чия піктограма написана золотом
   цілком: позолота і є те, чим цей розділ відрізняється від сусіднього. */
.gsl-catalog__ic-gold {
	stroke: var(--wp--preset--color--gold-icon);
	fill: none;
}

.gsl-catalog__ic-b {
	fill: var(--wp--preset--color--base);
}

.gsl-catalog__branch-short {
	display: none;
}

.gsl-catalog__arrow {
	margin-left: auto;
	color: var(--wp--preset--color--muted);
	flex-shrink: 0;
}

.gsl-catalog__panes {
	flex: 1;
	min-width: 0;
	padding: var(--wp--preset--spacing--30) var(--wp--preset--spacing--60);
}

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

/* Off the phone the drill-down back button is furniture. */
.gsl-catalog__back {
	display: none;
	align-items: center;
	gap: var(--wp--preset--spacing--20);
	border: 0;
	background: transparent;
	padding: var(--wp--preset--spacing--20) 0;
	color: var(--wp--preset--color--muted);
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	cursor: pointer;
}

.gsl-catalog__all {
	display: flex;
	align-items: baseline;
	gap: var(--wp--preset--spacing--30);
	padding-block: var(--wp--preset--spacing--20);
	color: var(--wp--preset--color--ink);
	font-size: var(--wp--preset--font-size--base);
	font-weight: 700;
	text-decoration: none;
}

.gsl-catalog__all-name {
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.gsl-catalog__all-go {
	flex-shrink: 0;
	color: var(--wp--preset--color--brand-text);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.gsl-catalog__all:hover .gsl-catalog__all-go {
	text-decoration: underline;
}

/* Підрозділи — плитки з фотографією (власник, 22.09.2026). Картинка каже, що
   всередині, підпис каже, чим воно відрізняється від сусіда: між гілками фото
   впізнаються з першого погляду, а всередині однієї гілки три підрозділи
   темних ниток намистин схожі між собою, і розрізняє їх слово. */
.gsl-catalog__subs {
	display: grid;
	grid-template-columns: repeat(4, minmax(0, 1fr));
	gap: var(--wp--preset--spacing--30);
	margin: var(--wp--preset--spacing--30) 0 0;
	padding: 0;
	list-style: none;
}

.gsl-catalog__subs a {
	display: block;
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
}

/* Хвіст підрозділів під плитками: слова там, де картинка не окупається.
   Рядок коштує чверть висоти плитки, а ці підрозділи відкривають рідко. */
.gsl-catalog__rest {
	margin-top: var(--wp--preset--spacing--30);
	padding-top: var(--wp--preset--spacing--20);
	border-top: 1px solid var(--wp--preset--color--hairline);
}

.gsl-catalog__rest-head {
	display: block;
	font-size: var(--wp--preset--font-size--label);
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	margin-bottom: 2px;
}

.gsl-catalog__rest-item {
	display: flex;
	justify-content: space-between;
	gap: var(--wp--preset--spacing--20);
	padding: 7px 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.3;
	color: var(--wp--preset--color--ink);
	text-decoration: none;
	border-bottom: 1px solid var(--wp--preset--color--hairline);
}

.gsl-catalog__rest-item i {
	font-style: normal;
	color: var(--wp--preset--color--muted);
	font-size: var(--wp--preset--font-size--label);
}

/* Квадрат, а не пропорції фото: ряд плиток має лежати рівно, чого б там не
   зняли — нитку завдовжки 75 см чи один замочок. */
.gsl-catalog__shot {
	display: block;
	aspect-ratio: 1 / 1;
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: var(--wp--custom--radius--medium);
	background: var(--wp--preset--color--base);
}

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

/* Підрозділ без жодного фото лишається плиткою: порожнє місце тримає ряд. */
.gsl-catalog__shot--empty {
	background: var(--wp--preset--color--surface);
}

.gsl-catalog__sub-name {
	/* Довге слово мусить переноситися, а не зникати: плитка вужча за
	   «Напівнамистини», і без цього хвіст слова просто зрізало. */
	overflow-wrap: anywhere;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
	margin-top: 5px;
	font-weight: 600;
	line-height: 1.3;
	color: var(--wp--preset--color--ink);
}

.gsl-catalog__sub-n {
	font-size: var(--wp--preset--font-size--label);
	color: var(--wp--preset--color--muted);
}

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

/* Laptops shorter than the rail: the panel scrolls inside itself. */
@media (min-width: 641px) {
	.gsl-catalog__panel {
		max-height: calc(100dvh - 140px);
		overflow-y: auto;
		overscroll-behavior: contain;
	}
}

@media (max-width: 1080px) {
	.gsl-catalog__subs {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* ------------------------------------------- phone: split view (v2) -------
   The owner's call after living with the drill-down for an evening: the
   rail stays, the pane slides in beside it — the WB/AliExpress catalog
   shape. One screen, one action, no second screen. Short rail labels and
   micro family labels buy the one-screen budget. */

@media (max-width: 640px) {
	/* 114 px is what the page keeps above the drawer; the 54 px the language
	   bar used to hold at the bottom went back to the rail. */
	.gsl-catalog__flyout {
		height: calc(100dvh - 114px);
	}

	/* The wrap inset is desktop air; on the phone the rail earns it back -
	   the family labels were ellipsizing over dead margin (owner, 15.08). */
	.gsl-catalog__panel .gsl-wrap {
		padding-inline: var(--wp--preset--spacing--20);
	}

	/* The rail used to squeeze its rows to fit the screen — «прокрутка
	   уводит» (owner, 15.08.2026) — and with sixteen sections the squeeze
	   landed on 36 px, a target of about seven millimetres. The owner chose
	   the other side of that trade on 22.09.2026: the row is 44 px now, the
	   size Apple asks for, and the rail scrolls by about a row and a half.
	   Sixteen rows of a finger's height beat sixteen rows nobody can hit. */
	.gsl-catalog__rail {
		flex: 0 0 48%;
		padding-block: 0;
		display: flex;
		flex-direction: column;
		overflow-y: auto;
		overscroll-behavior: contain;
	}

	.gsl-catalog__family {
		/* Підпис сім'ї — не кнопка, тож він віддає висоту рядкам, які нею є. */
		padding: 2px var(--wp--preset--spacing--30) 0;
		border-top: 1px solid var(--wp--preset--color--border);
		letter-spacing: 0.04em;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.gsl-catalog__family:first-child {
		border-top: 0;
	}

	.gsl-catalog__branch {
		flex: 0 0 auto;
		min-height: 44px;
		padding: 0 var(--wp--preset--spacing--20) 0 var(--wp--preset--spacing--30);
		gap: 8px;
		font-size: var(--wp--preset--font-size--base);
		font-weight: 600;
		line-height: 1.15;
		white-space: nowrap;
		overflow: hidden;
	}

	.gsl-catalog__ic {
		width: 20px;
		height: 20px;
	}

	.gsl-catalog__branch-short {
		overflow: hidden;
		text-overflow: ellipsis;
	}

	.gsl-catalog__family {
		flex: 0 0 auto;
	}

	.gsl-catalog__branch.is-active {
		background: var(--wp--preset--color--cream);
		color: var(--wp--preset--color--ink);
	}

	.gsl-catalog__branch-full,
	.gsl-catalog__arrow {
		display: none;
	}

	.gsl-catalog__branch-short {
		display: inline;
	}

	.gsl-catalog__panes {
		padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--40);
		overflow-y: auto;
		overscroll-behavior: contain;
	}

	/* The pane arrives, it does not just appear. */
	.gsl-catalog__pane:not([hidden]) {
		animation: gsl-pane-in 0.18s ease;
	}

	.gsl-catalog__all {
		min-height: 44px;
		align-items: center;
		gap: var(--wp--preset--spacing--20);
		border-bottom: 1px solid var(--wp--preset--color--border);
		font-size: var(--wp--preset--font-size--small);
		white-space: nowrap;
	}

	/* The rail already names the branch - the pane keeps just the door. */
	.gsl-catalog__all-name {
		display: none;
	}

	/* На телефоні дві колонки: плитка стає мішенню в пів пальця завширшки, і
	   стоїть вона під правою рукою, якою телефон і тримають. */
	.gsl-catalog__subs {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: var(--wp--preset--spacing--20);
		margin-top: var(--wp--preset--spacing--20);
	}

	/* Плитка тут завширшки пів долоні, а назви в цьому каталозі довгі:
	   «Намистини силіконові та гризунці». Два рядки різали їх на півслові,
	   три вміщують майже всі — і підпис лишається підписом, а не загадкою. */
	.gsl-catalog__sub-name {
		-webkit-line-clamp: 3;
		line-clamp: 3;
		font-size: var(--wp--preset--font-size--label);
	}
}

@keyframes gsl-pane-in {
	from {
		opacity: 0;
		transform: translateX(14px);
	}

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

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

/* On a phone the toggle is a bare burger — three dark bars drawn with a
   mask so they take the text colour. */
@media (max-width: 640px) {
	.gsl-catalog__toggle {
		background: transparent;
		border: 0;
		color: var(--wp--preset--color--contrast);
		box-shadow: none;
		width: 44px;
		min-width: 44px;
		height: 44px;
		min-height: 0;
		padding: 0;
		justify-content: center;
	}

	.gsl-catalog__toggle > span,
	.gsl-catalog__toggle .gsl-catalog__chevron,
	.gsl-catalog__toggle > svg {
		display: none;
	}

	.gsl-catalog__toggle::before {
		content: "";
		width: 26px;
		height: 26px;
		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='M3 6.4h18v1.5H3zM3 11.2h18v1.5H3zM3 16h18v1.5H3z'/%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='M3 6.4h18v1.5H3zM3 11.2h18v1.5H3zM3 16h18v1.5H3z'%3E%3C/path%3E%3C/svg%3E") center / contain no-repeat;
	}
}

/* The language row of the drawer: phone-only (the top strip owns the
   switcher on desktop). The current-language chip gets the cream token -
   the utility-bar version mixes against a dark ground, which on the
   drawer's light one would fade to nothing. */
.gsl-catalog__lang {
	display: none;
}

@media (max-width: 640px) {
	.gsl-catalog__lang {
		display: block;
		flex: 0 0 auto;
		margin-top: var(--wp--preset--spacing--10);
		padding: var(--wp--preset--spacing--10) 0 var(--wp--preset--spacing--20);
		border-top: 1px solid var(--wp--preset--color--border);
	}

	.gsl-catalog__lang .gsl-lang {
		margin-inline-start: 0;
		justify-content: flex-start;
	}

	.gsl-catalog__lang .gsl-lang__item {
		display: inline-flex;
		align-items: center;
		min-height: 40px;
		padding-inline: var(--wp--preset--spacing--50);
	}

	.gsl-catalog__lang .gsl-lang__item.is-current {
		background: var(--wp--preset--color--cream);
		color: var(--wp--preset--color--ink);
	}
}

/* The panel is absolutely positioned, so its height never reaches the
   document scroll — the panel scrolls itself; dvh keeps the math honest
   when the mobile browser chrome collapses. */
@media (max-width: 640px) {
	.gsl-catalog__panel {
		max-height: calc(100dvh - 90px);
		overflow-y: auto;
		overscroll-behavior: contain;
	}
}
/* v8 — the pane gets the width, the rail keeps every section on the screen
   (owner, 24.09.2026). On a 390 px phone the rail held 166 px and the pane
   146, and the subsection photo was 67 px — «маленькі фото». The rail sheds
   width: 120 px, an 18 px pictogram, the small type for the short labels,
   which all fit on one line in both languages. The pane goes 146 → 209 and
   the photo 67 → 99.

   Two things the first cut got wrong, both reported from the phone within
   the hour. The rail wobbled sideways: `overflow-y: auto` makes overflow-x
   auto as well, and the language row — two pills of 136 px in a 120 px rail
   — was enough for a horizontal scroll nobody asked for. And it scrolled
   down: fixed 44 px rows (22.09) plus four family labels and a 56 px
   language row run 841 px on a 730 px rail. «Нам нужно, чтобы левые
   категории были все на одной странице.»

   So: the language row leaves the rail (render.php prints it inside the
   pane box now) and sits at the right end of the pane's header row, beside
   «Всі товари →», where it costs no height — absolutely positioned inside
   the scrolling pane box, so it scrolls away with the pane rather than
   hovering over the tiles. And the rows flex again, between 36 and 44 px: a
   finger's height where the screen allows (44 on a 414×896), every section
   on one screen where it does not (39 on a 676 px rail, the owner's phone). */
@media (max-width: 640px) {
	.gsl-catalog__rail {
		flex: 0 0 120px;
		overflow-x: hidden;
	}

	.gsl-catalog__branch {
		flex: 1 1 auto;
		min-height: 36px;
		max-height: 44px;
		gap: 6px;
		padding: 0 var(--wp--preset--spacing--10) 0 6px;
		font-size: var(--wp--preset--font-size--small);
	}

	.gsl-catalog__ic {
		width: 18px;
		height: 18px;
	}

	.gsl-catalog__family {
		flex: 0 0 auto;
		padding: 0 var(--wp--preset--spacing--20);
		line-height: 1.2;
	}

	.gsl-catalog__lang {
		position: absolute;
		top: 6px;
		right: var(--wp--preset--spacing--20);
		z-index: 2;
		margin: 0;
		padding: 0;
		border: 0;
	}

	.gsl-catalog__lang .gsl-lang__item {
		min-height: 32px;
		padding-inline: var(--wp--preset--spacing--30);
	}

	.gsl-catalog__panes {
		position: relative;
		padding: var(--wp--preset--spacing--20);
	}

	.gsl-catalog__subs {
		gap: 6px;
	}
}

/* v8.1 — the page holds still under the open drawer (owner, 24.09.2026):
   the class comes from view.js while the panel is open on a phone. Only the
   document stops scrolling — body is not pinned, so scrollY, the compact
   header and the page position stay exactly as they were. The rail and the
   panes contain their own overscroll, so a swipe that runs out of pane stops
   there instead of reaching the page. */
@media (max-width: 640px) {
	/* html only: overflow on body as well would make body a scroll box of
	   its own, and the sticky header would stick to it and ride away. */
	html.gsl-catalog-lock {
		overflow: hidden;
		overscroll-behavior: none;
	}

	.gsl-catalog__rail,
	.gsl-catalog__panes {
		overscroll-behavior: contain;
	}
}

/* v8.2 — the pane springs like the rail (owner, 24.09.2026: «везде так
   пружинит, стационарно не прикольно»). A phone only rubber-bands a box
   that can scroll; a branch with four subsections could not, so the pane
   stood dead while the rail bounced. The open pane is always one pixel
   taller than its box, so it scrolls — and bounces — whatever it holds.
   The page under the drawer still does not move (v8.1). */
@media (max-width: 640px) {
	.gsl-catalog__pane:not([hidden]) {
		min-height: calc(100% + 1px);
	}
}
