/* ═══════════════════════════════════════════════════════════════════════════
   beaüra — la capa que traduce nuestro diseño al marcado de Odoo.

   El diseño NO vive aquí: vive en site/styles.css, que se sube igual que
   como corre en local. Este archivo es sólo el puente, y existe por una
   razón concreta: Odoo pinta su tienda con clases de Bootstrap
   (`btn-primary`, `card`, `form-control`) que nuestro CSS no conoce.

   Así que aquí hay dos clases de reglas, y conviene no mezclarlas:

     1. Traducciones — le decimos a Bootstrap cuáles son nuestros colores y
        tipos, y de un plumazo se alinea casi todo.
     2. Parches puntuales — para lo que Bootstrap no deja arreglar por
        variable. Cada uno lleva escrito POR QUÉ existe; si algún día el
        parche deja de hacer falta, que se pueda borrar sin adivinar.

   Regla de oro: aquí se cambia cómo se VE. Nunca cómo se COMPORTA. El
   JavaScript de Odoo se agarra de sus propias clases para agregar al
   carrito, elegir variante y cobrar. Se les puede cambiar el aspecto;
   quitarlas o renombrarlas rompe la caja.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── 1. Traducciones ───────────────────────────────────────────────────────
   Bootstrap 5 lee estas variables. Al apuntarlas a nuestros tokens, los
   botones, enlaces, formularios y bordes de Odoo adoptan la paleta sin que
   tengamos que perseguir cada componente uno por uno. */
:root {
  --bs-primary: var(--lilac);
  --bs-primary-rgb: 198, 158, 212;
  --bs-link-color: var(--ink);
  --bs-link-hover-color: var(--lilac-deep);
  --bs-body-bg: var(--cream);
  --bs-body-color: var(--ink);
  --bs-body-font-family: 'Jost', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --bs-body-font-weight: 300;
  --bs-border-color: var(--line);
  --bs-border-radius: var(--radius);
  --bs-secondary-bg: var(--tint);
}

/* Odoo mete su contenido dentro de #wrapwrap; nuestro CSS le habla al body.
   Esto hace que el fondo y el color de texto lleguen adentro. */
#wrapwrap {
  background: var(--cream);
  color: var(--ink);
  font-family: var(--bs-body-font-family);
  font-weight: 300;
}

#wrapwrap h1, #wrapwrap h2, #wrapwrap h3, #wrapwrap h4, #wrapwrap h5 {
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 600;
  line-height: 1.08;
}

/* ── 2. Parches puntuales ──────────────────────────────────────────────────
   Cada uno con su motivo. */

/* La cabecera de Odoo, fuera de la vista.

   No se borra, se esconde. Cuando la quitábamos de verdad —un `replace` sobre
   //header— el sitio se veía igual de bien y se caía con error 500 en TODAS
   las páginas en cuanto alguien metía algo a la bolsa. Es decir: se rompía
   sólo para quien iba a comprar. El detalle completo está en
   tema/vistas/cabecera.xml.

   Va aquí y no en un atributo de la plantilla porque Odoo le calcula a su
   cabecera tanto `class` (con t-attf-class) como `style` al vuelo, y pisa
   cualquier cosa que le escribamos ahí. */
#wrapwrap > header#top[data-beaura-oculta] {
  display: none !important;
}

/* El subrayado que Bootstrap le pone a TODOS los enlaces al pasar el cursor:

     a:hover { text-decoration: underline; }

   En el menú principal eso se veía como dos rayas: la de Bootstrap pegada al
   texto y, más abajo, la barrita rosa que sí es nuestra y sí es a propósito
   (site/styles.css, `.nav__item>a::after`, que crece de 0 a 100%).

   Nuestro reset del diseño —`a{color:inherit;text-decoration:none}`— no la
   detiene: habla sólo del estado en reposo, y `a:hover` le gana porque la
   pseudo-clase suma un punto de especificidad. Por eso al medir el menú
   quieto no aparecía nada raro: la raya sólo existe con el cursor encima.

   Se apaga con la MISMA especificidad que la de Bootstrap, y gana por orden:
   esta hoja se carga después que la de Odoo (ver el <head>: assets_frontend,
   luego beaura-diseno.css, luego ésta). A propósito no se usa `#wrapwrap`:
   con un id se llevaría por delante los subrayados que el diseño sí pide.

   Es de todo el sitio y no sólo del menú, porque la regla de Bootstrap es
   `a:hover` a secas: también salía en las fichas de los mega menús y en el
   pie, encima de sus propios efectos. */
a:hover { text-decoration: none; }

/* La excepción: en Mi beaüra el subrayado al pasar el cursor SÍ es del diseño
   —esos enlaces no traen barrita— y es la única señal de que son enlaces. */
.mbh a:hover { text-decoration: underline; }

/* Los botones de Odoo son rectangulares y en mayúscula fina; los nuestros son
   píldoras. Bootstrap no expone el radio del botón como variable propia. */
#wrapwrap .btn-primary,
#wrapwrap .btn-secondary {
  border-radius: 100px;
  padding: .85rem 1.8rem;
  font-size: var(--fs-2xs);
  letter-spacing: .12em;
  text-transform: uppercase;
  font-weight: 500;
  border: 1px solid transparent;
  transition: .25s ease;
}
#wrapwrap .btn-primary { background: var(--lilac); color: #fff; }
#wrapwrap .btn-primary:hover { background: var(--lilac-deep); }
#wrapwrap .btn-secondary {
  background: transparent;
  color: var(--ink);
  border-color: var(--line);
}

/* La bolita del contador, con su color de vuelta.

   Odoo trae esta regla, y con `!important`:

     .badge, .o_filter_tag { background-color: var(--badge-bg, var(--background-color)) !important; }

   Ninguna de esas dos variables existe en nuestra cabecera, así que el fondo
   quedaba transparente: número blanco sobre crema, invisible aunque estuviera
   bien puesto. No se gana por orden —un `!important` no se pisa así—, se gana
   con más especificidad y otro `!important`. Va acotado a `.header` para no
   despintar las etiquetas de colores de Odoo, que llevan su propia clase. */
.header .badge { background-color: var(--lilac-deep) !important; }

/* El botón de agregar de las tarjetas de la tienda.

   Odoo lo dibuja encima de la foto y ahí normalmente sólo cabe el icono. Con
   el relleno de píldora de más abajo (.85rem 1.8rem) se inflaba a 76 px y
   salía como un globo lila colgado en la esquina de la tarjeta. Aquí vuelve a
   tamaño de icono; si la ventana da para que aparezca el texto, crece solo. */
#wrapwrap .o_wsale_product_btn .btn {
  padding: .6rem .9rem;
  font-size: var(--fs-2xs);
}

/* Las tarjetas de producto de Odoo traen sombra dura y esquina viva. */
#wrapwrap .card {
  border-color: var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* La retícula de la tienda. Este es un choque de nombres, y vale la pena
   entenderlo antes de "arreglarlo" de otro modo:

   · Para nosotros `.grid` es la retícula del catálogo: 4 columnas, una por
     producto.
   · Para Bootstrap —y por lo tanto para Odoo— `.grid` es una utilidad de 12
     columnas, y cada producto pide cuántas ocupa con `g-col-lg-4` (o sea, un
     tercio).

   Con nuestra definición ganando, cada producto pedía "4 columnas de 4" y se
   comía la fila entera: un solo producto por renglón, gigante. Aquí se le
   devuelve a la retícula de la tienda su malla de 12 para que el `g-col-*` que
   Odoo calcula desde "productos por fila" vuelva a significar lo que dice.

   El hueco sí se queda en el nuestro: se ve mejor y no rompe nada. */
#wrapwrap .o_wsale_products_grid_table.grid {
  grid-template-columns: repeat(var(--bs-columns, 12), 1fr);
}

/* Los campos del checkout: el foco azul de Bootstrap desentona con la lila. */
#wrapwrap .form-control:focus,
#wrapwrap .form-select:focus {
  border-color: var(--lilac);
  box-shadow: 0 0 0 .2rem rgba(198, 158, 212, .25);
}

/* ── Pendiente ─────────────────────────────────────────────────────────────
   Esto es el arranque, no el final. Falta —y se irá agregando conforme cada
   página se vaya vistiendo—: cabecera y pie propios, retícula de la tienda,
   ficha de producto, y los pasos del checkout. */

/* El título de la tienda cuando lo dibuja la tipografía "Beauria".

   El componente publica su caja de tinta en --nano-content-height, así que el
   aire de arriba y abajo no se adivina: se recorta con lo que él mismo reporta.
   Sin esto, la fotografía de las letras trae su propio margen y el título queda
   flotando lejos de la retícula de productos. */
/* El `display:block` lleva !important porque el encabezado de categoría trae
   la clase `d-flex` de Bootstrap, que también es !important: sin esto el
   componente queda como caja flexible y se descoloca. */
#wrapwrap .o_wsale_shop_title.con-nano,
#wrapwrap .o_wsale_category_title.con-nano{
  display: block !important;
  max-width: none;
  margin: .2rem 0 .3rem;
  line-height: 1;
  text-align: center;
  /* Respaldo: si el módulo de Nano Studio Pro no carga —red caída, bloqueador,
     un futuro en el que ese dominio ya no exista— el título hereda esto y se
     sigue leyendo como un encabezado, no como texto suelto. */
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 600;
  font-size: clamp(2rem, 5.5vw, 3.4rem);
  letter-spacing: .02em;
}

/* La caja de la letra reserva aire arriba y bajo la línea base, y por eso el
   título dejaba un hueco enorme debajo. El componente PUBLICA cuánto reserva
   en esas tres variables, así que se recorta con sus propias medidas en vez de
   adivinar un margen negativo. */
#wrapwrap .con-nano nano-type{
  display: block;
  width: 100%;
  margin-top: calc(var(--nano-cap-top, 0px) * -1);
  margin-bottom: calc((var(--nano-content-height, 0px) - var(--nano-baseline, 0px)) * -1);
}

/* El título de verdad, para buscadores y lectores de pantalla. */
#wrapwrap .solo-lectores{
  position: absolute !important;
  width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* La tira de categorías de la tienda, fuera.

   Odoo dibuja su propio carrusel de categorías arriba de la retícula
   (`o_wsale_filmstrip`): Anillos, Aretes, Arracadas, Cadenas, Charms… Son las
   mismas que ya están en el mega menú de la cabecera, así que la página queda
   con dos navegaciones encimadas — y además la tira mide 1767 px metidos en un
   carril de 1050, o sea que la mitad vive fuera de la pantalla.

   Se esconde, no se borra: si algún día se quita el mega menú, esta línea se
   comenta y vuelve. */
/* Lleva !important porque la tira trae `d-flex` de Bootstrap, que también lo
   lleva: sin esto la regla se escribe y no pasa nada. */
#wrapwrap .o_wsale_filmstrip_container { display: none !important; }

/* Los atributos de personalización YA NO SE ESCONDEN DESDE AQUÍ.

   Hubo aquí una regla que los tapaba por id (`[data-attribute_id="9"]`…) y
   que además nunca funcionó: Odoo no pone ese atributo en el bloque, así que
   el selector no encontraba nada.

   Se quitó porque el problema no era de CSS. Tipografía, Cantidad de Letras,
   Cantidad de Huellas, Tipo de Armado y «¿Qué formato deseas?» no son formas
   de BUSCAR una joya: son pasos para ARMARLA. Odoo distingue las dos cosas
   con el campo `visibility` del `product.attribute`, y en `hidden` los saca
   de la barra lateral pero los deja en la ficha, que es justo lo que hace
   falta. Los ocho quedaron en `hidden` el 2026-09-01; Material, Piedra y
   Medida se quedan en `visible` porque ésos sí son búsqueda.

   O sea: si algún día vuelve a aparecer un filtro que estorba, se cambia su
   `visibility` en Odoo, no se le pone una regla aquí. */
/* ══ LA BARRA LATERAL DE LA TIENDA ════════════════════════════════════════

   Se rehízo entera el 2026-09-01 porque el primer arreglo no servía, y la
   razón por la que no servía es la lección importante de este archivo.

   EL SÍNTOMA. En /shop la columna se cortaba: de sus cinco bloques, dos
   quedaban fuera de la pantalla y no había forma de llegar a ellos. Bajar la
   página no ayudaba, porque la columna va pegada (sticky) y baja contigo.

   EL PRIMER INTENTO, y por qué falló. Se le puso al `aside` un alto máximo y
   `display:flex` para que el riel de adentro creciera y se desplazara solo.
   El alto máximo sí entró; el `display:flex` NO. El aside lleva la clase
   `d-lg-block` de Bootstrap, que es `display:block !important`, y le ganó.
   Resultado: el riel nunca recibió una altura que respetar, su `overflow-y`
   nunca se activó, y el alto máximo se limitó a cortar el contenido con
   `overflow:visible` — o sea, a tirarlo fuera sin dejar cómo alcanzarlo.

   Es el mismo patrón que el alto del hero: una regla nuestra sin !important
   perdiendo en silencio contra una de Bootstrap que sí lo trae. Cuando una
   regla "no hace nada" en este proyecto, esto es lo primero que hay que
   descartar.

   LA SOLUCIÓN. Tres piezas que sólo funcionan juntas:

     1. El aside es una columna flexible, con !important para ganarle a
        `d-lg-block`, y SÓLO de 992 px para arriba. Fuera de esa medida manda
        `d-none`, que es lo que esconde la barra en móvil: si el !important se
        pusiera suelto, la barra aparecería en el teléfono.
     2. El aside se limita al hueco que de verdad queda en pantalla: la altura
        de la ventana menos la cabecera pegada (92 px) y un respiro.
     3. El riel crece hasta llenar ese hueco y ahí sí se desplaza solo. El
        `min-height:0` no es adorno: sin él un hijo flexible se niega a
        encoger por debajo de su contenido y el desplazamiento interno no
        aparece nunca.

   El precio se sube al principio con `order`, sin tocar la plantilla. */
@media (min-width: 992px){
  #wrapwrap aside#products_grid_before{
    display: flex !important;          /* gana a .d-lg-block */
    flex-direction: column;
    top: 92px;                          /* debajo de la cabecera pegada */
    max-height: calc(100vh - 92px - 1.25rem);
  }
  #wrapwrap .o_wsale_products_grid_before_rail{
    height: auto !important;            /* mata el .vh-100 de Bootstrap */
    min-height: 0;                      /* imprescindible: ver arriba */
    flex: 1 1 auto;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    padding-bottom: .5rem;
  }
  /* Los bloques no se encogen: si se encogieran, en vez de aparecer la barra
     de desplazamiento se aplastarían unos contra otros. */
  #wrapwrap .o_wsale_products_grid_before_rail > *{ flex: 0 0 auto; }
}

#wrapwrap #o_wsale_price_range_option{
  order: -1;                            /* el precio, hasta arriba */
  border-top: 0 !important;
  margin-bottom: .9rem;
}

/* El número de productos junto a cada casilla del filtro. Va en gris y más
   chico: es un dato de apoyo, no compite con el nombre del valor. */
#wrapwrap .filtro-cuenta{
  margin-left: .35rem;
  font-size: .78em;
  color: var(--muted, #71667C);
  font-variant-numeric: tabular-nums;
}
#wrapwrap .filtro-cuenta::before{ content: "("; }
#wrapwrap .filtro-cuenta::after { content: ")"; }

/* Una casilla que lleva a cero resultados es peor que ninguna casilla: en
   Pulseras salían «Titanio» o «Rodio» aunque no haya ni una. Odoo enseña
   TODOS los valores del atributo, no sólo los que existen en el listado.

   Se esconden por ausencia de número —si no hay cuenta, no hay piezas—, con
   una excepción importante: si la casilla está MARCADA se queda, porque si no
   la clienta que filtró hasta quedarse sin resultados no tendría con qué
   desmarcar y quedaría atrapada. */
#wrapwrap .js_attributes .form-check:not(:has(.filtro-cuenta)):not(:has(input:checked)){
  display: none;
}

/* ── Correcciones de móvil ────────────────────────────────────────────────

   1. LOS PUNTOS DE FOTO CONTRA LA CINTA DE «AGOTADO».

   Cuando un producto tiene segunda foto, Odoo dibuja dos puntitos para
   cambiarla. No son elementos: son el ::before y el ::after de la propia
   .oe_product_image, clavados en `bottom: 8px`. Nuestra cinta de agotado
   ocupa los 26 px de abajo, así que los puntos caían justo encima de la
   palabra y la partían por la mitad.

   Se suben por encima de la cinta, y sólo en las tarjetas que la tienen: el
   `:has()` es lo que evita moverlos en las 2,172 piezas que sí hay. */
#wrapwrap .oe_product_image:has(.card__agotado)::before,
#wrapwrap .oe_product_image:has(.card__agotado)::after{
  bottom: calc(var(--cinta-agotado, 26px) + 7px);
}

/* 2. EL BUSCADOR CHICO DE LA TIENDA, FUERA EN MÓVIL.

   Odoo pone su propio buscador arriba de la reja de productos. En teléfono
   queda de 57 px de ancho —ilegible— y además duplica el buscador de la
   cabecera, que es el que la clienta ya conoce. En escritorio se queda: ahí
   sí tiene espacio y no estorba. */
@media (max-width: 920px){
  #wrapwrap .o_wsale_products_header_search_form_container{ display: none !important; }
}

/* 3. LA TARJETA DE MÓVIL, CON LA FOTO MÁS GRANDE.

   Con dos columnas en un teléfono de 390 px la tarjeta medía 172x222 y la
   foto 158x158: chica para lo único que de verdad vende una joya.

   El primer intento fue alargar el marco a 4:5. NO SIRVIÓ, y vale la pena
   dejarlo escrito: las fotos del catálogo son cuadradas y van en `contain`,
   así que un marco más alto no agranda la foto — le pone franjas vacías
   arriba y abajo. La foto siguió midiendo 162.

   Lo que sí da píxeles es ancho, y el ancho estaba regalado en márgenes: el
   contenedor tenía 15 px a cada lado y la reja 16 px de separación. Bajando
   esos números y quitando el margen interior del marco, la foto pasa de 158
   a ~182 px de lado: 15% más de lado, 32% más de superficie, sin recortar
   nada de la joya. */
@media (max-width: 640px){
  #wrapwrap #products_grid{ padding-left: 8px !important; padding-right: 8px !important; }
  #wrapwrap .o_wsale_products_grid_table{ gap: 10px !important; }
  #wrapwrap .card__media{ padding: 0; }
  #wrapwrap .o_wsale_product_information{ padding: .7rem .5rem 1rem; }
}

/* ── El alto del hero en móvil, contra un !important de Odoo ──────────────

   Odoo trae esta regla en su hoja de frontend:

       @media (max-width: 767.98px){ section, .parallax, .row, .hr … {
         height: auto !important } }

   Nuestro hero es un <section>, así que POR DEBAJO DE 768 px Odoo le anulaba
   el alto y lo dejaba del tamaño de su contenido: 408 px en un teléfono de
   844, o sea chaparro, con el titular, los botones y los puntos apretados.

   Se le pasó por encima con !important, que aquí no es pereza: es la única
   forma de ganarle a otro !important, y por eso vive en esta hoja —la que
   existe para reconciliar a Odoo con el diseño— y no en styles.css.

   `100dvh` es la altura DINÁMICA: descuenta la barra del navegador, que en un
   teléfono real se come ~60 px que `100vh` ignora. El min-height es para el
   teléfono acostado, donde 100dvh serían 390 px y no cabría nada.

   OJO PARA EL FUTURO: esa regla de Odoo aplica a TODA sección nuestra. Si
   alguna otra pierde su alto por debajo de 768 px, la causa es ésta. */
@media (max-width: 767.98px){
  #wrapwrap section.hero{
    height: 100vh !important;
    height: 100dvh !important;
    min-height: min(560px, 100vw) !important;
  }
}

/* ── El aspecto de los filtros ────────────────────────────────────────────

   Los títulos venían como los deja Bootstrap: `<b>` dentro de un h6, o sea
   negro, grueso y de palo seco. En una página cuyos encabezados son todos
   Cormorant Garamond en ciruela, esa columna se leía como pegada de otro
   sitio.

   Pasan a la tipografía y al color de los títulos de sección (#6E5A85), con
   una línea fina arriba que separa un filtro de otro sin cajas ni fondos: la
   barra tiene que guiar la vista hacia los productos, no competir con ellos.
   Las casillas toman el lila de la marca con `accent-color`, que es una línea
   de CSS en vez de reinventar el control. */
#wrapwrap .js_attributes .accordion-header,
#wrapwrap .js_attributes h6,
#wrapwrap #o_wsale_price_range_option .accordion-header,
#wrapwrap #o_wsale_price_range_option label.h6{
  margin-bottom: .5rem;
}
#wrapwrap .js_attributes .accordion-header b,
#wrapwrap .js_attributes h6 b,
#wrapwrap #o_wsale_price_range_option .accordion-header b,
#wrapwrap #o_wsale_price_range_option label.h6 b{
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-weight: 600;
  font-size: 1.35rem;
  line-height: 1.2;
  color: #6E5A85;
  letter-spacing: .012em;
}

/* El icono ilustrado que [iconos-filtros.xml] mete antes de cada título.

   El <b> del escritorio viene con `d-lg-block` de Bootstrap, o sea que en
   pantalla grande es un bloque y empujaría al icono a su propio renglón. Por
   eso el encabezado se vuelve una fila flex: así el dibujo y el nombre van
   juntos sin tener que pelearse con la clase de Bootstrap. */
#wrapwrap .js_attributes h6,
#wrapwrap .js_attributes .accordion-header .accordion-button,
#wrapwrap #o_wsale_price_range_option label.h6,
#wrapwrap #o_wsale_price_range_option .accordion-button{
  display: flex;
  align-items: center;
  gap: .45rem;
}
#wrapwrap .filtro-ico{
  width: 26px; height: 26px;
  object-fit: contain;
  flex: 0 0 auto;
  opacity: .8;
}

#wrapwrap .js_attributes .accordion-item{
  border-top: 1px solid var(--line, #E9E0EC);
  padding-top: .9rem;
  margin-bottom: .5rem !important;
}
#wrapwrap .js_attributes .accordion-item:first-child{ border-top: 0; padding-top: 0; }

#wrapwrap .js_attributes .accordion-button,
#wrapwrap #o_wsale_price_range_option .accordion-button{
  padding-left: 0; padding-right: 0;
  background: transparent; box-shadow: none;
}
#wrapwrap .js_attributes .accordion-button::after,
#wrapwrap #o_wsale_price_range_option .accordion-button::after{
  filter: none; opacity: .55;
}

/* Las casillas y sus etiquetas */
#wrapwrap .js_attributes .form-check-input{
  accent-color: var(--lilac-deep, #B487C6);
  border-color: #D8CBDE;
  cursor: pointer;
}
#wrapwrap .js_attributes .form-check-input:checked{
  background-color: var(--lilac-deep, #B487C6);
  border-color: var(--lilac-deep, #B487C6);
}
#wrapwrap .js_attributes .form-check-input:focus{
  box-shadow: 0 0 0 .18rem rgba(198,158,212,.35);
  border-color: var(--lilac, #C69ED4);
}
#wrapwrap .js_attributes .form-check-label{
  color: var(--ink, #342A3B);
  cursor: pointer;
  transition: color .18s ease;
}
#wrapwrap .js_attributes .form-check:hover .form-check-label{ color: var(--lilac-deep, #B487C6); }
#wrapwrap .js_attributes .form-check-input:checked + .form-check-label{
  color: var(--lilac-deep, #B487C6); font-weight: 500;
}

/* «Ver más», que venía como enlace azul de Bootstrap */
#wrapwrap .o_wsale_view_more_btn{
  color: var(--lilac-deep, #B487C6) !important;
  font-size: var(--fs-2xs, .82rem);
  letter-spacing: .1em;
  text-transform: uppercase;
  text-decoration: none;
}

/* Cada opción en un renglón, con su número alineado a la derecha.

   Bootstrap arma la casilla con `padding-left` y un margen negativo, así que
   una etiqueta larga («Acero inoxidable 304») empujaba el número al renglón
   de abajo y la columna se veía descuadrada. En fila flexible el número se va
   al final con `margin-left:auto` y siempre cae donde el ojo lo busca. */
#wrapwrap .js_attributes .form-check{
  display: flex; align-items: center; gap: .55rem;
  padding-left: 0; margin-bottom: .4rem;
}
#wrapwrap .js_attributes .form-check-input{ margin: 0; float: none; flex: 0 0 auto; }
#wrapwrap .js_attributes .form-check-label{ flex: 1 1 auto; }
#wrapwrap .js_attributes .filtro-cuenta{ margin-left: auto; flex: 0 0 auto; }

/* El bloque del precio dejaba un hueco de ~130 px antes del primer filtro:
   su propio margen más el del acordeón de Odoo. */
#wrapwrap #o_wsale_price_range_option .accordion-item{ margin-bottom: 0; }
#wrapwrap #o_wsale_price_range_option .accordion-collapse{ padding-bottom: 0; }
#wrapwrap #o_wsale_price_range_option{ margin-bottom: .4rem; padding-bottom: .2rem; }

/* El hueco de ~130 px debajo del deslizador de precio no era margen nuestro:
   Odoo le pone `margin-bottom:48px` al envoltorio del rango, más el relleno
   del botón del acordeón. Sumados dejaban un vacío que separaba el precio del
   resto como si fueran dos barras distintas. */
#wrapwrap #o_wsale_price_range_option .multirange-wrapper{ margin-bottom: 10px !important; }
#wrapwrap #o_wsale_price_range_option .accordion-button{ padding-bottom: .35rem; }

/* La columna mide 240 px y con la etiqueta a 17 px un «Acero inoxidable 304»
   se partía en dos renglones. A 15 px cabe entero y la lista se lee de un
   golpe de vista, que es para lo que sirve una lista de filtros. */
#wrapwrap .js_attributes .form-check-label{ font-size: .94rem; line-height: 1.35; }
#wrapwrap .js_attributes .filtro-cuenta{ font-size: .8rem; }

/* ── La ficha de producto: quitar la segunda plasta blanca ────────────────

   El bloque de datos —nombre, SKU, precio, botón— venía con fondo blanco
   sólido. Como la mayoría de las fotos del catálogo son sobre fondo blanco,
   la ficha se leía como dos rectángulos blancos pegados sin frontera: no se
   distinguía dónde acababa la joya y empezaba el texto.

   Se le quita el fondo y queda directamente sobre el crema de la página. Así
   la foto —que sí es blanca— se recorta contra el crema y se lee como una
   pieza, que es lo que tiene que mirar la clienta. */
#wrapwrap #product_details{ background: transparent !important; }

/* ── El panel de filtros en teléfono ──────────────────────────────────────

   En móvil los filtros no van en la columna: Odoo los mete en un cajón
   lateral (#o_wsale_offcanvas) con un marcado distinto al de escritorio, y
   por eso los arreglos de la columna no llegaban aquí.

   Lo que se veía mal: «Material» y «Piedra» arrancaban pegados al borde
   izquierdo del cajón mientras «Rango de precio» iba con sangría, así que los
   títulos no compartían un margen y la lista se leía torcida. Cada bloque
   traía su propio relleno de Bootstrap.

   Se les da a todos el mismo margen que al cuerpo del cajón, y a las casillas
   el mismo, para que título y opciones caigan sobre la misma línea. */
@media (max-width: 991.98px){
  #wrapwrap #o_wsale_offcanvas .offcanvas-body{ padding-inline: 0; }
  #wrapwrap #o_wsale_offcanvas .accordion-item,
  #wrapwrap #o_wsale_offcanvas #o_wsale_price_range_option{
    padding-inline: 1.15rem;
    border-inline: 0;
  }
  #wrapwrap #o_wsale_offcanvas .accordion-button,
  #wrapwrap #o_wsale_offcanvas .accordion-body{
    padding-inline: 0;
  }
  #wrapwrap #o_wsale_offcanvas .form-check{
    padding-left: 0;
    margin-inline: 0;
  }
  #wrapwrap #o_wsale_offcanvas .list-group-item{ padding-inline: 0; }

  /* El bloque del precio envuelve su propio `.accordion-item`, así que con la
     regla de arriba recibía el margen DOS veces y quedaba más adentro que
     Material y Piedra. Se le quita al de dentro. */
  #wrapwrap #o_wsale_offcanvas [id^="o_wsale_price_range_option"] .accordion-item,
  #wrapwrap #o_wsale_offcanvas [id^="o_wsale_price_range_option"] .accordion-header,
  #wrapwrap #o_wsale_offcanvas [id^="o_wsale_price_range_option"] label{
    padding-inline: 0;
  }

  /* El título del precio venía en la tipografía de Odoo mientras Material y
     Piedra ya usaban la de la marca. */
  #wrapwrap #o_wsale_offcanvas .o_wsale_offcanvas_title,
  #wrapwrap #o_wsale_offcanvas .o_wsale_offcanvas_title b,
  #wrapwrap #o_wsale_offcanvas label.h6 b{
    font-family: 'Cormorant Garamond', Georgia, serif;
    font-weight: 600;
    font-size: 1.3rem;
    color: #6E5A85;
  }
}

/* ── El botón de comprar, fijo abajo en teléfono ──────────────────────────

   La ficha mide 3,296 px en un teléfono de 844: el botón de agregar vive a
   1,079 px del principio y desaparece en cuanto la clienta baja a ver las
   fotos, la descripción o las opciones. Justo cuando se decide, el botón no
   está.

   No se DUPLICA el botón: se fija el que ya existe. Duplicarlo sería tener
   dos controles del mismo formulario, con la cantidad en uno y el envío en el
   otro — y además Daniel pidió expresamente que no se repita.

   El `env(safe-area-inset-bottom)` es por los iPhone con barra de gestos: sin
   eso, el botón queda debajo de la rayita del sistema y no se puede tocar.
   Y la ficha recibe relleno abajo para que la barra no tape su último
   renglón. */
@media (max-width: 991.98px){
  #wrapwrap #add_to_cart_wrap{
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 80;
    display: flex !important; flex-wrap: nowrap !important;
    align-items: center; gap: .6rem;
    margin: 0 !important;
    padding: .7rem .9rem calc(.7rem + env(safe-area-inset-bottom, 0px));
    background: rgba(247, 243, 238, .97);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--line, #E9E0EC);
    box-shadow: 0 -12px 30px -22px rgba(80, 50, 90, .55);
  }
  #wrapwrap #add_to_cart_wrap .css_quantity{ flex: 0 0 auto; margin: 0 !important; }
  #wrapwrap #add_to_cart_wrap #add_to_cart{ flex: 1 1 auto; width: auto; margin: 0 !important; }

  /* Hueco al final para que la barra no se coma el último contenido. */
  #wrapwrap #product_detail{ padding-bottom: 92px; }
}

/* ── Cargar al bajar: el aviso y el paginador escondido ───────────────────
   El paginador se esconde pero NO se borra: sus enlaces son los que le dan a
   Google el resto del catálogo. Si el guion falla, se quita la clase del
   <body> y el paginador reaparece, que es la red de seguridad. */
#wrapwrap .beaura-scroll-infinito .products_pager,
body.beaura-scroll-infinito #wrapwrap .products_pager{
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
#wrapwrap .cargando-mas{
  display: flex; align-items: center; justify-content: center; gap: .6rem;
  padding: 2.2rem 1rem 3rem; color: var(--muted, #71667C);
  font-size: var(--fs-2xs, .82rem); letter-spacing: .1em; text-transform: uppercase;
}
#wrapwrap .cargando-mas__giro{
  width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--soft, #EBDCEE); border-top-color: var(--lilac-deep, #B487C6);
  animation: beauraGira .8s linear infinite;
}
#wrapwrap .cargando-mas--fin .cargando-mas__giro{ display: none; }
@keyframes beauraGira{ to{ transform: rotate(360deg) } }
@media (prefers-reduced-motion: reduce){
  #wrapwrap .cargando-mas__giro{ animation: none }
}

/* ── «Especificaciones» sin especificaciones ──────────────────────────────

   Odoo decide si dibuja esta sección con `t-if="attrib_categories"`, o sea
   «¿el producto tiene atributos?». Pero la TABLA de adentro sólo hace un
   renglón por atributo con MÁS DE UN VALOR. Material, Piedra y Medida tienen
   un valor por producto —un anillo es de acero 304, no de acero 304 o 316—,
   así que en la mayoría del catálogo la condición se cumple, la sección se
   dibuja… y la tabla sale vacía: un título «Especificaciones» con nada
   debajo.

   Se esconde la sección entera cuando no hay ni un renglón. `:has()` se
   encarga de mirar dentro, que es justo lo que a la condición de Odoo le
   falta.

   PENDIENTE, y es una mejora aparte: hoy el material NO se ve en ninguna
   parte de la ficha, y es de lo primero que una clienta de joyería quiere
   saber. Vale la pena escribir nuestro propio bloque que lo muestre en vez de
   depender de esta tabla. */
#wrapwrap #product_full_spec:not(:has(#product_specifications tr)){
  display: none;
}

/* Los datos de la pieza en la ficha: material, piedra, medida, peso.
   Renglones con el nombre a la izquierda y el valor a la derecha, separados
   por línea fina — se leen de un vistazo y no compiten con el precio. */
#wrapwrap .pieza-datos{ margin: 0 0 1.4rem; }
#wrapwrap .pieza-datos__fila{
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  padding: .5rem 0; border-bottom: 1px solid var(--line, #E9E0EC);
}
#wrapwrap .pieza-datos__fila:last-child{ border-bottom: 0; }
#wrapwrap .pieza-datos dt{
  font-size: var(--fs-3xs, .72rem); letter-spacing: .18em; text-transform: uppercase;
  color: var(--muted, #71667C); font-weight: 400; margin: 0; flex: 0 0 auto;
}
#wrapwrap .pieza-datos dd{
  margin: 0; text-align: right; color: var(--ink, #342A3B);
  font-size: var(--fs-xs, .92rem);
}

/* El listón del top 3 sobre la tarjeta de la tienda. La foto de Odoo ya es
   `position:relative` y recorta, así que el listón se ancla ahí igual que en
   la portada. Va por debajo de la cinta de «Agotado» —z-index menor— porque
   si una pieza está agotada eso es lo primero que hay que leer. */
#wrapwrap .oe_product_image > .rank{ z-index: 2; }
#wrapwrap .oe_product_image{ overflow: hidden; }

/* ══ Compra por volumen en el listado ═════════════════════════════════════
   Los controles viven en el CUERPO de la tarjeta y no encima de la foto: la
   foto es lo que vende la joya y ya carga el listón del top 3 y la cinta de
   agotado. Tres cosas más ahí arriba y no se vería la pieza. */
/* `align-items:stretch` y no `center`: así el −/+ mide lo mismo de alto que
   «Agregar» en vez de quedarse 5 px más bajo y flotando a media altura. La
   altura la manda el botón, que es quien la tiene por su padding. */
#wrapwrap .masivo{
  display: flex; align-items: stretch; gap: .4rem;
  margin-top: .7rem; padding: .7rem .7rem 0;
  border-top: 1px solid var(--line, #E9E0EC);
}

/* La esquina de acciones de Odoo, ya mudada a la foto (ver tienda.js). Lo
   único que hay que decirle es que mida lo que la foto: venía siendo un
   cuadrado del ancho de la tarjeta y por eso el botón de carrito se salía por
   abajo. Con esto se alinea a `flex-end` contra el borde real de la imagen y
   el resto lo sigue colocando Odoo. */
#wrapwrap .oe_product_image > .o_wsale_product_btn{
  inset:0; width:auto; height:auto;
  /* Y `aspect-ratio:auto`, que es la pieza que faltaba: Odoo se lo pone en
     1/1, y mientras esté ahí el alto sale del ancho —333— y no de la foto,
     por mucho `inset:0` que se le ponga. Ése era el cuadrado. */
  aspect-ratio:auto;
}
/* En una pieza agotada ese botón no puede hacer nada —Odoo rechaza agregarla—
   y encima se sentaría sobre la cinta de «Agotado», que es lo que hay que
   leer. Misma regla que para nuestra fila, que ahí tampoco se pone. */
#wrapwrap .oe_product_image:has(.card__agotado) .o_wsale_product_action_row{
  display:none;
}

/* La casilla: cuadro propio en lila, para que se lea como control de la
   tienda y no como una casilla suelta del navegador.

   Vive en la ESQUINA SUPERIOR DERECHA de la foto. Estaba en la fila, apretada
   entre el −/+ y «Agregar», y con tres controles en un ancho de tarjeta el
   botón se quedaba sin sitio: en teléfono hubo que bajarle la letra a 10 px
   para que cupiera «Agregar». Fuera de la fila, esa apretura desaparece.
   La esquina de arriba a la derecha es la única libre —el listón del top 3
   ocupa la izquierda y la cinta de «Agotado» el borde de abajo—.

   Lleva su propia pastilla blanca detrás y no va sola sobre la foto: media
   tienda son piezas sobre fondo claro, y un cuadro blanco con borde gris
   encima de un fondo blanco no se ve. */
#wrapwrap .oe_product_image > .masivo__sel{
  position:absolute; top:.5rem; right:.5rem; z-index:4;
  display:flex; align-items:center; cursor:pointer; margin:0; padding:.28rem;
  border-radius:9px; background:rgba(255,255,255,.86);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
  box-shadow:0 6px 16px -10px rgba(80,50,90,.7);
  transition:background .18s, box-shadow .18s;
}
#wrapwrap .oe_product_image > .masivo__sel:hover{ background:#fff }
/* Odoo ya pone SU corazón de favoritos en esa esquina —45 px de ancho, pegado
   al borde y visible siempre, no sólo al pasar el ratón—, así que la casilla
   se corre a su izquierda en vez de encimársele.

   El :has() cuelga de la TARJETA y no de la foto, que es donde estuvo primero
   y por eso no aplicaba nunca: el corazón no vive dentro de `.oe_product_image`
   sino en el cuerpo de la tarjeta, colocado encima con `position:absolute`.
   Mirar sólo dentro de la foto no lo encuentra jamás. */
#wrapwrap .oe_product_cart:has(.o_add_wishlist) .oe_product_image > .masivo__sel{
  right:3.2rem;
}
#wrapwrap .masivo__check{ position:absolute; opacity:0; width:0; height:0 }
#wrapwrap .masivo__sel span{
  display:block; width:19px; height:19px; border-radius:5px;
  border:1.5px solid #D8CBDE; background:#fff; transition:.15s;
}
#wrapwrap .masivo__check:checked + span{
  background: var(--lilac-deep, #B487C6); border-color: var(--lilac-deep, #B487C6);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='%23fff' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 8.5l3 3 6-6'/%3E%3C/svg%3E");
  background-size: 13px; background-position: center; background-repeat: no-repeat;
}
#wrapwrap .masivo__check:focus-visible + span{ box-shadow:0 0 0 3px rgba(198,158,212,.4) }

#wrapwrap .masivo__cant{
  display:flex; align-items:stretch; flex:0 0 auto;
  border:1px solid var(--line,#E9E0EC); border-radius:100px; overflow:hidden; background:#fff;
}
#wrapwrap .masivo__mas-menos{
  border:0; background:transparent; width:24px; height:auto; cursor:pointer;
  color: var(--ink,#342A3B); font-size:1rem; line-height:1; padding:0;
}
#wrapwrap .masivo__mas-menos:hover{ background: var(--tint,#F4ECF5) }
#wrapwrap .masivo__n{
  width:26px; border:0; text-align:center; font-size:var(--fs-2xs,.82rem);
  background:transparent; padding:0; font-variant-numeric:tabular-nums;
}
#wrapwrap .masivo__n:focus{ outline:none }
/* El botón se queda con lo que sobre —`flex:1 1 auto`—, así que el aire de la
   fila sale de aquí: cada píxel de padding lateral que gana `.masivo` se lo
   quita él. Es a propósito. En escritorio le quedan ~225 px para una palabra
   de ocho letras, de sobra. */
#wrapwrap .masivo__add{
  flex:1 1 auto; border:0; cursor:pointer; border-radius:100px;
  background: var(--lilac,#C69ED4); color:#fff;
  font-size:var(--fs-3xs,.72rem); letter-spacing:.09em; text-transform:uppercase;
  padding:.5rem .3rem; transition:.18s; min-width:0; white-space:nowrap;
}
#wrapwrap .masivo__add:hover{ background: var(--lilac-deep,#B487C6) }

/* «Agregar todo», en la barra de herramientas del listado */
#wrapwrap .btn-todo{
  border:1px solid var(--lilac,#C69ED4); background:transparent;
  color: var(--lilac-deep,#B487C6); border-radius:100px; cursor:pointer;
  font-size:var(--fs-3xs,.72rem); letter-spacing:.1em; text-transform:uppercase;
  padding:.45rem 1rem; margin-left:.4rem;
}
#wrapwrap .btn-todo:hover{ background:var(--lilac,#C69ED4); color:#fff }

/* La barra de selección: aparece abajo, fija, sólo con algo marcado. */
.selbar{
  position:fixed; left:50%; bottom:1.1rem; transform:translate(-50%, 140%);
  z-index:85; display:flex; align-items:center; gap:.8rem;
  background:var(--ink,#342A3B); color:var(--cream,#F7F3EE);
  border-radius:100px; padding:.6rem .7rem .6rem 1.3rem;
  box-shadow:0 18px 40px -18px rgba(40,20,50,.7);
  transition:transform .3s cubic-bezier(.2,.9,.3,1); max-width:calc(100vw - 2rem);
}
.selbar.is-on{ transform:translate(-50%, 0) }
.selbar__cuenta{ font-size:var(--fs-2xs,.82rem); letter-spacing:.04em; white-space:nowrap }
.selbar__limpiar{
  border:0; background:transparent; color:rgba(247,243,238,.7); cursor:pointer;
  font-size:var(--fs-3xs,.72rem); letter-spacing:.1em; text-transform:uppercase;
}
.selbar__limpiar:hover{ color:#fff }
.selbar__add{
  border:0; cursor:pointer; border-radius:100px; background:var(--lilac,#C69ED4); color:#fff;
  font-size:var(--fs-3xs,.72rem); letter-spacing:.1em; text-transform:uppercase;
  padding:.55rem 1.1rem; white-space:nowrap;
}
.selbar__add:hover{ background:#fff; color:var(--ink,#342A3B) }

/* La confirmación. Dice cuántas piezas, cuántos modelos y cuánto suman: con
   pedidos de mayoreo, preguntar «¿seguro?» sin decir el monto es una trampa. */
.confirmar{
  position:fixed; inset:0; z-index:130; display:grid; place-items:center;
  background:rgba(40,26,46,.5); backdrop-filter:blur(3px);
  opacity:0; visibility:hidden; transition:.24s; padding:1.2rem;
}
.confirmar.is-on{ opacity:1; visibility:visible }
.confirmar__panel{
  background:var(--cream,#F7F3EE); border-radius:20px; padding:1.9rem 1.8rem 1.5rem;
  max-width:26rem; width:100%; text-align:center;
  box-shadow:0 30px 60px -24px rgba(40,20,50,.55);
  transform:translateY(12px); transition:transform .24s;
}
.confirmar.is-on .confirmar__panel{ transform:none }
.confirmar__titulo{
  font-family:'Cormorant Garamond',Georgia,serif; font-weight:600;
  font-size:1.55rem; color:#6E5A85; margin:0 0 .5rem;
}
.confirmar__texto{ margin:0 0 1.2rem; color:var(--ink,#342A3B); font-size:var(--fs-xs,.92rem); line-height:1.55 }
.confirmar__nota{ color:var(--muted,#71667C); font-size:var(--fs-2xs,.82rem) }
.confirmar__barra{ height:4px; border-radius:4px; background:var(--soft,#EBDCEE); margin:0 0 1.1rem; display:none }
.confirmar__barra.is-on{ display:block }
.confirmar__barra span{ display:block; height:100%; border-radius:4px; background:var(--lilac-deep,#B487C6); width:0; transition:width .2s }
.confirmar__pies{ display:grid; grid-auto-flow:column; grid-auto-columns:1fr; gap:.7rem }
.confirmar__no,.confirmar__si{
  border-radius:100px; cursor:pointer; padding:.7rem 1rem;
  font-size:var(--fs-3xs,.72rem); letter-spacing:.1em; text-transform:uppercase;
}
.confirmar__no{ border:1px solid var(--line,#E9E0EC); background:transparent; color:var(--muted,#71667C) }
.confirmar__si{ border:0; background:var(--lilac-deep,#B487C6); color:#fff }
.confirmar__si[disabled]{ opacity:.6; cursor:default }

@media (max-width:640px){
  /* En teléfono la tarjeta mide 182 px y el cuerpo ya trae 8 px de padding,
     así que el aire lateral de la fila se pone corto —.35rem— y el resto se
     compensa apretando el −/+ y la letra del botón. Con la casilla fuera de
     la fila caben dos controles en vez de tres y la cuenta cierra; con tres
     no cerraba, y por eso el botón llegó a estar en 10 px. */
  #wrapwrap .masivo{ gap:.35rem; flex-wrap:nowrap; padding-left:.35rem; padding-right:.35rem }
  #wrapwrap .masivo__add{ font-size:11px; letter-spacing:.04em; padding:.5rem .25rem }
  #wrapwrap .masivo__mas-menos{ width:21px }
  #wrapwrap .masivo__n{ width:22px }
  #wrapwrap .oe_product_image > .masivo__sel{ top:.4rem; right:.4rem }
  #wrapwrap .oe_product_cart:has(.o_add_wishlist) .oe_product_image > .masivo__sel{ right:3rem }
  .selbar{ left:.7rem; right:.7rem; transform:translateY(140%); max-width:none; justify-content:space-between }
  .selbar.is-on{ transform:translateY(0) }
}

/* La tarjeta agotada no lleva controles sino este aviso, para que el hueco no
   quede vacío y las tarjetas de la fila sigan midiendo lo mismo. */
#wrapwrap .masivo--agotado{
  margin:.7rem 0 0; padding-top:.7rem; text-align:center;
  color: var(--muted,#71667C); font-size:var(--fs-3xs,.72rem);
  letter-spacing:.14em; text-transform:uppercase;
}

/* ── Las casillas de los atributos informativos ────────────────────────────

   En la ficha, Material / Piedra / Medida salían con una casilla al lado,
   como si fueran algo que elegir. No lo son: sus valores llevan la clase
   `no_variant`, o sea que marcarlas no cambia el producto, ni el precio, ni
   nada. Sólo confunden — el dato ya está, mejor puesto, en la tabla de la
   pieza que va arriba del botón.

   Se apagan por id de atributo (20 Material, 21 Piedra, 22 Medida) y NO el
   bloque entero, que es la parte importante: las piezas personalizadas usan
   ese mismo bloque para elegir tipografía, cantidad de letras o tipo de
   armado, y ésas sí son opciones de verdad. Apagar el bloque completo dejaría
   sin comprar los nombres y las iniciales.

   Se esconden con CSS y no se quitan del marcado a propósito: el JavaScript
   de Odoo (`js_variant_change`) lee esos inputs para armar la combinación. Si
   desaparecen del DOM, deja de encontrarlos. */
#wrapwrap li.variant_attribute[data-attribute-id="20"],
#wrapwrap li.variant_attribute[data-attribute-id="21"],
#wrapwrap li.variant_attribute[data-attribute-id="22"]{ display: none; }

/* Y si al esconderlas no queda ningún atributo de verdad, se va también el
   bloque: si no, deja un hueco de 1.5rem entre el precio y la tabla. */
#wrapwrap .o_wsale_product_details_content_section_attributes:not(:has(
  li.variant_attribute:not([data-attribute-id="20"]):not([data-attribute-id="21"]):not([data-attribute-id="22"])
)){ display: none; }

/* La tabla de la pieza pasa a ser la tarjeta lila de la parte de arriba.
   El tono que le gustaba al dueño estaba en el bloque de envíos, hasta el
   fondo de la columna donde casi nadie llega. Aquí arriba hace lo que un
   color tiene que hacer: llevar el ojo al dato que decide la compra. */
#wrapwrap .pieza-datos{
  margin: 0 0 1.4rem;
  padding: .9rem 1.1rem;
  background: var(--tint, #F7F1F8);
  border: 1px solid var(--line, #E9E0EC);
  border-radius: var(--radius, 14px);
}
#wrapwrap .pieza-datos__fila{ border-bottom-color: rgba(180, 135, 198, .28); }
#wrapwrap .pieza-datos dt{ color: var(--lilac-deep, #B487C6); }


/* ══ El corazón de favoritos ══════════════════════════════════════════════
   Odoo lo dibuja como un `.btn` de Bootstrap de 45×45 con `border-radius:100px`.
   El botón en sí no se ve —fondo transparente— pero al pasar el ratón Bootstrap
   le pinta su fondo de hover y aparece un círculo gris de 45 px alrededor de un
   corazón de 13: el círculo se lleva toda la atención y el corazón parece un
   accidente dentro.

   Aquí se invierte: fuera el círculo, y el corazón crece y se tiñe. El color de
   hover es nuestro lila, no el rojo de tienda de siempre — en una marca que ya
   es lila de arriba abajo, un rojo en la esquina de cada tarjeta se lee como un
   aviso de error, no como un «me gusta».

   Va con !important porque compite contra `.btn:hover` de Bootstrap, que gana
   por especificidad estando en su propia hoja. */
#wrapwrap .o_add_wishlist,
#wrapwrap .o_add_wishlist:hover,
#wrapwrap .o_add_wishlist:focus,
#wrapwrap .o_add_wishlist:active{
  width:auto !important; height:auto !important; padding:.5rem !important;
  background:transparent !important; border:0 !important; box-shadow:none !important;
}
#wrapwrap .o_add_wishlist .fa{
  font-size:1.25rem; line-height:1;
  transition:color .18s ease, transform .18s ease;
}
#wrapwrap .o_add_wishlist:hover .fa{ transform:scale(1.12) }

/* El color se pone en el ::before y no sólo en el elemento. Eso costó una
   pasada: teñir la <span> daba lila al medirlo y rojo al mirarlo, porque el
   corazón lo dibuja el pseudo-elemento de Font Awesome y Odoo le pinta ahí su
   propio rojo (#FF3D3A) al pasar el ratón. Mientras esa declaración exista, el
   color de la <span> no se ve. */
#wrapwrap .o_add_wishlist .fa,
#wrapwrap .o_add_wishlist .fa::before{ color:var(--ink,#342A3B) !important }
#wrapwrap .o_add_wishlist:hover .fa,
#wrapwrap .o_add_wishlist:hover .fa::before,
#wrapwrap .o_add_wishlist .fa-heart,
#wrapwrap .o_add_wishlist .fa-heart::before{
  color:var(--lilac-deep,#B487C6) !important;
}


/* ── El corazón de favoritos, retirado de la esquina ───────────────────────
   (Cambio pedido por el cliente, 28 sep 2026: «el corazón de favorita
   moverlo ya que sale recortado y a la orilla».)

   Odoo lo ancla en `top:0; right:0` dentro de `.o_wsale_product_btn`, que
   recorta con `overflow:hidden`, y encima la foto lleva 6.4 px de radio. Entre
   las dos cosas al corazón se le comía la esquina: de ahí «recortado», y de
   `right:0` venía «a la orilla».

   Arriba ya se había notado el problema —«pegado al borde», en el comentario
   de la casilla— pero se resolvió moviendo la casilla en vez del corazón.
   Ahora se mueve el corazón, que era lo que estorbaba, y los dos controles de
   la esquina comparten la misma sangría de .5rem.

   La casilla se corre en consecuencia: con el corazón ya dentro, 3.2rem la
   dejaba a 2 px de distancia en teléfono. */
#wrapwrap .oe_product_image > .o_wsale_product_btn > .o_add_wishlist{
  top:.5rem !important;
  right:.5rem !important;
}
#wrapwrap .oe_product_cart:has(.o_add_wishlist) .oe_product_image > .masivo__sel{
  right:3.7rem;
}
@media (max-width:767.98px){
  #wrapwrap .oe_product_cart:has(.o_add_wishlist) .oe_product_image > .masivo__sel{
    right:3.5rem;
  }
}

/* =========================================================================
   beaüra — portada, cambios de la llamada del 2026-10-05 (Ozcorp).
   Se suma después de beaura-diseno.css; no toca ese archivo.
   ========================================================================= */

/* a. Hero a media pantalla en teléfono. beaura-odoo.css lo fuerza a pantalla completa
      con `#wrapwrap section.hero { height: 100dvh !important }` en ≤767.98px; mismo
      selector y mismo corte para ganarle sin tocar ese archivo. */
@media (max-width: 767.98px) {
  #wrapwrap section.hero { height: 50svh !important; min-height: 340px !important; }
  .hero__sub { display: none; }
  .hero__content { padding-block: 1rem; }
  .hero__title { font-size: clamp(2rem, 9vw, 2.6rem); line-height: 1.05; margin-bottom: 0; }
  .hero__cta { flex-direction: row; gap: .6rem; margin-top: 1.1rem; }
  .hero__cta .btn { padding: .8rem 1rem; font-size: .72rem; flex: 1; }
}

/* b. Botón «Ver todas las colecciones» bajo los círculos. */
#categorias .section__foot { margin-top: 1.6rem; text-align: center; }

/* c. «Lo más vendido» como carrusel. */
#destacados .bs-carousel { position: relative; }
#destacados #productGrid {
  display: flex; gap: 1.6rem;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: 2px;
  scrollbar-width: none; padding-bottom: .4rem;
}
#destacados #productGrid::-webkit-scrollbar { display: none; }
#destacados #productGrid > * { flex: 0 0 calc((100% - 3 * 1.6rem) / 4); scroll-snap-align: start; }
@media (max-width: 1100px) {
  #destacados #productGrid > * { flex-basis: calc((100% - 2 * 1.6rem) / 3); }
}
@media (max-width: 760px) {
  #destacados #productGrid { gap: 1rem; }
  /* una tarjeta y media: que se note que hay más a la derecha */
  #destacados #productGrid > * { flex-basis: 62%; }
}
.bs-arrow {
  position: absolute; top: 38%; z-index: 2;
  width: 2.6rem; height: 2.6rem; border-radius: 50%;
  border: 1px solid rgba(110, 90, 133, .25); background: #fff; color: #6e5a85;
  font-size: 1.5rem; line-height: 1; cursor: pointer;
  box-shadow: 0 6px 18px -8px rgba(110, 90, 133, .45);
}
.bs-arrow--prev { left: -1.3rem; }
.bs-arrow--next { right: -1.3rem; }
.bs-arrow:focus-visible { outline: 2px solid #c56e90; outline-offset: 2px; }
@media (max-width: 760px) { .bs-arrow { display: none; } }

/* h. Kit Destello en la portada: un solo kit, centrado. */
#kitsHome .kits--home { display: block; max-width: 480px; margin: 0 auto; padding: 0; }
#kitsHome .kits--home .kit { margin: 0 auto; }
/* En /kits las piezas que salen de la bolsa tienen aire arriba; aquí se encimaban
   sobre el título de la sección y ensanchaban la página. Se quedan en la tarjeta. */
#kitsHome .kits--home .kit__stage { overflow: hidden; }

/* Newsletter: mensaje después de enviar (formulario de la portada y ventana de bienvenida). */
.news__msg { margin-top: .9rem; font-size: .95rem; text-align: center; color: inherit; }
.promo .news__msg { text-align: left; }

/* i. Reseñas reales: capturas de WhatsApp de clientas, en mosaico. */
#resenas .revs__grid--wa { display: block; columns: 3 260px; column-gap: 1.2rem; }
#resenas .wa-msg { break-inside: avoid; margin: 0 0 1.2rem; border-radius: 14px; overflow: hidden;
  background: #efeae2; box-shadow: 0 10px 28px -16px rgba(110, 90, 133, .45); }
#resenas .wa-msg img { display: block; width: 100%; height: auto; }
@media (max-width: 767.98px) {
  /* en teléfono, una fila que se desliza: once capturas en columna serían eternas */
  #resenas .revs__grid--wa { display: flex; columns: auto; gap: 1rem; overflow-x: auto;
    scroll-snap-type: x mandatory; scrollbar-width: none; padding-bottom: .4rem; align-items: flex-start; }
  #resenas .revs__grid--wa::-webkit-scrollbar { display: none; }
  #resenas .wa-msg { flex: 0 0 78%; margin: 0; scroll-snap-align: center; }
}
