/* Zmoton Smart Filters — frontend */

/* Color de marca: por defecto hereda el color global del theme/Elementor si
 * lo tienen configurado (--e-global-color-primary es la variable estándar
 * que genera Elementor con "Colores globales"; --wd-brand-color es la de
 * WoodMart), y solo si ninguno existe cae a un gris neutro. El admin puede
 * fijar un color propio en Ajustes → Colores: eso se imprime en un <style>
 * aparte que sale DESPUÉS de este archivo, así que gana por orden de cascada
 * sin tocar este valor por defecto. */
:root {
	--zsf-accent: var(--e-global-color-primary, var(--wd-brand-color, #333));
	--zsf-accent-hover: var(--zsf-accent);
}

.zsf-filter { margin: 0 0 22px; }
.zsf-filter .zsf-list { list-style: none; margin: 0; padding: 0; }
/* Columnas: solo en la lista de primer nivel (nunca en sub-listas de un
 * árbol de categorías — .zsf-sub no es hijo directo de .zsf-filter, así que
 * el selector de hijo directo ">" ya las deja afuera). La segunda parte
 * (">.zsf-list-scroll-wrap >") cubre el mismo caso cuando el modo "scroll"
 * además envuelve la lista en ese contenedor propio (ver zsf-frontend.js,
 * ensureScrollThumb) — sigue siendo la lista de primer nivel, solo que con
 * un nivel más de anidamiento en el medio. */
.zsf-filter--cols-2 > .zsf-list,
.zsf-filter--cols-2 > .zsf-list-scroll-wrap > .zsf-list { display: grid; grid-template-columns: 1fr 1fr; column-gap: 14px; }
/* Espaciado uniforme: anula el margen que el theme aplica a algunos <li> */
.zsf-filter .zsf-item,
.zsf-filter li.zsf-item { margin: 0 !important; padding: 0 !important; list-style: none !important; border: 0 !important; }
.zsf-filter .zsf-item::before,
.zsf-filter .zsf-item::marker { content: none !important; }
/* Sub-lista (acordeón / árbol) */
.zsf-sub { margin: 0; padding-left: 16px; }
.zsf-tree-style--guides .zsf-sub { border-left: 1px solid rgba(0, 0, 0, .1); margin-left: 8px; padding-left: 12px; }
.zsf-tree-style--compact .zsf-option { padding-top: 3px; padding-bottom: 3px; }

/* Fila: opción + slot de flecha */
.zsf-row { display: flex; align-items: center; }
.zsf-row .zsf-option { flex: 1 1 auto; min-width: 0; }

/* Slot de la flecha — reservado en TODAS las filas para alinear los contadores */
.zsf-toggle,
.zsf-toggle--empty { flex: none; width: 26px; height: 26px; }
.zsf-toggle {
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	color: inherit;
	opacity: .55;
	text-decoration: none;
}
.zsf-toggle:hover { opacity: 1; }
.zsf-toggle--empty { display: inline-block; }
/* Ícono fino tipo "caret", en vez del triangulito grueso armado con bordes
 * de antes — confirmado que ese se notaba visualmente distinto de las
 * flechas propias del theme (ej. WoodMart, que usa su propia tipografía de
 * íconos para el título colapsable de cada widget). En vez de depender de
 * esa tipografía (es del theme, no algo que el plugin pueda dar por
 * garantizado — cualquier otro theme no la va a tener, y hasta WoodMart
 * podría cambiarla en una actualización), se dibuja un chevron fino propio
 * por SVG vía `mask` — así se puede pintar con `currentColor` igual que
 * cualquier ícono de tipografía, pero sin esa dependencia. */
.zsf-chevron {
	display: inline-block;
	width: 11px; height: 11px;
	background-color: currentColor;
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
	-webkit-mask-size: contain;
	mask-size: contain;
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	transition: transform .18s ease;
}
.zsf-item.is-open > .zsf-row > .zsf-toggle .zsf-chevron { transform: rotate(180deg); }
.zsf-chevron--right { transform: rotate(-90deg); }

/* Drill-down */
.zsf-drill-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 10px;
	padding: 2px 0 8px;
	margin-bottom: 4px;
	border-bottom: 1px solid rgba(0, 0, 0, .1);
}
.zsf-back { display: inline-flex; align-items: center; gap: 6px; text-decoration: none; opacity: .75; font-size: .9em; }
.zsf-back:hover { opacity: 1; }
.zsf-back-arrow {
	width: 7px; height: 7px;
	border-left: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
}
.zsf-drill-current { font-weight: 700; }
.zsf-drill-parent { cursor: pointer; }

.zsf-option {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 5px 0;
	color: inherit;
	text-decoration: none;
	line-height: 1.3;
	transition: color .15s ease;
}
.zsf-option:hover { color: var(--zsf-accent-hover); }
.zsf-option .zsf-label { flex: 1 1 auto; }
.zsf-option .zsf-count {
	flex: none;
	font-size: .82em;
	opacity: .6;
	font-variant-numeric: tabular-nums;
	background: rgba(0, 0, 0, .05);
	border-radius: 20px;
	padding: 1px 8px;
	min-width: 26px;
	text-align: center;
}
.zsf-option.is-active { font-weight: 600; color: var(--zsf-accent); }
.zsf-option.is-active .zsf-count { background: var(--zsf-accent); color: #fff; opacity: 1; }
.zsf-option.is-disabled { opacity: .4; pointer-events: none; }

/* Checkbox visual */
.zsf-check {
	flex: none;
	width: 18px;
	height: 18px;
	border: 1.5px solid currentColor;
	border-radius: 4px;
	opacity: .55;
	position: relative;
	transition: all .15s ease;
}
.zsf-option:hover .zsf-check { opacity: 1; }
.zsf-option.is-active .zsf-check {
	background: var(--zsf-accent);
	border-color: var(--zsf-accent);
	opacity: 1;
}
.zsf-option.is-active .zsf-check::after {
	content: "";
	position: absolute;
	left: 5px; top: 1px;
	width: 5px; height: 10px;
	border: solid #fff;
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

/* Swatches */
.zsf-swatch {
	flex: none;
	width: 20px; height: 20px;
	border-radius: 50%;
	border: 1px solid rgba(0, 0, 0, .15);
	box-shadow: inset 0 0 0 2px #fff;
}
.zsf-option.is-active .zsf-swatch { box-shadow: inset 0 0 0 2px #fff, 0 0 0 2px var(--zsf-accent); }

/* "Ver más" en listas largas */
.zsf-item.zsf-more-item[hidden] { display: none; }
.zsf-show-more { padding: 4px 0 0; }
.zsf-show-more-btn {
	background: none;
	border: 0;
	padding: 0;
	margin: 0;
	cursor: pointer;
	font-size: .82em;
	font-weight: 400;
	color: inherit;
	opacity: .55;
	text-decoration: underline;
}
.zsf-show-more-btn:hover { opacity: .85; }

/* Listas largas en modo "barra de scroll" (alternativa al botón "Ver más"):
   la altura máxima la calcula zsf-frontend.js (applyTruncation) a partir de
   cuántas opciones caben según el límite configurado, y se aplica como
   estilo inline sobre el propio elemento.
   El scrollbar NATIVO del navegador no sirve para esto: en iOS Safari
   (confirmado en vivo) queda directamente invisible salvo el instante en
   que se lo toca, así que un usuario en celular no tendría ninguna pista
   de que hay más opciones para ver. En su lugar, zsf-frontend.js
   (ensureScrollThumb/updateScrollThumb) arma una barra PROPIA — se esconde
   el scrollbar nativo del todo para no duplicar.
   La barra propia NO puede vivir adentro de `.zsf-list--scroll` (el mismo
   elemento con `overflow-y:auto`): confirmado en vivo que un hijo con
   `position:absolute` de un contenedor que scrollea se mueve CON el
   contenido en vez de quedarse fija en pantalla como una barra real — subía
   fuera de vista apenas se scrolleaba un poco. Por eso zsf-frontend.js la
   arma como hermana de la lista, las dos adentro de un envoltorio propio
   (`.zsf-list-scroll-wrap`) que es el que de verdad no se mueve. */
.zsf-list-scroll-wrap { position: relative; }
.zsf-list--scroll { overflow-y: auto; scrollbar-width: none; }
/* El padding-right va con selector ".zsf-filter .zsf-list--scroll" (dos
 * clases) a propósito — con una sola clase quedaba pisado por el "padding:0"
 * de ".zsf-filter .zsf-list" de más arriba (misma cantidad de clases, pero
 * ESA regla aparece antes en la hoja de estilos), confirmado en vivo que la
 * barra terminaba superpuesta directo sobre los contadores de cada opción. */
.zsf-filter .zsf-list--scroll { padding-right: 22px; }
.zsf-list--scroll::-webkit-scrollbar { display: none; }

.zsf-scroll-track {
	position: absolute;
	top: 0;
	right: 4px;
	bottom: 0;
	width: 5px;
	background: rgba(0, 0, 0, .08);
	border-radius: 4px;
	pointer-events: none;
}
.zsf-scroll-thumb {
	position: absolute;
	left: 0;
	right: 0;
	background: #c3c7cc;
	border-radius: 4px;
}

/* Dropdown */
.zsf-dropdown { width: 100%; padding: 8px 10px; }

/* Search box */
.zsf-search { margin-bottom: 8px; }
.zsf-search-input { width: 100%; padding: 7px 10px; }

/* Price */
.zsf-price-slider {
	position: relative;
	height: 4px;
	background: rgba(0, 0, 0, .12);
	border-radius: 4px;
	margin: 18px 8px 22px;
}
.zsf-price-track { position: absolute; top: 0; bottom: 0; background: var(--zsf-accent); border-radius: 4px; }
.zsf-price-handle {
	position: absolute; top: 50%;
	width: 16px; height: 16px;
	margin: -8px 0 0 -8px;
	background: #fff;
	border: 2px solid var(--zsf-accent);
	border-radius: 50%;
	cursor: grab;
	touch-action: none;
}
.zsf-price-fields { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.zsf-price-fields input { width: 74px; padding: 6px 8px; }
.zsf-price-sep { opacity: .5; }
.zsf-price-apply { margin-left: auto; }

/* Barra de filtros activos (arriba de los productos) */
.zsf-active-bar {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	align-items: center;
	margin: 0 0 18px;
}
.zsf-active-bar.zsf-empty { display: none; margin: 0; }
.zsf-active-label { font-weight: 600; opacity: .7; margin-right: 2px; }

/* El widget "Filtros activos" no debe dejar un bloque vacío (título fantasma,
 * borde/padding del theme) cuando no hay nada que mostrar. Refuerzo en CSS puro
 * de lo que ya hace toggleHolder() en JS — cubre navegadores sin JS/:has() como
 * mejora progresiva, no como único mecanismo. */
.zsf-active-widget:has(.zsf-active-bar.zsf-empty) { display: none; }

/* Filtro de categoría/marca/atributo/precio sin ninguna opción para mostrar:
 * se oculta el widget entero (título incluido — ver ZSF_Widget::widget(), que
 * SIEMPRE imprime este marcador aunque esté vacío, para que el AJAX del
 * frontend pueda encontrarlo y actualizarlo en cualquier filtrado posterior). */
.zsf-widget-inner--empty { display: none; }
.zsf-widget:has(.zsf-widget-inner--empty) { display: none; }

/* Cartel "Estás viendo" — sin tipografía propia a propósito: hereda el estilo de
 * encabezado (h3) del theme, igual que hacía el fragmento de código que reemplaza. */
.zsf-viewing-label { margin: 0 0 18px; }

/* Active filters / chips */
.zsf-active { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.zsf-chip, .zsf-clear-all {
	display: inline-flex;
	align-items: center;
	gap: 5px;
	padding: 4px 12px;
	border-radius: 20px;
	font-size: .85em;
	text-decoration: none;
	line-height: 1.6;
}
.zsf-chip { background: rgba(0, 0, 0, .06); color: inherit; }
.zsf-chip:hover { background: rgba(0, 0, 0, .12); }
.zsf-chip-x { font-weight: 700; }
.zsf-clear-all { color: var(--zsf-accent); font-weight: 600; }

/* Aviso de "sin resultados" — se apoya en el estilo que el theme ya le da a
 * .woocommerce-info; este es solo un respaldo mínimo por si no lo estiliza. */
.zsf-no-products {
	padding: 14px 18px;
	margin: 0 0 18px;
	border-left: 3px solid var(--zsf-accent);
	background: rgba(0, 0, 0, .03);
}
/* Refuerzo: si el theme le da a .woocommerce-info un "display" propio (común
 * en WooCommerce/WoodMart), esa regla de clase puede pesar más que el
 * comportamiento por defecto del atributo `hidden` del navegador y dejarlo
 * visible igual aunque JS lo haya marcado oculto. Este selector es más
 * específico que una sola clase, así que gana siempre. */
.zsf-no-products[hidden] { display: none !important; }

/* Loading state: altura mínima mientras se reemplaza la grilla, para que la
 * página no "salte" entre el contenido viejo y el nuevo. */
.zsf-loading { min-height: 200px; }

/* Overlay de carga de página completa (desktop, tablet y celular por igual)
 * — `html.zsf-is-loading` ya lo pone/saca zsf-frontend.js (setLoading) en
 * cada filtrado por AJAX. Dos pseudo-elementos fijos sobre <html> en vez de
 * un nodo propio en el DOM: fondo semitransparente (::before) + spinner
 * centrado (::after), ambos por encima de cualquier cosa del theme. */
html.zsf-is-loading::before {
	content: "";
	position: fixed;
	inset: 0;
	background: rgba(255, 255, 255, .6);
	z-index: 100000;
}
html.zsf-is-loading::after {
	content: "";
	position: fixed;
	top: 50%; left: 50%;
	width: 40px; height: 40px;
	margin: -20px 0 0 -20px;
	border: 3px solid rgba(0, 0, 0, .15);
	border-top-color: var(--zsf-accent);
	border-radius: 50%;
	z-index: 100001;
	animation: zsf-spin .7s linear infinite;
}
@keyframes zsf-spin { to { transform: rotate(360deg); } }

/* Respeta usuarios con movimiento reducido. */
@media (prefers-reduced-motion: reduce) {
	html.zsf-is-loading::after { animation: none; }
	.zsf-option { transition: none; }
}
