/**
 * Kanvox Product Showcase — frontend styles.
 *
 * Only the chrome is styled here: tabs, toolbar, filter panel, states.
 * Product cards deliberately keep whatever design the merchant has configured
 * in Woodmart's product-hover setting, so this block matches the rest of the
 * shop instead of fighting it.
 *
 * SPECIFICITY NOTE
 * Woodmart styles bare `button` and `input` elements with fairly specific
 * selectors, which beat plain single-class rules and were flattening the tabs,
 * the search field and the filter button. Interactive elements are therefore
 * written at `.kvx-showcase.kvx-showcase` (0,3,0) — the same doubled-class
 * trick the theme itself uses for `.wd.wd` — and preceded by an explicit
 * reset. Layout-only rules stay at single specificity.
 *
 * Every colour is a custom property, so class-block-css.php (Gutenberg) and
 * Elementor's `selectors` (Elementor) can override any of them per instance.
 */

.kvx-showcase {
	--kvx-accent: #2f5fe8;
	--kvx-accent-weak: rgba(47, 95, 232, 0.08);
	--kvx-price: #e31b23;
	--kvx-ink: #111827;
	--kvx-muted: #6b7280;
	--kvx-line: #e5e7eb;
	--kvx-line-strong: #d1d5db;
	--kvx-surface: #fff;
	--kvx-surface-2: #f9fafb;
	--kvx-radius: 12px;
	--kvx-radius-pill: 999px;
	--kvx-tabs-gap: 8px;
	--kvx-grid-gap: 20px;
	--kvx-panel-w: 380px;
	--kvx-ctl-h: 40px;
	--kvx-icon: 17px;
	--kvx-dur: 0.22s;

	position: relative;
}

/* ------------------------------------------------------------------ *
 * Control reset — neutralises theme button/input styling
 * ------------------------------------------------------------------ */

/*
 * Woodmart's base.css styles EVERY button in the document with
 *
 *   :is(.btn, .button, button, [type=submit], [type=button]) {
 *       padding: var(--btn-padding, 5px 20px);
 *       min-height: var(--btn-height, 42px);
 *       text-transform: var(--btn-transform, uppercase);
 *       background-color: var(--btn-bgcolor, #F3F3F3);
 *       gap: 5px; ...
 *   }
 *
 * `:is()` takes the specificity of its heaviest argument — `.btn`, i.e. (0,1,0)
 * — so it loses to our (0,3,0) selectors, but only for properties we actually
 * declare and only for elements we actually list. Every control the block
 * renders must therefore appear below, including the pagination buttons, and
 * the reset must zero the box model itself (`box-sizing`, `padding`, `width`,
 * `height`, `min-height`) rather than assuming the theme left it alone.
 *
 * `input[type=search]` needs the same treatment for a second reason: the theme
 * forces `box-sizing: content-box` and `padding: 0 15px; width: 100%` on it,
 * which is what pushed the field out from under its pill and let the value and
 * placeholder ride over the magnifier.
 */
.kvx-showcase.kvx-showcase .kvx-tab,
.kvx-showcase.kvx-showcase .kvx-tabs__nav,
.kvx-showcase.kvx-showcase .kvx-filter-btn,
.kvx-showcase.kvx-showcase .kvx-search__clear,
.kvx-showcase.kvx-showcase .kvx-panel__close,
.kvx-showcase.kvx-showcase .kvx-btn,
.kvx-showcase.kvx-showcase .kvx-more,
.kvx-showcase.kvx-showcase .kvx-pages__num,
.kvx-showcase.kvx-showcase .kvx-pages__step,
.kvx-showcase.kvx-showcase .kvx-showcase__empty-reset,
.kvx-showcase.kvx-showcase .kvx-search__input,
.kvx-showcase.kvx-showcase .kvx-price__box input {
	-webkit-appearance: none;
	appearance: none;
	box-sizing: border-box;
	margin: 0;
	padding: 0;
	width: auto;
	height: auto;
	min-width: 0;
	min-height: 0;
	max-width: none;
	max-height: none;
	font-family: inherit;
	font-weight: 500;
	text-transform: none;
	letter-spacing: normal;
	text-decoration: none;
	text-shadow: none;
	box-shadow: none;
	background-image: none;
	transform: none;
	vertical-align: middle;
	line-height: 1.3;
}

.kvx-showcase.kvx-showcase .kvx-tab::before,
.kvx-showcase.kvx-showcase .kvx-tab::after,
.kvx-showcase.kvx-showcase .kvx-tabs__nav::before,
.kvx-showcase.kvx-showcase .kvx-tabs__nav::after,
.kvx-showcase.kvx-showcase .kvx-filter-btn::before,
.kvx-showcase.kvx-showcase .kvx-filter-btn::after,
.kvx-showcase.kvx-showcase .kvx-search__clear::before,
.kvx-showcase.kvx-showcase .kvx-search__clear::after,
.kvx-showcase.kvx-showcase .kvx-panel__close::before,
.kvx-showcase.kvx-showcase .kvx-panel__close::after,
.kvx-showcase.kvx-showcase .kvx-btn::before,
.kvx-showcase.kvx-showcase .kvx-btn::after,
.kvx-showcase.kvx-showcase .kvx-more::before,
.kvx-showcase.kvx-showcase .kvx-more::after,
.kvx-showcase.kvx-showcase .kvx-pages__num::before,
.kvx-showcase.kvx-showcase .kvx-pages__num::after,
.kvx-showcase.kvx-showcase .kvx-pages__step::before,
.kvx-showcase.kvx-showcase .kvx-pages__step::after {
	display: none;
}

/*
 * Icons are laid out as real flex items, so a collapsed icon does not just look
 * wrong — it lets its neighbour slide underneath. The size is pinned from both
 * ends (`width`/`height` plus matching `min-*`) and `flex: 0 0 auto` keeps
 * flexbox from shrinking it to nothing inside a tight control.
 */
.kvx-showcase.kvx-showcase .kvx-icon {
	display: block;
	flex: 0 0 auto;
	box-sizing: content-box;
	width: var(--kvx-icon);
	height: var(--kvx-icon);
	min-width: var(--kvx-icon);
	min-height: var(--kvx-icon);
	max-width: none;
	max-height: none;
	margin: 0;
	padding: 0;
	border: 0;
	overflow: visible;
	vertical-align: middle;
	fill: none;
	stroke: currentColor;
	pointer-events: none;
}

/* Knobs sit on top of their rail and mask it. */
.kvx-showcase .kvx-icon .kvx-knob {
	fill: var(--kvx-surface);
	stroke: currentColor;
}

/* ------------------------------------------------------------------ *
 * Top bar
 * ------------------------------------------------------------------ */

.kvx-showcase__bar {
	display: flex;
	align-items: center;
	gap: 16px;
	margin-bottom: 20px;
	min-width: 0;
}

.kvx-tabs__viewport {
	position: relative;
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	align-items: center;
}

.kvx-tools {
	flex: 0 0 auto;
	display: flex;
	align-items: center;
	gap: 10px;
}

/* ------------------------------------------------------------------ *
 * Tabs
 * ------------------------------------------------------------------ */

.kvx-tabs {
	display: flex;
	align-items: center;
	gap: var(--kvx-tabs-gap);
	overflow-x: auto;
	overflow-y: hidden;
	scroll-behavior: smooth;
	scrollbar-width: none;
	-ms-overflow-style: none;
	-webkit-overflow-scrolling: touch;
	scroll-snap-type: x proximity;
	padding: 2px;
	margin: -2px;
	min-width: 0;
}

.kvx-tabs::-webkit-scrollbar {
	display: none;
}

/* Inactive: white pill, hairline border, dark label. */
.kvx-showcase.kvx-showcase .kvx-tab {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 7px;
	height: var(--kvx-ctl-h);
	padding: 0 15px;
	border: 1px solid var(--kvx-line);
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	font-size: 13px;
	white-space: nowrap;
	cursor: pointer;
	scroll-snap-align: start;
	transition: border-color var(--kvx-dur) ease, color var(--kvx-dur) ease,
		background-color var(--kvx-dur) ease;
}

.kvx-showcase.kvx-showcase .kvx-tab:hover {
	border-color: var(--kvx-line-strong);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
}

/* Active: accent border, accent label, solid accent dot. */
.kvx-showcase.kvx-showcase .kvx-tab.is-active {
	border-color: var(--kvx-accent);
	background-color: var(--kvx-surface);
	color: var(--kvx-accent);
}

.kvx-showcase.kvx-showcase .kvx-tab:focus-visible {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

.kvx-showcase .kvx-tab__dot {
	flex: 0 0 auto;
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background-color: var(--kvx-line-strong);
	transition: background-color var(--kvx-dur) ease;
}

.kvx-showcase .kvx-tab.is-active .kvx-tab__dot {
	background-color: var(--kvx-accent);
}

.kvx-showcase .kvx-tab__label {
	display: inline-block;
}

/* Scroll arrows — only shown when the strip actually overflows. */

.kvx-showcase.kvx-showcase .kvx-tabs__nav {
	--kvx-icon: 15px;
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	min-width: 28px;
	height: 28px;
	padding: 0;
	border: 1px solid var(--kvx-line);
	border-radius: 50%;
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	cursor: pointer;
	z-index: 2;
}

.kvx-showcase.kvx-showcase .kvx-tabs__nav[hidden] {
	display: none;
}

.kvx-tabs__nav--prev {
	margin-right: 6px;
}

.kvx-tabs__nav--next {
	margin-left: 6px;
}

.kvx-showcase.kvx-showcase .kvx-tabs__nav:focus-visible {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

/* Edge fades hint that there is more to scroll. */

.kvx-tabs__viewport::before,
.kvx-tabs__viewport::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 32px;
	pointer-events: none;
	opacity: 0;
	transition: opacity var(--kvx-dur) ease;
	z-index: 1;
}

.kvx-tabs__viewport::before {
	left: 0;
	background: linear-gradient(to right, var(--kvx-surface), transparent);
}

.kvx-tabs__viewport::after {
	right: 0;
	background: linear-gradient(to left, var(--kvx-surface), transparent);
}

.kvx-has-overflow:not(.kvx-at-start) .kvx-tabs__viewport::before,
.kvx-has-overflow:not(.kvx-at-end) .kvx-tabs__viewport::after {
	opacity: 1;
}

/* ------------------------------------------------------------------ *
 * Search
 * ------------------------------------------------------------------ */

/*
 * The icon is a flex SIBLING of the input, not an overlay.
 *
 * The overlay approach depended on the input keeping a large `padding-left`,
 * and the theme's own input rules were resetting that — dropping the magnifier
 * straight on top of the placeholder. Here the icon occupies real space in the
 * row, so overlap is impossible no matter what padding the input ends up with.
 *
 * The pill border and background also live on the wrapper, which is a plain
 * <div>. Themes style `input` and `button` heavily; they almost never style an
 * arbitrary div, so the shape survives too.
 *
 * `overflow: hidden` is the last line of defence: even if something downstream
 * re-inflates the field, it is clipped to the pill instead of spilling across
 * the icon. The focus ring is the wrapper's own box-shadow, which is painted
 * outside the padding box and so is not clipped by this.
 */
.kvx-showcase .kvx-search {
	box-sizing: border-box;
	position: relative;
	display: flex;
	align-items: center;
	gap: 8px;
	width: 240px;
	max-width: 100%;
	height: var(--kvx-ctl-h);
	padding: 0 8px 0 12px;
	border: 1px solid var(--kvx-line);
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-surface);
	overflow: hidden;
	transition: border-color var(--kvx-dur) ease, box-shadow var(--kvx-dur) ease;
}

.kvx-showcase .kvx-search:focus-within {
	border-color: var(--kvx-accent);
	box-shadow: 0 0 0 3px var(--kvx-accent-weak);
}

/* Sized explicitly so the icon column exists even before the SVG paints. */
.kvx-showcase .kvx-search__icon {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: var(--kvx-icon);
	height: var(--kvx-icon);
	color: var(--kvx-muted);
	pointer-events: none;
}

/*
 * The input is a bare text field inside the pill — no chrome of its own.
 *
 * `flex: 1 1 0%` with `width: auto` is deliberate. The old `width: 100%` was a
 * percentage resolved against the wrapper, and Woodmart forces
 * `box-sizing: content-box` on `input[type=search]`, so any padding the theme
 * managed to keep was ADDED to that 100% — the field then overflowed the pill
 * and its text ran under the magnifier. Sizing purely from the free space
 * removes the percentage, and the explicit `box-sizing` removes the theme's
 * content-box override.
 *
 * `align-self: stretch` + `height: auto` fills the pill exactly, rather than
 * `height: 100%` which resolves against the wrapper's border box and left the
 * text sitting a couple of pixels low.
 */
.kvx-showcase.kvx-showcase .kvx-search__input,
.kvx-showcase.kvx-showcase .kvx-search__input:focus,
.kvx-showcase.kvx-showcase .kvx-search__input:hover {
	flex: 1 1 0%;
	box-sizing: border-box;
	align-self: stretch;
	width: auto;
	min-width: 0;
	max-width: 100%;
	height: auto;
	min-height: 0;
	margin: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background-color: transparent;
	background-image: none;
	color: var(--kvx-ink);
	font-size: 13px;
	font-weight: 400;
	line-height: 1.2;
	text-indent: 0;
	text-align: start;
	vertical-align: middle;
	box-shadow: none;
	outline: none;
	-webkit-appearance: none;
	appearance: none;
}

.kvx-showcase.kvx-showcase .kvx-search__input::placeholder {
	color: var(--kvx-muted);
	opacity: 1;
}

/* Kill the native clear affordance so ours is the only one. */
.kvx-showcase .kvx-search__input::-webkit-search-cancel-button,
.kvx-showcase .kvx-search__input::-webkit-search-decoration {
	-webkit-appearance: none;
	appearance: none;
}

.kvx-showcase.kvx-showcase .kvx-search__clear {
	--kvx-icon: 12px;
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 22px;
	min-width: 22px;
	height: 22px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: var(--kvx-surface-2);
	color: var(--kvx-muted);
	cursor: pointer;
}

/*
 * Visually-hidden labels. `.screen-reader-text` is defined by themes rather
 * than WordPress core, so we cannot assume it exists — without it the label
 * would take up space inside the flex row and shove the field sideways.
 */
.kvx-showcase .screen-reader-text {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.kvx-showcase.kvx-showcase .kvx-search__clear[hidden] {
	display: none;
}

.kvx-showcase.kvx-showcase .kvx-search__clear:hover {
	color: var(--kvx-ink);
}

/* Sizing rides on `--kvx-icon` (set on the button above) so the min-width and
   min-height floors in the icon reset scale with it. */

/* ------------------------------------------------------------------ *
 * Filter button
 * ------------------------------------------------------------------ */

.kvx-showcase.kvx-showcase .kvx-filter-btn {
	position: relative;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex: 0 0 auto;
	width: var(--kvx-ctl-h);
	min-width: var(--kvx-ctl-h);
	height: var(--kvx-ctl-h);
	padding: 0;
	border: 1px solid var(--kvx-line);
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	cursor: pointer;
	transition: border-color var(--kvx-dur) ease, color var(--kvx-dur) ease;
}

.kvx-showcase.kvx-showcase .kvx-filter-btn:hover,
.kvx-has-filters.kvx-showcase.kvx-showcase .kvx-filter-btn {
	border-color: var(--kvx-accent);
	color: var(--kvx-accent);
	background-color: var(--kvx-surface);
}

.kvx-showcase.kvx-showcase .kvx-filter-btn:focus-visible {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

.kvx-showcase .kvx-filter-btn__count {
	position: absolute;
	top: -5px;
	right: -5px;
	min-width: 18px;
	height: 18px;
	padding: 0 5px;
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-price);
	color: #fff;
	font-size: 10px;
	font-weight: 700;
	line-height: 18px;
	text-align: center;
	font-variant-numeric: tabular-nums;
}

.kvx-showcase .kvx-filter-btn__count[hidden] {
	display: none;
}

/* ------------------------------------------------------------------ *
 * Grid + states
 * ------------------------------------------------------------------ */

.kvx-showcase__count {
	margin: 0 0 12px;
	color: var(--kvx-muted);
	font-size: 13px;
	font-variant-numeric: tabular-nums;
}

.kvx-showcase__grid {
	position: relative;
	min-height: 120px;
	transition: opacity var(--kvx-dur) ease;
}

.kvx-is-loading .kvx-showcase__grid {
	opacity: 0.4;
	pointer-events: none;
}

.kvx-showcase__loader {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	pointer-events: none;
	opacity: 0;
	transition: opacity var(--kvx-dur) ease;
	z-index: 3;
}

.kvx-is-loading .kvx-showcase__loader {
	opacity: 1;
}

.kvx-spinner {
	display: block;
	width: 32px;
	height: 32px;
	border: 2px solid var(--kvx-line);
	border-top-color: var(--kvx-accent);
	border-radius: 50%;
	animation: kvx-spin 0.7s linear infinite;
}

@keyframes kvx-spin {
	to {
		transform: rotate(360deg);
	}
}

.kvx-showcase__empty,
.kvx-showcase__error {
	padding: 48px 20px;
	text-align: center;
	color: var(--kvx-muted);
}

.kvx-showcase__empty-title {
	margin: 0 0 6px;
	color: var(--kvx-ink);
	font-size: 16px;
	font-weight: 600;
}

.kvx-showcase__empty-hint {
	margin: 0 0 16px;
	font-size: 13px;
}

.kvx-showcase.kvx-showcase .kvx-showcase__empty-reset {
	height: var(--kvx-ctl-h);
	padding: 0 20px;
	border: 1px solid var(--kvx-line);
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	font-size: 13px;
	cursor: pointer;
}

.kvx-showcase.kvx-showcase .kvx-showcase__empty-reset:hover {
	border-color: var(--kvx-accent);
	color: var(--kvx-accent);
}

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

/*
 * The rail is written at `.kvx-showcase .kvx-showcase__pagination` (0,2,0)
 * rather than on the bare class, because the theme's layout helpers reach the
 * children of a block wrapper at single-class specificity and were winning the
 * `display`/`text-align` fight — which is what knocked both controls off centre.
 *
 * `width: 100%` matters as much as `justify-content`: as a flex child of some
 * of Woodmart's row wrappers the rail would otherwise shrink to fit its button
 * and then be positioned by the PARENT's alignment, so centring itself achieved
 * nothing. Claiming the full row makes the centring its own decision.
 */
.kvx-showcase .kvx-showcase__pagination {
	box-sizing: border-box;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	width: 100%;
	margin: 28px 0 0;
	padding: 0;
	text-align: center;
	clear: both;
}

/*
 * Two rules, not one selector list: an engine without `:has()` support would
 * throw away the whole list, taking the `:empty` fallback with it.
 *
 * `:empty` covers the post-AJAX state, where frontend.js has assigned an empty
 * innerHTML. `:has()` covers first paint, where render.php's indentation leaves
 * a whitespace text node behind and `:empty` no longer matches.
 */
.kvx-showcase .kvx-showcase__pagination:empty {
	display: none;
	margin-top: 0;
}

.kvx-showcase .kvx-showcase__pagination:not(:has(> *)) {
	display: none;
	margin-top: 0;
}

/* ---- load more ---- */

.kvx-showcase.kvx-showcase .kvx-more {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 9px;
	height: 42px;
	min-height: 42px;
	max-width: 100%;
	padding: 0 24px;
	margin: 0 auto;
	border: 1px solid var(--kvx-line-strong);
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	font-size: 13px;
	font-weight: 600;
	line-height: 1;
	text-align: center;
	cursor: pointer;
	transition: border-color var(--kvx-dur) ease, color var(--kvx-dur) ease;
}

.kvx-showcase.kvx-showcase .kvx-more:hover:not(:disabled) {
	border-color: var(--kvx-accent);
	color: var(--kvx-accent);
}

.kvx-showcase.kvx-showcase .kvx-more:disabled {
	cursor: default;
	opacity: 0.65;
}

.kvx-showcase.kvx-showcase .kvx-more:focus-visible {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

/* The spinner only takes up space while a page is in flight. */
.kvx-more__spinner {
	display: none;
	flex: 0 0 auto;
	box-sizing: border-box;
	width: 15px;
	height: 15px;
	border: 2px solid currentColor;
	border-top-color: transparent;
	border-radius: 50%;
	animation: kvx-spin 0.7s linear infinite;
}

.kvx-is-loading-more .kvx-more__spinner {
	display: block;
}

/* ---- numbered pages ---- */

/*
 * The <nav> is a flex child of the rail above, so it must claim the full row
 * before centring its own contents — otherwise it shrink-wraps the buttons and
 * inherits whatever alignment the surrounding layout happens to apply.
 */
.kvx-showcase .kvx-pages {
	box-sizing: border-box;
	display: flex;
	align-items: center;
	flex-wrap: wrap;
	justify-content: center;
	gap: 6px;
	width: 100%;
	margin: 0;
	padding: 0;
	text-align: center;
}

/*
 * These two were missing from the control reset entirely, so the theme's
 * `min-height: var(--btn-height, 42px)` was stretching them past their 38px
 * `height` — the numbers ended up in tall ovals that sat off the baseline of
 * the arrows. They are in the reset now; `min-height` is restated here so the
 * pill stays square whatever `--btn-height` the merchant has configured.
 */
.kvx-showcase.kvx-showcase .kvx-pages__num,
.kvx-showcase.kvx-showcase .kvx-pages__step {
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 36px;
	width: auto;
	height: 36px;
	min-height: 36px;
	padding: 0 8px;
	border: 1px solid var(--kvx-line);
	border-radius: var(--kvx-radius-pill);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	font-size: 13px;
	line-height: 1;
	font-variant-numeric: tabular-nums;
	cursor: pointer;
	transition: border-color var(--kvx-dur) ease, color var(--kvx-dur) ease,
		background-color var(--kvx-dur) ease;
}

/* Arrow buttons hold an icon rather than a number — no side padding wanted. */
.kvx-showcase.kvx-showcase .kvx-pages__step {
	--kvx-icon: 15px;
	width: 36px;
	padding: 0;
}

.kvx-showcase.kvx-showcase .kvx-pages__num:hover:not(.is-current),
.kvx-showcase.kvx-showcase .kvx-pages__step:hover:not(:disabled) {
	border-color: var(--kvx-accent);
	color: var(--kvx-accent);
}

.kvx-showcase.kvx-showcase .kvx-pages__num.is-current {
	border-color: var(--kvx-accent);
	background-color: var(--kvx-accent);
	color: #fff;
	cursor: default;
	font-weight: 600;
}

.kvx-showcase.kvx-showcase .kvx-pages__step:disabled {
	opacity: 0.4;
	cursor: default;
}

.kvx-showcase.kvx-showcase .kvx-pages__num:focus-visible,
.kvx-showcase.kvx-showcase .kvx-pages__step:focus-visible {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

.kvx-pages__gap {
	padding: 0 2px;
	color: var(--kvx-muted);
	user-select: none;
}

/* ------------------------------------------------------------------ *
 * Filter panel
 * ------------------------------------------------------------------ */

.kvx-panel-backdrop {
	position: fixed;
	inset: 0;
	background-color: rgba(17, 24, 39, 0.45);
	opacity: 0;
	transition: opacity var(--kvx-dur) ease;
	z-index: 999998;
}

.kvx-panel-backdrop[hidden] {
	display: none;
}

.kvx-panel-open .kvx-panel-backdrop {
	opacity: 1;
}

.kvx-panel {
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: var(--kvx-panel-w);
	max-width: 92vw;
	display: flex;
	flex-direction: column;
	background-color: var(--kvx-surface);
	box-shadow: -8px 0 40px rgba(17, 24, 39, 0.14);
	transform: translateX(100%);
	transition: transform var(--kvx-dur) cubic-bezier(0.4, 0, 0.2, 1);
	z-index: 999999;
}

.kvx-panel[hidden] {
	display: none;
}

.kvx-panel-open .kvx-panel {
	transform: translateX(0);
}

.kvx-panel__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	padding: 18px 20px;
	border-bottom: 1px solid var(--kvx-line);
}

.kvx-panel__title {
	margin: 0;
	font-size: 16px;
	font-weight: 600;
	color: var(--kvx-ink);
}

.kvx-showcase.kvx-showcase .kvx-panel__close {
	--kvx-icon: 16px;
	flex: 0 0 auto;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 30px;
	min-width: 30px;
	height: 30px;
	padding: 0;
	border: 0;
	border-radius: 50%;
	background-color: var(--kvx-surface-2);
	color: var(--kvx-ink);
	cursor: pointer;
}

.kvx-showcase.kvx-showcase .kvx-panel__close:hover {
	background-color: var(--kvx-line);
}

.kvx-panel__body {
	flex: 1 1 auto;
	overflow-y: auto;
	padding: 4px 20px 20px;
	-webkit-overflow-scrolling: touch;
}

.kvx-panel__foot {
	flex: 0 0 auto;
	display: flex;
	gap: 10px;
	padding: 16px 20px;
	border-top: 1px solid var(--kvx-line);
	background-color: var(--kvx-surface);
}

.kvx-showcase.kvx-showcase .kvx-btn {
	flex: 1 1 auto;
	height: 44px;
	padding: 0 18px;
	border-radius: var(--kvx-radius-pill);
	font-size: 13px;
	font-weight: 600;
	cursor: pointer;
	transition: opacity var(--kvx-dur) ease, border-color var(--kvx-dur) ease;
}

.kvx-showcase.kvx-showcase .kvx-btn--ghost {
	border: 1px solid var(--kvx-line);
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
}

.kvx-showcase.kvx-showcase .kvx-btn--ghost:hover {
	border-color: var(--kvx-line-strong);
}

.kvx-showcase.kvx-showcase .kvx-btn--solid {
	border: 1px solid var(--kvx-accent);
	background-color: var(--kvx-accent);
	color: #fff;
}

.kvx-showcase.kvx-showcase .kvx-btn--solid:hover {
	opacity: 0.9;
	color: #fff;
}

.kvx-showcase.kvx-showcase .kvx-btn:focus-visible {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

/* ---- panel fields ---- */

.kvx-field {
	margin: 0;
	padding: 18px 0;
	border: 0;
	border-bottom: 1px solid var(--kvx-line);
}

.kvx-field:last-of-type {
	border-bottom: 0;
}

.kvx-field__legend {
	padding: 0;
	margin-bottom: 12px;
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--kvx-muted);
}

.kvx-price {
	display: flex;
	align-items: center;
	gap: 10px;
}

.kvx-price__box {
	flex: 1 1 0;
	min-width: 0;
	margin: 0;
}

.kvx-showcase.kvx-showcase .kvx-price__box input {
	width: 100%;
	height: var(--kvx-ctl-h);
	padding: 0 12px;
	border: 1px solid var(--kvx-line);
	border-radius: 8px;
	background-color: var(--kvx-surface);
	color: var(--kvx-ink);
	font-size: 13px;
	font-weight: 400;
	font-variant-numeric: tabular-nums;
}

.kvx-showcase.kvx-showcase .kvx-price__box input:focus {
	border-color: var(--kvx-accent);
	box-shadow: 0 0 0 3px var(--kvx-accent-weak);
	outline: none;
}

.kvx-price__sep {
	color: var(--kvx-muted);
}

.kvx-checks {
	display: flex;
	flex-direction: column;
	gap: 10px;
	max-height: 240px;
	overflow-y: auto;
}

.kvx-checks--inline {
	flex-direction: row;
	flex-wrap: wrap;
	gap: 8px;
	max-height: none;
}

.kvx-showcase .kvx-check {
	display: flex;
	align-items: center;
	gap: 10px;
	margin: 0;
	cursor: pointer;
	font-size: 13px;
	color: var(--kvx-ink);
}

.kvx-showcase .kvx-check input,
.kvx-showcase .kvx-chip input {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
	margin: 0;
}

.kvx-check__box {
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	border: 1px solid var(--kvx-line-strong);
	border-radius: 5px;
	background-color: var(--kvx-surface);
	transition: border-color var(--kvx-dur) ease, background-color var(--kvx-dur) ease;
	position: relative;
}

.kvx-check__box--radio {
	border-radius: 50%;
}

.kvx-check input:checked + .kvx-check__box {
	border-color: var(--kvx-accent);
	background-color: var(--kvx-accent);
}

.kvx-check input:checked + .kvx-check__box::after {
	content: "";
	position: absolute;
	left: 5px;
	top: 1px;
	width: 5px;
	height: 10px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.kvx-check input:checked + .kvx-check__box--radio::after {
	left: 5px;
	top: 5px;
	width: 6px;
	height: 6px;
	border: 0;
	border-radius: 50%;
	background-color: #fff;
	transform: none;
}

.kvx-check input:focus-visible + .kvx-check__box {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

.kvx-check__label {
	flex: 1 1 auto;
}

.kvx-check__count {
	flex: 0 0 auto;
	color: var(--kvx-muted);
	font-size: 12px;
	font-variant-numeric: tabular-nums;
}

/* ------------------------------------------------------------------ *
 * Facet visibility
 * ------------------------------------------------------------------ */

/*
 * The UA rule for `[hidden]` is `display: none` at (0,0,1) — our own layout
 * rules for these elements are (0,2,0) and were silently beating it, so a term
 * the counter had hidden stayed on screen. Restated here with the attribute in
 * the selector so hiding always wins, without reaching for !important.
 */
.kvx-showcase .kvx-field[hidden],
.kvx-showcase .kvx-check[hidden],
.kvx-showcase .kvx-chip[hidden],
.kvx-showcase .kvx-swatch-opt[hidden] {
	display: none;
}

/* Depth indent for the category tree. Rendered as a flat list with an indent
   rather than nested <ul>s, so any single row can be hidden on its own. */
.kvx-showcase .kvx-check--child {
	padding-inline-start: calc(var(--kvx-depth, 0) * 18px);
}

/* ------------------------------------------------------------------ *
 * Swatches — brand logos and colour chips
 * ------------------------------------------------------------------ */

.kvx-checks--swatch {
	flex-direction: row;
	flex-wrap: wrap;
	gap: 10px;
	max-height: none;
}

.kvx-showcase .kvx-swatch-opt {
	position: relative;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 6px;
	width: 74px;
	margin: 0;
	cursor: pointer;
	font-size: 12px;
	color: var(--kvx-ink);
	text-align: center;
}

.kvx-showcase .kvx-swatch-opt input {
	position: absolute;
	opacity: 0;
	width: 0;
	height: 0;
	margin: 0;
}

.kvx-swatch {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	aspect-ratio: 1;
	padding: 6px;
	border: 1px solid var(--kvx-line);
	border-radius: 10px;
	background-color: var(--kvx-surface);
	overflow: hidden;
	transition: border-color var(--kvx-dur) ease, box-shadow var(--kvx-dur) ease;
}

/* Brand logos are wildly inconsistent in aspect and padding, so contain rather
   than cover — a squashed logo reads as a broken image. */
.kvx-swatch img {
	max-width: 100%;
	max-height: 100%;
	width: auto;
	height: auto;
	object-fit: contain;
}

.kvx-swatch--color {
	padding: 0;
}

.kvx-swatch__fill {
	display: block;
	width: 100%;
	height: 100%;
}

/* Fallback for a brand with neither logo nor colour set up in the theme. */
.kvx-swatch__initials {
	font-size: 15px;
	font-weight: 700;
	text-transform: uppercase;
	color: var(--kvx-muted);
}

.kvx-swatch-opt__label {
	display: block;
	width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	line-height: 1.3;
}

.kvx-swatch-opt input:checked + .kvx-swatch {
	border-color: var(--kvx-accent);
	box-shadow: 0 0 0 2px var(--kvx-accent-weak);
}

.kvx-swatch-opt input:checked ~ .kvx-swatch-opt__label {
	color: var(--kvx-accent);
	font-weight: 600;
}

.kvx-swatch-opt input:focus-visible + .kvx-swatch {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

.kvx-showcase .kvx-swatch-opt:hover .kvx-swatch {
	border-color: var(--kvx-line-strong);
}

/* The count rides along for parity with the checkbox rows, but a swatch grid is
   already dense — keep it quiet. */
.kvx-showcase .kvx-swatch-opt .kvx-check__count {
	font-size: 11px;
	line-height: 1;
}

.kvx-chip__count {
	margin-inline-start: 6px;
	opacity: 0.6;
	font-variant-numeric: tabular-nums;
}

.kvx-showcase .kvx-chip {
	margin: 0;
	cursor: pointer;
}

.kvx-chip__label {
	display: inline-flex;
	align-items: center;
	padding: 8px 14px;
	border: 1px solid var(--kvx-line);
	border-radius: var(--kvx-radius-pill);
	font-size: 12.5px;
	color: var(--kvx-ink);
	transition: border-color var(--kvx-dur) ease, color var(--kvx-dur) ease,
		background-color var(--kvx-dur) ease;
}

.kvx-chip input:checked + .kvx-chip__label {
	border-color: var(--kvx-accent);
	background-color: var(--kvx-accent-weak);
	color: var(--kvx-accent);
}

.kvx-chip input:focus-visible + .kvx-chip__label {
	outline: 2px solid var(--kvx-accent);
	outline-offset: 2px;
}

body.kvx-no-scroll {
	overflow: hidden;
}

/* ------------------------------------------------------------------ *
 * Responsive
 * ------------------------------------------------------------------ */

/* Matches the base rule's specificity — `.kvx-search` alone would never win. */
@media (max-width: 1024px) {
	.kvx-showcase .kvx-search {
		width: 190px;
	}
}

@media (max-width: 768.98px) {
	.kvx-showcase__bar {
		flex-wrap: wrap;
		gap: 12px;
	}

	.kvx-tabs__viewport {
		order: 2;
		flex: 1 1 100%;
	}

	.kvx-tools {
		order: 1;
		flex: 1 1 100%;
	}

	.kvx-showcase .kvx-search {
		flex: 1 1 auto;
		width: auto;
	}

	/* Arrow buttons are redundant next to touch scrolling. */
	.kvx-showcase.kvx-showcase .kvx-tabs__nav {
		display: none;
	}

	.kvx-panel {
		--kvx-panel-w: 100%;
		top: auto;
		right: 0;
		left: 0;
		bottom: 0;
		max-width: 100%;
		max-height: 88vh;
		border-radius: 16px 16px 0 0;
		transform: translateY(100%);
	}

	.kvx-panel-open .kvx-panel {
		transform: translateY(0);
	}
}

/**
 * Vertical tab variant.
 *
 * Opt in per instance. The strip becomes a scrollable column with a capped
 * height, which suits long category lists better than a wide swipe.
 */
@media (max-width: 768.98px) {
	.kvx-showcase--tabs-scroll-y .kvx-tabs {
		flex-direction: column;
		align-items: stretch;
		overflow-x: hidden;
		overflow-y: auto;
		max-height: 216px;
		scroll-snap-type: y proximity;
	}

	.kvx-showcase--tabs-scroll-y.kvx-showcase.kvx-showcase .kvx-tab {
		justify-content: flex-start;
		width: 100%;
	}

	.kvx-showcase--tabs-scroll-y .kvx-tabs__viewport::before,
	.kvx-showcase--tabs-scroll-y .kvx-tabs__viewport::after {
		left: 0;
		right: 0;
		width: auto;
		height: 24px;
		top: auto;
		bottom: auto;
	}

	.kvx-showcase--tabs-scroll-y .kvx-tabs__viewport::before {
		top: 0;
		background: linear-gradient(to bottom, var(--kvx-surface), transparent);
	}

	.kvx-showcase--tabs-scroll-y .kvx-tabs__viewport::after {
		bottom: 0;
		background: linear-gradient(to top, var(--kvx-surface), transparent);
	}
}

@media (prefers-reduced-motion: reduce) {
	.kvx-showcase *,
	.kvx-panel,
	.kvx-panel-backdrop {
		transition-duration: 0.01ms !important;
		animation-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}
