/* ==========================================================================
   Fondo continuo del Home

   El Home era el único lugar del sitio con un corte de color visible al
   scrollear: el hero pintaba --color-surface (#e2e2e2) y todo lo que venía
   después caía al blanco del body (css/styles.css). Ahora todo el Home
   comparte una sola base y ninguna sección pinta su propio fondo — hero,
   zigzag de categorías, aviso de compra por volumen y reseñas quedan como
   un único bloque continuo.

   El tono es --color-surface-soft (#f2f2ef), que ya estaba en tokens.css:
   gris muy claro y levemente cálido, sin inventar un hex nuevo fuera de la
   paleta. Se eligió por encima del blanco puro porque el vidrio esmerilado
   que viene después es translúcido y blanquecino: necesita una base algo
   más oscura que el panel para leerse como capa superpuesta.

   Color plano y no degradé a propósito: entre tonos tan cercanos entre sí,
   un degradé largo bandea (escalones visibles) en pantallas de 8 bits, que
   es justo el salto que se quiere evitar. La profundidad va a venir de la
   capa de ilustraciones y del blur que se montan encima en los pasos
   siguientes, no del fondo base.

   Alcance: solo Home. Este archivo lo carga únicamente index.html y las
   reglas cuelgan de body.home, así que Hogar, Químicos, Mayorista,
   Contacto y Nosotros conservan su fondo actual.
   ========================================================================== */

body.home {
  --home-bg: var(--color-surface-soft);
  background: var(--home-bg);
}

/* ==========================================================================
   Header — vidrio esmerilado

   Aproximación web del lenguaje "liquid glass" de iOS/visionOS — no es el
   material nativo de Apple (eso solo existe en SwiftUI/UIKit), es una
   aproximación con backdrop-filter: blur real sobre el contenido que pasa
   detrás (hero, hojas del isotipo, textura de moléculas), no un blur falso
   ni un simple fondo semitransparente sin desenfoque.

   Reemplaza el viejo esquema de dos estados (transparente sobre el hero /
   blanco opaco al scrollear, ver el comentario que quedó en css/styles.css
   donde vivía antes) por un aspecto ÚNICO y constante en cualquier punto
   del scroll: la barra siempre es vidrio. Los links y el logo no cambian
   de color con .is-scrolled — esa clase la sigue togglando js/main.js pero
   ya no tiene efecto visual en Home (se deja intacta por si algún día se
   quiere reintroducir un ajuste sutil al scrollear; no se retiró del JS
   porque no rompe nada dejarla).

   Solo esta instancia (index.html): el header es un componente compartido
   (css/styles.css, .site-header) que Hogar/Químicos/Mayorista/Contacto/
   Nosotros siguen usando tal cual (sticky, blanco opaco, sin blur) — todo
   este bloque cuelga de body.home.
   ========================================================================== */

body.home {
  /* Separación del borde superior y alto de la barra flotante. Valores
     propios de Home: el resto del sitio sigue usando --header-height
     (84px, tokens.css) para su header sticky de siempre — no se tocó ese
     token porque también calcula el offset del sidebar sticky en las
     páginas de catálogo (.filtro-sidebar, css/styles.css). */
  --home-header-gap: 16px;
  --home-header-height: 68px;
}

body.home .site-header {
  /* position/left/right:0 siguen viniendo de css/styles.css (necesarios
     para que el header flote fijo sobre el hero, ver el comentario ahí).
     Acá se angosta y se separa: ya no es de borde a borde, es una barra
     independiente centrada, con lugar de sobra a los costados. */
  top: var(--home-header-gap);
  left: var(--space-sm);
  right: var(--space-sm);
  max-width: 1160px;
  margin-inline: auto;
  height: var(--home-header-height);
  border-radius: 999px;
  border-bottom: none;
  /* El .site-header base (css/styles.css) pinta background:white sólido
     para el header de siempre — acá hay que apagarlo explícitamente. Si
     no, ese blanco opaco queda pintado DEBAJO de ::before (ver más abajo)
     y el backdrop-filter del pseudo-elemento termina "viendo" ese blanco
     propio en vez del contenido real de la página: todo el efecto de
     vidrio se anula en silencio (fondo liso, sin nada desenfocado detrás)
     aunque backdrop-filter esté aplicado y activo. */
  background: none;
  /* .site-header no pinta nada MÁS por sí mismo — el vidrio (blur, fondo
     translúcido, sombra, brillo superior) vive en ::before/::after de
     ESTE mismo elemento, no en .container (que sí contiene el <nav>).
     Motivo nada estético: en Home, .main-nav pasa a position:fixed en
     mobile para el menú desplegable (ver @media 1024px más abajo), y tanto
     backdrop-filter como transform en un ANCESTRO real de un elemento
     fixed le cambian el "containing block" — el menú quedaría encajonado
     dentro de la barra de 68px en vez de cubrir la pantalla. Un pseudo-
     elemento no es ancestro real de nada: puede tener el blur sin heredar
     ese problema a .main-nav. No mover backdrop-filter a .site-header ni
     a .container por esto mismo.

     El z-index:-1 del ::before (para que quede detrás de .container) no
     necesita isolation ni ningún truco extra: position:fixed ya crea su
     propio contexto de apilamiento siempre (a diferencia de position:
     relative, que solo lo hace con z-index numérico), así que ese -1
     queda contenido acá adentro sin poder afectar nada fuera de la
     barra. */
}

body.home .site-header::before,
body.home .site-header::after {
  content: '';
  position: absolute;
  pointer-events: none;
}

body.home .site-header::before {
  /* El vidrio en sí. Rango pedido: blur 16–24px (elegido 20, punto medio
     donde el contenido de atrás se ve claramente desenfocado sin volverse
     un manchón ilegible) + fondo blanco semitransparente 0,5–0,65 alpha
     (elegido 0,6: con menos, el texto pierde piso sobre fondos claros
     como el hero; con más, deja de leerse como vidrio y empieza a verse
     como una barra blanca sólida de siempre). -webkit- prefijado porque
     Safari todavía lo requiere. Si el navegador no soporta backdrop-
     filter, el fallback es liso: la barra queda blanco semitransparente
     SIN desenfoque — translúcida y legible, nunca rota. */
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: rgba(255, 255, 255, 0.6);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  /* Sombra suave hacia abajo para dar sensación de elevación real sobre
     el contenido — bien difusa y de baja opacidad, no una sombra dura de
     tarjeta. border-radius:inherit ya alcanza para que backdrop-filter y
     background respeten el contorno redondeado sin manchas ni bordes
     sucios: no hace falta overflow:hidden extra (y agregarlo en
     .site-header sí sería un problema, porque cortaría el menú mobile
     fixed de golpe contra los 68px de alto de la barra). */
  box-shadow: 0 14px 30px -12px rgba(33, 33, 33, 0.28);
}

body.home .site-header::after {
  /* "Reflejo de luz en el canto del vidrio": una línea de 1px en el borde
     superior, pero en vez de un color plano, un gradiente lineal
     blanco -> transparente -> blanco que se apaga hacia los dos extremos
     (inset 14% del ancho) para no cortar en seco contra las puntas
     redondeadas de la píldora. */
  top: 0;
  left: 14%;
  right: 14%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.9), transparent);
}

/* El menú mobile (position:fixed, @media 1024px en css/styles.css — ver
   "Sistema de breakpoints" en tokens.css) usaba inset: var(--header-height)
   0 0 0 para arrancar justo debajo del header de siempre. Acá el header
   flota más abajo y es más bajo (--home-header-height, no
   --header-height), así que el punto de arranque cambia; el resto del
   inset (right/bottom/left:0) se hereda tal cual de esa regla. Mismo corte
   de 1024px que esa regla a propósito: si quedaran en anchos distintos, en
   la franja entre ambos el menú hamburguesa ya estaría activo pero con el
   offset de escritorio, dejando un hueco o una superposición con el
   header flotante de Home.

   Sin + var(--space-sm) a propósito: ese aire extra dejaba una franja
   transparente de 16px entre el borde inferior del header flotante y el
   techo del panel (que sí es opaco, .main-nav en css/styles.css) por donde
   se colaba el contenido de la página de atrás (reseñas/banner) al abrir
   el menú scrolleado. Arrancando justo en el borde del header no queda
   ningún hueco sin cubrir. */
@media (max-width: 1024px) {
  body.home .main-nav {
    top: calc(var(--home-header-gap) + var(--home-header-height));
    /* Mismo inset lateral que la píldora (left/right: var(--space-sm),
       ver body.home .site-header más arriba) en vez del 0 0 de borde a
       borde que trae la regla compartida — así los dos lados quedan
       alineados exactamente, como si el panel fuera la píldora
       estirándose hacia abajo, no un cuadro ancho aparte debajo de una
       barra angosta. */
    left: var(--space-sm);
    right: var(--space-sm);
    /* Mismo vidrio que la barra (idéntico blur/alpha que
       body.home .site-header::before) en vez del blanco opaco que usa
       el panel compartido — la idea es que se lea como el MISMO material
       continuando hacia abajo, no un panel sólido distinto que aparece
       debajo de uno translúcido. */
    background: rgba(255, 255, 255, 0.6);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
  }

  /* La píldora es 100% redondeada (border-radius:999px) — con el menú
     abierto, las puntas de ABAJO se aplanan a 0 (el panel, que arranca
     ahí mismo, ya trae su propio radio grande solo abajo, ver
     css/styles.css) para que el conjunto lea como una sola pieza con
     esquinas superiores redondas y esquinas inferiores redondas EN LA
     BASE DEL PANEL, no dos siluetas redondeadas independientes apiladas
     con un quiebre en el medio. border-radius:inherit en ::before (ver
     arriba) sigue este cambio solo. */
  body.home .site-header:has(#main-nav.is-open) {
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
  }

  /* La sombra propia de la píldora (en ::before, ver arriba) proyecta
     hacia abajo — con el panel pegado justo debajo, esa sombra quedaría
     asomando en la costura entre ambos, como una línea oscura de más.
     Con el menú abierto, la apaga acá y la elevación de todo el
     conjunto pasa a depender solo de la sombra del panel (.main-nav,
     css/styles.css) — un único borde con sombra en la base de la forma
     completa, no dos. */
  body.home .site-header:has(#main-nav.is-open)::before {
    box-shadow: none;
  }
}

/* Chip de vidrio detrás del ícono del carrito: mismo lenguaje que la
   barra pero deliberadamente más discreto (menos blur, menos opacidad)
   para no competir con el vidrio principal — es un detalle dentro de la
   barra, no una segunda superficie del mismo peso visual. */
body.home .site-header .cart-toggle {
  background: rgba(255, 255, 255, 0.4);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

body.home .site-header .cart-toggle:hover {
  background: rgba(255, 255, 255, 0.65);
}

/* ==========================================================================
   Capa de fondo — moléculas

   Textura decorativa de estructuras químicas reales (bicarbonato de sodio,
   ácido cítrico, percarbonato de sodio y LAS — el detalle de cada una vive
   como comentario en assets/patterns/quimica-fondo.svg), guiño a "vendemos
   materia prima real". Es SOLO textura: opacidad muy baja (4,5%), pensada
   para no notarse a simple vista y solo percibirse si alguien se detiene a
   mirar el fondo — igual que las anotaciones de un cuaderno de laboratorio
   o el watermark de un paper científico, nunca un elemento protagonista.

   Una sola capa continua para todo el Home: se posiciona respecto de
   <main> (no del body ni de cada <section>), así el patrón no se corta ni
   reinicia en los límites de sección — hero, zigzag y reseñas comparten el
   mismo tile sin costura. El div va como PRIMER hijo de <main> en el
   markup, así que pinta antes (queda detrás) de .hero/.categorias/.resenas
   sin necesidad de z-index: alcanza con el orden del DOM entre elementos
   posicionados de la misma pila (ver nota de accesibilidad/interacción
   abajo).

   El SVG (1800×1800) ya trae las 4 moléculas escaladas/rotadas levemente y
   dispersas de forma orgánica (scatter por distancia mínima, no grilla) y
   coloreadas en el verde de marca — a esta opacidad el matiz es
   imperceptible, pero mantiene el "guiño de marca" en el código fuente.
   Es estático: no hay JS ni animación, se generó una sola vez y se congeló
   como archivo.
   ========================================================================== */

body.home main {
  position: relative;
  /* isolation:isolate crea un contexto de apilamiento propio para <main>,
     sin depender de un z-index numérico ni de en qué orden del DOM caiga
     cada sección respecto a la capa decorativa. Así el z-index:-1 de
     abajo queda contenido DENTRO de main (no puede "escaparse" y colarse
     detrás del header fijo o el panel del carrito, que viven fuera de
     main) y a la vez se garantiza que quede detrás de .hero/.categorias/
     .resenas sin importar si esas secciones son position:static o no. */
  isolation: isolate;
}

.chem-bg-layer {
  position: absolute;
  inset: 0;
  z-index: -1;
  background-image: url('../assets/patterns/quimica-fondo.svg');
  background-repeat: repeat;
  background-position: top left;
  /* Subida de 0.045 a 0.085 (2026-09-15): al 4,5% original el patrón
     quedaba casi imperceptible a simple vista ("se ve plano"), pese a
     estar dentro del 3-6% pedido en su momento. 0.085 lo hace notarse
     como detalle de fondo sin mirar de cerca, sin pasar a protagonista —
     ajuste puro de opacidad, mismo trazo/color/distribución de siempre. */
  opacity: 0.085;
  /* Decorativa pura: no debe capturar clicks/hover ni el foco de teclado,
     y aria-hidden en el HTML ya la saca del árbol de accesibilidad. */
  pointer-events: none;
}

/* ==========================================================================
   Hero
   ========================================================================== */

.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  padding-block: var(--space-lg);
  overflow: hidden;
  /* Sin fondo propio: hereda --home-bg del body (ver "Fondo continuo del
     Home" al inicio de este archivo). Antes pintaba --color-surface, que
     era el origen del corte contra las secciones siguientes. */
  background: transparent;
}

/* Se probó un degradé animado con blobs de color y una transición
   pared/piso, y se dio marcha atrás con esa idea. Después pintaba un
   color sólido (#e2e2e2), que era la mitad del corte de color del Home.
   Ahora no pinta nada: el div se mantiene en el markup a propósito,
   queda como capa disponible para las ilustraciones sutiles del próximo
   paso, encima del fondo continuo del body. */
.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: transparent;
}

.bg-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.28) saturate(1.05);
}

.hero .container {
  position: relative;
  z-index: 1;
  max-width: 904px;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero h1 {
  /* Verde oscuro derivado de --color-accent — ver body.home en
     css/styles.css para la definición y el porqué del valor exacto. */
  color: var(--hero-dark-green);
  font-size: clamp(2.1rem, 5vw, 3.4rem);
  letter-spacing: -0.01em;
  text-align: center;
  /* Espacio prolijo respecto del header arriba, y respecto de la
     navegación por isotipo debajo (ya no hay hero-subhead en el medio
     que aporte ese aire por su cuenta). */
  margin-top: var(--space-xl);
  margin-bottom: var(--space-xl);
}

.hero h1 .text-accent {
  color: var(--color-accent);
}

/* Mobile (hasta 640px, ver "Sistema de breakpoints" en tokens.css): el <br>
   después de "Mendoza" en el markup separa el título en dos oraciones a
   propósito, pero clamp() nunca baja del piso de 2.1rem fuera de este
   rango — a ese tamaño "De nuestra fábrica en Mendoza" NO entra en una
   sola línea y el navegador la corta donde le queda ("De nuestra
   fábrica" / "en Mendoza"), dejando un salto que no es el intencional y
   encima desbalanceado contra la segunda oración. Bajar el tamaño acá
   (probado contra el ancho real de línea, 375-430px) es lo que hace que
   cada oración vuelva a entrar completa en su propia línea: el <br>
   vuelve a ser el único corte, con las dos líneas resultantes de longitud
   pareja.

   Antes este corte vivía en 480px mientras el isotipo de abajo (mismo
   .hero) ya pasaba a su versión compacta en 640px — entre 481-640px el
   título quedaba con el clamp GRANDE (que no entra en una línea, wrap
   desparejo del navegador) sobre un isotipo ya en modo mobile. Con los
   dos en 640px cambian de estado juntos, sin esa franja mezclada. */
@media (max-width: 640px) {
  /* El header de Home es position:fixed (body.home .site-header) — no
     reserva espacio en el flujo normal, así que .hero arranca en el
     mismo y=0 de la página y el header queda flotando ENCIMA de lo que
     sea que haya ahí. El único margin-top del h1 (--space-lg, ver la
     regla de desktop más arriba) sumado al padding-block de .hero daba
     80px — el header mide 84px (--home-header-gap + --home-header-height)
     — así que el título quedaba 4px POR DEBAJO del borde del header, no
     separado de él (medido con Playwright: header.bottom=84,
     h1.top=80, gap real de -4px, en los 5 anchos de iPhone probados —
     el "fix anterior" ajustó el margin-top del h1 a mano hasta que se
     vio bien en un ancho de prueba, pero esa suma nunca restaba el alto
     real del header, así que quedó short por una diferencia chica que
     alcanza para tapar el título en dispositivo real).

     Acá en vez de eso el padding-top de .hero se calcula directamente a
     partir de las mismas variables que ya definen el alto del header
     flotante (--home-header-gap + --home-header-height, ver body.home
     más arriba) más un aire explícito (--space-md) — así el espacio
     visible entre header y título queda garantizado por construcción,
     no por una suma que coincida de casualidad. El margin-top propio
     del h1 pasa a 0 acá (esa separación ya la da el padding-top de
     .hero; dejar los dos sumaría espacio de más). */
  .hero {
    padding-top: calc(var(--home-header-gap) + var(--home-header-height) + var(--space-md));
  }

  .hero h1 {
    font-size: clamp(1.35rem, 5.5vw, 1.6rem);
    margin-top: 0;
    margin-bottom: var(--space-lg);
  }
}

.hero-subhead {
  font-size: clamp(1rem, 2vw, 1.2rem);
  color: rgba(255, 255, 255, 0.85);
  max-width: 62ch;
  margin-bottom: var(--space-lg);
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-sm);
}

.btn-hero {
  font-size: 1.05rem;
  padding: 1.1rem 2rem;
}

/* ==========================================================================
   Hero — navegación por isotipo (Hogar / Químicos / Mayoristas)

   Los 3 pétalos son el path real de assets/logos/isotipo-color.svg, sin
   modificar. Versión desktop: un solo SVG con el viewBox completo del
   isotipo (los 3 entrelazados como en el logo real). Versión mobile:
   mismas 3 siluetas pero cada una recortada a su propio bounding box —
   ver comentario en index.html sobre por qué (evita puntas diminutas).
   ========================================================================== */

.isotipo-halo-wrap {
  /* Este wrapper tiene el tamaño/aspect-ratio que antes tenía .isotipo-nav
     directamente — ahora ambos, el halo y el isotipo, son hijos suyos y
     comparten el mismo box de referencia (615.09 x 406.14, igual que el
     viewBox del SVG), que es el sistema de coordenadas en el que está
     calculado el recorte de .isotipo-halo más abajo. */
  position: relative;
  width: min(100%, 560px);
  margin-inline: auto;
  aspect-ratio: 615.09 / 406.14;
  /* Geometría del halo (usada por .isotipo-halo) declarada acá como
     custom properties — separa el polígono de 275 puntos (un bloque de
     datos, no algo que se lea línea por línea) del resto de las reglas. */
  /* Recalculado (2026-09-15, ajuste de continuidad en la base): el
     ClipperOffset original usaba un arcTolerance grueso para el join
     redondo — en la unión de las 3 hojas eso "cortaba de más" la curva
     justo en el punto donde convergen (y, en menor medida, en la punta
     superior de Químicos), dejando el halo con solo ~12-15 unidades de
     grosor real ahí contra ~18 en el resto del contorno (medido muestreando
     distancia real punto-a-silueta, no a ojo). Recalculado con arcTolerance
     mucho más fino (0.05 vs. el default) sobre las mismas 3 siluetas y el
     mismo offset de 18 unidades — ahora el grosor es ~18 ± 0.3 en TODO el
     contorno, base incluida. Mismo mecanismo de siempre (polígono
     precalculado, no un blur en vivo), solo se corrigió la precisión del
     cálculo. Si el isotipo cambia de forma, recalcular de nuevo con la
     misma tolerancia fina, no volver al valor grueso. */
  --halo-inset: -4.316% -2.912% -4.432% -2.902%; /* top right bottom left */
  --halo-clip: polygon(51.527% 0.000%, 52.426% 0.481%, 53.205% 1.312%, 53.944% 2.221%, 54.670% 3.152%, 55.383% 4.105%, 56.083% 5.081%, 56.767% 6.078%, 57.438% 7.096%, 58.093% 8.136%, 58.734% 9.196%, 59.358% 10.276%, 59.967% 11.375%, 60.559% 12.494%, 61.134% 13.631%, 61.692% 14.787%, 62.233% 15.961%, 62.756% 17.152%, 63.261% 18.361%, 63.747% 19.585%, 64.214% 20.826%, 64.662% 22.082%, 65.090% 23.353%, 65.497% 24.639%, 65.885% 25.937%, 66.251% 27.249%, 66.596% 28.574%, 66.920% 29.910%, 67.221% 31.258%, 67.500% 32.616%, 67.756% 33.984%, 67.989% 35.360%, 68.198% 36.745%, 68.401% 38.079%, 69.240% 37.383%, 70.091% 36.718%, 70.953% 36.086%, 71.825% 35.485%, 72.707% 34.915%, 73.598% 34.378%, 74.498% 33.873%, 75.405% 33.399%, 76.320% 32.957%, 77.242% 32.548%, 78.170% 32.170%, 79.104% 31.823%, 80.043% 31.509%, 80.986% 31.227%, 81.934% 30.976%, 82.885% 30.756%, 83.839% 30.568%, 84.796% 30.411%, 85.755% 30.286%, 86.716% 30.192%, 87.678% 30.128%, 88.640% 30.095%, 89.603% 30.093%, 90.566% 30.122%, 91.528% 30.181%, 92.489% 30.270%, 93.448% 30.390%, 94.406% 30.539%, 95.361% 30.718%, 96.313% 30.927%, 97.262% 31.165%, 98.199% 31.484%, 99.024% 32.198%, 99.640% 33.278%, 99.967% 34.603%, 100.000% 36.019%, 99.962% 37.437%, 99.912% 38.854%, 99.847% 40.269%, 99.768% 41.683%, 99.675% 43.095%, 99.567% 44.505%, 99.443% 45.912%, 99.302% 47.316%, 99.146% 48.716%, 98.972% 50.111%, 98.780% 51.502%, 98.571% 52.887%, 98.342% 54.265%, 98.095% 55.636%, 97.828% 56.999%, 97.541% 58.354%, 97.234% 59.698%, 96.906% 61.033%, 96.557% 62.355%, 96.187% 63.665%, 95.795% 64.961%, 95.382% 66.242%, 94.947% 67.508%, 94.490% 68.757%, 94.011% 69.988%, 93.511% 71.200%, 92.989% 72.392%, 92.445% 73.563%, 91.881% 74.713%, 91.296% 75.840%, 90.691% 76.944%, 90.067% 78.023%, 89.423% 79.078%, 88.760% 80.108%, 88.081% 81.114%, 87.387% 82.097%, 86.679% 83.058%, 85.957% 83.997%, 85.222% 84.913%, 84.473% 85.805%, 83.712% 86.674%, 82.938% 87.518%, 82.152% 88.338%, 81.355% 89.134%, 80.547% 89.904%, 79.727% 90.650%, 78.897% 91.369%, 78.057% 92.063%, 77.208% 92.730%, 76.348% 93.370%, 75.480% 93.984%, 74.604% 94.570%, 73.718% 95.128%, 72.825% 95.659%, 71.925% 96.161%, 71.017% 96.634%, 70.103% 97.078%, 69.182% 97.493%, 68.255% 97.877%, 67.323% 98.231%, 66.385% 98.554%, 65.443% 98.846%, 64.497% 99.106%, 63.546% 99.334%, 62.593% 99.529%, 61.636% 99.692%, 60.677% 99.820%, 59.717% 99.915%, 58.755% 99.975%, 57.792% 100.000%, 56.829% 99.990%, 55.867% 99.943%, 54.906% 99.861%, 53.946% 99.741%, 53.005% 99.468%, 52.171% 98.775%, 51.557% 97.692%, 50.679% 98.134%, 49.722% 98.167%, 48.801% 97.775%, 48.151% 98.802%, 47.303% 99.456%, 46.355% 99.693%, 45.396% 99.824%, 44.435% 99.919%, 43.473% 99.977%, 42.510% 99.999%, 41.548% 99.985%, 40.585% 99.937%, 39.624% 99.854%, 38.665% 99.736%, 37.707% 99.584%, 36.753% 99.400%, 35.801% 99.182%, 34.854% 98.933%, 33.910% 98.651%, 32.971% 98.338%, 32.037% 97.994%, 31.108% 97.620%, 30.185% 97.215%, 29.269% 96.780%, 28.359% 96.317%, 27.456% 95.824%, 26.560% 95.302%, 25.673% 94.753%, 24.793% 94.176%, 23.922% 93.571%, 23.060% 92.939%, 22.207% 92.280%, 21.364% 91.595%, 20.531% 90.884%, 19.708% 90.147%, 18.896% 89.385%, 18.095% 88.598%, 17.306% 87.785%, 16.528% 86.949%, 15.763% 86.088%, 15.010% 85.203%, 14.270% 84.295%, 13.544% 83.364%, 12.831% 82.410%, 12.133% 81.433%, 11.449% 80.435%, 10.781% 79.413%, 10.131% 78.367%, 9.500% 77.295%, 8.888% 76.199%, 8.297% 75.080%, 7.726% 73.937%, 7.175% 72.773%, 6.647% 71.587%, 6.139% 70.382%, 5.653% 69.157%, 5.189% 67.913%, 4.747% 66.653%, 4.326% 65.377%, 3.928% 64.085%, 3.551% 62.780%, 3.195% 61.461%, 2.860% 60.131%, 2.546% 58.790%, 2.253% 57.438%, 1.980% 56.078%, 1.726% 54.709%, 1.492% 53.333%, 1.276% 51.950%, 1.079% 50.562%, 0.899% 49.168%, 0.737% 47.769%, 0.591% 46.367%, 0.462% 44.961%, 0.349% 43.552%, 0.251% 42.140%, 0.167% 40.727%, 0.098% 39.311%, 0.043% 37.895%, 0.001% 36.477%, 0.000% 35.060%, 0.270% 33.704%, 0.793% 32.519%, 1.558% 31.672%, 2.470% 31.235%, 3.418% 30.989%, 4.369% 30.772%, 5.324% 30.585%, 6.281% 30.427%, 7.239% 30.299%, 8.200% 30.202%, 9.162% 30.134%, 10.124% 30.098%, 11.087% 30.091%, 12.050% 30.115%, 13.012% 30.171%, 13.973% 30.257%, 14.932% 30.374%, 15.890% 30.522%, 16.845% 30.702%, 17.797% 30.913%, 18.746% 31.156%, 19.690% 31.430%, 20.631% 31.736%, 21.566% 32.073%, 22.495% 32.443%, 23.419% 32.844%, 24.336% 33.277%, 25.245% 33.742%, 26.147% 34.239%, 27.040% 34.769%, 27.925% 35.329%, 28.799% 35.922%, 29.664% 36.547%, 30.518% 37.203%, 31.360% 37.891%, 32.189% 38.611%, 33.006% 39.362%, 33.697% 39.769%, 33.847% 38.367%, 34.022% 36.972%, 34.223% 35.585%, 34.448% 34.205%, 34.698% 32.835%, 34.973% 31.476%, 35.273% 30.127%, 35.596% 28.790%, 35.943% 27.467%, 36.312% 26.157%, 36.704% 24.860%, 37.117% 23.579%, 37.552% 22.313%, 38.007% 21.063%, 38.481% 19.828%, 38.975% 18.610%, 39.487% 17.408%, 40.016% 16.223%, 40.562% 15.054%, 41.124% 13.903%, 41.702% 12.767%, 42.294% 11.649%, 42.901% 10.547%, 43.520% 9.461%, 44.153% 8.391%, 44.798% 7.338%, 45.454% 6.299%, 46.121% 5.277%, 46.799% 4.269%, 47.487% 3.276%, 48.184% 2.298%, 48.891% 1.333%, 49.668% 0.505%, 50.569% 0.027%);
}

.isotipo-nav {
  display: block;
  width: 100%;
  height: 100%;
  /* position:relative (sin z-index) alcanza para que el isotipo quede
     PINTADO ARRIBA de .isotipo-halo pese a venir después en el DOM: un
     elemento posicionado siempre pinta por encima de uno no posicionado
     del mismo contexto de apilamiento, sin importar el orden — si
     .isotipo-nav se quedara position:static, el halo (position:absolute)
     taparía las hojas en vez de quedar detrás. */
  position: relative;
  /* La sombra de elevación vive ACÁ (no en .isotipo-halo, el vidrio en
     sí) — ver el porqué en el comentario largo de "Halo de vidrio" más
     abajo. Al ser drop-shadow (no box-shadow) sigue el contorno real de
     las hojas (opacas), no un rectángulo; al estar en .isotipo-nav, que
     pinta ENCIMA de .isotipo-halo, la sombra cae sobre el vidrio y se
     asoma más allá de su borde — nunca se filtra "hacia adentro" de la
     propia silueta como pasaría poniéndola en el elemento translúcido.

     Reforzada (offset/blur/alpha más altos que la primera versión) para
     que el conjunto se lea más CLARAMENTE elevado sobre el fondo del
     Home — más contraste entre el vidrio claro de arriba y la sombra
     oscura de abajo, en vez de un aura pareja y plana. */
  filter: drop-shadow(0 16px 26px rgba(33, 33, 33, 0.32));
}

/* ==========================================================================
   Halo de vidrio — isotipo

   Aura de vidrio esmerilado detrás de la silueta completa de las 3 hojas,
   mismo lenguaje que la navbar (ver "Header — vidrio esmerilado" al
   principio de este archivo): fondo blanco translúcido con degradé sutil
   (más claro arriba, simulando el reflejo de luz que en la navbar era una
   línea — acá no hay un "borde superior" recto porque la silueta termina
   en una punta, así que el highlight es un degradé de luz general dentro
   de la propia forma en vez de una línea siguiendo el contorno) +
   backdrop-filter: blur + sombra suave hacia abajo.

   LA PARTE DELICADA — por qué esto NO es un blur/filtro en vivo sobre la
   silueta, sino un polígono precalculado:

   1) El recorte sigue el contorno REAL de las 3 hojas, agrandado ~18
      unidades de viewBox hacia afuera (~16px a 560px de ancho), pero
      sigue siendo un solo trazo limpio (clip-path), no un blur/glow con
      caída difusa — un glow de verdad (feGaussianBlur) daría exactamente
      las "manchas" y "bordes sucios" que se pidió evitar en los ángulos
      filosos de las hojas. Clip-path no tiene ese problema: es geometría
      vectorial exacta, sin rasterizar nada.

   2) El polígono (275 puntos) salió de un script aparte (Node +
      svg-path-properties para aplanar las curvas Bézier de las 3 hojas en
      puntos, + clipper-lib para "inflar" cada una 18 unidades hacia afuera
      con esquinas redondeadas y UNIRLAS en un solo contorno) — no vive en
      el repo, es un cálculo de una sola vez cuyo resultado quedó pegado
      acá abajo. Si el isotipo cambia de forma alguna vez, este clip-path
      queda desactualizado y hay que recalcularlo — no se puede ajustar “a
      mano” tocando números sueltos del polígono.

   3) Las coordenadas del polígono están en % del box AGRANDADO de
      .isotipo-halo (no del box original 615.09×406.14) — por eso el halo
      necesita su propio left/top/right/bottom NEGATIVOS (para sobresalir
      del box de .isotipo-halo-wrap) Y un clip-path con números que ya
      contemplan ese desborde. Cambiar un valor sin el otro rompe el
      recorte.

   Por qué NO backdrop-filter en .isotipo-nav ni en el SVG: el halo va
   DETRÁS (ver .isotipo-nav position:relative arriba) — así el blur nunca
   toca las fotos ni los textos "Hogar/Químicos/Mayoristas", que están
   siempre en el elemento de ENCIMA, nítido.

   Por qué la sombra vive en .isotipo-nav (el contenido de encima, opaco)
   y NO en .isotipo-halo (el vidrio en sí) — bug real encontrado acá:
   drop-shadow (a diferencia de box-shadow) SÍ sigue el contorno real de
   la silueta, pero la sombra se compone DETRÁS del propio elemento usando
   su mismo canal alfa antes de que el elemento se pinte. Si el elemento
   tiene fondo translúcido (como el vidrio, ~0.8 de opacity), esa sombra
   oscura se asoma A TRAVÉS de su propia transparencia — no solo "por
   fuera" del contorno, tiñe TODA la superficie de gris. Medido: con
   drop-shadow puesto directo en .isotipo-halo, el relleno blanco (que
   solo, sin filter, da un sano rgb(252,252,251)) terminaba en
   rgb(240,240,240) — más oscuro que el propio fondo del Home
   (242,242,239) en vez de más claro. Poner la sombra en un SEGUNDO
   elemento propio (mismo contorno, detrás del vidrio, con fondo opaco)
   tampoco alcanza: backdrop-filter en .isotipo-halo no distingue "esto es
   una sombra", así que "ve" ese opaco entero detrás suyo y lo difumina
   igual, mismo síntoma por otra razón.

   La sombra en .isotipo-nav evita las dos formas del problema: .isotipo-
   nav es 100% opaco (fotos + colores de marca, sin transparencia), así
   que su propia sombra nunca se filtra a través de sí mismo; y al pintar
   ENCIMA de .isotipo-halo (nunca detrás), esa sombra jamás entra en el
   backdrop-filter del vidrio (que solo mira hacia atrás, nunca hacia
   adelante). El resultado es una sombra que cae limpiamente SOBRE el
   vidrio y se asoma un poco más allá de su borde — la lectura visual de
   "las hojas, objeto opaco, flotando sobre el vidrio, que a su vez flota
   sobre el fondo del Home".
   ========================================================================== */

.isotipo-halo {
  position: absolute;
  inset: var(--halo-inset);
  clip-path: var(--halo-clip);
  /* El fondo del Home acá es casi blanco (#f2f2ef) — blanco translúcido
     sobre un fondo ya casi blanco cambia MUY poco por sí solo (medido:
     con alpha 0.5-0.7 la diferencia real de color era de apenas 3-4 sobre
     255, casi invisible). Subido a 0.78-0.94 para que el propio relleno
     alcance a leerse como una superficie distinta, no solo el degradé o
     la sombra.

     Dos capas de fondo (la primera pinta ENCIMA de la segunda): un
     radial-gradient de brillo concentrado arriba (centrado por encima del
     propio contorno, en y:-5%, así que solo se alcanza a ver su mitad
     inferior) simula el "reflejo de luz en el canto del vidrio" que en la
     navbar era una línea recta — acá no puede ser una línea porque el
     borde superior de la silueta termina en una punta, no es recto; este
     brillo puntual arriba cumple el mismo rol sin necesitar seguir un
     contorno filoso. Se suma al linear-gradient de siempre (más claro
     arriba, más oscuro al medio), ensanchado un poco (0.94→0.68→0.82, antes
     0.92→0.78→0.84) para que el propio degradé de base también contraste
     más — el pedido explícito fue "hoy este detalle no se nota lo
     suficiente". */
  background:
    radial-gradient(120% 65% at 50% -5%, rgba(255, 255, 255, 0.95) 0%, rgba(255, 255, 255, 0) 48%),
    linear-gradient(180deg, rgba(255, 255, 255, 0.94) 0%, rgba(255, 255, 255, 0.68) 55%, rgba(255, 255, 255, 0.82) 100%);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  pointer-events: none;
}

.isotipo-nav-svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* --leaf-glow: color propio de cada hoja para su resplandor (ver más abajo
   ".isotipo-leaf — resplandor de color propio"). Uno por clase, mismo
   patrón que .isotipo-leaf-bg (fill) unas líneas más abajo — declarado acá
   arriba de .isotipo-leaf para que quede junto al resto de las variantes
   por hoja, aunque .isotipo-leaf sea quien lo consume. */
.isotipo-leaf--hogar {
  --leaf-glow: rgba(63, 155, 81, 0.32);
}

.isotipo-leaf--quimicos {
  --leaf-glow: rgba(50, 197, 216, 0.32);
}

.isotipo-leaf--mayoristas {
  --leaf-glow: rgba(141, 198, 65, 0.32);
}

/* ".isotipo-leaf — resplandor de color propio"

   Cada hoja emite un resplandor sutil de SU PROPIO color hacia afuera de
   su silueta (verde para Hogar, cian para Químicos, lima para Mayoristas)
   — se SUMA al halo de vidrio blanco (.isotipo-halo), no lo reemplaza: es
   un segundo drop-shadow, sin offset (0 0, el "glow" sale parejo en todas
   direcciones, no cae para un lado como una sombra normal), blur amplio
   (22px) y alpha bajo (0.32) para que tiña sin volverse un halo de color
   protagonista. drop-shadow (no box-shadow) para que siga el contorno
   real de la hoja, no su bounding-box rectangular — mismo motivo que la
   sombra de elevación de .isotipo-nav más abajo.

   Por qué en .isotipo-leaf (cada hoja individual, opaca) y no en
   .isotipo-halo (el vidrio, translúcido): la regla general del proyecto
   para vidrio+sombra sobre silueta irregular — un drop-shadow puesto en
   el MISMO elemento que tiene fondo translúcido se filtra a través de esa
   transparencia y tiñe la superficie entera en vez de proyectarse hacia
   afuera (bug ya documentado en el comentario largo de "Halo de vidrio").
   Cada .isotipo-leaf es 100% opaco (foto + color de fondo, sin huecos) y
   pinta ENCIMA del vidrio, así que su resplandor cae limpio sobre el
   vidrio blanco y se mezcla con él sin ese problema. */
.isotipo-leaf {
  cursor: pointer;
  transition: transform 250ms ease, filter 250ms ease;
  filter: drop-shadow(0 0 22px var(--leaf-glow));
}

.isotipo-leaf-bg {
  fill: var(--color-accent);
}

.isotipo-leaf--quimicos .isotipo-leaf-bg {
  fill: var(--color-accent-cyan);
}

.isotipo-leaf--mayoristas .isotipo-leaf-bg {
  fill: var(--color-accent-lime);
}

.isotipo-leaf-photo {
  opacity: 0.35;
  transition: opacity 250ms ease;
}

/* Hover (desktop) y focus por teclado dan la misma señal: elevación +
   más opacidad de foto. El nombre de categoría no cambia — se mantiene
   legible siempre, con drop-shadow propio, no depende del hover. Se
   encadena el resplandor de color (var(--leaf-glow), igual que en reposo)
   con la sombra de elevación al hover — si no, hover "apagaría" el color
   en vez de sumarle la elevación. */
.isotipo-leaf:hover,
.isotipo-leaf:focus-visible {
  transform: translateY(-6px);
  filter: drop-shadow(0 0 22px var(--leaf-glow)) drop-shadow(0 12px 20px rgba(0, 0, 0, 0.28));
}

.isotipo-leaf:hover .isotipo-leaf-photo,
.isotipo-leaf:focus-visible .isotipo-leaf-photo {
  opacity: 0.55;
}

/* El anillo de foco cae sobre el fondo de la página (outline-offset lo saca
   fuera de la silueta), no sobre el pétalo de color. Con el fondo claro y
   continuo, el blanco de antes quedaba invisible (1,06:1 sobre #f2f2ef);
   --hero-dark-green da 7,7:1 sobre la misma base. */
.isotipo-leaf:focus-visible {
  outline: 3px solid var(--hero-dark-green);
  outline-offset: 4px;
}

.isotipo-leaf-label {
  font-family: var(--font-heading);
  font-size: 25px;
  fill: var(--color-white);
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.55));
  pointer-events: none;
}

/* Mobile: MISMA composición que desktop (las 3 hojas unidas, halo de
   vidrio, resplandor de color y sombra), solo escalada — ya no hay una
   versión aparte apilada verticalmente (la vieja .isotipo-nav-mobile con
   sus propios SVGs recortados por hoja se quitó del markup: perdía la
   figura unificada que se pidió mantener). .isotipo-halo-wrap ya es
   fluido por sí solo (width: min(100%, 560px) + aspect-ratio, más arriba)
   así que en pantallas angostas se achica solo, sin ningún override acá.

   Lo único que SÍ necesita ajuste manual es el texto: al escalar el SVG
   completo, .isotipo-leaf-label (25 unidades de viewBox) se achica en la
   misma proporción que el gráfico — a ~335-390px de ancho de pantalla
   (el rango real de los celulares donde entra este breakpoint) el texto
   terminaba rindiendo ~14-16px reales, legible pero justo para un nombre
   de categoría superpuesto sobre una foto. Subido a 34 unidades acá (vs.
   25 en desktop): no es la misma proporción que el resto del gráfico a
   propósito — el pedido fue que el texto pueda quedar "más grande en
   relación al gráfico" que en desktop con tal de seguir siendo cómodo de
   leer.

   "Mayoristas" a 34 unidades SÍ se desborda de su silueta (bug real,
   detectado en dispositivo — no en 640px puntual sino en TODO el rango
   mobile, ya que estas unidades son del viewBox del SVG y no dependen
   del ancho real de pantalla). Confirmado geométricamente con
   `SVGGeometryElement.isPointInFill()` contra el path real del clip de
   esa hoja (no a ojo): a 34 unidades el texto sale tanto por los costados
   como por arriba; el límite real está entre 26 y 26.5 unidades. Bajado
   a 24 para esa hoja en particular (ver `.isotipo-leaf--mayoristas
   .isotipo-leaf-label` más abajo) — con margen de sobra, verificado que
   sigue adentro en los 5 anchos reales de iPhone. Es la única de las 3
   palabras que lo necesita ("Hogar" y "Químicos" sí entran a 34, ya
   verificado antes) — por eso el ajuste es específico a
   `.isotipo-leaf--mayoristas`, no un cambio general de
   `.isotipo-leaf-label`.

   Se queda en 640px (mobile) y NO sube a 1024px con el resto de los
   ajustes de este hero (ver `.hero { min-height }` más abajo, que sí
   migró a 1024px): `.isotipo-halo-wrap` tiene un tope de 560px de ancho
   (`width: min(100%, 560px)`, más arriba) que ya se alcanza a partir de
   ~640px de viewport — medido con Playwright, el isotipo renderiza a su
   tamaño MÁXIMO (mismo tamaño que en desktop) en TODO el rango
   641-1920px. Subir este font-size hasta 1024px agrandaría el texto
   sobre un gráfico que ya está a tamaño completo, desproporcionado. */
@media (max-width: 640px) {
  .isotipo-leaf-label {
    font-size: 34px;
  }

  /* Solo "Mayoristas" (la más larga de las 3) se desborda a 34 unidades
     — ver el comentario grande más arriba. Achicada puntualmente para
     esta hoja nada más; "Hogar"/"Químicos" se quedan en 34. */
  .isotipo-leaf--mayoristas .isotipo-leaf-label {
    font-size: 24px;
  }

  /* Bug real de renderizado en WebKit/Safari (no reproducía en Chromium,
     confirmado comparando con el motor webkit de Playwright): con el
     drop-shadow de elevación aplicado a .isotipo-nav como UN solo filtro
     sobre las 3 hojas combinadas, Safari deja una línea vertical visible
     justo en el punto donde las 3 siluetas se unen — cortando lo que
     debería verse como una sombra/reflejo continuo de lado a lado.
     Confirmado el origen apagando capas una por una: con
     .isotipo-nav{filter:none} la línea desaparece del todo (no está en
     .isotipo-halo, que renderiza limpio solo).

     Fix: en vez de un filter combinado en .isotipo-nav, cada
     .isotipo-leaf ya tiene su PROPIO drop-shadow (el resplandor de
     color, ver más abajo) que renderiza sin este problema — se le suma
     ahí mismo la sombra de elevación (mismos valores que tenía en
     .isotipo-nav) y se apaga el filter combinado. Solo en mobile: en
     desktop el bug no se reprodujo (confirmado, no tocar esa versión). */
  .isotipo-nav {
    filter: none;
  }

  .isotipo-leaf {
    filter: drop-shadow(0 0 22px var(--leaf-glow)) drop-shadow(0 16px 26px rgba(33, 33, 33, 0.32));
  }
}

/* .hero fuerza min-height:100vh en desktop para centrar el título+isotipo
   dentro de la pantalla completa. Sin contenido de sobra que lo justifique
   (título compacto + isotipo ya escalado, ver los ajustes de arriba), ese
   mismo 100vh deja al conjunto centrado dentro de una franja vacía del alto
   de pantalla, empujando el carrusel de volumen mucho más abajo de lo
   necesario. Acá el hero pasa a medir lo que su contenido más el padding
   necesite, ni más ni menos.

   En 1024px (tablet, ver "Sistema de breakpoints" en tokens.css), no en
   640px: esta regla vivía en el mismo bloque que `.isotipo-leaf-label`
   arriba, atada a 640px porque se agregó junto con ese ajuste — pero a
   diferencia del label, el problema del 100vh vacío no depende del tamaño
   del isotipo, depende de si el viewport es TAN alto en relación al
   contenido como para dejar aire de sobra, algo que sigue pasando en todo
   el rango de tablet (confirmado en ~768px, ancho real de iPad portrait:
   con min-height:100vh seguía apareciendo el mismo hueco vacío que se
   había arreglado para mobile). */
@media (max-width: 1024px) {
  .hero {
    min-height: auto;
  }
}

/* ==========================================================================
   Categorías — aviso de compra por volumen (carrusel rotativo)

   Cartel breve arriba del zigzag de categorías, no un bloque de texto más:
   fondo sólido de marca, mensaje corto que rota (js/home.js) y CTA fijo a
   Mayorista & Comercios. El detalle completo de niveles/mínimos se queda
   solo en esa página — acá va nada más la mención + el link.
   ========================================================================== */

.volumen-banner {
  padding-top: var(--space-lg);
}

.volumen-banner-inner {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  /* --color-accent (el verde "normal" de marca) da 3.49:1 con texto
     blanco encima, aun opaco al 100% — no llega al 4.5:1 de AA para texto
     normal (el mensaje rotativo no es lo bastante grande/negrita como
     para contar como "texto grande" en todos los anchos de pantalla).
     --color-accent-dark sí llega (≈4.93:1, verificado con Playwright) y
     es un verde ya usado en el sitio (hover de botones), no un color
     nuevo. */
  background: var(--color-accent-dark);
  color: var(--color-white);
  border-radius: var(--radius-md);
  padding: 1rem var(--space-lg);
  box-shadow: var(--shadow-md);
}

.volumen-banner-icon {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
}

.volumen-banner-icon svg {
  width: 22px;
  height: 22px;
  stroke: var(--color-white);
}

.volumen-banner-text-wrap {
  flex: 1;
  min-width: 0;
  display: block;
  overflow: hidden;
}

.volumen-banner-text {
  display: block;
  font-family: var(--font-heading);
  font-size: clamp(1rem, 2vw, 1.2rem);
  font-weight: 600;
  line-height: 1.4;
  transition: opacity 300ms ease, transform 300ms ease;
}

.volumen-banner-text.is-fading {
  opacity: 0;
  transform: translateY(6px);
}

/* El look del botón en sí (fondo, blur, borde con highlight, sombra,
   hover) ahora lo da .btn-glass (componente reusable, css/styles.css) —
   acá solo queda lo que es puramente de LAYOUT dentro de este banner
   puntual: que no se achique en el flex y cómo se acomoda en mobile. */
.volumen-banner-cta {
  flex-shrink: 0;
}

/* El relleno NEUTRO por defecto de .btn-glass (blanco muy translúcido,
   pensado para vivir sobre un fondo de color) en la práctica ACLARA el
   verde del banner en vez de oscurecerlo — contra un fondo ya oscuro
   (--color-accent-dark, ver .volumen-banner-inner) eso hace caer el
   contraste del texto blanco por debajo de 3:1 (2.16:1 medido en
   auditoría). Mismo criterio que .glass-surface en los chips de Mayorista
   & Comercios: sobre un fondo con el que "blanco sobre blanco" no
   contrasta, el tinte del vidrio tiene que ser OSCURO, no claro. Acá se
   nota poco por dentro — el diferenciador real de "esto es un botón
   flotando" sigue siendo el brillo del borde + el highlight radial
   (blancos, sin cambios). Verificado con Playwright: ≥6:1 con este tinte
   (con margen de sobra; el fondo ya oscurecido del banner por sí solo da
   ≈4.93:1, este tinte solo suma). */
.volumen-banner-cta.btn-glass::after {
  background:
    radial-gradient(120% 140% at 50% -30%, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0) 55%) padding-box,
    linear-gradient(180deg, rgba(15, 20, 18, 0.46) 0%, rgba(15, 20, 18, 0.3) 100%) padding-box,
    linear-gradient(180deg, rgba(255, 255, 255, 0.9) 0%, rgba(255, 255, 255, 0.08) 45%, rgba(255, 255, 255, 0.32) 100%) border-box;
}

.volumen-banner-cta.btn-glass:hover::after,
.volumen-banner-cta.btn-glass:focus-visible::after {
  background:
    radial-gradient(120% 140% at 50% -30%, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0) 55%) padding-box,
    linear-gradient(180deg, rgba(15, 20, 18, 0.54) 0%, rgba(15, 20, 18, 0.36) 100%) padding-box,
    linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0.14) 45%, rgba(255, 255, 255, 0.42) 100%) border-box;
}

/* En mobile Y tablet (hasta 1024px, ver "Sistema de breakpoints" en
   tokens.css) el banner deja de ser edge-to-edge: mismo margen lateral
   (--container-pad) que ya separa navbar y tarjetas del borde de
   pantalla, para que el fondo sólido + border-radius (heredado, sin
   cambios) se vean como una card más y no como una franja cortada.

   Este bloque vivía en 640px nada más — el bug real que motivó unificar
   el sistema de breakpoints: `.volumen-banner-inner` es un `.container`
   (css/styles.css), que sí tiene padding-inline propio SIEMPRE, pero eso
   es padding INTERNO del contenido, no separa el fondo/borde-radius de la
   propia card del borde del viewport (ese fondo llena el 100% del ancho
   de `.volumen-banner`, el div exterior, hasta que el viewport supera
   --container-max/1280px). Sin este padding-inline en `.volumen-banner`
   mismo, en cualquier ancho por debajo de 1280px la card queda pegada a
   los bordes — confirmado en 768px (iPad portrait) antes de este fix. */
@media (max-width: 1024px) {
  .volumen-banner {
    padding-inline: var(--container-pad);
  }

  .volumen-banner-inner {
    flex-wrap: wrap;
    row-gap: var(--space-sm);
    padding: var(--space-sm) var(--space-md);
  }

  .volumen-banner-text {
    font-size: 0.95rem;
  }

  .volumen-banner-cta {
    flex-basis: 100%;
    justify-content: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  .volumen-banner-text {
    transition: none;
  }
}

/* ==========================================================================
   Categorías — zigzag
   ========================================================================== */

.categorias {
  padding-block: var(--space-2xl);
}

/* padding-top de --space-2xl (96px) pensado para el aire ANTES del primer
   bloque del zigzag (.categoria-block) — pero en mobile/tablet
   .volumen-banner, no un .categoria-block, es el primer hijo real de
   .categorias, y ya trae su propio padding-top (--space-lg). Sumados al
   padding-bottom de .hero, quedaban ~176px de espacio vacío entre el
   isotipo (ya escalado y compacto) y el banner. Solo se achica el
   padding-TOP acá — el padding-bottom, que separa el último
   .categoria-block de .resenas, y el comportamiento en desktop, quedan
   intactos.

   Subido de 640px a 1024px junto con `.hero { min-height }` más arriba:
   mismo motivo — el espacio de sobra que este padding compensa aparece en
   toda la franja de tablet, no solo en mobile puro. */
@media (max-width: 1024px) {
  .categorias {
    padding-top: var(--space-lg);
  }
}

.categoria-block {
  position: relative;
  display: flex;
  min-height: 60vh;
  align-items: center;
  padding-block: var(--space-2xl);
  overflow: hidden;
}

.categoria-block + .categoria-block {
  border-top: 1px solid var(--color-surface);
}

.categoria-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.categoria-inner {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-pad);
  display: flex;
}

.categoria-content {
  max-width: 560px;
}

.categoria-right .categoria-content {
  margin-left: auto;
  text-align: right;
}

.categoria-right .hero-actions,
.categoria-right .categoria-block .btn-secondary {
  margin-left: auto;
}

.reveal-mask {
  overflow: hidden;
}

.reveal-content {
  display: block;
  transform: translate3d(0, 100%, 0);
  visibility: hidden;
  font-size: clamp(2.4rem, 7vw, 5rem);
  line-height: 1;
  margin-bottom: var(--space-sm);
}

.reveal-content.is-visible {
  visibility: visible;
  animation: reveal-from-bottom 0.8s cubic-bezier(0.25, 1, 0.5, 1) forwards;
}

@keyframes reveal-from-bottom {
  0% {
    transform: translate3d(0, 100%, 0);
  }
  100% {
    transform: translate3d(0, 0, 0);
  }
}

.categoria-blurb {
  font-size: 1.05rem;
  color: var(--color-text-soft);
  margin-bottom: var(--space-md);
  max-width: 48ch;
}

.categoria-right .categoria-blurb {
  margin-left: auto;
}

/* ==========================================================================
   Reseñas — título animado (home)

   El componente del carrusel en sí (.resenas, .reviews-*, .review-*) es
   compartido con contacto.html y vive en css/styles.css. Acá solo queda
   lo que es específico del efecto de reveal del título, exclusivo del
   home — contacto.html usa un <h2 class="resenas-heading"> simple, sin
   este wrapper de animación.
   ========================================================================== */

/* El componente .resenas es compartido con contacto.html y su fondo
   (--color-surface-soft) vive en css/styles.css. En el Home se neutraliza
   para que la sección tome el fondo continuo del body en vez de pintar el
   suyo: hoy renderizan igual, pero así queda atado a --home-bg y no a una
   coincidencia de valores. contacto.html no se toca. */
body.home .resenas {
  background: transparent;
}

.resenas > .container > .reveal-mask {
  text-align: center;
}

.resenas h2.reveal-content {
  font-size: clamp(1.8rem, 4vw, 2.6rem);
  margin-inline: auto;
}

/* ==========================================================================
   Responsive
   ========================================================================== */

@media (max-width: 1024px) {
  .categoria-block {
    min-height: auto;
    padding-block: var(--space-xl);
  }

  .categoria-inner {
    display: block;
  }

  .categoria-content,
  .categoria-right .categoria-content {
    max-width: 100%;
    text-align: left;
    margin-left: 0;
  }

  .categoria-right .categoria-blurb {
    margin-left: 0;
  }

  .categoria-right .hero-actions,
  .categoria-right .categoria-block .btn-secondary {
    margin-left: 0;
  }
}
