/* ══════════════════════════════════════════════════════════════════════
   LAS TARJETAS DE AGROCALIA — los tres formatos
   ══════════════════════════════════════════════════════════════════════

   `ag-card` la completa · `ag-mini` la compacta · `ag-subasta` la fila.

   Comparten foto, etiqueta, corazón, nombre, vendedor, nota y precio: lo común
   se declara una vez y cada formato solo cambia sus medidas.

   ── LOS COLORES SON LOS DEL ESCAPARATE ───────────────────────────────
   Tokens `--sd-*` con respaldo en el punto de uso, porque los sirve
   `TSellersUI` y estas tarjetas se pintan también dentro del panel de cuenta,
   que no lo carga.

   ── NO SE ESCOPAN BAJO UNA PANTALLA ──────────────────────────────────
   A propósito: son globales y se usan en el catálogo, en favoritos, en las
   colecciones y en el perfil del agricultor. El prefijo `ag-` es lo que las
   acota, y por eso todas las clases lo llevan.
   ────────────────────────────────────────────────────────────────────── */

.ag-cards { display: none; }

/* ── LO QUE LA REJILLA NECESITA SABER DE LA TARJETA ──────────────────
   Las rejillas del escaparate y de favoritos se montan con estos tokens, y los
   declaraba `TProductCard`. Al retirarlo a `old/` (10/09/2026) dejaron de
   llegar y las rejillas caían a sus respaldos: funcionaba, pero el ancho de la
   tarjeta lo decidía la pantalla en vez de la tarjeta.

   Van en `:root` a propósito: un token declarado sobre `.ag-card` no lo ve su
   contenedor, que es justo quien lo usa. */
:root{
    /* EL MÍNIMO. Por debajo de 260 la foto se queda pequeña y el nombre se
       parte en tres líneas. */
    --tf-card-min: 260px;

    /* Y EL TOPE, porque «líquida» no es «sin límite»: una fila con una sola
       tarjeta le daba el ancho entero de la página, y eso no es una tarjeta de
       producto, es un banner. */
    --tf-card-max: 350px;

    --tf-card-gap: 20px;
}

.ag-card, .ag-mini, .ag-subasta,
.ag-card *, .ag-mini *, .ag-subasta * { box-sizing: border-box; }

/* ── LOS `<span>` DE LA TARJETA HEREDAN SU LETRA, A LA FUERZA ────────
 *
 * `boot.css` declara `div, span, p, ul, li, ol { font: 12px Inter, sans-serif }`
 * y ese ATAJO `font` fija tamaño Y peso de un golpe. Un selector de elemento
 * (0,0,1) le gana siempre a un valor HEREDADO --que no tiene especificidad
 * ninguna-- así que todo el texto que la tarjeta mete en un `<span>` salía a
 * 12px y en redonda, dijera lo que dijera su contenedor. Medido el 26/09/2026:
 *
 *     .ag-vendedor  13 / 400   →  su span  12 / 400
 *     .ag-lugar     12,5 / 400 →  su span  12 / 400
 *     .ag-meta-it   11,5 / 500 →  su span  12 / 400
 *     .ag-reloj     12 / 700   →  su span  12 / 400   ← el que más se notaba
 *
 * O sea que el reloj de la subasta se declaraba en negrita y salía normal, y
 * no había forma de verlo leyendo esta hoja: hay que mirar `getComputedStyle`
 * DEL SPAN, no del bloque. Misma familia que las otras trampas de `boot.css`
 * (ver `Documentacion/Memoria/boot-css-pisa-color-heredado.md`).
 *
 * `font-size`/`font-weight`/`line-height` y no el atajo `font: inherit`: ese
 * arrastraría también `font-variant` y `font-stretch`, y aquí solo estorban
 * los tres de arriba. */
.ag-card :is(.ag-vendedor, .ag-lugar, .ag-nota, .ag-meta-it, .ag-reloj) > span,
.ag-mini :is(.ag-vendedor, .ag-lugar, .ag-nota, .ag-meta-it) > span,
.ag-subasta :is(.ag-vendedor, .ag-lugar, .ag-nota, .ag-meta-it) > span {
    font-size: inherit; font-weight: inherit; line-height: inherit;
}

/* ── LO COMÚN ───────────────────────────────────────────────────────── */

.ag-card, .ag-mini, .ag-subasta {
    position: relative;
    background: #fff;
    border: 1px solid var(--sd-borde, #e4eae4);
    border-radius: 14px;
    overflow: hidden;
}
.ag-card:hover, .ag-mini:hover, .ag-subasta:hover {
    border-color: #cfe0d3;
    box-shadow: 0 4px 14px rgba(20,40,25,.09);
}

/* La tapa cubre la tarjeta para poder pulsar en cualquier sitio. Va DEBAJO del
   corazón y del botón en el apilado: si no, se traga sus clics. */
.ag-card .ag-tapa, .ag-mini .ag-tapa, .ag-subasta .ag-tapa {
    position: absolute; inset: 0; z-index: 1;
    border: 0; text-decoration: none;
}

.ag-card .ag-foto, .ag-mini .ag-foto, .ag-subasta .ag-foto {
    position: relative; display: block;
    overflow: hidden;
    background: var(--sd-gris, #f2f5f2);
}
.ag-card .ag-foto img, .ag-mini .ag-foto img, .ag-subasta .ag-foto img {
    width: 100%; height: 100%; display: block;

    /* CUBRE EL HUECO, Y ANCLADA ARRIBA. `cover` recorta lo que sobra en vez de
       deformar la foto; `object-position: top` decide POR DÓNDE recorta, y en
       una foto de producto lo que importa está arriba --el género-- mientras que
       abajo suele haber caja, suelo o mesa. Con el centrado de fábrica, una foto
       vertical entraba por la mitad y la tarjeta enseñaba el palé. */
    object-fit: cover;
    object-position: top;
}

/* SIN FOTO, EL HUECO CON SU ICONO: un rectángulo vacío se lee como una imagen
   que no ha cargado, y la gente recarga la página. */
.ag-card .ag-sinfoto, .ag-mini .ag-sinfoto, .ag-subasta .ag-sinfoto {
    position: absolute; inset: 0;
    display: flex; align-items: center; justify-content: center;
    color: #c3cfc6;
}
.ag-card .ag-sinfoto iconify-icon,
.ag-mini .ag-sinfoto iconify-icon,
.ag-subasta .ag-sinfoto iconify-icon { font-size: 30px; }

/* Oculto mientras la foto carga bien -- TAgroCard.js lo vuelve a enseñar
   solo si el `<img>` falla (`onerror`). Con `display:none` en vez de
   quitarlo del DOM, sigue ahí para ese caso; `.remove()` no se puede
   deshacer.

   ── Y CON LA TARJETA DELANTE, QUE SI NO NO OCULTA NADA (26/09/2026) ──
   Estaba como `.ag-sinfoto--oculto` a secas --0,0,1,0-- contra la regla que lo
   enseña, `.ag-card .ag-sinfoto` --0,0,2,0--: perdía por especificidad, así que
   el icono de «sin foto» salía SIEMPRE, también encima de las fotos que sí
   habían cargado. Se veía como un cuadradito gris en mitad de cada producto y
   no daba ningún error: el JS y el render de PHP llevaban meses poniendo una
   clase que no hacía nada. */
.ag-card .ag-sinfoto--oculto,
.ag-mini .ag-sinfoto--oculto,
.ag-subasta .ag-sinfoto--oculto { display: none; }

/* ── LA ETIQUETA DE LA ESQUINA ──────────────────────────────────────── */

.ag-card .ag-etiqueta, .ag-mini .ag-etiqueta {
    position: absolute; top: 10px; left: 10px; z-index: 2;
    display: inline-block;
    padding: 5px 12px;
    border-radius: 999px;
    font-size: 12px; font-weight: 700; line-height: 1.3;
    color: #fff;
    background: var(--sd-verde, #1d753b);
    box-shadow: 0 1px 4px rgba(20,40,25,.2);
}
.ag-mini .ag-etiqueta { top: 8px; left: 8px; padding: 3px 9px; font-size: 11px; }

/* 18px Y NO 10: la foto entró 8px hacia dentro (ver `.ag-card .ag-foto`), así
   que la esquina y el corazón se quedaban montados sobre su borde. Se suman
   los mismos 8 para que sigan cayendo DENTRO de la foto. */
.ag-card .ag-etiqueta { top: 18px; left: 18px; }
.ag-card .ag-fav      { top: 18px; right: 18px; }

/* ── LOS CUATRO TONOS, Y DOS NO LLEGABAN A AA ──────────────────────
 *
 * Medido el 26/09/2026 con la letra blanca que declara `.ag-etiqueta`:
 *
 *     ámbar  #e8a33d + #fff → 2,16    verde #1d753b + #fff → 5,74
 *     rojo   #ef5350 + #fff → 3,49    azul  #2f6fd0 + #fff → 4,88
 *
 * WCAG 2.1 AA pide 4,5 para texto normal, y esto son 12px. El ámbar es el que
 * más se ve --«Producción integrada» sale en media rejilla-- y era el peor.
 *
 * EL ÁMBAR NO SE ARREGLA OSCURECIÉNDOLO: para que quepa letra blanca hay que
 * bajarlo hasta que deja de ser ámbar y se vuelve marrón. Lleva LETRA OSCURA
 * (6,37) y se queda con su color. El rojo sí: #d32f2f con blanco da 4,98.
 *
 * Mismo hallazgo y misma decisión que en `TAuctionCard` (otra sesión, el mismo
 * día): ahí el ámbar con blanco daba 2,59 y se resolvió igual. */
.ag-card .ag-et--verde, .ag-mini .ag-et--verde { background: #1d753b; }
.ag-card .ag-et--ambar, .ag-mini .ag-et--ambar { background: #e8a33d; color: #3d2a00; }
.ag-card .ag-et--azul,  .ag-mini .ag-et--azul  { background: #2f6fd0; }
.ag-card .ag-et--rojo,  .ag-mini .ag-et--rojo  { background: #d32f2f; }

/* ── EL CORAZÓN ─────────────────────────────────────────────────────── */

.ag-card .ag-fav, .ag-mini .ag-fav {
    height: auto; min-height: 0;
    position: absolute; top: 9px; right: 9px; z-index: 3;
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px;
    margin: 0; padding: 0;
    background: rgba(255,255,255,.95);
    border: 0; border-radius: 999px;
    color: #9aa8a0;
    cursor: pointer;
    box-shadow: 0 1px 5px rgba(20,40,25,.18);
}
.ag-mini .ag-fav { top: 7px; right: 7px; width: 28px; height: 28px; }

/* El corazón es un SVG inline --no un `<iconify-icon>`-- justo para poder
   rellenarlo: dentro de un shadow DOM el `fill="none"` de Lucide no se alcanza
   desde aquí. */
.ag-card .ag-corazon, .ag-mini .ag-corazon { width: 18px; height: 18px; fill: none; }
.ag-mini .ag-corazon { width: 15px; height: 15px; }

.ag-card .ag-fav:hover, .ag-mini .ag-fav:hover { color: #e11d48; }

/* GUARDADO: rojo y RELLENO. Con solo el contorno no se distingue de «se puede
   guardar», que es justo lo contrario de lo que dice. */
.ag-card .ag-fav.on, .ag-mini .ag-fav.on { color: #e11d48; }
.ag-card .ag-fav.on .ag-corazon, .ag-mini .ag-fav.on .ag-corazon { fill: #e11d48; }

/* ── EL CUERPO ──────────────────────────────────────────────────────── */

/* EL CUERPO CRECE PARA QUE EL BOTÓN SE QUEDE ABAJO.
   Sin esto, el botón sube o baja según lo que haya encima --un nombre de una
   línea o de dos, un producto con lugar y otro sin él-- y en una rejilla eso se
   ve como una fila de botones a distintas alturas. Con el cuerpo en columna y
   el botón con `margin-top:auto`, su sitio no depende del contenido: siempre al
   pie de la tarjeta. */
.ag-card .ag-cuerpo, .ag-mini .ag-cuerpo {
    position: relative; z-index: 2;
    pointer-events: none;
    flex: 1;
    display: flex; flex-direction: column;
}
/* El cuerpo deja pasar el clic a la tapa, salvo lo que sí se pulsa. */
.ag-card .ag-cuerpo .ag-btn, .ag-mini .ag-cuerpo .ag-btn { pointer-events: auto; }

.ag-card .ag-cuerpo { padding: 13px 14px 14px; }
.ag-mini .ag-cuerpo { padding: 8px 10px 9px; min-height: 0; }

.ag-card .ag-nombre, .ag-mini .ag-nombre, .ag-subasta .ag-nombre {
    margin: 0; padding: 0;
    font-weight: 800; line-height: 1.3;
    color: var(--sd-tinta, #16211a);
}
.ag-card .ag-nombre { font-size: 15px; }
/* HASTA DOS LÍNEAS, y sin encogerse. Antes era una sola línea con puntos
   suspensivos porque la tarjeta medía 150px fijos; pero el cuerpo no cabía en
   esos 150 --foto de 71, relleno y cuatro líneas-- y el flex, al ser el nombre
   `overflow:hidden`, lo comprimía por debajo de su altura: el título salía
   cortado por abajo y montado sobre el vendedor. Con `flex:0 0 auto` cada línea
   conserva su altura y es la tarjeta la que crece (ver `.ag-mini`). */
.ag-mini .ag-nombre {
    flex: 0 0 auto;
    font-size: 12.5px;
    overflow: hidden;
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
    line-clamp: 2;
}
.ag-subasta .ag-nombre { font-size: 13.5px; }

.ag-card .ag-vendedor, .ag-mini .ag-vendedor, .ag-subasta .ag-vendedor {
    margin: 3px 0 0; padding: 0;
    line-height: 1.35;
    color: var(--sd-suave, #6b7a70);
}

/* El icono del vendedor en su columna, como el del lugar: flex de dos
   columnas y todo el texto en la segunda. */
.ag-card .ag-vendedor { display: flex; align-items: center; gap: 6px; }
.ag-card .ag-vendedor > iconify-icon { flex: 0 0 auto; font-size: 14px; color: var(--sd-suave, #93a09a); }

/* En la compacta y en la fila no hay sitio para el icono. */
.ag-mini .ag-vendedor > iconify-icon,
.ag-subasta .ag-vendedor > iconify-icon { display: none; }
.ag-card .ag-vendedor { font-size: 13px; }
.ag-mini .ag-vendedor {
    flex: 0 0 auto;
    font-size: 11px; margin-top: 1px;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.ag-subasta .ag-vendedor { font-size: 12px; }

/* ── EL LUGAR ───────────────────────────────────────────────────────── */

.ag-card .ag-lugar {
    display: flex; align-items: center; gap: 5px;
    margin: 5px 0 0; padding: 0;
    font-size: 12.5px; line-height: 1.35;
    color: var(--sd-suave, #6b7a70);
}
/* El tamaño se declara EN el icono: `iconify-icon` no hereda el `font-size`. */
.ag-card .ag-lugar iconify-icon { flex: 0 0 auto; font-size: 14px; }

/* ── LA NOTA ────────────────────────────────────────────────────────── */

.ag-card .ag-nota, .ag-mini .ag-nota {
    display: flex; align-items: center; gap: 5px;
    margin: 6px 0 0; padding: 0;
}
.ag-mini .ag-nota { margin-top: 3px; }

/* La estrella va RELLENA. Es el trazo de Lucide copiado de su propia
   definición --su `<path>` trae `fill="none"` y con `iconify-icon` vive en un
   shadow DOM que ninguna regla alcanza-- así que no se mezcla ninguna familia
   de iconos: solo se pinta el interior. */
.ag-card .ag-estrella, .ag-mini .ag-estrella {
    width: 16px; height: 16px; flex: 0 0 auto;
    fill: #feac08; color: #feac08;
}
.ag-mini .ag-estrella { width: 14px; height: 14px; }

.ag-card .ag-nota b { font-size: 13.5px; font-weight: 700; color: var(--sd-tinta, #16211a); }
.ag-mini .ag-nota b { font-size: 12px; font-weight: 700; color: var(--sd-tinta, #16211a); }
.ag-card .ag-nota small { font-size: 13px; color: var(--sd-suave, #6b7a70); }
.ag-mini .ag-nota small { font-size: 11.5px; color: var(--sd-suave, #6b7a70); }

/* ── EL PRECIO, Y EL DESCUENTO A SU DERECHA ─────────────────────────── */

.ag-card .ag-precios, .ag-mini .ag-precios {
    display: flex; align-items: baseline; flex-wrap: wrap; gap: 8px;
    margin: 9px 0 0; padding: 0;
}
.ag-mini .ag-precios { margin: 0; gap: 5px; }

.ag-card .ag-precio {
    font-size: 18px;
    font-weight: 600;
    color: var(--sd-tinta, #16211a);
    font-family: sans-serif;
}
.ag-mini .ag-precio { font-size: 14.5px; font-weight: 800; color: var(--sd-tinta, #16211a); }

/* EN OFERTA EL PRECIO VA EN ROJO: es lo que lo distingue de un precio normal de
   un vistazo. El tachado de al lado se lee después, no antes. */
.ag-card .ag-precio.ag-rebajado, .ag-mini .ag-precio.ag-rebajado { color: #e11d48; }

.ag-card .ag-antes, .ag-mini .ag-antes {
    font-size: 14px; font-weight: 600;
    color: var(--sd-suave, #93a09a);
    text-decoration: line-through;
}
.ag-mini .ag-antes { font-size: 11.5px; }

/* ── LA SUBASTA: EL RÓTULO DEL PRECIO Y EL RELOJ ────────────────────
   En una subasta la cifra NO es el precio: es lo que va costando ahora mismo.
   El rótulo va en su propia línea, encima, y ocupa la fila entera
   (`flex-basis:100%`) porque `.ag-precios` es un flex en línea de base. */
.ag-card .ag-precio-rotulo, .ag-mini .ag-precio-rotulo {
    flex-basis: 100%;
    font-size: 11px; font-weight: 700; line-height: 1.2;
    text-transform: uppercase; letter-spacing: .4px;
    color: var(--sd-suave-aa, #5f6b65);
}
.ag-mini .ag-precio-rotulo { font-size: 10px; }

/* EL RELOJ, EN ÁMBAR Y NO EN ROJO: el rojo de esta hoja es el del precio
   rebajado, y dos rojos en la misma tarjeta dicen dos cosas distintas. Icono en
   su columna y todo el texto en la segunda, como manda la regla de alineación
   del proyecto. */
.ag-card .ag-reloj {
    /* `align-self` Y `width:fit-content`: el cuerpo de la tarjeta es un flex en
       columna, y en un flex `inline-flex` no basta -- el hijo se estira igual y
       la píldora salía de borde a borde. */
    display: inline-flex; align-self: flex-start; width: fit-content;
    align-items: center; gap: 6px;
    margin: 9px 0 0; padding: 4px 9px;
    border-radius: 99px;
    background: #fff7e6; border: 1px solid #f5d999;
    font-size: 12px; font-weight: 700; line-height: 1.2;
    color: #8a5a00;
}
.ag-card .ag-reloj iconify-icon { flex: 0 0 auto; font-size: 14px; }

/* TERMINADA: la píldora pasa a gris. El ámbar avisa de que queda poco, y en una
   subasta cerrada ya no queda nada que avisar. #475569 sobre #f1f5f9: 7,2. */
.ag-card.es-finalizada .ag-reloj { background: #f1f5f9; border-color: #e2e8f0; color: #475569; }
.ag-card.es-finalizada .ag-reloj small { color: #475569; }
.ag-card .ag-reloj span { color: inherit; }
.ag-card .ag-reloj small {
    /* #a07a33 daba 3,70 sobre el fondo de la píldora y esto son 11px: por
       debajo del 4,5 de AA. Con #8a6620, 4,92. */
    font-size: 11px; font-weight: 500; color: #8a6620;
}

/* LA MENCIÓN DEL IVA: discreta pero legible (suelo de 10 px) y con contraste
   AA sobre el blanco de la tarjeta. El `span` no hereda el tamaño en este
   sitio --una regla global con `font:` lo fija--, así que se declara. */
.ag-card .ag-iva, .ag-mini .ag-iva, .ag-subasta .ag-iva {
    font-size: 11px; font-weight: 500; line-height: 1.2;
    color: var(--sd-suave-aa, #5f6b65);
}
.ag-mini .ag-iva { font-size: 10px; flex-basis: 100%; }
.ag-subasta .ag-iva { display: block; font-size: 10px; }

/* EL PRECIO POR KILO O LITRO: su propia línea bajo el precio, sobrio. Mismo tono
   que la mención del IVA, que es dato de lectura y no cifra de decisión. */
.ag-card .ag-ud, .ag-mini .ag-ud, .ag-subasta .ag-ud {
    flex-basis: 100%;
    font-size: 11px; font-weight: 500; line-height: 1.2;
    color: var(--sd-suave-aa, #5f6b65);
    font-variant-numeric: tabular-nums;
}
.ag-card .ag-ud { margin-top: -4px; }
.ag-mini .ag-ud { font-size: 10px; }
.ag-subasta .ag-ud { display: block; font-size: 10px; }

.ag-card .ag-dto {
    padding: 2px 8px;
    background: #ef5350; border-radius: 7px;
    font-size: 12px; font-weight: 700; color: #fff;
}

/* ── EL BOTÓN ───────────────────────────────────────────────────────── */

/* `height:auto` a la fuerza: la hoja global le pone `height:25px; display:flex`
   a todo `button` dentro de un TComponentES6, y estas tarjetas se pintan
   también dentro del panel de cuenta. */
.ag-card .ag-btn, .ag-mini .ag-btn, .ag-subasta .ag-btn {
    height: auto; min-height: 0;
    display: inline-flex; align-items: center; justify-content: center; gap: 8px;
    margin: 0;
    background: var(--sd-verde, #116f34);
    border: 0; border-radius: 10px;
    font-size: 13.5px; font-weight: 700; line-height: 1.2;
    color: #fff;
    cursor: pointer; box-shadow: none;
    pointer-events: auto;
}
.ag-card .ag-btn:hover, .ag-mini .ag-btn:hover, .ag-subasta .ag-btn:hover {
    background: var(--sd-verde-oscuro, #0b5a2a);
}
.ag-card .ag-btn iconify-icon, .ag-mini .ag-btn iconify-icon, .ag-subasta .ag-btn iconify-icon { font-size: 16px; }

/* El rótulo del botón, en su `<span>`: así se puede quitar en la vista de lista
   sin tocar el icono. */
.ag-card .ag-btn-txt { display: inline; }

/* EL PIE. `margin-top: auto` lo empuja al fondo, que es lo que hace que todas
   las tarjetas de una fila tengan el botón a la misma altura. */
.ag-card .ag-pie { margin-top: auto; display: flex; align-items: center; gap: 10px;
                   padding: 12px 14px 14px; }

/* ── LA ACCIÓN DE LA TARJETA VERTICAL ES «VER PRODUCTO» ────────────
 *
 * Diseño del usuario (26/09/2026): el botón de carrito sale de la rejilla y la
 * tarjeta ofrece una sola puerta, en línea y no maciza. En un catálogo
 * agrícola casi nada se compra de un clic --hay mínimos, calibres y formatos
 * que decidir-- así que el carrito desde la rejilla prometía un atajo que casi
 * ningún artículo admite.
 *
 * El apaisado y la vista de lista lo vuelven a encender desde
 * `TStorefront.css`, que gana por especificidad. */
.ag-card .ag-pie .ag-btn { display: none; }

/* «VER PRODUCTO», a todo lo ancho y en línea. */
.ag-card .ag-ver {
    display: flex; flex: 1; width: 100%;
    align-items: center; justify-content: center; gap: 8px;
    padding: 10px 14px;
    /* EL BORDE, MÁS MARCADO QUE `--sd-borde`. Ese gris está pensado para
       separar superficies --el canto de una tarjeta sobre el fondo-- y sobre
       blanco casi no se ve; en un botón el borde ES el botón, porque no tiene
       fondo que lo dibuje. */
    border: 1px solid var(--ag-borde-btn, #a9bdaf); border-radius: 10px;
    font-size: 13px; font-weight: 600; line-height: 1.2;
    color: var(--sd-verde, #116f34); text-decoration: none;
    white-space: nowrap;
    pointer-events: auto; position: relative; z-index: 3;
}
.ag-card .ag-ver:hover { background: var(--sd-gris, #f2f5f2); }
.ag-card .ag-ver:hover { border-color: var(--sd-verde, #116f34); }

/* ── EL BORDE SE PONÍA NEGRO AL VISITARLO, Y NO SE VE MIDIENDO ──────
 *
 * La hoja global declara `a, a:active, a:focus, a:visited { … border: 0px; }`.
 * Ese shorthand deja `border-color` en `currentColor`, y el color del borde es
 * de las pocas propiedades que `:visited` SÍ puede cambiar --el navegador
 * bloquea el resto por privacidad--. Como `a:visited` (0,1,1) gana a una clase
 * suelta (0,1,0), este botón salía con el borde casi negro en cuanto se había
 * pinchado el producto una vez, mientras los no visitados seguían grises: dos
 * bordes distintos en la misma fila.
 *
 * **`getComputedStyle` no lo delata**: devuelve a propósito el valor del enlace
 * SIN visitar. Hay que declarar el `:visited` explícito.
 * Ver `Documentacion/Memoria/borde-negro-por-a-visited.md`. */
.ag-card .ag-ver:link,
.ag-card .ag-ver:visited,
.ag-card .ag-ver:hover,
.ag-card .ag-ver:active,
.ag-card .ag-ver:focus {
    border: 1px solid var(--ag-borde-btn, #a9bdaf);
    color: var(--sd-verde, #116f34);
}
/* El hueco mínimo sobre el botón lo pone el bloque de precios, no el botón: si
   lo pusiera él, `margin-top:auto` lo perdería. */
.ag-card .ag-precios { margin-bottom: 12px; }

/* En la compacta se queda en su icono: a todo lo ancho se comería la tarjeta. */
.ag-mini .ag-btn-icono { width: 30px; height: 30px; flex: 0 0 30px; padding: 0; border-radius: 8px; }

.ag-subasta .ag-btn { padding: 8px 14px; font-size: 12.5px; }

/* ── FORMATO 1: LA COMPLETA ─────────────────────────────────────────── */

/* `height:100%` para que la tarjeta ocupe toda la celda de la rejilla: es lo
   que permite que el botón se vaya al fondo. Una rejilla estira sus celdas,
   pero la tarjeta tiene que aceptar el alto. */
.ag-card { display: flex; flex-direction: column; height: 100%; }

/* EL THUMB: TODO EL ANCHO DE LA TARJETA, 138 de alto.
   ── EL `max-width: 210px` ESTABA MAL Y SE VEÍA ────────────────────
   La maqueta mide 210 x 138 porque SU tarjeta mide 210 de ancho. Copiar los dos
   números dejó la foto centrada dentro de una tarjeta de 298: un rectángulo
   despegado de los bordes, con dos franjas blancas a los lados que se leen como
   un fallo de montaje. Lo que la maqueta dice de verdad es que la foto ocupa el
   ancho ENTERO y mide 138 de alto.
   El alto sí se fija --no `aspect-ratio`-- para que las tarjetas de una fila
   tengan el texto a la misma altura, y `object-fit: cover` en el `img` recorta
   lo que sobre en vez de deformar la foto. */
/* ── Y VA METIDA, CON SUS CUATRO ESQUINAS REDONDEADAS (26/09/2026) ──
   Petición expresa del usuario sobre la maqueta. Antes iba a sangre y con las
   esquinas de arriba cuadradas, pegada al canto de la tarjeta: la foto se leía
   como el fondo del bloque y no como el producto. Con 8px de aire alrededor y
   12 de radio, la tarjeta enmarca la foto -- y el marco blanco es lo que hace
   que se lea como una ficha. */
.ag-card .ag-foto {
    display: block; width: 100%; height: 150px;
    margin: 8px 0 0; width: calc(100% - 16px); margin-left: 8px;
    border-radius: 12px;
}

/* ── FORMATO 2: LA COMPACTA ─────────────────────────────────────────── */

/* LA COMPACTA MIDE 178 de ancho y AL MENOS 150 de alto, con el thumb de 71: es
   una tarjeta de panel lateral, donde caben dos por fila. Dos tarjetas
   seguidas quedan iguales porque la fila las estira, no porque el alto sea fijo
   --fijo, el cuerpo no cabía y se solapaban título y vendedor--. */
.ag-mini {
    display: flex; flex-direction: column;
    /* Alto mínimo y no fijo: el cuerpo (nombre en dos líneas, vendedor, precio
       y «IVA incluido») no cabe en 79px, y con `height` fija se comprimía. */
    width: 178px; min-height: 150px;
    max-width: 100%;
}
.ag-mini .ag-foto { height: 71px; flex: 0 0 71px; }

.ag-mini .ag-mini-pie {
    display: flex; align-items: center; justify-content: space-between; gap: 8px;
    /* Al pie, por lo mismo que en la completa. */
    margin-top: auto; padding-top: 6px;
}
.ag-mini .ag-mini-pie .ag-precios { margin: 0; }

/* ── FORMATO 3: LA FILA DE SUBASTA ──────────────────────────────────── */

/* LA FILA DE SUBASTA: 75 de alto y el thumb CUADRADO de 57 x 57. Las dos
   medidas salen de la maqueta (el PNG va a escala 1:1) y el alto es
   exactamente el thumb más sus 9 de aire arriba y abajo. */
.ag-subasta {
    display: grid;
    grid-template-columns: 57px minmax(0, 1fr) auto;
    gap: 12px; align-items: center;
    height: 75px; padding: 9px;
}
.ag-subasta .ag-foto { width: 57px; height: 57px; flex: 0 0 57px; border-radius: 10px; }

.ag-subasta .ag-subasta-txt { position: relative; z-index: 2; min-width: 0; pointer-events: none; }

.ag-subasta .ag-queda {
    display: inline-flex; align-items: center; gap: 5px;
    margin-top: 6px; padding: 3px 9px;
    background: #fdecec; border-radius: 999px;
    font-size: 11.5px; font-weight: 700; color: #d92d20;
}
.ag-subasta .ag-queda iconify-icon { font-size: 13px; }

/* LA PÍLDORA VA EN ROJO SIEMPRE, falten dos horas o falten tres días. Aquí
   había un `.ag-holgado` que la pasaba a gris con más de un día por delante --
   idea mía, no de la maqueta, y lo que conseguía era que la misma fila se viera
   de dos maneras distintas sin que nada lo explicara. La maqueta pinta una sola
   píldora, y en una subasta el tiempo SIEMPRE es el dato que decide. */

/* ── LA FILA COMO ARTÍCULO NORMAL ───────────────────────────────────
   El mismo formato sirve para lo que no es subasta: cambian los textos, no la
   colocación. En vez de la cuenta atrás va el lugar, que es lo que la tarjeta
   completa pone en esa misma posición. */
.ag-subasta .ag-lugar {
    display: inline-flex; align-items: center; gap: 5px;
    margin: 6px 0 0; padding: 0;
    font-size: 12px; line-height: 1.35;
    color: var(--sd-suave, #6b7a70);
}
.ag-subasta .ag-lugar iconify-icon { flex: 0 0 auto; font-size: 13px; }

.ag-subasta .ag-subasta-puja { position: relative; z-index: 2; text-align: right; }
.ag-subasta .ag-subasta-puja small { display: block; font-size: 11px; color: var(--sd-suave, #6b7a70); }
.ag-subasta .ag-subasta-puja b {
    display: block; margin-top: 2px;
    font-size: 15px; font-weight: 800; color: var(--sd-tinta, #16211a);
}
.ag-subasta .ag-subasta-puja .ag-btn { margin-top: 7px; }

/* ── EL FOCO TIENE QUE VERSE ────────────────────────────────────────── */

.ag-card .ag-btn:focus-visible, .ag-mini .ag-btn:focus-visible, .ag-subasta .ag-btn:focus-visible,
.ag-card .ag-fav:focus-visible, .ag-mini .ag-fav:focus-visible,
.ag-card .ag-tapa:focus-visible, .ag-mini .ag-tapa:focus-visible, .ag-subasta .ag-tapa:focus-visible {
    outline: 2px solid var(--sd-verde, #04713a);
    outline-offset: 2px;
}

/* ══ LAS ETIQUETAS Y LOS DATOS DE VENTA ════════════════════════════════
 *
 * NACÍAN OCULTAS y las encendía la hoja de cada pantalla. Desde el 26/09/2026
 * son parte de la tarjeta vertical --diseño del usuario-- y se ven SIEMPRE:
 * las píldoras bajo el precio (qué es la mercancía) y la fila de datos debajo
 * (cómo y cuándo se compra). El apaisado y la vista de lista las siguen
 * colocando a su manera desde `TStorefront.css`, que gana por especificidad.
 *
 * Y LAS PÍLDORAS VAN BAJO EL PRECIO Y NO SOBRE LA FOTO, a propósito:
 * amontonarlas encima tapa el producto, que es lo único que vende en una
 * rejilla. Sobre la foto se queda solo la etiqueta de esquina.
 *
 * CANDIDATAS A LA HOJA COMÚN del área de cliente junto con el resto de la
 * tarjeta; van aquí porque son de la tarjeta, no de la tienda.
 */
.ag-card .ag-tags,
.ag-card .ag-meta { display: flex; }

/* ── LAS ETIQUETAS: qué es la mercancía ───────────────────────────── */
.ag-card .ag-tags { flex-wrap: wrap; gap: 6px; margin-top: 9px; }

.ag-card .ag-tag {
    display: inline-flex; align-items: center;
    padding: 4px 11px;
    /* REDONDEO COMPLETO, como la maqueta: una píldora, no una etiqueta
       cuadrada. Es lo que la distingue del rótulo de la esquina. */
    border-radius: 999px;
    background: #f1f4f1;
    border: 1px solid transparent;
    color: var(--sd-texto, #46514a);
    font-size: 11.5px; font-weight: 700; line-height: 1.4;
    white-space: nowrap;
}

/* ── LOS DOS TONOS DE LA MAQUETA ───────────────────────────────────
   `eco` es una afirmación verificada --lleva certificado detrás-- y va maciza
   en verde; `info` es un dato del género (el calibre, un sello de finca) y va
   en azul pálido con letra azul. Medidos: 5,10 y 7,26 sobre sus fondos. */
.ag-card .ag-tag.es-eco  { background: #1d753b; border-color: #1d753b; color: #fff; }
.ag-card .ag-tag.es-info { background: #e8f0fb; border-color: #d3e3f7; color: #1f4f8f; }

/* El cultivo ecológico con su verde: es el que el comprador busca, y en gris
   pesa lo mismo que el formato del envase. */
.ag-card .ag-tag.es-eco {
    background: #e8f5ec;
    border-color: #bfe3cb;
    color: #1d753b;
}

/* Y los sellos de finca en azul apagado: son una afirmación del agricultor
   --«Producción integrada», «GlobalG.A.P.»--, no un certificado ecológico, y
   con el mismo verde se leerían como lo segundo. */
.ag-card .ag-tag.es-info {
    background: #eaf2fb;
    border-color: #c8ddf4;
    color: #1c5b96;
}

/* ── LOS DATOS DE VENTA: cómo y cuándo se compra ────────────────────
 *
 * SIN FONDO Y SIN FILETE (26/09/2026). Los llevaba --un `#fbfdfb` con borde
 * arriba-- y con las píldoras encima la tarjeta se leía partida en tres
 * bandas: ficha, píldoras y «pie». En la maqueta es una línea de texto
 * pequeño más, no una franja: lo que la separa es el aire, no una caja.
 *
 * Y SE PARTE EN DOS LÍNEAS antes que recortarse: «Envío disponible» cortado a
 * la mitad no dice nada. En el apaisado manda lo contrario --una sola línea
 * con puntos suspensivos-- y lo impone `TStorefront.css`, que gana. */
.ag-card .ag-meta {
    flex-wrap: wrap;
    align-items: center;
    gap: 5px 14px;
    margin: 10px 14px 0;
    padding: 0;
    border-top: 0;
    background: none;

    /* COMO EL CUERPO: la tapa que hace pulsable la tarjeta entera vive debajo,
       y sin esto esta franja se traga el clic en toda su altura. */
    position: relative; z-index: 2;
    pointer-events: none;
}

.ag-card .ag-meta-it {
    display: inline-flex; align-items: center; gap: 5px;
    font-size: 11.5px; font-weight: 500; line-height: 1.3;
    color: var(--sd-suave-aa, #5f6b65);
    white-space: nowrap;
}
.ag-card .ag-meta-it iconify-icon { flex: 0 0 auto; font-size: 14px; color: var(--sd-verde, #116f34); }
.ag-card .ag-meta-it span { color: inherit; }

/* ══ EL PIE, YA FUERA DEL CUERPO ═══════════════════════════════════════
 *
 * Se sacó de `.ag-cuerpo` para que en apaisado pueda compartir fila con los
 * datos de venta. En la tarjeta vertical no cambia nada a la vista --sigue
 * siendo lo último y pegado al fondo por su `margin-top: auto`-- pero necesita
 * lo que antes le daba el cuerpo: el relleno lateral y, sobre todo, el paso del
 * ratón. El cuerpo es `pointer-events: none` para que la tapa que hace pulsable
 * la tarjeta entera reciba el clic, y sus botones lo recuperaban con una regla
 * propia; fuera de él, sin esto, el botón de comprar dejaba de responder EN
 * TODAS LAS PANTALLAS y sin un solo error.
 */
.ag-card > .ag-cuerpo { padding-bottom: 0; }

.ag-card > .ag-pie {
    padding: 10px 14px 14px;
    position: relative; z-index: 2;
    pointer-events: none;
}
.ag-card > .ag-pie > * { pointer-events: auto; }

/* ══ EL SELLO DE VERIFICADO ════════════════════════════════════════════
   Relleno y azul: de trazo se lee como «se puede verificar». Va pegado al
   nombre del vendedor, en su línea. */
.ag-card .ag-vendedor { display: flex; align-items: center; gap: 5px; }

.ag-card .ag-verificado {
    flex: 0 0 auto;
    width: 15px; height: 15px;
    color: #1d8cf0;
}

/* ── LA ETIQUETA NO SE SALE DE LA TARJETA ──────────────────────────────
 *
 * `top/left` fijos y ningún tope de ancho: con un sello de dos palabras no se
 * notaba, pero desde que la etiqueta puede traer el sello de cultivo del
 * agricultor --«Sin tratamiento postcosecha»-- se salía por la derecha de la
 * tarjeta y se metía por debajo del corazón. El hueco que se le deja a la
 * derecha es el del corazón (34px) más su margen.
 */
.ag-card .ag-etiqueta, .ag-mini .ag-etiqueta {
    max-width: calc(100% - 56px);
    white-space: normal;
    line-height: 1.25;
}




/* ═══════════════════════════════════════════════════════════════════════════
   EL DIRECTORIO DE AGRICULTORES — la hoja común de las dos pantallas
   ═══════════════════════════════════════════════════════════════════════════

   Todo cuelga de `.sd`. Aquí vive lo que las DOS pantallas comparten --la
   tarjeta del vendedor y sus cuatro tallas, los sellos, las píldoras, el bloque
   de búsqueda, las cifras, las etiquetas de lo filtrado y la columna de
   criterios--; lo propio de cada una está en su propio componente.

   Los verdes están MUESTREADOS del PNG de la maqueta (botón #01753b, «Buscar»
   #01642c, pie #005c2d), no elegidos a ojo. Y los cuatro colores de medalla,
   muestreados de las piezas de `/assets/sellers/`: es el mismo dorado del sello
   el que rodea la tarjeta.

   CANDIDATO A LA HOJA COMÚN DEL ÁREA DE CLIENTE (ver CLAUDE.md): la tarjeta,
   las píldoras, la valoración y los botones se repiten ya en TOrderDetail y
   TReturnOrder con otros valores. Cuando esa hoja se extraiga, esto sube tal
   cual.
   ═══════════════════════════════════════════════════════════════════════════ */

.sd{
    --sd-verde:        #04713a;
    --sd-verde-vivo:   #01753b;
    --sd-verde-oscuro: #005c2d;
    --sd-verde-claro:  #eef6ee;
    --sd-verde-borde:  #cfe3d2;

    --sd-tinta:  #16211a;
    --sd-texto:  #46514a;
    --sd-suave:  #6b7a70;
    --sd-tenue:  #93a399;

    --sd-crema:  #f7faf6;
    --sd-borde:  #e4eae4;
    --sd-oro:    #e2a812;

    /* ── LOS COLORES DE LAS MEDALLAS ──────────────────────────────
       Muestreados de las piezas: el tono dominante de cada escarapela. Con
       ellos se rodea la tarjeta del vendedor que tiene ese nivel, para que la
       medalla y su borde sean lo mismo y no dos verdes distintos. */
    --sd-m-oro:      #d9a51e;
    --sd-m-plata:    #a8adb4;
    --sd-m-bronce:   #c1783a;
    --sd-m-diamante: #9aa0e8;

    --sd-radio:  14px;
    --sd-sombra: 0 2px 10px rgba(20,40,25,.06);

    color: var(--sd-texto);
    font-size: 14px;
    line-height: 1.45;
}

.sd *{ box-sizing: border-box; }
.sd img{ display:block; max-width:100%; }
.sd a{ color:inherit; text-decoration:none; }
.sd h1,.sd h2,.sd h3,.sd h4{ margin:0; color:var(--sd-tinta); }

/* EL TAMAÑO SE DECLARA EN EL ICONO, NO EN SU CAJA: `iconify-icon` no hereda el
   `font-size` del padre y sin esto todos saldrían al tamaño por defecto. */
.sd iconify-icon{ display:inline-block; vertical-align:-.125em; }

/* La hoja global del sitio pinta de negro el borde de cualquier enlace ya
   visitado (`a:visited`), y estas tarjetas SON enlaces: sin esto, volver a una
   búsqueda las enseña todas con marco negro. `getComputedStyle` no lo delata. */
.sd a:visited, .sd a:visited *{ border-color: inherit; color: inherit; }

/* El contenido recogido a la medida de la página; las franjas van a sangre. */
.sd-ancho{ max-width:1200px; margin:0 auto; padding:0 20px; }

/* ═══ BOTONES ══════════════════════════════════════════════════════ */
.sd .sd-btn{
    display:inline-flex; align-items:center; justify-content:center; gap:8px;
    height:40px; padding:0 18px; border:1px solid transparent; border-radius:9px;
    font-size:13.5px; font-weight:700; cursor:pointer; white-space:nowrap;
    font-family:inherit; transition:background .15s, border-color .15s, color .15s;
}
.sd .sd-btn-primary{ background:var(--sd-verde); color:#fff; }
.sd .sd-btn-primary:hover{ background:var(--sd-verde-oscuro); color:#fff; }
.sd .sd-btn-secondary{ background:#fff; color:var(--sd-tinta); border-color:var(--sd-borde); }
.sd .sd-btn-secondary:hover{ background:var(--sd-crema); color:var(--sd-tinta); }
.sd .sd-btn-blanco{ background:#fff; color:var(--sd-tinta); }
.sd .sd-btn-sm{ height:34px; padding:0 14px; font-size:12.5px; }
.sd .sd-btn-block{ width:100%; }

/* ═══ TÍTULOS DE SECCIÓN ═══════════════════════════════════════════ */
.sd-seccion{ padding:34px 0 0; }
.sd-tit{ display:flex; align-items:flex-end; gap:16px; margin-bottom:16px; }
.sd-tit-txt{ flex:1; min-width:0; }
.sd-tit h2{ font-size:17px; font-weight:800; letter-spacing:.3px; text-transform:uppercase;
            border-bottom:3px solid var(--sd-verde); display:inline-block; padding-bottom:6px; }
.sd-tit p{ margin:8px 0 0; font-size:12.5px; color:var(--sd-suave); }
.sd .sd-tit-mas{ flex:0 0 auto; font-size:12.5px; font-weight:700; color:var(--sd-verde);
                 display:inline-flex; align-items:center; gap:6px; }

/* ═══ EL BLOQUE DE BÚSQUEDA ════════════════════════════════════════ */
.sd-busca{ background:#fff; border:1px solid var(--sd-borde); border-radius:var(--sd-radio);
           box-shadow:0 14px 34px rgba(18,40,24,.13); padding:18px; }
.sd-busca-fila{ display:flex; gap:12px; }
.sd-busca-txt{ flex:1; display:flex; align-items:center; gap:10px; height:48px;
               border:1px solid var(--sd-borde); border-radius:10px; padding:0 14px; background:#fff; }
.sd-busca-txt iconify-icon{ font-size:18px; color:var(--sd-tenue); flex:0 0 auto; }
.sd-busca-txt input{ flex:1; min-width:0; border:0; outline:none; font-size:14px;
                     font-family:inherit; color:var(--sd-tinta); background:transparent; }
.sd .sd-btn-buscar{ height:48px; padding:0 30px; font-size:14px;
                    background:var(--sd-verde-oscuro); color:#fff; border-radius:10px; }

.sd-filtros{ display:grid; grid-template-columns:repeat(3,1fr); gap:14px; margin-top:14px; }
.sd-campo{ border:1px solid var(--sd-borde); border-radius:10px; padding:8px 12px 6px; background:#fff; }
.sd-campo label{ display:block; font-size:11px; color:var(--sd-suave); }
.sd-campo select{ width:100%; border:0; outline:none; background:transparent; font-size:13.5px;
                  font-weight:600; color:var(--sd-tinta); font-family:inherit; padding:2px 0; cursor:pointer; }

/* Los dos interruptores. APAGADOS DE SALIDA: encendidos esconden a la mayoría
   del censo y la primera pantalla del directorio parece vacía. */
.sd-switches{ display:grid; grid-template-columns:repeat(2,1fr); gap:14px; margin-top:14px; }
.sd-switch{ display:flex; align-items:center; gap:10px; border:1px solid var(--sd-borde);
            border-radius:10px; padding:10px 14px; cursor:pointer; background:#fff; }
.sd-switch > iconify-icon{ font-size:19px; color:var(--sd-verde); flex:0 0 auto; }
.sd-switch-txt{ flex:1; min-width:0; }
.sd-switch-txt b{ display:block; font-size:13px; color:var(--sd-tinta); font-weight:600; }
.sd-switch-txt small{ display:block; font-size:11px; color:var(--sd-suave); }
.sd-palanca{ flex:0 0 auto; width:44px; height:24px; border-radius:99px; background:#d8ded8;
             position:relative; transition:background .18s; }
.sd-palanca::after{ content:''; position:absolute; top:3px; left:3px; width:18px; height:18px;
                    border-radius:50%; background:#fff; box-shadow:0 1px 3px rgba(0,0,0,.25); transition:left .18s; }
.sd-switch.on .sd-palanca{ background:var(--sd-verde); }
.sd-switch.on .sd-palanca::after{ left:23px; }

/* ═══ CIFRAS ═══════════════════════════════════════════════════════ */
.sd-cifras{ display:grid; grid-template-columns:repeat(4,1fr); background:var(--sd-crema);
            border:1px solid var(--sd-borde); border-radius:var(--sd-radio); margin-top:22px; }
.sd-cifra{ display:flex; align-items:center; gap:12px; padding:16px 20px; }
.sd-cifra + .sd-cifra{ border-left:1px solid var(--sd-borde); }
.sd-cifra > iconify-icon{ font-size:22px; color:var(--sd-verde); flex:0 0 auto; }
.sd-cifra div{ flex:1; min-width:0; }
.sd-cifra b{ display:block; font-size:19px; font-weight:800; color:var(--sd-tinta); line-height:1.15; }
.sd-cifra small{ display:block; font-size:11.5px; color:var(--sd-suave); }

/* ═══ PIEZAS DE UNA TARJETA ════════════════════════════════════════ */

/* EL SELLO VERIFICADO ES UNA IMAGEN, Y LA REGLA SE ESCRIBE CON `img`.
   `.sd img{display:block}` (0,1,1) le gana a `.sd-verificado` (0,1,0) y el sello
   se iba a su propia línea debajo del nombre -- el mismo mordisco que ya estaba
   documentado en `.sd-card-foto img.sd-card-sello`. Con la clase Y el elemento,
   esta manda. Bajado tres píxeles para que se siente en la base del nombre y no
   sobre su altura de mayúsculas. */
.sd img.sd-verificado{ display:inline-block; vertical-align:-3px; width:16px; height:16px;
                       margin-left:5px; object-fit:contain; }

/* Icono a la izquierda y TODO el texto en la segunda columna: la regla de
   alineación del proyecto. Nada de `margin-left` a ojo para compensar el icono. */
.sd-linea{ display:flex; align-items:flex-start; gap:6px; margin-top:5px; }
.sd-linea > iconify-icon{ font-size:13px; color:var(--sd-tenue); flex:0 0 auto; margin-top:2px; }
.sd-linea span{ flex:1; min-width:0; font-size:12px; color:var(--sd-suave); }

.sd-rating{ display:flex; align-items:center; gap:5px; margin-top:7px; font-size:12.5px; }
.sd-rating b{ color:var(--sd-tinta); font-weight:700; }
.sd-rating iconify-icon{ color:var(--sd-oro); font-size:13px; }
.sd-rating small{ color:var(--sd-suave); font-size:11.5px; }

.sd-hechos{ display:flex; gap:14px; margin-top:10px; margin-bottom:12px; padding-top:10px;
            border-top:1px solid var(--sd-borde); }
.sd-hecho{ display:flex; align-items:flex-start; gap:6px; flex:1; min-width:0; }
.sd-hecho > iconify-icon{ font-size:14px; color:var(--sd-verde); flex:0 0 auto; margin-top:1px; }
.sd-hecho div{ flex:1; min-width:0; }
.sd-hecho b{ display:block; font-size:12px; color:var(--sd-tinta); }
.sd-hecho small{ display:block; font-size:10.5px; color:var(--sd-suave); }

.sd-pills{ display:flex; flex-wrap:wrap; gap:6px; margin-top:10px; }
.sd-pill{ font-size:10.5px; font-weight:700; border-radius:99px; padding:3px 9px;
          background:var(--sd-verde-claro); color:var(--sd-verde-oscuro); border:1px solid var(--sd-verde-borde); }

.sd-nivel{ display:inline-flex; align-items:center; gap:4px; background:var(--sd-crema);
           border:1px solid var(--sd-borde); border-radius:99px; padding:2px 9px 2px 3px;
           font-size:10px; font-weight:700; color:var(--sd-tinta); white-space:nowrap; }
.sd-nivel img{ width:18px; height:18px; object-fit:contain; }

.sd-proteccion{ display:flex; align-items:center; gap:7px; margin-top:auto;
                background:var(--sd-verde-claro); border-top:1px solid var(--sd-verde-borde);
                padding:9px 14px; }
.sd-proteccion iconify-icon{ color:var(--sd-verde); font-size:14px; flex:0 0 auto; }
.sd-proteccion span{ font-size:11.5px; font-weight:700; color:var(--sd-verde-oscuro); }

/* El avatar: con foto o con su inicial. Un círculo con letra se lee como una
   identidad; un hueco gris, no. */
.sd-avatar{ flex:0 0 auto; width:44px; height:44px; border-radius:50%; overflow:hidden;
            background:var(--sd-verde-claro); color:var(--sd-verde-oscuro); font-weight:800;
            display:flex; align-items:center; justify-content:center; font-size:15px;
            border:1px solid var(--sd-verde-borde); }
.sd-avatar img{ width:100%; height:100%; object-fit:cover; }

/* La foto de portada cuando el vendedor no ha subido ninguna: su inicial sobre
   el verde de la casa. NUNCA una foto de archivo: sería enseñar una finca que
   no es la suya. */
.sd-portada-vacia{ position:absolute; inset:0; z-index:1; display:flex; align-items:center;
                   justify-content:center; gap:10px; color:#7ba57f;
                   background:linear-gradient(135deg, #e8f2e6 0%, #d7e9d6 100%); }
.sd-portada-vacia iconify-icon{ font-size:26px; }
/* Las iniciales, para que el hueco se lea como una identidad y no como una foto
   que no ha cargado. */
.sd-portada-vacia b{ font-size:22px; font-weight:800; letter-spacing:1px; color:#6f9c74; }

/* ═══ LA TARJETA ════════════════════════════════════════════════════
   Vive en `TSellerCard` (Storefront/templates), con sus tokens puestos en la
   propia tarjeta: así no pierde el borde fuera de `.sd`, en favoritos. */

/* ═══ CARRIL ═══════════════════════════════════════════════════════ */
.sd-carril{ position:relative; }
.sd-carril-pista{ display:grid; grid-auto-flow:column; grid-auto-columns:calc((100% - 4*14px)/5);
                  gap:14px; overflow-x:auto; scroll-behavior:smooth; padding:4px 2px 8px;
                  scrollbar-width:none; }
.sd-carril-pista::-webkit-scrollbar{ display:none; }
.sd-flecha{ position:absolute; top:50%; right:-16px; transform:translateY(-50%); z-index:3;
            width:34px; height:34px; border-radius:50%; background:#fff; border:1px solid var(--sd-borde);
            box-shadow:0 3px 10px rgba(20,40,25,.16); display:flex; align-items:center; justify-content:center;
            cursor:pointer; color:var(--sd-tinta); }

/* ═══ ETIQUETAS DE LO FILTRADO ═════════════════════════════════════
   Arriba del todo y quitables una a una. Un filtro puesto hace tres pantallas
   y olvidado es la causa número uno de «no hay resultados». */
.sd-chips{ display:flex; align-items:center; flex-wrap:wrap; gap:8px; margin-bottom:12px; }
.sd-chips-tit{ font-size:11.5px; font-weight:700; color:var(--sd-suave);
               text-transform:uppercase; letter-spacing:.4px; }
.sd-chip{ display:inline-flex; align-items:center; gap:6px; background:var(--sd-verde-claro);
          border:1px solid var(--sd-verde-borde); border-radius:99px; padding:4px 6px 4px 11px;
          font-size:11.5px; font-weight:600; color:var(--sd-verde-oscuro); }
.sd-chip button{ border:0; background:rgba(0,0,0,.06); color:inherit; cursor:pointer;
                 width:16px; height:16px; border-radius:50%; display:flex; align-items:center;
                 justify-content:center; font-size:10px; padding:0; }
.sd-chip button:hover{ background:var(--sd-verde); color:#fff; }
.sd-chips-limpiar{ font-size:11.5px; font-weight:700; color:var(--sd-verde); cursor:pointer;
                   display:inline-flex; align-items:center; gap:5px; background:none; border:0;
                   font-family:inherit; }

/* ═══ COLUMNA DE CRITERIOS ═════════════════════════════════════════ */
.sd-panel{ background:#fff; border:1px solid var(--sd-borde); border-radius:var(--sd-radio);
           box-shadow:var(--sd-sombra); overflow:hidden; }
.sd-panel-cab{ display:flex; align-items:center; gap:8px; padding:11px 14px;
               border-bottom:1px solid var(--sd-borde); }
.sd-panel-cab > iconify-icon{ color:var(--sd-verde); font-size:16px; flex:0 0 auto; }
.sd-panel-cab b{ flex:1; min-width:0; font-size:13px; color:var(--sd-tinta); }
.sd-panel-cab a{ font-size:11.5px; font-weight:700; color:var(--sd-verde); cursor:pointer; }

.sd-grupo{ border-bottom:1px solid var(--sd-borde); }
.sd-grupo:last-child{ border-bottom:0; }
/* 20 ARRIBA Y 12 ABAJO, Y NO LOS 11 IGUALES DE ANTES.
   Cada grupo lleva su línea de separación (`.sd-grupo`), así que el rótulo se
   leía pegado a la raya. Y no van iguales a propósito: un título pertenece a lo
   que tiene DEBAJO, así que se separa más de la línea de arriba --que es el
   final del grupo anterior-- que de sus propias opciones. Con los dos iguales,
   la columna se lee como una tabla de filas sueltas y no como una lista de
   secciones. El relleno lateral no se toca: lo comparte con el cuerpo. */
.sd-grupo-cab{ width:100%; display:flex; align-items:center; gap:8px; padding:20px 14px 12px;
               background:none; border:0; cursor:pointer; font-family:inherit; text-align:left; }
.sd-grupo-cab b{ flex:1; min-width:0; font-size:12.5px; font-weight:700; color:var(--sd-tinta); }
.sd-grupo-cab > iconify-icon:first-child{ font-size:15px; color:var(--sd-verde); flex:0 0 auto; }
.sd-grupo-flecha{ font-size:15px; color:var(--sd-tenue); transition:transform .15s; }
.sd-grupo.cerrado .sd-grupo-flecha{ transform:rotate(-90deg); }
/* Y el cuerpo cierra con 16: es lo que deja el aire de debajo del último
   control parecido al de encima del título siguiente, contando que ahí hay
   además una línea. */
.sd-grupo-cuerpo{ padding:0 14px 16px; }
.sd-grupo.cerrado .sd-grupo-cuerpo{ display:none; }

.sd-buscasub{ display:flex; align-items:center; gap:6px; border:1px solid var(--sd-borde);
              border-radius:8px; padding:5px 9px; margin-bottom:8px; }
.sd-buscasub iconify-icon{ font-size:14px; color:var(--sd-tenue); flex:0 0 auto; }
.sd-buscasub input{ flex:1; min-width:0; border:0; outline:none; font-family:inherit; font-size:12px; }

/* Una casilla, con SU RECUENTO: sin él no se sabe si un filtro deja dos
   resultados o doscientos, y se prueba a ciegas. */
.sd-check{ display:flex; align-items:center; gap:8px; padding:4px 0; cursor:pointer; }
.sd-check input{ position:absolute; opacity:0; width:0; height:0; }
.sd-marca{ flex:0 0 auto; width:16px; height:16px; border:1px solid #c8d2c8; border-radius:4px;
           background:#fff; display:flex; align-items:center; justify-content:center;
           color:#fff; font-size:11px; }
.sd-check input:checked + .sd-marca{ background:var(--sd-verde); border-color:var(--sd-verde); }
.sd-marca iconify-icon{ visibility:hidden; }
.sd-check input:checked + .sd-marca iconify-icon{ visibility:visible; }
.sd-check-txt{ flex:1; min-width:0; font-size:12px; color:var(--sd-texto);
               display:flex; align-items:center; gap:6px; }
.sd-check-txt img{ width:17px; height:17px; object-fit:contain; }
.sd-check i{ flex:0 0 auto; font-style:normal; font-size:10.5px; color:var(--sd-tenue); }
.sd-check input:checked ~ .sd-check-txt{ color:var(--sd-verde-oscuro); font-weight:600; }
.sd-vermas{ display:inline-block; margin-top:6px; font-size:11.5px; font-weight:700;
            color:var(--sd-verde); cursor:pointer; }

/* Valoración mínima: una sola respuesta, así que píldoras y no casillas. */
.sd-notas{ display:flex; flex-wrap:wrap; gap:6px; }
.sd-nota{ cursor:pointer; }
.sd-nota input{ position:absolute; opacity:0; }
.sd-nota span{ display:inline-flex; align-items:center; gap:4px; border:1px solid var(--sd-borde);
               border-radius:99px; padding:4px 10px; font-size:11.5px; color:var(--sd-texto); }
.sd-nota span iconify-icon{ color:var(--sd-oro); font-size:12px; }
.sd-nota input:checked + span{ background:var(--sd-verde-claro); border-color:var(--sd-verde);
                               color:var(--sd-verde-oscuro); font-weight:700; }

/* ═══ BARRA DE RESULTADOS Y VISTAS ═════════════════════════════════ */
.sd-barra{ display:flex; align-items:center; gap:10px; margin-bottom:14px; }
.sd-barra h2{ font-size:15px; font-weight:800; display:flex; align-items:center; gap:8px;
              text-transform:none; border:0; padding:0; }
.sd-barra h2 iconify-icon{ color:var(--sd-verde); font-size:17px; }
.sd-barra small{ color:var(--sd-suave); font-size:12px; }
.sd-barra-sp{ flex:1; }

.sd-vista{ display:flex; border:1px solid var(--sd-borde); border-radius:8px; overflow:hidden; }
.sd-vista button{ width:34px; height:34px; border:0; background:#fff; cursor:pointer;
                  color:var(--sd-suave); font-size:16px; }
.sd-vista button.on{ background:var(--sd-verde-claro); color:var(--sd-verde-oscuro); }

/* ═══ PAGINACIÓN ═══════════════════════════════════════════════════ */
/* LA PAGINACIÓN ES UN <nav>, Y ESO LA VESTÍA SOLA.
   `www_oneway/base.php` tiene una regla global para `nav` --la que pinta la
   barra de categorías del sitio-- con fondo blanco y `border-bottom: 1px solid
   #bbb`. Como el paginador también es un `nav`, se llevaba la raya gris de
   extremo a extremo por debajo de los resultados, como si allí acabara una
   sección. El fondo blanco se deja puesto a propósito; la raya se quita. */
.sd-pag{ display:flex; justify-content:center; align-items:center; gap:6px; margin:22px 0 6px;
         background-color:#FFF; border-bottom:0; }
.sd-pag a,.sd-pag span{ min-width:32px; height:32px; border-radius:8px; border:1px solid var(--sd-borde);
                        background:#fff; display:flex; align-items:center; justify-content:center;
                        font-size:12.5px; font-weight:700; color:var(--sd-tinta); cursor:pointer; }
.sd-pag .on{ background:var(--sd-verde); border-color:var(--sd-verde); color:#fff; }
.sd-pag .vacio{ border:0; background:transparent; color:var(--sd-tenue); cursor:default; }

/* ═══ COMPROMISOS ══════════════════════════════════════════════════ */
.sd-promesas{ display:grid; grid-template-columns:repeat(4,1fr); gap:22px; background:var(--sd-crema);
              border:1px solid var(--sd-borde); border-radius:var(--sd-radio);
              padding:20px 22px; margin:34px 0 40px; }
.sd-promesa{ display:flex; align-items:flex-start; gap:12px; }
.sd-promesa > span{ flex:0 0 auto; width:38px; height:38px; border-radius:50%; background:#fff;
                    border:1px solid var(--sd-verde-borde); display:flex; align-items:center;
                    justify-content:center; color:var(--sd-verde); font-size:18px; }
.sd-promesa div{ flex:1; min-width:0; }
.sd-promesa b{ display:block; font-size:13px; color:var(--sd-verde-oscuro); }
.sd-promesa small{ display:block; font-size:11.5px; color:var(--sd-suave); margin-top:3px; }

/* ═══ SIN RESULTADOS ═══════════════════════════════════════════════
   Y con la salida puesta: decir «no hay nada» sin ofrecer cómo deshacer el
   filtro que lo ha dejado vacío es dejar al visitante en un callejón. */
.sd-vacio{ text-align:center; padding:44px 20px; background:#fff;
           border:1px dashed var(--sd-borde); border-radius:var(--sd-radio); }
.sd-vacio iconify-icon{ font-size:32px; color:var(--sd-tenue); }
.sd-vacio b{ display:block; margin-top:10px; font-size:15px; color:var(--sd-tinta); }
.sd-vacio small{ display:block; margin:6px 0 14px; font-size:12.5px; color:var(--sd-suave); }

@media (max-width:1100px){
    .sd-promesas{ grid-template-columns:repeat(2,1fr); }
    .sd-carril-pista{ grid-auto-columns:calc((100% - 2*14px)/3); }
}
@media (max-width:760px){
    .sd-filtros,.sd-switches,.sd-cifras{ grid-template-columns:1fr; }
    .sd-cifra + .sd-cifra{ border-left:0; border-top:1px solid var(--sd-borde); }
    .sd-carril-pista{ grid-auto-columns:78%; }
    .sd-promesas{ grid-template-columns:1fr; }

    /* A 400 px el botón «Buscar» se salía 48 px por la derecha (medido el
       15/09/2026, al soltar el ancho mínimo del sitio): la caja de texto no
       baja de su contenido sin `min-width:0`. Caja arriba y botón debajo. */
    .sd-busca-fila{ flex-wrap:wrap; }
    .sd-busca-txt{ min-width:0; flex:1 1 100%; }
    .sd .sd-btn-buscar{ flex:1 1 100%; }

    /* Y las flechas del carril, dentro del borde: a -16 px empujaban la página. */
    .sd-flecha{ right:0; }
}



/**
 * ═══════════════════════════════════════════════════════════════════════════
 *  LA TIENDA — lo que el sistema `sd-*` no cubre
 * ═══════════════════════════════════════════════════════════════════════════
 *
 * Los paneles de filtro, los grupos plegables, las casillas con recuento, los
 * chips, la barra de resultados y el cambio de vista vienen de `TSellersUI` sin
 * tocar una línea: es el mismo filtro del buscador de agricultores, como debe
 * ser. Aquí solo hay tres cosas que allí no existen:
 *
 *   · la PORTADA de la sección, con la foto y el texto de la categoría,
 *   · la disposición de dos columnas de esta página,
 *   · y la TARJETA DE PRODUCTO, en sus tres formas: compra directa, subasta y
 *     patrocinada grande.
 *
 * Todo cuelga de `.tf` para no alcanzar a nada de fuera, y usa los tokens
 * `--sd-*` que ya declara `TSellersUI`: colores propios aquí serían una segunda
 * paleta para la misma pantalla.
 */

/* ══ EL ANCHO DE ESTA PÁGINA ═══════════════════════════════════════
 *
 * `sd-ancho` se recoge a 1.200px, que es lo que le conviene a un directorio de
 * fichas de vendedor. Un buscador de productos NO: aquí lo que se compara son
 * cinco columnas de tarjetas, y a 1.200 con la columna de filtros restando
 * quedan 930 para la rejilla -- tarjetas de 175px con el nombre en cuatro
 * líneas. Se ensancha SOLO dentro de `.tf`, sin tocar la hoja común, que es de
 * las dos páginas. */
.tf .sd-ancho{ max-width: none; padding: 0; }

/* ── ALINEADA CON LA CABECERA DEL SITIO ─────────────────────────────
 *
 * Antes esto era `max-width: 1560px` con los 20px de relleno de `sd-ancho`: el
 * cuerpo arrancaba en x=124 y el logo de la cabecera en x=50, dos verticales
 * distintas en la misma pantalla --y con más ancho, cada vez más separadas--.
 * La cabecera y el cuerpo cuelgan de la MISMA columna (`.body-content`, que ya
 * topa en 1728px y pone los 30px de gutter), así que basta con que la caja no
 * se recoja por su cuenta: el borde izquierdo del logo, el de la portada y el
 * del filtro coinciden, y lo mismo el derecho. Y de paso la rejilla gana ancho,
 * que era la razón de ensancharla. */

/* ══ LA PORTADA DE LA SECCIÓN ══════════════════════════════════════ */

/* La caja común de la página: portada, cifras, cuerpo y garantías comparten
   columna, así que se declara una vez y todo cuelga de ella. */
.tf-caja{ padding-bottom: 8px; }

.tf-portada{
    position: relative;
    display: flex;
    align-items: flex-end;
    min-height: 260px;
    /* EL TEXTO NO PEGA CON EL BORDE DE LA FOTO: 0 a los lados dejaba el titular
       y la descripción rozando la esquina redondeada de la portada. */
    padding: 34px 40px 30px;
    overflow: hidden;
    border-radius: var(--sd-radio, 14px);

    /* PEGADA A LA CABECERA, SIN HUECO. El token `--tf-hueco` separa una zona
       de la SIGUIENTE, y la portada no tiene anterior: es lo primero de la
       página. Con su margen arriba quedaba una franja de fondo entre la
       cabecera y la foto que se lee como un fallo de carga. */
    margin-top: 0;
}

/* LA FOTO, EN SU PROPIA CAPA Y NO COMO FONDO DEL BLOQUE. Así el JS le cambia
   la `background-image` sin tocar el degradado de encima, que es fijo: con las
   dos en la misma declaración, cada cambio de categoría tendría que reescribir
   también el velo. */
.tf-portada-foto{
    position: absolute; inset: 0;

    /* EL ENCUADRE, POR ENCIMA DEL CENTRO Y NO EN EL CENTRO.
     *
     * La caja es una franja de 1250x260 --casi 5:1-- y las portadas son fotos
     * normales, de 2:1 para abajo: `cover` las recorta a lo alto y solo se ve
     * una banda. Centrada, esa banda parte al sujeto por la mitad: en la
     * portada genérica se llevaba por delante el sombrero del agricultor por
     * arriba y la caja de aguacates por abajo, que es justo lo que la foto
     * viene a enseñar.
     *
     * El 35% sube la banda: en una foto de persona la cara vive en el tercio
     * superior, y ahí es donde tiene que caer el recorte. */
    background-position: center 35%;
    background-size: cover;
    background-repeat: no-repeat;
}

/* El velo va de opaco a transparente hacia la derecha: el texto vive a la
   izquierda y la foto tiene que seguir viéndose al otro lado.

   ── LA MESETA LLEGA HASTA DONDE LLEGA EL TEXTO (25/09/2026) ─────────
   Caía a .58 en el 42% y la descripción mide 620px: su segunda mitad quedaba
   sobre velo flojo. Con el titular --34px en negrita-- no se notaba; con la
   descripción a 13.5px sí, y solo se ha visto ahora porque hasta hoy ninguna
   categoría tenía descripción escrita (todas a 0 caracteres). La meseta se
   mantiene hasta el 56% --donde acaba la columna de texto-- y de ahí cae igual
   de rápido: la foto sigue entera en su mitad derecha, que es lo que el velo
   venía a proteger. */
.tf-portada-velo{
    position: absolute; inset: 0;
    background: linear-gradient(90deg,
        rgba(8, 30, 16, .86) 0%,
        rgba(8, 30, 16, .74) 38%,
        rgba(8, 30, 16, .52) 56%,
        rgba(8, 30, 16, .12) 82%,
        rgba(8, 30, 16, 0) 100%);
}

/* `min-width: 0`, QUE ES ÍTEM DE UN FLEX. `.tf-portada` es `display:flex`, y un
   ítem flex no baja de su ancho de contenido salvo que se le diga: la fila de
   familias en móvil --que va en una sola línea con arrastre-- estiraba este
   hueco a 1.334px dentro de una portada de 373px, y el `overflow:hidden` de la
   portada se comía las nueve últimas familias. No se veían y no había forma de
   llegar a ellas. Medido en el navegador a 420px de ancho. */
.tf-portada-txt{ position: relative; z-index: 1; min-width: 0; flex: 1; }

.tf-portada h1{
    /* PADDING A CERO, Y NO ES ADORNO: la hoja del sitio le da `padding: 10px`
       a todo `h1`, así que el titular arrancaba 10px a la derecha de su propia
       descripción. Dos verticales en el mismo bloque de texto -- se lee
       torcido aunque cada línea esté bien puesta. */
    margin: 0 0 8px;
    padding: 0;
    font-size: 34px; font-weight: 800; letter-spacing: -.8px;
    color: #fff;
}

/* LA DESCRIPCIÓN ADMITE MARCADO --la escribe un editor con el editor rico-- así
   que se le da estilo a lo que puede traer dentro: párrafos, negritas, listas.
   Sin esto, un `<ul>` heredaría los topos y el margen del navegador y saldría
   descolocado sobre la foto. */
.tf-portada-desc{
    max-width: 620px;
    font-size: 13.5px; line-height: 1.6;
    color: rgba(255,255,255,.92);
}
/* ── `color: inherit`, Y ES LO QUE HACÍA ILEGIBLE LA DESCRIPCIÓN ───────
   `boot.css` trae `p{ color: #000 }` para todo el sitio, y una regla que apunta
   al `<p>` le gana al blanco HEREDADO del contenedor, por floja que sea. Como
   la descripción la escribe el editor rico --y el editor rico envuelve en
   `<p>`--, el texto de cualquier categoría con descripción salía NEGRO sobre la
   portada oscura: se leía como una mancha, y las negritas (que sí tenían su
   regla) blancas en medio. Medido: `getComputedStyle(p).color` daba
   `rgb(0,0,0)` con el contenedor en `rgba(255,255,255,.92)`.
   La misma trampa que `a span` en las píldoras de familia, unas líneas abajo. */
.tf-portada-desc p{ margin: 0 0 8px; color: inherit; }
.tf-portada-desc p:last-child{ margin-bottom: 0; }
.tf-portada-desc b, .tf-portada-desc strong{ color: #fff; }
.tf-portada-desc ul{ margin: 6px 0; padding-left: 18px; color: inherit; }
.tf-portada-desc li{ margin: 2px 0; color: inherit; }
.tf-portada-desc a{ color: #fff; text-decoration: underline; }
.tf-portada-desc a:visited{ color: #fff; }

/* Las píldoras de la cabecera. */
.tf-pills{ display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; }
.tf-pill{
    display: inline-flex; align-items: center; gap: 6px;
    padding: 5px 12px;
    border-radius: 999px;
    background: rgba(255,255,255,.14);
    border: 1px solid rgba(255,255,255,.28);
    color: #fff;
    font-size: 11.5px; font-weight: 700;
    backdrop-filter: blur(2px);
}
.tf-pill iconify-icon{ font-size: 13px; }

/* ══ SUBCATEGORÍAS ═════════════════════════════════════════════════════
 *
 * La fila de familias que va ENCIMA DE LA REJILLA, en la columna de resultados.
 * Estuvo primero sobre la portada --de ahí las reglas oscuras de más abajo, que
 * siguen valiendo si alguna vez vuelve ahí-- y se bajó aquí porque sobre la foto
 * competía con las píldoras de tono y su contraste dependía de la imagen.
 *
 * CANDIDATO A LA HOJA COMÚN del área de cliente: una fila de enlaces con dibujo
 * y recuento es lo que necesitan también el perfil del agricultor y la
 * colección. Mientras no exista, vive aquí y queda dicho.
 */
.tf-subcats-zona{
    margin: var(--tf-hueco) 0 0;
    padding: 14px 16px 16px;
    background: #fff;
    border: 1px solid var(--sd-borde);
    border-radius: var(--sd-radio, 14px);
}

/* El rótulo, con la misma talla que los títulos de grupo de la columna de
   filtros: es la misma jerarquía --un grupo de opciones-- y con dos tallas
   distintas la pantalla se lee como dos pantallas. */
/* CON LA ZONA DELANTE, Y HACE FALTA: el reseteo de títulos del escaparate
   --`.sd h1, .sd h2, .sd h3, .sd h4 { margin: 0 }`, (0,1,1)-- le ganaba a
   `.tf-subcats-t` (0,1,0) y le dejaba el margen de abajo en CERO, así que el
   rótulo salía pegado a las píldoras. Medido: `margin-bottom` calculado 0px
   con 10px declarados. Lo mismo le puede pasar a cualquier título de
   componente que viva dentro de `.sd`: se declara con su contenedor delante. */
.tf-subcats-zona .tf-subcats-t{
    margin: 0 0 10px;
    padding: 0;                      /* la hoja del sitio le mete 10px a los h2 */
    font-size: 12.5px; font-weight: 700;
    color: var(--sd-tinta);
    letter-spacing: 0;
}

.tf-subcats{ display: flex; flex-wrap: wrap; gap: 8px; }

/* ── LA PÍLDORA ────────────────────────────────────────────────────────
 *
 * EL `:visited` VA EN CADA REGLA, Y CON LA CLASE DEL CONTENEDOR DELANTE. Las
 * dos hojas viejas del sitio le meten mano a los enlaces ya visitados sin
 * clase que las acote --`boot.css` con `a:visited{ color:#910c88; border:0 }` y
 * `TSellersUI` con `.sd a:visited{ border-color: inherit }`-- y las dos EMPATAN
 * a especificidad con `.tf-subcat:visited` (0,0,1,1), así que ganan por orden
 * de hoja. Se vio en pantalla: las familias por las que ya se había pasado
 * salían con el borde NEGRO --`inherit` en un borde da el `currentColor` del
 * padre-- y las demás en gris claro, o sea media fila subrayada al azar según
 * por dónde hubiera navegado el visitante. Con `.tf-subcats` delante son
 * 0,0,2,1 y se acabó. Lo mismo hay que hacer con el texto de dentro, más abajo:
 * ahí el rival es `a span`, y una regla al hijo le gana a lo HEREDADO del
 * padre por floja que sea. */
.tf-subcats .tf-subcat,
.tf-subcats .tf-subcat:visited{
    display: inline-flex; align-items: center; gap: 8px;
    padding: 5px 12px 5px 5px;
    border-radius: 999px;
    background: var(--sd-crema);
    border: 1px solid var(--sd-borde);
    color: var(--sd-tinta);
    text-decoration: none;
    transition: border-color .15s, background .15s, box-shadow .15s;
}
.tf-subcats .tf-subcat:hover,
.tf-subcats .tf-subcat:focus-visible{
    background: #fff;
    border-color: var(--sd-verde);
    box-shadow: var(--sd-sombra, 0 2px 10px rgba(20,40,25,.06));
    text-decoration: none;
}
.tf-subcats .tf-subcat:focus-visible{ outline: 2px solid var(--sd-verde); outline-offset: 2px; }

/* EL DIBUJO, SIEMPRE EN SU HUECO Y SIEMPRE DEL MISMO TAMAÑO. La imagen que sube
   ADMIN puede venir de cualquier proporción --y de último recurso entra la
   PORTADA, que es casi 5:1--: sin `object-fit` se deformaría, y sin el círculo
   fijo cada píldora mediría una cosa. */
.tf-subcats .tf-subcat-ico{
    flex: 0 0 auto;
    width: 30px; height: 30px;
    display: grid; place-items: center;
    border-radius: 50%;
    overflow: hidden;
    background: #fff;
    border: 1px solid var(--sd-borde);
    color: var(--sd-verde);
}
.tf-subcats .tf-subcat-ico img{ width: 100%; height: 100%; object-fit: cover; display: block; }
.tf-subcats .tf-subcat-ico iconify-icon{ font-size: 19px; }

.tf-subcats .tf-subcat:hover .tf-subcat-ico{ border-color: var(--sd-verde); }

/* El nombre, con su color dicho: `boot.css` pinta `a span{ color:#910c88;
   font-size:11px }` para todo el sitio y una regla al hijo le gana al color
   heredado del enlace, por floja que sea. */
.tf-subcats .tf-subcat .tf-subcat-n,
.tf-subcats .tf-subcat:visited .tf-subcat-n{
    color: var(--sd-tinta);
    font-size: 12.5px; font-weight: 600;
    line-height: 1.2;
}

/* El recuento, en su propia cápsula: sin ella, «Miel y conservas 12» se lee
   como parte del nombre de la familia. */
.tf-subcats .tf-subcat > b,
.tf-subcats .tf-subcat:visited > b{
    padding: 1px 7px;
    border-radius: 999px;
    background: #eef3ee;
    color: var(--sd-suave);
    font-size: 11px; font-weight: 700;
}
.tf-subcats .tf-subcat:hover > b{ background: #e6f2ea; color: var(--sd-verde); }

/* ── EL BOTÓN DE «VER TODAS» ───────────────────────────────────────────
   Nace oculto --con el atributo `hidden`, que el JS quita solo si de verdad no
   caben-- y es de TEXTO, no una píldora más: si se pareciera a las familias se
   leería como una de ellas, y lo que hace es otra cosa. */
.tf-subcats-mas{
    display: inline-flex; align-items: center; gap: 6px;
    margin-top: 10px;
    padding: 4px 2px;
    border: 0; background: none;
    color: var(--sd-verde);
    font-family: inherit; font-size: 12.5px; font-weight: 700;
    cursor: pointer;
}
.tf-subcats-mas[hidden]{ display: none; }
.tf-subcats-mas:hover{ text-decoration: underline; }
.tf-subcats-mas:focus-visible{ outline: 2px solid var(--sd-verde); outline-offset: 2px; border-radius: 6px; }
.tf-subcats-mas iconify-icon{ font-size: 15px; transition: transform .15s; }
.tf-subcats-mas[aria-expanded="true"] iconify-icon{ transform: rotate(180deg); }

/* ── LA QUE SE ESTÁ MIRANDO ────────────────────────────────────────────
 *
 * Marcada con el verde de la casa: borde, fondo blanco y el dibujo sobre verde.
 * No basta con el borde --a 1px y en una fila de doce no se ve-- ni basta con el
 * fondo: el borde es lo que se distingue de lejos y el relleno del icono lo que
 * se distingue de cerca.
 *
 * Y ADEMÁS `aria-current="page"` en el marcado, que es lo que lo dice sin
 * mirar: un color no llega a quien usa lector de pantalla, y tampoco a quien no
 * distingue el verde del gris (WCAG 2.1 AA: el color no puede ser el único
 * portador de la información).
 */
.tf-subcats .tf-subcat.es-activa,
.tf-subcats .tf-subcat.es-activa:visited{
    background: #fff;
    border-color: var(--sd-verde);
    box-shadow: 0 0 0 1px var(--sd-verde) inset;
}
/* EL ICONO DE LA SELECCIONADA VA SIN ARO. Con su círculo y su borde había DOS
   marcos concéntricos diciendo lo mismo --el de la píldora y el del icono-- y el
   dibujo quedaba encerrado en una moneda. Lo que marca la elección es el borde
   que rodea la píldora entera; dentro, el icono flota sobre el blanco. */
.tf-subcats .tf-subcat.es-activa .tf-subcat-ico{
    background: transparent;
    border-color: transparent;
}
.tf-subcats .tf-subcat.es-activa .tf-subcat-n{ color: var(--sd-verde-oscuro, #0b5a2d); }

.tf-subcats .tf-subcat.es-activa > b{
    background: var(--sd-verde);
    color: #fff;
}

/* ── Y LA VARIANTE DE LA PORTADA ───────────────────────────────────────
   La misma fila sobre la foto: fondo translúcido y todo en blanco. Se conserva
   acotada a `.tf-portada` --que le gana en especificidad a la clara-- por si la
   fila vuelve a la cabecera; si se decide que no, este bloque se borra entero y
   no se lleva nada por delante. */
.tf-portada .tf-subcats{ margin-top: 12px; }

.tf-portada .tf-subcats .tf-subcat,
.tf-portada .tf-subcats .tf-subcat:visited{
    padding: 4px 10px 4px 4px;
    background: rgba(255,255,255,.10);
    border-color: rgba(255,255,255,.26);
    color: #fff;
    backdrop-filter: blur(2px);
    box-shadow: none;
}
.tf-portada .tf-subcats .tf-subcat-ico{
    width: 22px; height: 22px;
    background: rgba(255,255,255,.16);
    border-color: rgba(255,255,255,.3);
    color: #fff;
}
.tf-portada .tf-subcats .tf-subcat-ico iconify-icon{ font-size: 12px; }
.tf-portada .tf-subcats .tf-subcat .tf-subcat-n,
.tf-portada .tf-subcats .tf-subcat:visited .tf-subcat-n{ color: #fff; font-size: 11.5px; font-weight: 700; }
.tf-portada .tf-subcats .tf-subcat:hover,
.tf-portada .tf-subcats .tf-subcat:focus-visible{
    background: rgba(255,255,255,.22);
    border-color: rgba(255,255,255,.5);
    color: #fff;
    box-shadow: none;
}
.tf-portada .tf-subcats .tf-subcat:hover .tf-subcat-ico{ border-color: rgba(255,255,255,.55); }
/* El foco se ve SIEMPRE: son enlaces de navegación sobre una foto, y el
   contorno del navegador se pierde contra cualquier portada oscura (WCAG 2.1
   AA, foco visible). */
.tf-portada .tf-subcats .tf-subcat:focus-visible{ outline: 2px solid #fff; outline-offset: 2px; }

.tf-portada .tf-subcats .tf-subcat > b,
.tf-portada .tf-subcats .tf-subcat:visited > b{
    background: rgba(0,0,0,.28);
    color: rgba(255,255,255,.95);
    font-size: 10.5px; font-weight: 800;
}
.tf-portada .tf-subcats .tf-subcat:hover > b{ background: rgba(0,0,0,.28); color: rgba(255,255,255,.95); }

/* Cada una con su tono, que es lo que las distingue de un vistazo. */
.tf-pill.es-eco{ background: rgba(61,220,115,.22); border-color: rgba(61,220,115,.5); }
.tf-pill.es-directa{ background: rgba(90,170,255,.20); border-color: rgba(90,170,255,.45); }
.tf-pill.es-subasta{ background: rgba(190,140,255,.20); border-color: rgba(190,140,255,.45); }
.tf-pill.es-local{ background: rgba(240,180,41,.22); border-color: rgba(240,180,41,.5); }

/* ══ LA BARRA DE CIFRAS ════════════════════════════════════════════ */

/* Sin fondo ni borde: la franja blanca que había alrededor dejaba una banda
   partida por detrás de la barra. La tarjeta se basta sola. */
.tf-cifras-zona{ background: transparent; }

/* LA BARRA, EN SU TARJETA Y NO A SANGRE. Con 8px de radio se separa de la
   portada de arriba y de la rejilla de abajo: pegada al borde de la página se
   leía como una franja del fondo, no como el resumen de la búsqueda. */
.tf-cifras{
    display: flex;
    align-items: center;
    gap: 22px;
    flex-wrap: wrap;

    /* DEBAJO DE LA PORTADA, NO ENCIMA. Tenía `margin-top: -18px` para
       montarla sobre la foto, y lo que hacía era comerse el borde inferior de
       la portada y quedar medio dentro medio fuera: ni una cosa ni la otra.
       Separada, la portada termina donde termina y la barra empieza donde
       empieza. */
    margin: var(--tf-hueco) 0 0;
    padding: 12px 18px;
    border: 1px solid var(--sd-borde);
    border-radius: 8px;
    background: #fff;
    box-shadow: 0 2px 10px rgba(16,50,24,.06);
}

.tf-cifras-datos{ display: flex; align-items: center; gap: 22px; flex: 1; min-width: 0; flex-wrap: wrap; }

/* El orden y la vista, al otro extremo de la misma barra. */
.tf-cifras-orden{ display: flex; align-items: center; gap: 10px; flex: 0 0 auto; }
.tf-cifras-orden > label{ font-size: 12px; color: var(--sd-suave); white-space: nowrap; }
.tf-cifras-orden .sd-campo{ padding: 6px 10px 5px; }

/* Cada cifra separada por una línea fina, como en el diseño: sin ella, tres
   números seguidos se leen como uno solo de nueve dígitos. */
.tf-cifras-datos > * + *{ padding-left: 22px; border-left: 1px solid var(--sd-borde); }

.tf-recuento{ display: flex; align-items: center; gap: 12px; padding: 4px 0 12px; }
.tf-recuento small{ margin-left: auto; font-size: 12px; color: var(--sd-suave); }

/* El título de la rejilla comparte línea con el «Mostrando 1-24 de…»: son la
   misma pregunta --qué hay y cuánto se está viendo-- y en dos líneas la
   pantalla gana un escalón para no decir nada nuevo. */
.tf-recuento-t{
    display: flex; align-items: center; gap: 8px;
    margin: 0; padding: 0;              /* la hoja del sitio le mete 10px a los h2 */
    font-size: 16.5px; font-weight: 800; letter-spacing: -.2px;
    color: var(--sd-tinta);
}
.tf-recuento-t iconify-icon{ font-size: 18px; color: var(--sd-verde); }
.tf-recuento-t b{ font-weight: 800; color: var(--sd-suave); }

/* ── Y EL `<span>` DEL RÓTULO, A LA FUERZA ───────────────────────────
 *
 * «Todos los productos» salía en redonda y pequeño mientras «(41)» --que es un
 * `<b>`-- salía en negrita: el mismo título con dos pesos. No era esta hoja:
 * `boot.css` declara `div, span, p, ul, li, ol { font: 12px Inter, sans-serif }`
 * y ese ATAJO `font` fija tamaño Y peso de un golpe. Un selector de elemento
 * (0,0,1) le gana siempre a un valor HEREDADO, que no tiene especificidad
 * ninguna, así que el `font-weight: 800` del `h2` no llegaba al `span`.
 *
 * Misma familia que las trampas de `boot-css-pisa-color-heredado.md`, y
 * tampoco se ve leyendo esta hoja: hay que mirar `getComputedStyle` DEL SPAN,
 * no del título. */
.tf-recuento-t span{ font-size: inherit; font-weight: inherit; line-height: inherit; }

.tf-cifra{ display: flex; flex-direction: column; }
.tf-cifra b{ font-size: 19px; font-weight: 800; color: var(--sd-tinta); font-variant-numeric: tabular-nums; }
.tf-cifra small{ font-size: 11.5px; color: var(--sd-suave); }

/* El resumen de la izquierda: icono en su columna y TODO el texto en la
   segunda, que es la regla de alineación del proyecto. */
.tf-resumen{ display: flex; align-items: flex-start; gap: 11px; flex: 1; min-width: 240px; }
.tf-resumen > span{
    flex: 0 0 auto;
    display: grid; place-items: center;
    width: 34px; height: 34px;
    border-radius: 10px;
    background: var(--sd-verde-claro);
    color: var(--sd-verde);
    font-size: 17px;
}
.tf-resumen small{ display: block; font-size: 12px; line-height: 1.5; color: var(--sd-texto); }

/* Las caras de los vendedores, montadas unas sobre otras. */
.tf-caras{ display: flex; align-items: center; }
.tf-caras img, .tf-caras span{
    width: 30px; height: 30px;
    border-radius: 50%;
    border: 2px solid #fff;
    margin-left: -9px;
    object-fit: cover;
    display: grid; place-items: center;
    background: var(--sd-verde-claro);
    color: var(--sd-verde);
    font-size: 10.5px; font-weight: 800;
}
.tf-caras > *:first-child{ margin-left: 0; }
.tf-caras .tf-mas-caras{ background: #eef1ef; color: var(--sd-suave); }

/* ══ LAS DOS COLUMNAS ══════════════════════════════════════════════ */

.tf-cuerpo{
    display: grid;
    grid-template-columns: 246px minmax(0, 1fr);
    gap: 22px;
    align-items: start;
    padding: 22px 0 8px;
}

/* ── LA COLUMNA DE CRITERIOS SE QUEDA A LA VISTA ────────────────────
 *
 * Con quince filtros y cuarenta resultados, tener que subir para cambiar uno es
 * lo que hace que no se cambien.
 *
 * ── Y SIN ALTURA NI BARRA PROPIA ───────────────────────────────────
 *
 * Tuvo `max-height: calc(100vh - 112px)` con `overflow-y: auto`, para que los
 * últimos grupos --Garantías, Disponibilidad-- se pudieran alcanzar con la
 * columna pegada. El precio era una segunda barra de desplazamiento dentro de
 * la página: se rueda la rueda sobre los filtros y se mueve el panel, se rueda
 * dos píxeles más allá y se mueve la página, y ninguna de las dos llega a donde
 * se iba. Un panel de filtros con su propio recorte además ESCONDE lo que hay
 * debajo sin decir que está ahí.
 *
 * Así que la columna se desplaza CON la página --`overflow: visible`, sin
 * tope-- y por eso deja de estar pegada: `sticky` con un contenido más alto que
 * la ventana clava el panel arriba y su parte de abajo ya no se puede
 * alcanzar de ninguna manera, que es peor que las dos barras.
 */
.tf-lado{
    position: static;
    max-height: none;
    overflow: visible;
}

.tf-lado-botones{ display: flex; flex-direction: column; gap: 8px; margin-top: 12px; }

/* El buscador dentro de la sección, con el mismo aire que `sd-buscasub` pero a
   lo ancho del panel.

   EL MARGEN DE ARRIBA NO ERA CERO POR GUSTO, ERA UN DESCUIDO: encima van los
   chips de lo elegido y el botón de limpiar, y los dos nacen con
   `display:none`. Sin ningún filtro puesto --que es como se abre la página--
   no queda nada en medio y el buscador salía pegado al borde de abajo de la
   cabecera «Filtrar». Con los 12 px queda igual que cuando sí hay chips. */
.tf-busca-lado{
    display: flex; align-items: center; gap: 7px;
    margin: 12px 14px 8px;
    padding: 7px 10px;
    border: 1px solid var(--sd-borde);
    border-radius: 9px;
}
.tf-busca-lado iconify-icon{ font-size: 15px; color: var(--sd-tenue); flex: 0 0 auto; }
.tf-busca-lado input{
    flex: 1; min-width: 0;
    border: 0; outline: none;
    font-family: inherit; font-size: 12.5px;
}

/* ── LA SEPARACIÓN ENTRE LAS ZONAS, EN UN SOLO SITIO ───────────────
 *
 * Portada, barra de cifras, subcategorías y «Productos destacados» son cuatro
 * cajas apiladas en esta columna, y cada una traía su propio margen: 14 arriba
 * de la portada, 16 encima de la barra, CERO encima de las subcategorías --que
 * se quedaban pegadas a la barra, como si fueran la misma tarjeta-- y 18 y 20
 * debajo. Cuatro cifras distintas para el mismo hueco.
 *
 * Aquí se declaran los dos que hay, y cada zona los USA en vez de escribir el
 * suyo. `--tf-hueco` separa tarjeta de tarjeta; `--tf-hueco-seccion` es mayor
 * a propósito, porque lo que viene después es un TÍTULO y tiene que respirar
 * más que lo que va entre dos cajas iguales --si no, la sección nueva se lee
 * como una tarjeta más de la pila--.
 *
 * Y con los márgenes SOLO ARRIBA: en flujo normal los verticales contiguos se
 * funden y gana el mayor, así que teniendo cada zona el suyo abajo Y el de la
 * siguiente arriba nunca se sabe cuál manda. */
.tf-col{ min-width: 0; --tf-hueco: 16px; --tf-hueco-seccion: 26px; }

/* ══ LA REJILLA ════════════════════════════════════════════════════ */

/* CUANTAS QUEPAN, CON EL ANCHO DE LA TARJETA COMO TOPE.
   Con `repeat(5, 1fr)` fijo, en una pantalla de 2560px salían cinco tarjetas de
   más de 400px: la ficha se estiraba porque le sobraba sitio. Ahora la columna
   nunca pasa de `--tf-card-max` --el tope que declara la propia tarjeta
   (`TAgroCard.css`), el mismo en el escaparate, en las colecciones y en el
   perfil del agricultor-- y se ponen las que quepan.

   OJO CON `auto-fit`: el tope de arriba se declaró pero el `1fr` de aquí lo
   dejaba sin efecto -- con una sola tarjeta en la fila, `auto-fit` COLAPSA
   las columnas vacías y la única que queda, al ser `1fr` (flexible), se come
   todo el ancho libre: la ficha se convertía en un banner (22/09/2026,
   comprobado en `/tienda` filtrando hasta dejar un producto). `auto-fill`
   NO colapsa esas columnas -- las deja vacías e invisibles, así que el
   sobrante va a ellas y no a la tarjeta -- y con `var(--tf-card-max)` como
   tope, ya no hace falta que sea `fr`: una columna de ancho fijo no se
   estira aunque sobre sitio. */
.tf-rejilla{
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--tf-card-min, 260px)), var(--tf-card-max, 350px)));
    gap: var(--tf-card-gap, 20px);
}

/* En lista, una fila por producto: la foto a la izquierda y el resto en línea.
   Es la misma tarjeta con otra dirección, no otra tarjeta. */
.tf-rejilla.es-lista{ grid-template-columns: minmax(0, 1fr); }

/* ══ UNA SECCIÓN DE LA COLUMNA ═════════════════════════════════════════
 *
 * «Productos destacados» y «Todos los productos»: un título que dice qué es la
 * lista que viene debajo. Sin ellos las dos listas iban pegadas y las primeras
 * tarjetas de la rejilla se leían como parte de lo destacado.
 *
 * CANDIDATO A LA HOJA COMÚN del área de cliente: la colección y el perfil del
 * agricultor titulan igual sus bloques.
 */
/* ARRIBA Y ABAJO EL HUECO DE SECCIÓN: encima porque lo que abre es un título
   --y con el hueco de tarjeta se leía como una caja más de la pila de arriba--,
   y debajo porque lo que viene es el recuento de la rejilla. */
.tf-seccion{ margin: var(--tf-hueco-seccion) 0; }

/* ICONO EN SU COLUMNA Y TODO EL TEXTO EN LA SEGUNDA, que es la regla de
   alineación de la casa: con el icono dentro del bloque de texto, el subtítulo
   arranca en una vertical distinta de la del título. */
.tf-seccion-cab{ display: flex; align-items: flex-start; gap: 10px; margin: 0 0 12px; }

/* LA ESTRELLA, GRANDE Y MACIZA. A 19px y de trazo se perdía contra el título;
   es lo que dice de un vistazo que esta sección no es la rejilla de abajo. */
.tf-seccion-ico{
    flex: 0 0 auto;
    display: grid; place-items: center;
    width: 30px; height: 30px;
    color: var(--sd-oro, #e2a812);
    font-size: 26px;
}
.tf-seccion-ico svg{ width: 26px; height: 26px; display: block; }
.tf-seccion-txt{ flex: 1; min-width: 0; }

.tf-seccion-txt h2{
    margin: 0; padding: 0;              /* la hoja del sitio le mete 10px a los h2 */
    font-size: 16.5px; font-weight: 800; letter-spacing: -.2px;
    color: var(--sd-tinta);
}
.tf-seccion-txt small{
    display: block; margin-top: 2px;
    font-size: 12.5px; line-height: 1.45;
    color: var(--sd-suave);
}

/* ══ LOS DESTACADOS, APAISADOS ═════════════════════════════════════════
 *
 * TRES POR FILA Y A LO ANCHO. En vertical se veían igual que los 262 de abajo,
 * y lo que se paga por un destacado es justo que se distinga. A lo ancho caben
 * la foto grande, las etiquetas de la mercancía y los datos de venta.
 */
.tf-destacados{
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
    gap: 14px;
}

/* ── LA TARJETA APAISADA: LOS DESTACADOS Y LA VISTA DE LISTA ─────────
 *
 * UN SOLO BLOQUE PARA LOS DOS. La vista de lista tenía su propia definición con
 * `flex-direction: row`, y al sacar el pie fuera del cuerpo se convirtió en una
 * TERCERA COLUMNA: en un móvil, los botones se metían encima del nombre y del
 * precio --se veía el título cortado a «Agua Hass» y «Ver producto» tapando la
 * valoración--. Son la misma tarjeta con el mismo problema, así que ahora es la
 * misma regla: foto y ficha arriba, datos y acción en su fila de abajo.
 *
 * TRES COLUMNAS Y DOS FILAS, y no una fila de `flex`:
 *
 *     ┌──────────┬───────────────────────┬──────────┐
 *     │  foto    │  cuerpo (2 columnas)             │
 *     ├──────────┴───────────────┬───────┴──────────┤
 *     │  datos de venta          │   acción         │
 *     └──────────────────────────┴──────────────────┘
 *
 * El pie de la tarjeta comparte fila con los datos de venta --reloj, pujas,
 * kilos a la izquierda; el botón a la derecha-- y la línea que los separa del
 * resto cruza la tarjeta de lado a lado, por debajo de la foto también. Con
 * `flex-direction: row` los datos quedarían como una tercera columna y el botón
 * flotando a media altura del texto.
 */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card{
    display: grid;
    grid-template-columns: 162px minmax(0, 1fr) auto;
    /* LA FILA DE ABAJO MIDE 30 px, Y ES UNA MEDIDA, NO UN MÍNIMO. Con `auto`
       la marcaba el botón --38 px más su relleno-- y salían 46: demasiado para
       una línea de texto pequeño y un botón. Los tres que viven dentro
       --los datos, el carrito y «Ver producto»-- se ajustan a ella más abajo,
       porque si uno solo se pasa, la fila crece y el 30 no sirve de nada. */
    grid-template-rows: auto 30px;
    max-width: none;

    /* ── Y AIRE ABAJO, QUE NO LO TENÍA (26/09/2026) ──────────────────
     *
     * La fila de 30px es la ÚLTIMA del grid, así que sin relleno en el
     * contenedor quedaba pegada al canto de la tarjeta: los datos y el botón
     * tocaban el borde y se leían como si estuvieran cortados. La foto ya
     * entra 12px por arriba, por la izquierda y por abajo, así que estos 12
     * cierran la caja con la misma medida en los cuatro lados. */
    padding-bottom: 12px;
}

/* LA FOTO, METIDA HACIA DENTRO Y REDONDA POR LAS CUATRO ESQUINAS. A sangre
   contra el borde se lee como el fondo de la tarjeta; con su margen y su radio
   se lee como lo que es: la foto del lote. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-foto{
    grid-area: 1 / 1 / 2 / 2;
    width: auto; height: auto;
    margin: 12px 0 12px 12px;
    border-radius: 12px;
    align-self: stretch;
}

:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-cuerpo{
    grid-area: 1 / 2 / 2 / 4;
    padding: 12px 14px 12px;
}

/* LA ETIQUETA Y EL CORAZÓN SIGUEN A LA FOTO. Están posicionados contra la
   TARJETA, así que al meter la foto hacia dentro hay que moverlos con ella: si
   no, la etiqueta queda flotando sobre el borde y el corazón, fuera de la
   imagen. Y con tope de ancho, que un sello largo --«Sin tratamiento
   postcosecha»-- se salía de la columna de la foto y caía encima del título. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-etiqueta{
    top: 20px; left: 20px;
    max-width: 130px;
    white-space: normal;
    line-height: 1.25;
    font-size: 10.5px;
    padding: 4px 9px;
}
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-fav{ top: 14px; right: 14px; }

/* ── LA FILA DE ABAJO: DATOS A LA IZQUIERDA, ACCIÓN A LA DERECHA ──────
 *
 * SIN LÍNEA QUE LA SEPARE. La llevó, y sobraba: la foto ya termina donde
 * empieza la fila y el cambio de contenido --de la ficha a las condiciones de
 * la venta-- se nota solo. Con el filete, la tarjeta se leía partida en dos
 * mitades y parecían dos bloques pegados en vez de uno.
 *
 * Y APRETADA: son una línea de texto pequeño y un botón, no un pie de página.
 */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-meta{
    grid-area: 2 / 1 / 3 / 3;
    display: flex;
    /* Sin relleno arriba ni abajo: en 30 px lo pone todo el centrado. */
    padding: 0 6px 0 14px;
    border-top: 0;
    background: transparent;
    /* EN UNA SOLA LÍNEA. La tarjeta vertical los deja envolver --ahí la franja
       crece y no pasa nada-- pero en una fila de altura fija, envolver sería
       cortar la segunda línea por la mitad, que se lee peor que no verla. */
    flex-wrap: nowrap;
    min-width: 0;
    overflow: hidden;
    /* Y más juntos: 16 px de separación se pensaron para una franja que podía
       envolver. En una sola línea, cada hueco es texto que no cabe. */
    gap: 0 10px;
}

/* SI NO CABEN, SE ACORTAN CON PUNTOS SUSPENSIVOS, no se van por el borde.
 *
 * Medido en el catálogo: de 24 tarjetas, 4 pasan del ancho de su columna --tres
 * datos («Finaliza en 6d 11h», «5 pujas», «10 Ud») en 222 px--. Sin esto, el
 * `overflow: hidden` de arriba se los lleva EN SILENCIO: el último dato
 * desaparece sin dejar rastro y nadie sabe que falta algo. Con los puntos, se
 * ve que hay más y el dato sigue en el `title` y en la ficha.
 */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-meta-it{
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* El icono NO se encoge: es lo que identifica el dato de un vistazo, y un
   icono a medias no dice nada. Lo que cede es el texto. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-meta-it iconify-icon{
    flex: 0 0 auto;
}
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card > .ag-pie{
    grid-area: 2 / 3 / 3 / 4;
    margin-top: 0;
    padding: 0 12px 0 0;
    border-top: 0;
    background: transparent;
    justify-content: flex-end;
    /* `center` y no `flex-end`: con la fila a 30 px y los botones a 30 px es lo
       mismo, pero si algún día uno mide menos queda a media altura en vez de
       colgado del borde de abajo. */
    align-items: center;
}

/* Y las etiquetas del producto, que aquí sí caben. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-tags{ display: flex; }

/* En la rejilla de LISTA las etiquetas se quedan fuera: ahí la fila es más
   estrecha --caben tres por pantalla-- y entre el nombre a dos líneas, el
   precio y los datos de venta ya no hay hueco. En destacados sí, que son tres
   tarjetas grandes y es donde se decide sin abrir. */
.tf-rejilla.es-lista .ag-card .ag-tags{ display: none; }

/* El nombre, a dos líneas: en una fila, un título de cuatro empuja el precio
   fuera de la tarjeta. Y con hueco para el corazón, que va en su esquina. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-nombre{
    padding-right: 30px;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-precios{ margin-bottom: 0; margin-top: 6px; }

/* ── LOS DOS BOTONES ──────────────────────────────────────────────────
 *
 * COMPRA DIRECTA: «Ver producto» y el carrito, que es el atajo.
 * SUBASTA: un solo botón verde, «Ver detalle», porque una subasta no se añade
 * al carrito -- se entra a pujar, y ofrecer las dos cosas es ofrecer una que no
 * existe.
 */
/* LOS DOS BOTONES MIDEN LO QUE LA FILA. El carrito era 38 y era él quien
   marcaba la altura; «Ver producto» sacaba su altura del relleno (9 px arriba y
   abajo sobre 13 px de texto). Ahora los dos dicen 30 y el relleno del segundo
   pasa a ser solo horizontal: con `height` y relleno vertical a la vez, el
   navegador suma los dos y el botón vuelve a pasarse. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-pie .ag-btn{
    flex: 0 0 auto; width: 30px; height: 30px;
    padding: 0; border-radius: 10px;
    order: 2;
}
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-ver{
    height: 30px;
    padding: 0 12px;
}
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-btn-txt{ display: none; }
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-ver{ display: inline-flex; white-space: nowrap; }

:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card.es-subasta .ag-pie .ag-btn{ display: none; }
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card.es-subasta .ag-ver{
    background: var(--sd-verde);
    border-color: var(--sd-verde);
    color: #fff;
    font-weight: 700;
    /* Solo horizontal, por lo mismo que arriba: su `10px 16px` sumaba 20 px a
       los 30 de altura y la subasta se salía de la fila ella sola. */
    padding: 0 16px;
}
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card.es-subasta .ag-ver:hover{
    background: var(--sd-verde-oscuro, #005c2d);
    border-color: var(--sd-verde-oscuro, #005c2d);
}
/* La flecha, en CSS: es adorno del botón --dice «vas a otro sitio»-- y no texto
   que deba leer nadie en voz alta. */
:is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card.es-subasta .ag-ver::after{
    content: '→';
    margin-left: 8px;
    font-size: 14px;
    line-height: 1;
}

.tf-mas{ display: flex; justify-content: center; padding: 22px 0 4px; }

/* ══ LAS GARANTÍAS ═════════════════════════════════════════════════
 *
 * Se fueron con su marcado (30/08/2026): las cuatro promesas son del SITIO y
 * las pinta `base.php` encima del pie para todas las páginas, con su hoja en
 * `TPlataforma/css/TGarantias.css`. Aquí eran una copia con otras palabras y
 * otro aspecto, y desde que la franja global sale en la tienda, dos franjas
 * casi iguales seguidas.
 */

/* ══ PANTALLA ESTRECHA ═════════════════════════════════════════════ */

/* LOS CORTES DE 1180 Y 980 SE HAN IDO: contaban columnas a mano --cuatro, tres--
   y con la rejilla en `auto-fill` eso ya lo hace el ancho disponible. Dejarlos
   solo servía para forzar columnas más anchas que la tarjeta y dejar un hueco
   en blanco dentro de cada celda. */
@media (max-width: 980px){
    .tf-destacados{ grid-template-columns: minmax(0, 1fr); }
}

/* ══════════════════════════════════════════════════════════════════
 *  LAS PIEZAS DE MÓVIL: EN ESCRITORIO NO EXISTEN
 * ══════════════════════════════════════════════════════════════════
 *
 * Nacen apagadas y las enciende el `@media` de abajo. Escrito así --y no al
 * revés-- porque escritorio es lo que ya estaba probado: una pieza nueva que
 * naciera visible rompería la pantalla de trabajo mientras se construye la del
 * teléfono.
 */
.tf-chips-barra,
.tf-hoja-cab,
.tf-hoja-pie,
.tf-velo,
.tf-portada-cifras{ display: none; }

/* EL BOTÓN, ACOTADO CON `.tf` Y NO SUELTO, y no es manía de escribir: la hoja
   del marco le pone `display:flex; height:25px` a TODO `button` dentro de un
   `.TComponentES6`, y esa regla pesa 0,1,1 -- le gana a `.tf-btn-filtros`, que
   pesa 0,1,0. Escrito suelto, el botón salía en ESCRITORIO, donde no pinta
   nada, y medía 25 px de alto en el teléfono. */
.tf .tf-btn-filtros{ display: none; }

/* Texto que solo lee el lector de pantalla: el número de filtros del botón va
   también en palabras, porque «2» dentro de una píldora no se dice solo. */
.tf-solo-lector{
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* ── EL BOTÓN «FILTROS (N)» ────────────────────────────────────────── */
.tf .tf-btn-filtros{
    flex: 0 0 auto;
    align-items: center; gap: 7px;
    height: auto; min-height: 44px;        /* el global `button{height:25px}` */
    margin: 0; padding: 0 14px;
    border: 1px solid var(--sd-verde);
    border-radius: 10px;
    background: var(--sd-verde);
    color: #fff;
    font-family: inherit; font-size: 13.5px; font-weight: 700;
    cursor: pointer;
}
.tf .tf-btn-filtros:hover{ background: var(--sd-verde-oscuro); }
.tf .tf-btn-filtros iconify-icon{ font-size: 17px; }

/* El contador nace vacío y solo ocupa sitio cuando hay algo que contar. */
.tf-btn-filtros-n{ display: none; }
.tf .tf-btn-filtros.es-con-filtros .tf-btn-filtros-n{
    display: inline-grid; place-items: center;
    min-width: 20px; height: 20px; padding: 0 5px;
    border-radius: 999px;
    background: #fff;
    color: var(--sd-verde);
    font-size: 11.5px; font-weight: 800;
}

/* ── LA CABECERA DE LA HOJA ────────────────────────────────────────
   Icono en su columna y TODO el texto en la segunda, para que el título y el
   subtítulo arranquen en la misma vertical. Es la regla de alineación del
   proyecto, y es lo que separa una cabecera de una fila de trozos. */
.tf-hoja-cab{
    align-items: flex-start;
    gap: 10px;
    flex: 0 0 auto;
    padding: 12px 16px;
    border-bottom: 1px solid var(--sd-borde);
}
.tf-hoja-cab > iconify-icon{ flex: 0 0 auto; font-size: 20px; color: var(--sd-verde); margin-top: 2px; }
.tf-hoja-cab-txt{ flex: 1; min-width: 0; }
.tf-hoja-cab-txt b{ display: block; font-size: 16px; font-weight: 800; color: var(--sd-tinta); }
.tf-hoja-cab-txt small{ display: block; margin-top: 2px; font-size: 12px; color: var(--sd-suave); }

.tf .tf-hoja-x{
    flex: 0 0 auto;
    width: 44px; height: 44px;
    margin: -8px -8px 0 0; padding: 0;
    border: 0; border-radius: 10px;
    background: none;
    color: var(--sd-suave);
    cursor: pointer;
}
.tf .tf-hoja-x:hover{ background: var(--sd-crema); color: var(--sd-tinta); }
.tf .tf-hoja-x iconify-icon{ font-size: 20px; }

/* ── EL PIE DE LA HOJA ─────────────────────────────────────────────
   `btn-secondary` el que descarta y `btn-primary` el que decide: sin clase,
   «Limpiar» pesaría lo mismo que el botón que enseña los resultados. */
.tf-hoja-pie{
    flex: 0 0 auto;
    gap: 10px;
    padding: 12px 16px;
    padding-bottom: calc(12px + env(safe-area-inset-bottom, 0px));
    border-top: 1px solid var(--sd-borde);
    background: #fff;
}
.tf .tf-hoja-pie .sd-btn{ height: 48px; }
.tf .tf-hoja-limpiar{ flex: 0 0 auto; }
.tf .tf-hoja-ver{ flex: 1; min-width: 0; }

/* La línea de cifras de la portada compacta. */
.tf-portada-cifras{
    margin: 0;
    font-size: 12.5px; line-height: 1.45;
    color: rgba(255,255,255,.92);
}

/* EL FOCO, VISIBLE EN TODO LO QUE SE PULSA. Sin esto, la hoja se puede
   recorrer con el tabulador y no se ve dónde está uno -- que es exactamente lo
   que el requisito de foco visible viene a impedir (WCAG 2.4.7). */
.tf .tf-btn-filtros:focus-visible,
.tf .tf-hoja-x:focus-visible,
.tf .tf-chips-limpiar:focus-visible,
.tf .tf-hoja-pie .sd-btn:focus-visible,
.tf-chip button:focus-visible{
    outline: 3px solid #2563eb;
    outline-offset: 2px;
}

/* ══════════════════════════════════════════════════════════════════
 *  POR DEBAJO DE 860 px: LA MISMA PANTALLA, OTRA PRESENTACIÓN
 * ══════════════════════════════════════════════════════════════════
 *
 * Aquí estaba escrito «SIN CAJÓN NI BOTÓN DE ABRIR»: la columna se apilaba
 * entera encima de la rejilla. El razonamiento valía --un botón para abrir lo
 * que ya está a la vista no hace nada-- pero MEDIDO en un teléfono no se
 * sostenía: los nueve grupos abiertos ocupan 1.277 px, y la primera tarjeta
 * empezaba a 2.093, o sea a dos pantallas y media de casillas. Un catálogo en
 * el que hay que bajar dos pantallas para ver un producto no es un catálogo.
 *
 * Así que por debajo de 860 px --y SOLO por debajo-- la columna se esconde
 * detrás de un botón y se presenta como hoja (teléfono) o como panel lateral
 * (tableta). Por encima no cambia nada: la columna de siempre a la izquierda.
 *
 * ── UN SOLO PANEL, NO UNA COPIA ─────────────────────────────────────
 *
 * La hoja ES `#tfLado`, el mismo marcado con los mismos grupos y los mismos
 * recuentos. Con dos copias, los números se separan el primer día.
 *
 * Contrato y medidas: Documentacion/PendingWorks/TIENDA-MOVIL.md.
 */
/* ══ LA PORTADA EN TABLET: LA FOTO VUELVE, PERO COMEDIDA ══════════════
 *
 * Estaba escondida de 860 hacia abajo, con la foto, la descripción y las
 * píldoras a `display:none`. El motivo escrito era de MÓVIL --«a 400 px la
 * franja de 5:1 se recorta a una banda de la que no se entiende nada y cuesta
 * 260 px de la primera pantalla»-- y es cierto a 400. Pero el corte estaba en
 * 860, así que se llevaba por delante toda la tableta, donde sí hay sitio: a
 * 820 la franja cabe en 168 px --un 14 % de la pantalla, no un 33 %-- y la
 * descripción entra en dos líneas.
 *
 * Así que la foto vuelve entre 621 y 860, pero COMEDIDA:
 *
 *   · 168 px de alto en vez de los 260 del monitor;
 *   · la descripción a dos líneas como tope (`line-clamp`), para que una
 *     categoría con tres párrafos no vuelva a comerse la primera pantalla;
 *   · y el ancho del texto al 64 %, que es hasta donde el velo aguanta el
 *     contraste --ver la nota del velo--.
 *
 * Por debajo de 620 no cambia nada: ahí sigue sin foto y con el fondo verde,
 * que es la decisión de móvil y sigue siendo la buena. */
@media (max-width: 860px) and (min-width: 621px){

    .tf-portada{
        min-height: 168px;
        padding: 20px 18px;
    }

    /* A SANGRE, DE BORDE A BORDE DE LA PANTALLA.
     *
     * Los 16 px que la metían hacia dentro no son de esta hoja: son el
     * relleno de `.body-content`, el carril del sitio, y de él cuelga TODO lo
     * de la página. Aquí se le sale con un margen negativo del mismo valor,
     * que es lo único que no obliga a tocar ese carril --y tocarlo movería
     * también la rejilla, los filtros y el pie--.
     *
     * NO SE USA `calc(50% - 50vw)`, que es el truco habitual: `vw` incluye la
     * barra de scroll, así que en un navegador con barra clásica --15 px
     * medidos aquí-- la franja sobresale y aparece scroll horizontal en toda
     * la página.
     *
     * Y sin radio: una banda que toca los dos bordes con las esquinas
     * redondeadas se lee como una tarjeta a la que le falta sitio. */
    .tf-portada{
        margin-left: -16px;
        margin-right: -16px;
        border-radius: 0;
    }

    /* EL VELO, MÁS CERRADO QUE EN EL MONITOR. Allí se apaga del todo al 100 %
       porque hay 1250 px y el texto ocupa la mitad; aquí el texto llega al
       64 % de una caja de 805, así que el velo tiene que seguir dando cuerpo
       hasta el final. Medido sobre la foto: ver el commit. */
    .tf-portada-velo{
        background: linear-gradient(90deg,
            rgba(8, 30, 16, .90) 0%,
            rgba(8, 30, 16, .84) 42%,
            rgba(8, 30, 16, .66) 68%,
            rgba(8, 30, 16, .42) 100%);
    }

    .tf-portada-txt{ max-width: 64%; }

    /* DOS LÍNEAS Y PUNTO. La descripción la escribe el editor rico y puede
       traer lo que sea; sin tope, una categoría con tres párrafos devuelve el
       problema que esto viene a resolver. */
    .tf-portada-desc{
        font-size: 13px; line-height: 1.5;
        display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
        overflow: hidden;
    }
}

/* ── EN EL MÓVIL, LO MISMO PERO MÁS CORTO ─────────────────────────────
 *
 * Aquí estuvo la portada SIN foto, sin descripción y sin píldoras, con este
 * motivo: «a 400 px la franja de 5:1 se recorta a una banda de la que no se
 * entiende nada y cuesta 260 px de la primera pantalla». Lo segundo era
 * verdad; lo primero se arregla con la altura, no escondiendo la foto. Se
 * enseñan las tres, en 132 px --la mitad que en el monitor y un 16 % de una
 * pantalla de 800--.
 *
 * ── EL VELO, AQUÍ VERTICAL Y PAREJO ───────────────────────────────
 *
 * En tablet el velo es horizontal porque el texto ocupa el 64 % y queda foto
 * limpia a la derecha. Aquí no: el texto ocupa del 80 % al 96 % --medido--,
 * así que no hay «zona sin texto» que dejar despejada y un degradado lateral
 * dejaría el final de las líneas sin fondo. Va parejo de arriba abajo y con
 * cuerpo suficiente para el PEOR caso: sobre una foto BLANCA, .72 compone
 * (77,93,83) y deja el texto blanco en 7,0:1. Por debajo de .60 ya no llega.
 *
 * La foto queda como textura, no como imagen, y es lo que toca: a este ancho
 * el texto la cubre entera. */
@media (max-width: 620px){
    .tf-portada{
        min-height: 132px;
        padding: 16px;

        /* A sangre también aquí, por lo mismo que en tablet: el relleno de
           `.body-content` son los mismos 16 px a este ancho --comprobado--. */
        margin-left: -16px;
        margin-right: -16px;
        border-radius: 0;
    }

    .tf-portada-velo{
        background: linear-gradient(180deg,
            rgba(8, 30, 16, .84) 0%,
            rgba(8, 30, 16, .76) 60%,
            rgba(8, 30, 16, .72) 100%);
    }

    /* A todo el ancho: aquí no hay columna que respetar. */
    .tf-portada-txt{ max-width: 100%; }

    .tf-portada h1{ font-size: 21px; }

    .tf-portada-desc{
        font-size: 12.5px; line-height: 1.45;
        display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
        overflow: hidden;
    }

    /* LAS PÍLDORAS, QUE AQUÍ SÍ ENVUELVEN. Son cuatro y a 400 px no caben en
       una línea; envolver es mejor que arrastrar, porque el arrastre esconde
       --el mismo motivo por el que las subcategorías de más abajo van en dos
       filas con su botón y no en un carril--. */
    .tf-pills{ flex-wrap: wrap; gap: 6px; }
}

@media (max-width: 860px){

    /* SIN LOS 4 px DE ARRIBA: con la portada ya sin margen, eran lo único que
       quedaba separándola de la cabecera. */
    .tf-cuerpo{ grid-template-columns: minmax(0, 1fr); padding-top: 0; }
    .tf-portada h1{ font-size: 24px; letter-spacing: -.5px; }

    /* EL CARRIL, SOLO EL DEL SITIO. `sd-ancho` suma sus 20 px a los 16 de
       `body-content`: 72 px de márgenes en una pantalla de 400 para que la
       rejilla se quede en 328. Los 16 del sitio ya son el gutter. */
    .tf .sd-ancho{ padding: 0; }

    /* EL RITMO SE ENCOGE CON LA PANTALLA, pero sigue saliendo de un solo
       sitio: se cambia el token y se mueven las cuatro zonas a la vez. */
    .tf-col{ --tf-hueco: 12px; --tf-hueco-seccion: 20px; }

    /* LAS FAMILIAS, RECORTADAS A DOS FILAS Y CON SU BOTÓN.
     *
     * Estuvieron en una sola línea con arrastre lateral, y el arrastre ESCONDE:
     * en un móvil se veían DOS de doce y nada decía que hubiera más -- quien no
     * prueba a arrastrar, no las encuentra. Dos filas enseñan cuatro o cinco, y
     * el botón de debajo dice exactamente cuántas quedan.
     *
     * El tope son DOS FILAS de píldora (42px) más el hueco entre ellas (8px).
     * Con `max-height` y no escondiendo las que sobran, porque CUÁLES sobran
     * depende del ancho y eso no se sabe hasta que el navegador lo reparte. */
    .tf-subcats{
        max-height: 92px;
        overflow: hidden;
    }
    .tf-subcats.es-abierta{ max-height: none; }

    /* SIN `margin-bottom`: el hueco lo pone `--tf-hueco` arriba de cada zona,
       y repetirlo aquí abajo devolvía las dos medidas que se vinieron a
       quitar. Solo cambia el relleno, que es lo propio del móvil. */
    .tf-subcats-zona{ padding: 12px 14px 14px; }

    .tf-portada-cifras{ display: block; }

    /* ── LA BARRA PEGAJOSA ───────────────────────────────────────────
       Es la MISMA barra de cifras: se esconden las cifras y quedan el botón de
       filtros, el orden y la vista. El orden va aparte de los filtros a
       propósito: es lo que más se toca y no puede costar abrir una hoja.

       `--tf-barra-top` lo pone el JS con el alto REAL de la cabecera del
       sitio, que es pegajosa y se recoge al bajar (108 px abierta, 56
       recogida). Un número escrito aquí dejaría la barra medio tapada en una
       de las dos posturas. */
    .tf-cifras-zona{
        position: sticky;
        top: var(--tf-barra-top, 56px);
        /* CON 15 NO BASTABA: las tarjetas de la rejilla --con su propio
           `position: relative` para la etiqueta y el corazón, ver
           `TAgroCard.css`-- ganaban por debajo y se veían POR ENCIMA de esta
           barra pegajosa en cuanto se hacía scroll. Por debajo de la hoja de
           filtros (1100+) y del chat de soporte (9000), que sí tienen que
           tapar todo lo demás. */
        z-index: 100;
        margin: 0 -16px;
        padding: 8px 16px;
        background: transparent;
        transition: background .15s, box-shadow .15s;
    }

    /* Pegada: fondo y sombra. Suelta: nada, para no dibujar una franja sobre
       la portada. La clase la pone el JS. */
    .tf-cifras-zona.es-pegada{
        background: #fff;
        box-shadow: 0 4px 12px rgba(16,50,24,.10);
    }

    .tf-cifras{
        margin: 0;
        padding: 0;
        border: 0;
        border-radius: 0;
        background: transparent;
        box-shadow: none;
        gap: 8px;
        flex-wrap: nowrap;
    }

    .tf-cifras-datos{ display: none; }

    .tf-cifras-orden{ flex: 1; min-width: 0; gap: 8px; }
    .tf-cifras-orden > label{ display: none; }   /* el `aria-label` ya lo nombra */
    .tf-cifras-orden .sd-campo{ flex: 1; min-width: 0; padding: 0; }

    .tf-cifras-orden .sd-campo select{
        width: 100%;
        min-height: 44px;
        padding: 0 10px;
        border: 1px solid var(--sd-borde);
        border-radius: 10px;
        background: #fff;
        font-family: inherit; font-size: 13px; font-weight: 600;
        color: var(--sd-tinta);
    }

    .tf .sd-vista{ flex: 0 0 auto; }
    .tf .sd-vista button{ width: 42px; height: 42px; }

    /* ── EL BOTÓN DE FILTROS ─────────────────────────────────────── */
    .tf .tf-btn-filtros{ display: inline-flex; }

    /* ── LOS CHIPS, FUERA DEL PANEL ──────────────────────────────────
       En una fila con desplazamiento PROPIO: con `flex-wrap`, ocho filtros
       puestos son tres filas que empujan la rejilla fuera de la pantalla otra
       vez, que es el problema que se venía a arreglar. */
    .tf-chips-barra{
        display: flex;
        align-items: center;
        gap: 8px;
        padding: 8px 0 2px;
    }
    .tf-chips-barra.es-vacia{ display: none; }

    .tf-chips-lista{
        flex: 1; min-width: 0;
        display: flex; gap: 7px;
        overflow-x: auto;
        scrollbar-width: none;
        padding-bottom: 2px;
    }
    .tf-chips-lista::-webkit-scrollbar{ display: none; }
    .tf-chips-lista .tf-chip{ flex: 0 0 auto; }

    .tf .tf-chips-limpiar{
        flex: 0 0 auto;
        height: auto; min-height: 32px;
        margin: 0; padding: 0 6px;
        border: 0; background: none;
        color: var(--sd-verde);
        font-family: inherit; font-size: 12px; font-weight: 700;
        cursor: pointer;
    }

    .tf-recuento{ padding: 6px 0 10px; }
    .tf-recuento small{ margin-left: 0; }

    /* ══ LA HOJA DE FILTROS ══════════════════════════════════════════
       Cerrada, la columna no existe: no ocupa sitio ni recibe el tabulador. */
    .tf-lado{ display: none; }

    /* LA CABECERA DEL PANEL DE ESCRITORIO SE CALLA: su título y su «Limpiar»
       los dice ahora la cabecera de la hoja, y dos títulos seguidos --uno sin
       información-- es el error que más se repite. Lo mismo con los chips de
       dentro (están arriba, en la barra) y con el botón de limpiar del final
       (está en el pie). */
    .tf-lado .sd-panel-cab,
    .tf-lado .tf-chips,
    .tf-lado .tf-limpiar-zona{ display: none; }

    /* ── ABIERTA ────────────────────────────────────────────────────
     *
     * LO `fixed` NO SALE DE SU CONTEXTO DE APILADO, Y AQUÍ HAY DOS.
     *
     * La hoja y su velo son `position: fixed`, pero viven dentro de
     * `.body-content` (`position:relative; z-index:1`) y este dentro de
     * `<main>` (`position:relative; z-index:3`): las dos cajas crean contexto,
     * así que TODO lo de dentro se compara con la cabecera del sitio
     * --`z-index: 1000` colgando del `body`-- usando el 3 del `main`, no el
     * número que lleve la hoja. Medido el 16/09/2026: el velo tapaba la página
     * pero la cabecera se pintaba por encima y se podía seguir pulsando.
     *
     * Por eso se sube el ANTEPASADO, y solo mientras la hoja está abierta.
     * Subir el z-index de la hoja no habría servido de nada -- y es lo que
     * parece que falta cuando se mira solo el elemento.
     */
    html.tf-filtros-abiertos body > main{ z-index: 1100; }
    html.tf-filtros-abiertos .body-content{ z-index: 1100; }

    html.tf-filtros-abiertos,
    html.tf-filtros-abiertos body{ overflow: hidden; }

    /* El globo del chat de soporte vive en z-index 9000 y cae justo encima del
       pie de la hoja: tapa «Ver N productos», que es el botón que cierra. */
    html.tf-filtros-abiertos #sopChat{ visibility: hidden; }

    .tf-velo{ display: none; }

    html.tf-filtros-abiertos .tf-velo{
        display: block;
        position: fixed;
        top: 0; right: 0; bottom: 0; left: 0;
        z-index: 1190;
        background: rgba(15,23,20,.38);
    }

    html.tf-filtros-abiertos .tf-lado{
        display: flex;
        flex-direction: column;
        position: fixed;
        z-index: 1200;
        left: 0; right: 0; bottom: 0;
        height: 86vh;
        max-height: 86vh;
        background: #fff;
        border-radius: 18px 18px 0 0;
        box-shadow: 0 -10px 30px rgba(0,0,0,.18);
    }

    @media (prefers-reduced-motion: no-preference){
        html.tf-filtros-abiertos .tf-lado{ animation: tf-hoja-sube .2s ease-out; }
    }

    /* El panel se queda sin caja y pasa a ser el CUERPO con desplazamiento
       propio. `overscroll-behavior: contain` para que al llegar al final no se
       arrastre la página de debajo. */
    html.tf-filtros-abiertos .tf-lado .sd-panel{
        flex: 1;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        -webkit-overflow-scrolling: touch;
        border: 0;
        border-radius: 0;
        box-shadow: none;
    }

    html.tf-filtros-abiertos .tf-hoja-cab{ display: flex; }
    html.tf-filtros-abiertos .tf-hoja-pie{ display: flex; }

    /* Los controles del panel, a dedo: 44 px es lo que se acierta sin mirar. */
    .tf-lado .sd-grupo-cab{ min-height: 48px; }
    .tf-lado .sd-check{ min-height: 40px; }
    .tf .tf-busca-lado{ margin: 12px 14px 4px; padding: 10px 12px; }
    .tf .tf-busca-lado input{ font-size: 16px; }   /* 16: Safari no amplía */
}

/* ── LA TABLETA EN VERTICAL: PANEL LATERAL, NO HOJA ──────────────────
 *
 * De 601 a 860 px la rejilla sigue a la vista a la derecha del panel, así que
 * se ve cambiar mientras se filtra -- y por eso aquí los criterios se aplican
 * al momento (lo decide el JS por este mismo ancho). En un teléfono no cabe
 * esa conversación: la hoja tapa la pantalla entera. */
@media (min-width: 601px) and (max-width: 860px){

    /* EL VELO, MÁS FLOJO QUE EN EL TELÉFONO. Aquí la rejilla se ve a la
       derecha y cambia mientras se filtra: con el 38 % del teléfono se lee
       como una pantalla apagada y deja de contar lo que está contando. */
    html.tf-filtros-abiertos .tf-velo{ background: rgba(15,23,20,.20); }

    html.tf-filtros-abiertos .tf-lado{
        top: 0; bottom: 0; right: auto;
        width: 380px; max-width: 86vw;
        height: auto; max-height: none;
        border-radius: 0 18px 18px 0;
        box-shadow: 10px 0 30px rgba(0,0,0,.18);
    }

    @media (prefers-reduced-motion: no-preference){
        html.tf-filtros-abiertos .tf-lado{ animation-name: tf-hoja-entra; }
    }
}

@keyframes tf-hoja-sube{ from{ transform: translateY(24px); opacity: .6; } }
@keyframes tf-hoja-entra{ from{ transform: translateX(-24px); opacity: .6; } }

/* ── A 400 px, DOS COLUMNAS ──────────────────────────────────────────
 *
 * Una columna con la tarjeta grande deja UN producto por pantalla, y comparar
 * es la mitad de lo que se hace en un catálogo. Con dos caben cuatro sin bajar.
 * El mínimo de la rejilla se baja AQUÍ y no en `:root`: el tope de 260 px es el
 * bueno en cuanto hay sitio. */
@media (max-width: 560px){

    .tf-rejilla{
        --tf-card-min: 150px;
        --tf-card-gap: 10px;
    }

    /* LA TARJETA, COMPACTA. Es la misma `TAgroCard`, apretada: en 179 px de
       ancho el nombre a 15 px se parte en cuatro líneas y el botón a todo lo
       ancho se come la ficha. No se cambia de formato --seguiría siendo otro
       marcado que mantener-- sino la talla de lo que ya hay. */
    .tf-rejilla .ag-card .ag-foto{ height: 104px; }
    .tf-rejilla .ag-card .ag-cuerpo{ padding: 9px 10px 10px; }
    .tf-rejilla .ag-card .ag-nombre{ font-size: 13px; }
    .tf-rejilla .ag-card .ag-vendedor{ font-size: 11.5px; }

    /* EL LUGAR SE VA, no el vendedor: en una tarjeta de dos por fila lo que
       decide es qué es y de quién, y la provincia ya está en los filtros. */
    .tf-rejilla .ag-card .ag-lugar{ display: none; }

    .tf-rejilla .ag-card .ag-nota{ margin-top: 4px; }
    .tf-rejilla .ag-card .ag-precios{ margin-top: 6px; gap: 5px; }
    .tf-rejilla .ag-card .ag-precio{ font-size: 15px; font-weight: 800; }
    .tf-rejilla .ag-card .ag-antes{ font-size: 11.5px; }
    .tf-rejilla .ag-card .ag-iva,
    .tf-rejilla .ag-card .ag-ud{ font-size: 10px; }
    .tf-rejilla .ag-card .ag-dto{ padding: 1px 6px; font-size: 10.5px; }

    .tf-rejilla .ag-card .ag-pie{ margin-top: 8px; }
    .tf-rejilla .ag-card .ag-pie .ag-btn{ padding: 9px 8px; font-size: 12px; gap: 5px; }
    .tf-rejilla .ag-card .ag-pie .ag-btn iconify-icon{ font-size: 14px; }

    /* AQUÍ IBA `.tf-rejilla.es-lista{ grid-template-columns: minmax(0,1fr) }`
       «para que en lista haya una sola columna en el móvil», Y NO SERVÍA DE
       NADA: la regla general de más abajo tiene la MISMA especificidad y va
       DESPUÉS en el fichero, así que ganaba ella. El arreglo está allí, en el
       propio `minmax`; repetirlo aquí solo escondía el fallo. */
    /* LA TARJETA APAISADA, MÁS ESTRECHA. Con la columna de foto de 162px en un
       móvil de 373px, al nombre le quedan 190: cabe «Aguacate Hass ·» y poco
       más. A 112 la foto sigue diciendo qué es y el título respira. */
    :is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card{
        grid-template-columns: 112px minmax(0, 1fr) auto;
    }
    :is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-foto{
        margin: 10px 0 10px 10px;
    }
    :is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-cuerpo{
        padding: 10px 12px 10px;
    }
    :is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-etiqueta{
        top: 16px; left: 16px;
        max-width: 92px;
    }
    :is(.tf-destacados.es-apaisada, .tf-rejilla.es-lista) .ag-card .ag-meta{
        padding-left: 12px;
    }
}


/* ══ LOS FILTROS PUESTOS, DEBAJO DEL TÍTULO ════════════════════════
 *
 * En tonos suaves y no en el verde de marca: son un ESTADO, no una acción, y
 * compitiendo en color con el botón de limpiar y con las casillas marcadas la
 * columna se convierte en un semáforo. Lo que tiene que destacar de un chip es
 * su X, que es lo único que se pulsa.
 */
/* LA ZONA RESPIRA, y no es cosmética: aquí se apilan hasta ocho chips en dos o
   tres filas, y con `2px` abajo la última quedaba pegada al botón de limpiar --
   dos bloques distintos leyéndose como uno. Va separada por arriba de la
   cabecera y por abajo del botón, que es lo que la convierte en «lo que llevas
   puesto» en vez de en un renglón más. */
.tf-chips{
    display: flex; flex-wrap: wrap; gap: 7px;
    padding: 12px 14px;
    border-top: 1px solid var(--sd-borde);
}

.tf-chip{
    display: inline-flex; align-items: center; gap: 5px;
    padding: 3px 5px 3px 10px;
    border-radius: 999px;
    background: #f1f4f1;
    border: 1px solid #e2e8e2;
    color: var(--sd-texto);
    font-size: 11px; font-weight: 600;
    max-width: 100%;
}

.tf-chip button{
    flex: 0 0 auto;
    width: 15px; height: 15px;
    display: grid; place-items: center;
    border: 0; border-radius: 50%;
    background: rgba(0,0,0,.07);
    color: var(--sd-suave);
    font-size: 11px; line-height: 1;
    font-family: inherit;
    padding: 0; cursor: pointer;
}
.tf-chip button:hover{ background: #e11d48; color: #fff; }

/* ══ LA VISTA DE LISTA: 350 × 128 ══════════════════════════════════
 *
 * Talla fija a propósito. En lista lo que se compara son filas, y con la altura
 * libre cada tarjeta mide lo que mida su nombre: dos líneas aquí, cuatro allá,
 * y la vista deja de ser una lista para ser una escalera.
 *
 * Las tarjetas se reparten en tantas columnas como quepan de 350px, en vez de
 * ocupar el ancho entero: una fila de 1.300px con una foto de 128 y el resto
 * vacío no es una lista, es un desperdicio.
 */
/* `auto-fit` EN LA COLUMNA, TOPE EN LA TARJETA.
   Con `auto-fill` y `max-width: 350px`, la rejilla reservaba columnas de un
   ancho que la tarjeta no llegaba a ocupar: en 1.300px cabían tres de 350 y
   sobraban 250 repartidos como huecos entre ellas -- las fichas se veían
   sueltas y separadas, que es lo que se notaba. Con `auto-fit` las columnas se
   reparten el ancho que hay y la tarjeta lo llena; el mínimo evita que en
   pantalla ancha salgan seis columnas de nada.

   Y ESO DEJABA UN SEGUNDO FALLO (22/09/2026): sin `max-width` en la tarjeta,
   un resultado SUELTO -- un filtro que deja uno solo -- se comía la pista
   entera, que con una sola tarjeta visible es toda la fila: la ficha salía a
   más de 1.000px, un cartel y no una fila de lista. El tope vuelve, pero en
   `.ag-card` (ver más abajo) y no en la columna: así con varias tarjetas
   siguen repartiéndose el ancho sin huecos, y con una sola no pasa de su
   tamaño razonable. */
.tf-rejilla.es-lista{
    /* 360 Y NO 320: la fila apaisada --foto de 128px, nombre, precio y los dos
       botones-- necesita ese ancho para que el título no se apriete. A 320, con
       la caja ya a todo el ancho de la cabecera, salían 4 columnas de 341px y el
       título se metía bajo el corazón. */
    /* `min(100%, 360px)` Y NO `360px` A SECAS. Un mínimo mayor que el hueco no
       encoge: la pista se queda en 360 y la tarjeta se sale de la rejilla. En
       un teléfono de 390 px el carril útil son 343, así que la fila sobresalía
       17 px y la página entera se desplazaba de lado -- medido el 27/09/2026:
       `scrollWidth` 376 contra un `clientWidth` de 375. Con `min(100%, …)` el
       mínimo nunca pasa del ancho disponible y la columna cae sola a una.
       Es el mismo remedio que ya llevaba `.tf-rejilla` unas líneas más arriba. */
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 360px), 1fr));
    gap: 12px;
}

/* La vista de lista usa LA MISMA tarjeta apaisada que los destacados: su
   bloque está más arriba, con el selector compartido. Aquí solo queda cuántas
   caben por fila. */

/* ══ EL DESLIZADOR DE PRECIO ═══════════════════════════════════════
 *
 * Dos `input[range]` sobre el mismo carril. No hay control nativo de rango con
 * dos asas, y esta es la forma de tener las dos sin traerse una librería: el
 * navegador pone el arrastre, el teclado y la accesibilidad.
 */
.tf-rango{ padding-top: 2px; }

.tf-rango-cajas{ display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.tf-rango-cajas label{ display: block; }
.tf-rango-cajas small{ display: block; font-size: 11px; color: var(--sd-suave); margin-bottom: 3px; }
.tf-rango-cajas input{
    width: 100%;
    padding: 6px 9px;
    border: 1px solid var(--sd-borde);
    border-radius: 8px;
    font-family: inherit; font-size: 12.5px;
    font-variant-numeric: tabular-nums;
}

/* EL CARRIL VA DE CENTRO A CENTRO DE LAS ASAS. El navegador mueve el pulgar
   de `--tf-asa/2` a `100% - --tf-asa/2`, no de borde a borde: con la pista a
   todo el ancho, la línea asomaba por los dos lados y el tramo verde no
   empezaba donde el asa. Todo cuelga de `--tf-asa`, y el JS solo pasa la
   fracción (`--a`, `--b`). */
.tf-rango-barra{
    --tf-asa: 16px;
    position: relative; height: 22px; margin-top: 12px;
}

.tf-rango-pista,
.tf-rango-activo{
    position: absolute; top: 9px;
    height: 4px; border-radius: 99px;
}
.tf-rango-pista{
    left: calc(var(--tf-asa) / 2); right: calc(var(--tf-asa) / 2);
    background: #e2e8e2;
}
.tf-rango-activo{
    left:  calc(var(--tf-asa) / 2 + (100% - var(--tf-asa)) * var(--a, 0));
    right: calc(var(--tf-asa) / 2 + (100% - var(--tf-asa)) * (1 - var(--b, 1)));
    background: var(--sd-verde);
}

/* LAS DOS ASAS, TRANSPARENTES SALVO EL PULGAR.
   `pointer-events: none` en la pista y `auto` solo en el pulgar: si el carril
   entero recibiera el ratón, el de arriba taparía al de abajo y una de las dos
   asas no se podría coger nunca -- que es el fallo clásico de este montaje. */
.tf-rango-asa{
    position: absolute; left: 0; right: 0; top: 0;
    width: 100%; height: 22px; margin: 0;
    background: none; border: 0;
    -webkit-appearance: none; appearance: none;
    pointer-events: none;
}
.tf-rango-asa:focus{ outline: none; }

/* `border-box`: el borde va DENTRO del diámetro, o el asa mediría 22px y no
   los `--tf-asa` con los que se calcula el carril. En WebKit el pulgar se
   apoya arriba del carril, así que el carril mide lo que la barra y el pulgar
   baja la mitad de lo que sobra; Firefox ya lo centra solo. */
.tf-rango-asa::-webkit-slider-runnable-track{ height: 22px; background: transparent; border: 0; }
.tf-rango-asa::-moz-range-track{ height: 22px; background: transparent; border: 0; }

.tf-rango-asa::-webkit-slider-thumb{
    -webkit-appearance: none; appearance: none;
    pointer-events: auto;
    box-sizing: border-box;
    width: var(--tf-asa); height: var(--tf-asa);
    margin-top: calc((22px - var(--tf-asa)) / 2);
    border-radius: 50%;
    background: #fff;
    border: 3px solid var(--sd-verde);
    cursor: grab;
    box-shadow: 0 1px 4px rgba(16,50,24,.25);
}
.tf-rango-asa::-moz-range-thumb{
    pointer-events: auto;
    box-sizing: border-box;
    width: var(--tf-asa); height: var(--tf-asa);
    border-radius: 50%;
    background: #fff;
    border: 3px solid var(--sd-verde);
    cursor: grab;
    box-shadow: 0 1px 4px rgba(16,50,24,.25);
}
.tf-rango-asa:focus-visible::-webkit-slider-thumb{ outline: 2px solid var(--sd-verde); outline-offset: 2px; }
.tf-rango-asa:focus-visible::-moz-range-thumb{ outline: 2px solid var(--sd-verde); outline-offset: 2px; }

/* ══ LA VALORACIÓN ═════════════════════════════════════════════════ */

/* UNA ESTRELLA, BIEN VISIBLE, y el resto escrito. Eran cinco de 13px en dos
   grises que había que contar para saber si ponía «4 y más» o «3 y más». */
.tf-estrella-filtro{
    color: var(--sd-oro);
    font-size: 15px;
    line-height: 1;
    margin-right: 6px;
}
.sd-check-txt{ display: inline-flex; align-items: center; }
.tf-valoracion em{ font-style: normal; font-size: 11.5px; color: var(--sd-suave); margin-left: 4px; }

/* ══ LOS INTERRUPTORES DE GARANTÍA ═════════════════════════════════
 *
 * Reutilizan `.sd-switch` del buscador de agricultores --misma forma, mismo
 * tamaño de palanca-- y aquí van UNO DEBAJO DE OTRO: la columna mide 246px y en
 * dos por fila, que es como están allí, no cabría ni el rótulo.
 *
 * La casilla de verdad se esconde pero SIGUE EXISTIENDO: es la que lleva el
 * estado, la que recibe el foco del teclado y la que dispara el manejador común
 * de los filtros. Con `display: none` se sale del orden de tabulación y el
 * interruptor deja de poder encenderse sin ratón.
 */
.tf-switches{ grid-template-columns: 1fr; gap: 10px; margin: 4px 0 2px; padding: 0 14px 14px; }

.tf-switch-input{
    position: absolute;
    width: 1px; height: 1px;
    margin: -1px; padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}
/* El foco del teclado se ve en la fila entera, que es lo que se está tocando. */
.tf-switch-input:focus-visible + iconify-icon,
.tf-switch-input:focus-visible ~ .sd-palanca{ outline: 2px solid var(--sd-verde); outline-offset: 2px; }

.tf-switches .sd-switch{ padding: 9px 12px; gap: 9px; }
.tf-switches .sd-switch.on{ border-color: var(--sd-verde-borde, #cfe3d2); background: var(--sd-verde-claro, #eef6ee); }
.tf-switches .sd-switch-txt b{ font-size: 12.5px; font-weight: 700; }
.tf-switches .sd-palanca{ width: 40px; height: 22px; }
.tf-switches .sd-palanca::after{ width: 16px; height: 16px; }
.tf-switches .sd-switch.on .sd-palanca::after{ left: 21px; }

/* ══ LA PROVINCIA ══════════════════════════════════════════════════ */

.tf-select{
    width: 100%;
    padding: 7px 9px;
    border: 1px solid var(--sd-borde);
    border-radius: 8px;
    background: #fff;
    font-family: inherit; font-size: 12.5px;
    color: var(--sd-texto);
    cursor: pointer;
}

/* El botón, separado de los chips que hay encima: pegado a ellos parecía el
   último de la lista en vez de la acción que se los lleva por delante. */
.tf-limpiar-zona{ padding: 0 14px 12px; }


/* ══════════════════════════════════════════════════════════════════
 *  PASADA TIPOGRÁFICA CONTRA LA PLANTILLA
 * ══════════════════════════════════════════════════════════════════
 *
 * Medido en el navegador y comparado con el diseño. La familia ya coincidía
 * --Inter en toda la página, que es la del sitio-- pero los TAMAÑOS estaban
 * todos un punto o dos por debajo: se escribieron mirando la retícula, no la
 * maqueta, y el resultado es una pantalla que se lee «apretada» sin que se sepa
 * por qué.
 *
 * Los que más se notan son los dos que el ojo usa para recorrer la rejilla: el
 * nombre del producto y el precio. Si esos dos están pequeños, la tarjeta
 * parece una fila de tabla.
 */

/* ── LA COLUMNA DE CRITERIOS ────────────────────────────────────── */

/* El título de cada grupo, un punto por encima de sus opciones: es lo que
   permite recorrer la columna sin leerla entera. */
.tf .sd-grupo-cab b{ font-size: 13px; font-weight: 700; }
.tf .sd-check-txt{ font-size: 12.5px; }
.tf .sd-check small{ font-size: 11px; color: var(--sd-tenue); }
.tf .sd-panel-cab b{ font-size: 14px; }

/* ── LA BARRA DE CIFRAS ─────────────────────────────────────────── */

.tf-cifra b{ font-size: 21px; letter-spacing: -.5px; }
.tf-cifra small{ font-size: 11.5px; }
.tf-resumen small{ font-size: 12.5px; }
.tf-cifras-orden > label{ font-size: 12.5px; }
.tf-cifras-orden .sd-campo select{ font-size: 13px; }

/* ── LA PORTADA ─────────────────────────────────────────────────── */

/* 34px estaba bien para «Todo el catálogo»; con un nombre de categoría corto
   --«Aguacates»-- la plantilla lo lleva más grande. Se deja crecer con el
   ancho en vez de fijarlo: `clamp` da el mínimo del móvil, el ideal y el tope. */
.tf-portada h1{ font-size: clamp(26px, 3.2vw, 40px); letter-spacing: -1.2px; }
.tf-portada-desc{ font-size: 14px; }
.tf-pill{ font-size: 12px; }


/* ══ CERCA DE MÍ ═══════════════════════════════════════════════════
   Cuatro radios en dos filas: en una sola, «200 km» se queda en 50px y el
   número no se lee. */
.tf-cerca{ display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }

.tf-km{
    height: auto;                       /* el global `button{height:25px}` */
    padding: 7px 6px;
    border: 1px solid var(--sd-borde);
    border-radius: 8px;
    background: #fff;
    color: var(--sd-texto);
    font-family: inherit; font-size: 12px; font-weight: 600;
    cursor: pointer;
    font-variant-numeric: tabular-nums;
}
.tf-km:hover{ border-color: var(--sd-verde-borde); background: var(--sd-crema); }
.tf-km.es-on{ border-color: var(--sd-verde); background: var(--sd-verde-claro); color: var(--sd-verde-oscuro); }

.tf-cerca-nota{
    display: block;
    margin-top: 8px;
    font-size: 11px; line-height: 1.45; color: var(--sd-suave);
}
.tf-cerca-nota.es-mal{ color: #b3183c; }



/* ══════════════════════════════════════════════════════════════════════
   TContentReportForm — «Denunciar contenido»

   Esta hoja VIAJA CON TODA PÁGINA (pageComponents), y por eso el botón se
   define aquí: lo ponen la ficha de producto, el perfil del vendedor y cada
   valoración, y así los tres se ven igual sin que ninguno lo redefina.

   ── DISCRETO, PERO ACCESIBLE ─────────────────────────────────────────
   Es una opción que casi nadie usa y que no puede competir con «Añadir a la
   cesta»: texto pequeño, sin fondo ni borde. Pero el gris cumple AA
   (#556259 sobre blanco, 6,3:1) y el foco se ve.

   ── LA CLASE DOBLADA ─────────────────────────────────────────────────
   `.TComponentES6 button` impone display:flex y 25px de alto a todo botón
   dentro de un componente, y la hoja de la ficha arrastra reglas globales
   sobre `button`: con `button.crf-boton.crf-boton` se gana sin depender del
   orden de carga.

   Candidato a la hoja común del área pública cuando se extraiga.
   ══════════════════════════════════════════════════════════════════════ */

button.crf-boton.crf-boton{
    display: inline-flex; align-items: center; gap: 5px;
    height: auto; min-height: 0; width: auto;
    margin: 0; padding: 4px 2px;
    background: none; border: 0; border-radius: 4px; box-shadow: none;
    font-family: inherit; font-size: 12px; font-weight: 600; line-height: 1.3;
    color: #556259; cursor: pointer;
    text-decoration: none;
}
button.crf-boton.crf-boton:hover{ color: #9b1c14; text-decoration: underline; }
button.crf-boton.crf-boton:focus-visible{ outline: 2px solid #04713a; outline-offset: 2px; }
button.crf-boton.crf-boton iconify-icon{ font-size: 13px; flex: 0 0 auto; }

/* La fila que lo coloca al final de un bloque, alineado a la derecha. */
.crf-fila{ display: flex; justify-content: flex-end; margin-top: 10px; }

/* La variante de la página /denunciar-contenido: aquí SÍ es la acción principal. */
button.crf-boton.crf-boton--principal{
    padding: 10px 18px; border-radius: 8px;
    background: #04713a; color: #fff; font-size: 14px;
}
button.crf-boton.crf-boton--principal:hover{ background: #005c2d; color: #fff; text-decoration: none; }
button.crf-boton.crf-boton--principal iconify-icon{ font-size: 16px; }

/* ── LA PÁGINA ───────────────────────────────────────────────────────── */

.crf [hidden]{ display: none !important; }

.crf .crf-pagina{
    max-width: 880px; margin: 34px auto; padding: 0 16px;
    color: #16211a; font-size: 14px;
}

.crf .crf-cab{ display: flex; gap: 14px; align-items: flex-start; margin-bottom: 26px; }
.crf .crf-cab-ico{
    flex: 0 0 auto; width: 46px; height: 46px; border-radius: 12px;
    display: flex; align-items: center; justify-content: center;
    background: #eef6ee; color: #04713a;
}
.crf .crf-cab-ico iconify-icon{ font-size: 24px; }
.crf .crf-cab-txt{ flex: 1; min-width: 0; }
.crf .crf-cab-txt h1{ margin: 0 0 6px; font-size: 24px; line-height: 1.25; }
.crf .crf-cab-txt p{ margin: 0; color: #4a564e; line-height: 1.5; font-size: 14px; }

.crf .crf-pasos{ display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 14px; }
.crf .crf-paso{
    display: flex; gap: 10px; align-items: flex-start;
    padding: 14px; border: 1px solid #e3e9e4; border-radius: 12px; background: #fff;
}
.crf .crf-paso-ico{ flex: 0 0 auto; color: #04713a; }
.crf .crf-paso-ico iconify-icon{ font-size: 20px; }
.crf .crf-paso > div{ flex: 1; min-width: 0; }
.crf .crf-paso b{ display: block; margin-bottom: 4px; font-size: 14px; }
.crf .crf-paso small{ display: block; color: #4a564e; font-size: 13px; line-height: 1.45; }

.crf .crf-accion{ display: flex; flex-wrap: wrap; align-items: center; gap: 14px; margin-top: 26px; }
.crf .crf-accion small{ color: #4a564e; font-size: 12px; }
.crf .crf-accion a{ color: #04713a; }

/* ── EL FORMULARIO ──────────────────────────────────────────────────────
   `rows` no pinta nada: una regla global le fija 22px a todo textarea y la de
   los controles un min-height de 60px. La altura se pide por clase. */
.crf-explicacion textarea,
textarea.crf-explicacion{ min-height: 120px !important; height: 120px !important; }

p.crf-nota{
    margin: 4px 0 0; padding: 9px 11px; border-radius: 8px;
    background: #f3f6f4; color: #3f4a43; font-size: 12.5px; line-height: 1.45;
}

/* ── EL ACUSE ───────────────────────────────────────────────────────── */

.crf-acuse{ max-width: 520px; padding: 4px 2px; color: #16211a; font-size: 14px; }
.crf-acuse .crf-acuse-fila{ display: flex; gap: 10px; align-items: flex-start; margin-bottom: 12px; }
.crf-acuse .crf-acuse-ico{ flex: 0 0 auto; color: #04713a; }
.crf-acuse .crf-acuse-ico iconify-icon{ font-size: 26px; }
.crf-acuse .crf-acuse-txt{ flex: 1; min-width: 0; }
.crf-acuse .crf-acuse-txt b{ display: block; font-size: 16px; margin-bottom: 3px; }
.crf-acuse .crf-acuse-txt small{ display: block; font-size: 13px; color: #4a564e; }
.crf-acuse p{ margin: 0 0 10px; line-height: 1.5; font-size: 14px; }
.crf-acuse .crf-acuse-pie{ display: flex; justify-content: flex-end; margin-top: 14px; }



/* ═══════════════════════════════════════════════════════════════════════════
 *  RECUPERAR LA CONTRASEÑA — la ficha dentro de la ventana
 *
 *  Copia la ficha de la pantalla (`TRegisterQuick`, `.rqk-solo-form`): el
 *  logotipo a 44 px, el título de 26 px, el campo de 11 px de radio con el
 *  verde de foco y el botón verde a todo lo ancho. CANDIDATO A LA HOJA COMÚN
 *  del área pública, junto con aquella: hoy son dos copias de los mismos
 *  valores (tokens `--rq-*` allí, `--fgp-*` aquí).
 * ═══════════════════════════════════════════════════════════════════════════ */

.fgp{
    --fgp-verde:        #2d6a2f;
    --fgp-verde-vivo:   #3f8f43;
    --fgp-verde-oscuro: #14532d;
    --fgp-verde-borde:  #dbe8d6;
    --fgp-verde-caja:   #f5faf3;
    --fgp-texto: #14261a;
    --fgp-suave: #5b6b60;
    --fgp-tenue: #93a399;

    padding: 18px 28px 26px;
    color: var(--fgp-texto);
    font-size: 13px;
    line-height: 1.5;
    text-align: left;
}

.fgp .fgp-marca{ display: block; height: 44px; width: auto; margin: 0 0 22px; }

.fgp .fgp-titulo{
    margin: 0 0 5px;
    font-size: 26px; font-weight: 800;
    letter-spacing: -.5px;
    line-height: 1.2;
    color: #07090d;
}

.fgp .fgp-sub{ margin: 0 0 14px; font-size: 13px; color: var(--fgp-suave); }

/* `!important` COMO EN `.rqk-campo`: una regla global del sitio pone los
   `label` en fila con `!important`, y sin esto el rótulo y el campo salían
   uno al lado del otro y el campo a media anchura (medido: 225 de 400 px). */
.fgp .fgp-campo{
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 5px;
    margin: 0 0 14px;
}

.fgp .fgp-rotulo{ align-self: stretch; font-size: 12px; font-weight: 600; }

.fgp .fgp-con-ico{ position: relative; display: block; width: 100%; }
.fgp .fgp-con-ico > iconify-icon{
    position: absolute; left: 13px; top: 50%;
    transform: translateY(-50%);
    font-size: 15px; color: var(--fgp-tenue);
    pointer-events: none;
}

.fgp .fgp-con-ico input{
    width: 100%;
    box-sizing: border-box;
    height: auto;
    padding: 12px 14px 12px 38px;
    border: 1px solid #dbe4dd;
    border-radius: 11px;
    background: #fff;
    font-size: 13px; font-family: inherit;
    color: var(--fgp-texto);
}
.fgp .fgp-con-ico input::placeholder{ color: var(--fgp-tenue); }
.fgp .fgp-con-ico input:focus{
    outline: none;
    border-color: var(--fgp-verde-vivo);
    box-shadow: 0 0 0 3px rgba(63,143,67,.12);
}

.fgp .fgp-error{ display: none; font-size: 11px; color: #b91c1c; font-style: normal; }
.fgp .fgp-campo.mal input{ border-color: #f87171; background: #fef2f2; }
.fgp .fgp-campo.mal .fgp-error{ display: block; }

/* EL BOTÓN, EL DE LA FICHA (`.rqk-btn-crear`). `height:auto` porque la regla
   global `.TComponentES6 button{height:25px}` lo aplastaría. */
.fgp .fgp-btn{
    display: flex; align-items: center; justify-content: center; gap: 9px;
    width: 100%;
    height: auto;
    padding: 13px;
    border: 0;
    border-radius: 11px;
    background: var(--fgp-verde);
    color: #fff;
    font-size: 14.5px; font-weight: 700; font-family: inherit;
    cursor: pointer;
}
.fgp .fgp-btn:hover{ background: var(--fgp-verde-oscuro); }
.fgp .fgp-btn:focus-visible{ outline: 3px solid rgba(63,143,67,.35); outline-offset: 2px; }
.fgp .fgp-btn:disabled{ opacity: .7; cursor: default; }
.fgp .fgp-btn iconify-icon{ font-size: 17px; }

/* EL AVISO: la misma caja verde que el de la pantalla (`.rqk-olv-hecho`). */
.fgp .fgp-hecho{
    display: none;
    gap: 10px;
    margin-top: 14px;
    padding: 12px 14px;
    border-radius: 11px;
    border: 1px solid var(--fgp-verde-borde);
    background: var(--fgp-verde-caja);
    color: #2f5136;
    font-size: 12.5px; line-height: 1.5;
}
.fgp .fgp-hecho.on{ display: flex; }
.fgp .fgp-hecho > iconify-icon{ flex: 0 0 auto; font-size: 18px; color: var(--fgp-verde-vivo); }
.fgp .fgp-hecho > div{ flex: 1; min-width: 0; }

.fgp .fgp-ya{ margin: 14px 0 0; text-align: center; font-size: 12.5px; }
.fgp .fgp-ya a{ color: var(--fgp-verde); font-weight: 700; text-decoration: underline; }

/* LA VENTANA, CON LAS ESQUINAS DE LA TARJETA de la pantalla (`--rq-radio`,
   30 px; algo menos aquí porque la ventana es más pequeña). Va por la
   `hostClass` que pone `open()`: el overlay vive fuera del árbol de `.fgp`. */
.TOverlayWin.fgp-ventana{ border-radius: 24px; overflow: hidden; }

@media (max-width: 600px){
    .fgp{ padding: 14px 18px 22px; }
    .fgp .fgp-marca{ height: 32px; }
    .fgp .fgp-titulo{ font-size: 22px; }
}



