.catalog-toolbar {
	align-items: center;
	margin-bottom: var(--wp--preset--spacing--6);
	padding-bottom: var(--wp--preset--spacing--4);
	border-bottom: 1px solid var(--wp--preset--color--border);
}

.catalog-layout {
	align-items: flex-start;
	gap: var(--wp--preset--spacing--10);
	flex-wrap: wrap;
}

.catalog-layout__filters {
	flex: 1 1 240px;
	max-width: 280px;
	background: var(--wp--preset--color--base-subtle);
	border-radius: 16px;
	padding: var(--wp--preset--spacing--5);
}

.catalog-layout__content {
	flex: 10 1 0%;
	min-width: 280px;
	transition: opacity var(--wp--custom--duration--fast) var(--wp--custom--ease--out);
}

/*
 * Set by catalog-filters.js while an AJAX filter/sort/page request is in
 * flight. A dim rather than a spinner: the grid the shopper was just looking
 * at is still the most useful thing on screen until the new one arrives.
 */
.catalog-layout__content.is-loading {
	opacity: 0.5;
	pointer-events: none;
}

/*
 * Every logical filter section (active chips, price, each attribute group,
 * availability) is one .catalog-filter__group div and direct child of
 * .catalog-filters, so `gap` gives consistent, adequate spacing between
 * sections without relying on margin collapsing through the group divs -
 * that previously left the section headings sitting right on top of the
 * section above once each group became its own wrapper element.
 */
.catalog-filters {
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--6);
}

.catalog-filter__heading {
	font-size: var(--wp--preset--font-size--sm);
	margin-top: 0;
	margin-bottom: var(--wp--preset--spacing--2);
}

.catalog-filter__list {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--2);
}

.catalog-filter__option {
	position: relative;
	display: block;
	padding-left: var(--wp--preset--spacing--6);
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--sm);
}

.catalog-filter__option::before {
	content: "";
	position: absolute;
	left: 0;
	top: 2px;
	width: 16px;
	height: 16px;
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 4px;
	background: var(--wp--preset--color--base);
}

.catalog-filter__option.is-active {
	font-weight: 600;
	color: var(--wp--preset--color--primary);
}

.catalog-filter__option.is-active::before {
	background: var(--wp--preset--color--primary);
	border-color: var(--wp--preset--color--primary);
}

.catalog-filter__option.is-active::after {
	content: "";
	position: absolute;
	left: 5px;
	top: 5px;
	width: 6px;
	height: 9px;
	border: solid var(--wp--preset--color--base);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.catalog-filter__count {
	color: var(--wp--preset--color--contrast-subtle);
	font-weight: 400;
}

.catalog-filter__price {
	display: flex;
	gap: var(--wp--preset--spacing--2);
	margin-bottom: var(--wp--preset--spacing--2);
}

.catalog-filter__price input[type="number"] {
	width: 0;
	flex: 1 1 auto;
	padding: var(--wp--preset--spacing--2);
	border: 1px solid var(--wp--preset--color--border);
	border-radius: 8px;
}

.catalog-filter__price button {
	flex-shrink: 0;
	padding: var(--wp--preset--spacing--2) var(--wp--preset--spacing--3);
	border: none;
	border-radius: 8px;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	cursor: pointer;
	font-size: var(--wp--preset--font-size--sm);
}

.catalog-filter__price button:hover {
	background: var(--wp--preset--color--primary-hover);
}

.catalog-filter__chips {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--2);
	margin-bottom: var(--wp--preset--spacing--2);
}

.catalog-filter__chip {
	display: inline-block;
	padding: var(--wp--preset--spacing--1) var(--wp--preset--spacing--2);
	background: var(--wp--preset--color--primary-tint);
	color: var(--wp--preset--color--primary);
	border-radius: 999px;
	font-size: var(--wp--preset--font-size--xs);
	text-decoration: none;
}

.catalog-filter__clear {
	display: inline-block;
	font-size: var(--wp--preset--font-size--xs);
	color: var(--wp--preset--color--contrast-subtle);
	margin-bottom: var(--wp--preset--spacing--3);
}

/* --- Catalog grid ---------------------------------------------------- */

/*
 * The catalogue sits next to a filter rail, so it gets three columns where
 * the full-width homepage showcase gets four.
 */
.pgrid--catalog {
	grid-template-columns: repeat(3, minmax(0, 1fr));
}

@media (max-width: 1100px) {
	.pgrid--catalog {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
}

/*
 * The homepage turns .pgrid into a swipe carousel on phones; in the
 * catalogue a vertical list is the right pattern, so opt back out.
 */
@media (max-width: 781px) {
	.pgrid--catalog {
		display: grid;
		grid-template-columns: 1fr;
		gap: var(--wp--preset--spacing--5);
		overflow-x: visible;
		margin-inline: 0;
		padding-inline: 0;
		scroll-snap-type: none;
	}

	.pgrid--catalog .pgrid__item {
		flex: initial;
	}
}

/* --- Empty state ------------------------------------------------------ */

.catalog-empty {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--wp--preset--spacing--3);
	padding: var(--wp--preset--spacing--16) var(--wp--preset--spacing--8);
	background: var(--wp--preset--color--base-soft);
	border-radius: var(--wp--custom--radius--lg);
}

.catalog-empty__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--xl-2);
	font-weight: 700;
	letter-spacing: -0.02em;
}

.catalog-empty__text {
	margin: 0 0 var(--wp--preset--spacing--2);
	color: var(--wp--preset--color--contrast-subtle);
}

/* --- Pagination -------------------------------------------------------- */

.catalog-pagination {
	margin-top: var(--wp--preset--spacing--12);
}

.catalog-pagination ul {
	list-style: none;
	margin: 0;
	padding: 0;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--wp--preset--spacing--2);
}

.catalog-pagination a,
.catalog-pagination span {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 44px;
	height: 44px;
	padding-inline: var(--wp--preset--spacing--3);
	border: 1px solid var(--wp--custom--border--on-light);
	border-radius: var(--wp--custom--radius--md);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	font-variant-numeric: tabular-nums;
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
	transition:
		background-color var(--wp--custom--duration--fast) var(--wp--custom--ease--out),
		border-color var(--wp--custom--duration--fast) var(--wp--custom--ease--out),
		color var(--wp--custom--duration--fast) var(--wp--custom--ease--out);
}

.catalog-pagination a:hover {
	border-color: var(--wp--preset--color--contrast);
}

.catalog-pagination .current {
	background: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
}

.catalog-pagination .dots {
	border-color: transparent;
	min-width: 0;
	padding-inline: var(--wp--preset--spacing--1);
}

/* --- Filters: toggle + bottom sheet on phones ------------------------- */

.filters__toggle {
	box-sizing: border-box; /* width:100% plus a 1px border must not overflow. */
	list-style: none;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	gap: var(--wp--preset--spacing--2);
	min-height: 48px;
	padding: 0 var(--wp--preset--spacing--5);
	border: 1px solid var(--wp--preset--color--contrast);
	border-radius: var(--wp--custom--radius--md);
	background: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--sm);
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
}

.filters__toggle::-webkit-details-marker {
	display: none;
}

.filters__toggle-count {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 20px;
	height: 20px;
	padding: 0 6px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--xs);
	font-variant-numeric: tabular-nums;
}

/*
 * The panel heading stays in the accessibility tree on desktop even though it
 * is not drawn: display:none would remove it, and the filter group headings
 * below it would then skip straight from the page h1 to h3.
 */
.filters__panel-head {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.filters__panel-title {
	margin: 0;
	font-size: var(--wp--preset--font-size--lg);
	font-weight: 700;
	letter-spacing: -0.02em;
}

/*
 * Desktop: no toggle, panel always open. Author styles beat the UA rule that
 * hides a closed <details>'s content, so no `open` attribute is needed - which
 * matters because PHP cannot know the viewport width.
 */
@media (min-width: 782px) {
	.filters__toggle {
		display: none;
	}

	.filters > .filters__panel {
		display: block;
		content-visibility: visible;
	}
}

@media (max-width: 781px) {
	/* Collapsed, the whole filter rail is one 48px button. */
	.catalog-layout__filters {
		flex: 1 1 100%;
		max-width: none;
		background: none;
		padding: 0;
		margin-bottom: var(--wp--preset--spacing--5);
	}

	.filters__toggle {
		width: 100%;
	}

	/* Backdrop: it is the summary itself, so tapping it closes the sheet. */
	.filters[open] .filters__toggle::before {
		content: "";
		position: fixed;
		inset: 0;
		z-index: 120;
		background: rgba(5, 5, 5, 0.5);
	}

	.filters[open] > .filters__panel {
		position: fixed;
		left: 0;
		right: 0;
		bottom: 0;
		z-index: 121;
		max-height: 82vh;
		overflow-y: auto;
		overscroll-behavior: contain;
		background: var(--wp--preset--color--base);
		border-radius: var(--wp--custom--radius--lg) var(--wp--custom--radius--lg) 0 0;
		box-shadow: var(--wp--custom--shadow--lg);
		padding: var(--wp--preset--spacing--5);
		padding-bottom: calc(var(--wp--preset--spacing--8) + env(safe-area-inset-bottom, 0px));
		animation: ef-sheet-in var(--wp--custom--duration--base) var(--wp--custom--ease--out);
	}

	.filters[open] .filters__panel-head {
		position: static;
		width: auto;
		height: auto;
		overflow: visible;
		clip-path: none;
		white-space: normal;
		display: flex;
		align-items: center;
		justify-content: space-between;
		margin-bottom: var(--wp--preset--spacing--4);
		padding-bottom: var(--wp--preset--spacing--3);
		border-bottom: 1px solid var(--wp--custom--border--on-light);
	}

	/* Grab handle, the usual affordance for a sheet. */
	.filters[open] .filters__panel-head::after {
		content: "";
		position: absolute;
		top: var(--wp--preset--spacing--2);
		left: 50%;
		transform: translateX(-50%);
		width: 40px;
		height: 4px;
		border-radius: var(--wp--custom--radius--pill);
		background: var(--wp--preset--color--border);
	}

	.filters[open] > .filters__panel {
		position: fixed;
	}

	.filters__panel {
		position: relative;
	}

	/* Comfortable tap targets inside the sheet. */
	.catalog-filter__option {
		padding-block: var(--wp--preset--spacing--2);
	}
}

/*
 * Deliberately a 16px nudge, not a full translateY(100%) slide.
 *
 * A frame-0 state of translateY(100%) parks the sheet entirely off-screen, so
 * anywhere the animation does not actually run - a throttled background tab,
 * a rendering hiccup - the control the shopper just tapped is invisible and
 * unreachable. Starting 16px low keeps the sheet usable even if it never
 * animates at all.
 */
@keyframes ef-sheet-in {
	from {
		transform: translateY(16px);
	}
}

@media (max-width: 781px) {
	/*
	 * Everything inside the filter sheet is operated with a thumb, so the
	 * rows, the price inputs and the sorting select all get a full 44px.
	 * The checkbox pseudo-element is centred against the row rather than
	 * pinned to the first text line.
	 */
	.catalog-filter__option {
		display: flex;
		align-items: center;
		min-height: 44px;
		padding-block: 0;
	}

	.catalog-filter__option::before {
		top: 50%;
		transform: translateY(-50%);
	}

	.catalog-filter__option.is-active::after {
		top: 50%;
		margin-top: -6px;
	}

	.catalog-filter__price input[type="number"],
	.catalog-filter__price button {
		min-height: 44px;
	}

	.catalog-toolbar .woocommerce-ordering select,
	.wp-block-woocommerce-catalog-sorting select {
		min-height: 44px;
		padding-inline: var(--wp--preset--spacing--3);
		border: 1px solid var(--wp--custom--border--on-light);
		border-radius: var(--wp--custom--radius--md);
		background: var(--wp--preset--color--base);
		font-size: var(--wp--preset--font-size--sm);
	}

	/*
	 * line-height alone does not grow an inline anchor's hit box - the rect
	 * still follows the font metrics. inline-block plus vertical padding is
	 * what actually makes a breadcrumb tappable.
	 */
	.wp-block-woocommerce-breadcrumbs a {
		display: inline-block;
		padding-block: 12px;
	}
}
