/* Hoja del PANEL del asesor. Externa y no en línea, y por una medición: el
   parcial mandaba 26 KB de CSS (8 KB comprimidos) dentro del HTML de CADA
   página, y el panel no existe hasta que alguien pulsa el orbe. Un byte
   pagado en el primer pintado para algo que puede no abrirse nunca es LCP
   regalado.

   Lo que SÍ sigue en línea, en `_asesor_widget.html`, es el lanzador y su
   saludo: eso se pinta arriba del pliegue desde el primer paint, y sacarlo
   movería el orbe de sitio después de pintar — un CLS que ya se pagó una vez
   y no se vuelve a pagar.

   Mismo patrón que `plum.css` (preload + swap): no bloquea el primer pintado
   y llega mucho antes de que nadie pulse nada.

   Generada desde el parcial el 2026-08-20. El corte está en
   `.asr__panel[hidden]`, la primera regla que sólo aplica con el panel
   abierto; de ahí hacia abajo no hay una sola regla del lanzador. */
/* ── Panel ───────────────────────────────────────────────────────────────── */

.asr__panel[hidden]{display:none}
/* El `[hidden]` de arriba NO es redundante: un `display` de autor GANA al
   atributo, y con `display:flex` el panel se quedaba abierto desde que carga la
   página aunque el HTML dijera `hidden`. Medido: `hidden=true` y
   `display:flex`, 377px de alto. Esta trampa ya mordió cuatro veces en este
   repo — se comprueba el display CALCULADO, nunca el atributo. */
/* El alto descuenta las barras fijas de ARRIBA, no sólo los márgenes.
   Medido a 1280x700 con la conversación crecida: el panel llegaba a 668px de
   alto, o sea a `top:16`, y el nav —que va de 34 a 78 y pinta con z-index
   1000— le tapaba el título. Un panel de chat cuyo encabezado desaparece
   detrás de la navegación no es un detalle de maqueta: es no saber qué
   ventana estás mirando ni dónde está su botón de cerrar.
   `--asr-arriba` es el borde inferior de esas barras, y lo mide el JS porque
   ninguna de las dos tiene alto fijo. Sin JS vale 0 y manda el margen de
   siempre. */
.asr__panel{position:fixed;right:1rem;bottom:1rem;width:min(408px,calc(100vw - 2rem));
  max-height:min(680px,calc(100dvh - var(--asr-arriba,0px) - 2rem));
  display:flex;flex-direction:column;
  background:var(--pl-surface-0);border:0;
  border-radius:var(--pl-radius-xl,20px);overflow:hidden;z-index:1100;
  /* Elevación, sin borde. Un panel flotante es un objeto POR ENCIMA de la
     página, y decirlo con las dos cosas a la vez —un pelo de 1px más un halo
     de 60px— no decía ninguna. Se elige la elevación y se le da
     desplazamiento real.
     En oscuro no queda un borde que lo separe, así que se separa por luz: el
     panel sube un escalón de superficie sobre la página. Es lo mismo que hace
     el resto del sistema, y no depende de una línea de 1px que en oscuro casi
     no se ve. */
  box-shadow:0 18px 38px rgba(var(--pl-shadow-brand-rgb,124,58,237),.20),
             0 2px 8px rgba(0,0,0,.06)}
[data-theme="dark"] .asr__panel{background:var(--pl-surface-1)}

/* En el teléfono el asesor ocupa todo el ancho y todo el alto QUE HAY: de
   debajo de la barra de navegación hasta encima de la barra de pagar. Las dos
   siguen viéndose y siguen pulsándose — decisión del dueño (2026-08-19), y es
   lo que la tienda necesita: el carrito y el botón de pagar no pueden
   desaparecer porque alguien abrió el chat.

   El hueco NO se puede escribir a mano en el CSS: la barra de pagar sólo
   existe cuando hay algo en el carrito, y la de navegación cambia de alto al
   bajar la página. Lo mide `asesor.js` al abrir y lo deja en `--asr-arriba` y
   `--asr-abajo`. Si esa medida no llega, los dos valen 0 y el panel ocupa la
   pantalla entera: se ve raro, pero se usa.

   Dos detalles que no son adorno:

   · `100dvh`, no `100vh`: con la barra del navegador a la vista, `vh` mide de
     más y el campo de escribir se queda debajo del borde.
   · El borde seguro (`env(safe-area-inset-*)`) sólo hace falta del lado que
     TOQUE el filo de la pantalla. Si ya hay una barra en medio, ella se ocupa
     del suyo, y sumarlo otra vez son 34px de aire en un panel que se pelea
     por cada línea — de ahí el `calc()` que le resta el hueco. */
@media (max-width:767.98px){
  /* `--asr-top` y `--asr-alto` sólo existen mientras el teclado está abierto:
     ahí el panel se ancla al viewport VISUAL, porque iOS empuja el de la
     página hacia arriba y se lleva con él todo lo que sea `position:fixed`.
     Sin teclado no están declaradas y mandan los respaldos de siempre, que es
     el hueco entre la barra de navegación y la de pagar. */
  .asr__panel{
    left:0;right:0;width:auto;max-height:none;border:0;border-radius:0;
    top:var(--asr-top, var(--asr-arriba,0px));bottom:auto;
    height:var(--asr-alto,
      calc(100dvh - var(--asr-arriba,0px) - var(--asr-abajo,0px)))}
  .asr__panel .asr__cab{
    padding-top:max(1rem,calc(env(safe-area-inset-top,0px) - var(--asr-arriba,0px)))}
  .asr__panel .asr__forma{
    padding-bottom:max(1rem,calc(env(safe-area-inset-bottom,0px) - var(--asr-abajo,0px)))}

  /* Con el panel tapando la pantalla, el dedo no puede mover la página de
     detrás: el `overflow:hidden` de la raíz deja el documento sin scroll de
     usuario. Ojo al comprobarlo — un `window.scrollBy()` SIGUE funcionando
     por especificación aunque la raíz esté en `hidden`, así que medirlo así
     da un falso «no funciona». Lo que se comprueba es el `overflow` calculado
     de la raíz, y el gesto real. */
  html.asr-abierto, html.asr-abierto body{overflow:hidden}
}

.asr__cab{display:flex;align-items:center;gap:.7rem;
  padding:.85rem 1.1rem;border-bottom:1px solid var(--pl-border);
  background:var(--pl-surface-1)}
.asr__avatar{flex:none;display:flex;align-items:center;justify-content:center;
  width:34px;height:34px;border-radius:50%;
  background:var(--pl-brand);color:var(--pl-brand-on,#fff)}
.asr__cab-txt{display:flex;flex-direction:column;gap:.1rem;min-width:0;flex:1}
.asr__titulo{margin:0;font-family:var(--pl-font-display,inherit);
  font-size:1.02rem;font-weight:600;letter-spacing:-.02em;color:var(--pl-ink)}
/* `ink-soft`, no `faint`: esto DECLARA que del otro lado hay un modelo, y una
   declaración no es metadato decorativo. */
/* 12.8px y no 11.84: por debajo de 12 el texto deja de leerse en pantallas de
   alta densidad. Y dice sólo lo que tiene que decir — la versión larga
   («precios y existencia de la tienda») no cabía en los 408px del panel y se
   cortaba con puntos suspensivos; eso ya lo cuenta el primer mensaje. */
.asr__cab-sub{font-size:.8rem;line-height:1.3;color:var(--pl-ink-soft);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.asr__cerrar{display:flex;align-items:center;justify-content:center;
  width:36px;height:36px;border:0;border-radius:var(--ico-radio,50%);background:transparent;
  color:var(--pl-ink-soft);cursor:pointer;transition:background .15s ease}
.asr__cerrar:hover{background:var(--pl-surface-2);color:var(--pl-ink)}
.asr__cerrar:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}

.asr__hilo{flex:1;overflow-y:auto;padding:1rem 1.1rem;display:flex;
  flex-direction:column;gap:.85rem;overscroll-behavior:contain}
/* Lo que dice el asesor va en burbuja, como lo que dice el cliente. Antes era
   un párrafo suelto contra el fondo del panel: con tarjetas y tablas de por
   medio se leía como texto de la página, no como el turno de alguien. La
   esquina viva es la de abajo-izquierda, espejo de `.asr__pide`. */
.asr__dice{margin:0;align-self:flex-start;max-width:92%;
  padding:.6rem .85rem;border-radius:14px 14px 14px 4px;
  background:var(--pl-surface-1);border:1px solid var(--pl-border);
  font-size:.94rem;line-height:1.55;color:var(--pl-ink)}
.asr__pide{margin:0;align-self:flex-end;max-width:85%;padding:.5rem .8rem;
  border-radius:14px 14px 4px 14px;background:var(--pl-brand-soft);
  color:var(--pl-ink);font-size:.9rem;line-height:1.45}

.asr__sugerencias{display:flex;flex-wrap:wrap;gap:.4rem}
.asr__sug{display:inline-flex;align-items:center;min-height:var(--cta-alto-sm,36px);
  padding:0 .75rem;border:1px solid var(--pl-border-strong);
  border-radius:var(--cta-radio,10px);background:transparent;color:var(--pl-ink-soft);
  font-size:.82rem;cursor:pointer;transition:border-color .15s ease,color .15s ease}
.asr__sug:hover{border-color:var(--pl-brand);color:var(--pl-brand)}
.asr__sug:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}
/* En el teléfono los chips suben a 44px y su texto a 14: son lo PRIMERO que
   se toca en toda la conversación —quien abre el asesor y no sabe qué
   escribir pulsa uno— y a 36px con letra de 13 quedaban por debajo del blanco
   mínimo del pulgar que usa el resto del sitio. */
@media (max-width:767.98px){
  .asr__sug{min-height:var(--cta-alto,44px);font-size:.875rem;padding:0 .9rem}
  /* Y el cuerpo del hilo a 16px, que es el mínimo de lectura en móvil que
     fija el propio producto. */
  .asr__dice,.asr__pide{font-size:1rem}
}

/* ── Fichas ──────────────────────────────────────────────────────────────── */
.asr__fichas{display:flex;flex-direction:column;gap:.5rem}
.asr__ficha{display:flex;gap:.75rem;align-items:center;padding:.6rem;
  border:1px solid var(--pl-border);border-radius:var(--pl-radius-lg,14px);
  background:var(--pl-surface-1);color:inherit;text-decoration:none;
  transition:border-color .15s ease,transform .15s cubic-bezier(.2,.8,.3,1)}
.asr__ficha:hover{border-color:var(--pl-brand);transform:translateX(2px)}
.asr__ficha:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}
.asr__foto{flex:none;width:56px;height:56px;display:flex;align-items:center;
  justify-content:center;border-radius:10px;background:var(--pl-surface-2);
  overflow:hidden}
.asr__foto img{max-width:100%;max-height:100%;object-fit:contain}
.asr__datos{min-width:0;display:flex;flex-direction:column;gap:.15rem}
.asr__nombre{font-size:.86rem;font-weight:600;line-height:1.3;color:var(--pl-ink);
  overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical}
.asr__spec{font-size:.75rem;color:var(--pl-ink-soft);white-space:nowrap;
  overflow:hidden;text-overflow:ellipsis}
.asr__precio{font-size:.92rem;font-weight:700;color:var(--pl-brand);
  font-variant-numeric:tabular-nums}

/* ── Carrusel de producto (variante D, elegida el 2026-08-19) ───────────────
   Foto arriba, nombre, chips de specs, y un pie con el precio a la izquierda
   y dos botones circulares a la derecha. Sin contador de vendidos: el dueño
   lo quitó al elegir este diseño.

   `flex:none` en la caja NO es decoración: `[data-asesor-hilo]` es una
   columna flex y un hijo con `overflow-x` se encoge hasta su borde. Ya pasó
   con la tabla comparativa — salió de 2px de alto con 422 dentro. */
/* La caja tiene `tabindex` y `role=group` desde el JS: con el ratón se arrastra
   y se desliza, pero con teclado no había forma de llegar a la cuarta tarjeta
   sin tabular por todos los botones de las tres primeras. Con foco propio,
   ← y → mueven de tarjeta en tarjeta. */
.asr__carrusel{position:relative;flex:none;overflow-x:auto;overflow-y:hidden;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x mandatory;
  scrollbar-width:none;margin:0 -1.1rem;padding:0 1.1rem;
  scroll-padding-left:1.1rem}
.asr__carrusel::-webkit-scrollbar{display:none}
.asr__carrusel:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px;
  border-radius:var(--pl-radius-lg,14px)}
.asr__pista{display:flex;gap:.75rem;width:max-content}

/* ── Flechas del carrusel (ratón) ─────────────────────────────────────────
   Van en la MISMA fila que los puntos, una a cada lado: ‹ · · · · · ›. Antes
   estaban en su propia fila alineadas a la derecha, y eran dos controles del
   mismo carrusel en dos sitios distintos — el ojo tenía que buscar el segundo.
   Juntos son un solo mando y ocupan una fila menos en un panel que se pelea
   por cada línea.

   Sólo donde hay puntero fino: en el teléfono se arrastra con el dedo y la
   flecha sería un blanco que estorba. No aparecen al pasar el ratón —un
   control que hay que descubrir moviendo el ratón no se descubre— sino que
   están, y se apagan al llegar al extremo. */
.asr__flecha{display:none}
@media (hover:hover) and (pointer:fine){
  .asr__flecha{display:flex;align-items:center;justify-content:center;
    flex:none;width:28px;height:28px;border:1px solid var(--pl-border-strong);
    border-radius:50%;background:var(--pl-surface-0);color:var(--pl-ink-soft);
    cursor:pointer;transition:background .15s ease,color .15s ease,
                              border-color .15s ease,opacity .15s ease}
  .asr__flecha:hover{background:var(--pl-surface-2);color:var(--pl-ink);
    border-color:var(--pl-brand)}
  .asr__flecha:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}
  /* Apagada, no escondida: que el borde siga ahí es lo que dice «llegaste al
     final» en vez de dejar un hueco que parece un fallo de maqueta. */
  .asr__flecha[disabled]{opacity:.4;cursor:default;
    border-color:var(--pl-border);color:var(--pl-ink-faint)}
}

/* ── Agarrar y arrastrar ──────────────────────────────────────────────────
   La mano dice que se puede arrastrar antes de intentarlo; sin ella el gesto
   existe pero nadie lo prueba. Sólo con puntero fino: en táctil el arrastre
   nativo ya funciona y la mano no se ve. */
@media (hover:hover) and (pointer:fine){
  /* `user-select` apagado SIEMPRE, no sólo mientras se arrastra: la clase
     `is-arrastrando` llega a los 5px, y en esos primeros píxeles el navegador
     ya empezó a seleccionar el nombre del equipo. El gesto acababa moviendo
     el carrusel con media tarjeta pintada de azul. */
  .asr__carrusel{cursor:grab;user-select:none;-webkit-user-select:none}
  .asr__carrusel.is-arrastrando{cursor:grabbing;
    /* Mientras la mano tira, el enganche se apaga: con `mandatory` puesto el
       navegador pelea contra el arrastre y la tira da tirones. Vuelve al
       soltar, y entonces engancha a la tarjeta más cercana. */
    scroll-snap-type:none}
  .asr__carrusel.is-arrastrando img{pointer-events:none}
}

/* 240px deja asomar la siguiente tarjeta dentro del panel de 360: sin ese
   trozo visible nadie sabe que hay más y el tercer equipo no se ve nunca. */
.asr__tarj{flex:none;width:240px;scroll-snap-align:start;
  display:flex;flex-direction:column;
  border:1px solid var(--pl-border);border-radius:var(--pl-radius-lg,14px);
  background:var(--pl-surface-1);overflow:hidden}
.asr__tarj-cuerpo{display:flex;flex-direction:column;gap:.4rem;padding:.6rem;
  color:inherit;text-decoration:none;flex:1 1 auto}
.asr__tarj-cuerpo:focus-visible{outline:2px solid var(--pl-brand);
  outline-offset:-2px}
/* Blanco PURO, no el gris de superficie: la foto va con su fondo original
   —el del catálogo, sin recortar— y ese fondo es blanco. Sobre `surface-2`
   se veía el rectángulo de la foto recortado contra el gris de la tarjeta. */
.asr__tarj-foto{display:flex;align-items:center;justify-content:center;
  aspect-ratio:4/3;border-radius:10px;background:#fff;overflow:hidden}
.asr__tarj-foto img{max-width:100%;max-height:100%;object-fit:contain}
.asr__nombre{margin:0;font-size:.86rem;font-weight:600;line-height:1.3;
  color:var(--pl-ink);overflow:hidden;display:-webkit-box;-webkit-line-clamp:2;
  -webkit-box-orient:vertical}
.asr__chips{display:flex;flex-wrap:wrap;gap:.25rem}
.asr__chip{font-size:.7rem;line-height:1.4;padding:.1rem .4rem;
  border-radius:6px;background:var(--pl-surface-2);color:var(--pl-ink-soft);
  max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* El pie: precio a la izquierda, acciones a la derecha, siempre al fondo de
   la tarjeta aunque el nombre ocupe una línea o dos. */
.asr__pie{display:flex;align-items:center;justify-content:space-between;
  gap:.4rem;padding:.5rem .6rem;border-top:1px solid var(--pl-border);
  background:var(--pl-surface-2)}
.asr__pie-precio{display:flex;flex-direction:column;min-width:0}
.asr__precio{font-size:.95rem;font-weight:700;color:var(--pl-brand);
  font-variant-numeric:tabular-nums;line-height:1.2}
.asr__itbis{font-size:.65rem;color:var(--pl-ink-soft);line-height:1.3}

/* 48px, no 40. Las cinco variantes que devolvió Stitch incumplían su propio
   mínimo de 44 —la peor traía un botón de 24px— y esto se usa con el pulgar. */
.asr__iconos{display:flex;gap:.35rem;flex:none}
.asr__ico{display:inline-flex;align-items:center;justify-content:center;
  width:48px;height:48px;border-radius:999px;cursor:pointer;
  border:1px solid var(--pl-brand);background:var(--pl-surface-0);
  color:var(--pl-brand);text-decoration:none;
  transition:background-color .15s ease,color .15s ease,border-color .15s ease}
.asr__ico--carrito{background:var(--pl-brand);border-color:var(--pl-brand);
  color:var(--pl-surface-0)}
.asr__ico:hover{filter:brightness(1.06)}
.asr__ico:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}
.asr__ico:disabled{cursor:default}
.asr__ico.is-agregado{background:var(--pl-ok,#15694a);
  border-color:var(--pl-ok,#15694a);color:#fff}
.asr__ico.is-error{background:var(--pl-surface-0);
  border-color:var(--pl-danger,#b3261e);color:var(--pl-danger,#b3261e)}

/* Los puntos son botones de verdad —se pueden pulsar y enfocar—, con el área
   táctil por dentro: el punto se ve de 6px pero se toca en 24. */
.asr__puntos{display:flex;justify-content:center;align-items:center;
  gap:.15rem;flex:none}
/* La fila del mando: flecha, puntos, flecha. El hueco es mayor que el que
   separa los puntos entre sí para que se lean como tres piezas y no como una
   ristra. */
.asr__mando{display:flex;align-items:center;justify-content:center;
  gap:.6rem;flex:none}
.asr__punto{width:24px;height:24px;padding:0;border:0;background:none;
  cursor:pointer;display:inline-flex;align-items:center;justify-content:center}
.asr__punto::before{content:"";width:6px;height:6px;border-radius:999px;
  background:var(--pl-border);transition:background-color .15s ease}
.asr__punto.is-aqui::before{background:var(--pl-brand)}
.asr__punto:focus-visible{outline:2px solid var(--pl-brand);outline-offset:0}

/* Los filtros que están puestos ahora mismo. Van DEBAJO de los equipos, en
   voz baja: son la explicación de por qué salen estos y no otros, no el
   titular de la respuesta. */
.asr__filtros{margin:0;font-size:.72rem;color:var(--pl-ink-soft);
  padding:.35rem .6rem;border-radius:999px;background:var(--pl-surface-2);
  align-self:flex-start}

.asr__elegir{align-self:flex-start;min-height:var(--cta-alto-sm,36px);
  padding:.3rem .7rem;border:1px solid var(--pl-border);
  border-radius:999px;background:var(--pl-surface-0);color:var(--pl-ink-soft);
  font:inherit;font-size:.78rem;cursor:pointer;
  transition:border-color .15s ease,color .15s ease}
.asr__elegir:hover{border-color:var(--pl-brand);color:var(--pl-brand)}
.asr__elegir:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}

/* Enlace que acompaña una respuesta de conocimiento (hoy, la landing de
   financiamiento). Sólo aparece cuando el servidor lo manda, y el servidor
   sólo lo manda si esa landing está viva. */
.asr__enlace{display:inline-flex;align-items:center;gap:.35rem;
  min-height:var(--cta-alto-sm,36px);padding:.3rem .7rem;border-radius:999px;
  border:1px solid var(--pl-brand);color:var(--pl-brand);font-size:.78rem;
  font-weight:600;text-decoration:none}
.asr__enlace:hover{background:var(--pl-brand);color:var(--pl-surface-0)}
.asr__enlace:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}

.asr__forma{display:flex;gap:.5rem;padding:.85rem 1.1rem 1rem;
  border-top:1px solid var(--pl-border);background:var(--pl-surface-0)}
.asr__entrada{flex:1;min-width:0;min-height:var(--cta-alto,44px);padding:0 .9rem;
  border:1px solid var(--pl-border-strong);border-radius:var(--cta-radio,10px);
  background:var(--pl-surface-1);color:var(--pl-ink);font-size:.92rem}
/* 16px CLAVADOS en el teléfono, y no `.92rem` heredando de la raíz.
   Safari de iOS hace zoom sobre cualquier campo por debajo de 16px al
   enfocarlo, y ese zoom no se deshace al salir: la tienda se queda ampliada.
   Hoy el `.92rem` da 16px de casualidad —porque la raíz de este sistema mide
   más de 16— y el día que alguien afine la escala tipográfica vuelve el
   zoom sin que nadie relacione una cosa con la otra.
   La otra salida conocida —`user-scalable=no` en el viewport— apaga el zoom
   de TODA la página y eso incumple WCAG 1.4.4. */
@media (max-width:767.98px){
  .asr__entrada{font-size:16px}
}
.asr__entrada::placeholder{color:var(--pl-ink-faint)}
.asr__entrada:focus{outline:2px solid var(--pl-brand);outline-offset:1px;
  border-color:var(--pl-brand)}
.asr__enviar{flex:none;width:var(--cta-alto,44px);height:var(--cta-alto,44px);display:flex;align-items:center;
  justify-content:center;border:0;border-radius:var(--ico-radio,50%);background:var(--pl-brand);
  color:var(--pl-brand-on,#fff);cursor:pointer;transition:background .15s ease}
.asr__enviar:hover{background:var(--pl-brand-hover)}
.asr__enviar:disabled{opacity:.55;cursor:default}
.asr__enviar:focus-visible{outline:2px solid var(--pl-brand);outline-offset:2px}

/* Estado de espera: tres puntos, sin librería y sin spinner genérico. */
.asr__espera{display:inline-flex;gap:.28rem;align-items:center;padding:.2rem 0}
.asr__espera i{width:6px;height:6px;border-radius:50%;background:var(--pl-ink-faint);
  animation:asrLatir 1.1s ease-in-out infinite}
.asr__espera i:nth-child(2){animation-delay:.15s}
.asr__espera i:nth-child(3){animation-delay:.3s}
@keyframes asrLatir{0%,60%,100%{opacity:.28;transform:translateY(0)}
                    30%{opacity:1;transform:translateY(-3px)}}

.asr__error{margin:0;font-size:.88rem;line-height:1.5;color:var(--pl-err)}

@media (prefers-reduced-motion:reduce){
  .asr__lanzador,.asr__ficha{transition:none}
  .asr__lanzador:hover,.asr__ficha:hover{transform:none}
  .asr__espera i{animation:none;opacity:.5}
}
