=== SupuBot ===
Contributors: supubot
Tags: woocommerce, chatbot, ia, leads, asesor, ventas
Requires at least: 5.8
Tested up to: 6.7
Requires PHP: 7.4
Stable tag: 1.20.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Asistente técnico-comercial con IA, configurable por cliente. Diagnostica necesidades, recomienda productos, captura leads cualificados dentro de WordPress y permite exportarlos en CSV/Excel. Sin CRM externo.

== Description ==

SupuBot es un producto reutilizable para distintos clientes. Añade a tu WordPress/WooCommerce un asesor conversacional que:

* Diagnostica la necesidad del cliente según el sector y catálogo configurados.
* Hace preguntas útiles y recomienda con prudencia (respeta las reglas comerciales del cliente: no inventar precios, stock ni compatibilidades sin datos).
* Detecta la oportunidad comercial y asigna un nivel (baja / media / alta).
* Genera un resumen interno para el asesor y captura el lead en menos de 3 clics.
* Guarda todo dentro de WordPress: nada de CRM ni herramientas externas.
* Exporta leads y conversaciones a CSV, con corpus anonimizado para analizar preguntas y mejorar la base de conocimiento.

= Multi-cliente =
Toda la marca y las reglas se configuran en **SupuBot → Ajustes**: nombre de empresa, sector, descripción, productos, reglas comerciales, responsable, comisión, email de aviso, nombre visible del asistente, mensajes, CTAs, botones, colores, posición y logo. No hay ningún dato de cliente hardcodeado en el código.

= Proveedores IA =
Configurable: OpenAI o Gemini. Las claves API se guardan en el servidor y nunca se exponen en el frontend.

= WooCommerce opcional =
Si WooCommerce está activo, SupuBot detecta el contexto del producto (ID, nombre, SKU, categoría, URL, formato, precio público/stock según ajustes). Si NO está activo, SupuBot no se rompe y sigue funcionando como chat IA normal que capta leads.

= Seguridad y anti-spam =
Nonce de WordPress con renovación automática para páginas en caché, honeypot, rate limit por IP, límites diarios de consultas IA por IP y por sitio, límite de mensajes por sesión, límite de leads por IP/día, validación de email y teléfono, bloqueo de mensajes repetidos, sanitización de entradas, escape de salidas, consultas SQL preparadas y Cloudflare Turnstile opcional. La IP no se almacena en claro: se guarda un hash anonimizado. Las cabeceras de IP real solo se aceptan desde redes de proxy confiables.

= Privacidad =
SupuBot añade texto sugerido a la guía de política de privacidad de WordPress e integra sus leads y conversaciones con las herramientas nativas de exportación y borrado de datos personales por email. El texto informa del envío de contexto a OpenAI o Gemini, de Turnstile, de sessionStorage y de la conservación de datos; el responsable del sitio debe adaptarlo a su tratamiento real.

== Installation ==

1. Sube la carpeta `supubot` a `/wp-content/plugins/`.
2. Activa el plugin desde el menú Plugins de WordPress.
3. Ve a **SupuBot → Ajustes** y configura el cliente (empresa, sector, reglas), el proveedor IA y su clave API, y la personalización del widget.
4. (Opcional) Añade entradas en **SupuBot → Base de conocimiento** para que las respuestas usen datos reales.

== Menú de administración ==

SupuBot → Dashboard · Leads · Conversaciones · Base de conocimiento · Exportar · Ajustes.

== Endpoints REST ==

* POST /wp-json/supubot/v1/chat
* POST /wp-json/supubot/v1/lead
* GET  /wp-json/supubot/v1/product-context

== Changelog ==

= 1.20.0 =
* La IA ve las características reales de cada producto (medidas, material, adhesivo, eje…) en la ficha que se está viendo y en el catálogo que consulta. Así deja de suponer datos técnicos.
* Si el cliente acepta («sí», «vale», «perfecto»…) la oferta de enviar su consulta, se abre el formulario al momento. El botón principal también abre el formulario directamente. Antes, algunas consultas aceptadas nunca llegaban al equipo.
* Cuando el asistente ofrece enviar la consulta, el botón del formulario aparece siempre el primero.
* El filtro de promesas falsas detecta también «procedo a enviar», «envío la solicitud» y «he añadido … a tu consulta».
* Medidas: los seguimientos del tipo «10 rollos de cada medida» conservan las medidas dichas antes, y la lista automática solo muestra productos con la medida pedida.
* La lista automática de productos solo sustituye a la IA cuando falla, niega tener datos que sí existen o no enseña ningún producto ante una pregunta de precio.
* El enlace automático de la base de conocimiento exige que el tema esté en el título o la categoría de la entrada.
* El chat reintenta con un nonce nuevo también cuando WordPress lo rechaza («Ha fallado la comprobación de la cookie»). Antes, una página en caché de más de un día dejaba el chat sin funcionar.
* Nuevas reglas generales para la IA: no cambiar los datos que da el cliente, respetar lo que ya eligió, no inventar proveedores ni referencias y no decir «no falta nada» si falta algún dato.

= 1.19.0 =
* Modo gratis y modo premium. Sin licencia SupuBot funciona con límites: 50 conversaciones con IA al mes, 10 entradas en la base de conocimiento y el aviso «Con la tecnología de SupuBot» en el chat.
* Con trial o licencia activa se desbloquea todo: catálogo WooCommerce (búsqueda de productos, tarjetas con precio y stock, página de producto y vocabulario del cliente), nivel de oportunidad y resumen para el asesor, aviso por email de cada lead, exportación a CSV/Excel, marca propia (logo, avatar, icono, colores y posición), estadísticas comerciales, plantillas por sector y actualizaciones automáticas.
* Al agotar las conversaciones del mes el chat no da error: ofrece el formulario para que el equipo responda. Las conversaciones ya empezadas continúan.
* Nunca se borra nada: sin licencia los leads y conversaciones siguen visibles, lo ya creado sigue funcionando y la marca configurada se conserva y vuelve a aplicarse al activar. Seguridad, anti-spam y RGPD nunca se limitan.
* Las funciones con licencia se marcan con la etiqueta PRO en el panel, con enlace a SupuBot → Licencia.
* Importante: las webs que ya usan SupuBot deben activar su licencia antes de actualizar a esta versión para no perder el catálogo ni los avisos por email.

= 1.18.0 =
* Actualizaciones automáticas desde SupuHub: con una licencia activa, las nuevas versiones de SupuBot aparecen en Escritorio → Actualizaciones y se instalan con un clic, como cualquier plugin.
* Nueva pantalla SupuBot → Licencia: activar, comprobar estado y desactivar la clave; muestra estado, caducidad, dominio y sitios en uso.
* SupuBot sigue funcionando al 100 % con o sin licencia: la licencia solo da acceso a las actualizaciones. Si caduca, se ve que hay versión nueva y el motivo, pero nada del chat, los leads ni el catálogo se bloquea.
* La clave se guarda cifrada y nunca se muestra entera. Si SupuHub no responde, se mantiene el último estado conocido y se reintenta sin afectar al escritorio.
* Compatibilidad: no cambia tablas ni ajustes existentes. Esta versión se instala a mano una última vez; las siguientes llegarán solas.

= 1.17.5 =
* Cloudflare Turnstile: si el formulario del chat mide menos de 300 px (el mínimo del tamaño flexible de Cloudflare), se usa el tamaño compacto centrado en lugar de salirse por la derecha. Solo CSS/JavaScript.

= 1.17.4 =
* Respuestas automáticas solo con coincidencia clara: el botón de producto del catálogo y la lista automática de precios ya no se generan cuando solo una palabra de la consulta casa con el producto (antes, "tintero para MEDS16" mostraba bolsas de aire y "precio de etiquetas impresas con mi diseño" listaba etiquetadoras). La IA sigue recibiendo esos candidatos y decide con criterio.
* Las consultas de soporte técnico (averías, errores) nunca reciben un botón automático de producto.

= 1.17.3 =
* Buscador: cuando el cliente indica una medida y existen productos con esa medida exacta, solo se consideran esos. Antes, "¿cuánto vale la caja de bolsas de vacío 35x50?" podía mostrar bolsas de aire (sin medida) en lugar de la bolsa de vacío 35 x 50.
* Las medidas con unidades entre los números ("110 mm x 300 m", "45m x 30 mm") se reconocen igual que "110x300".

= 1.17.2 =
* Corrección: "Vale" como asentimiento ("Vale, ¿entonces ya está registrada mi consulta?") ya no se interpreta como pregunta de precio. Antes podía responder con una lista de productos del contexto anterior en lugar de contestar a la pregunta. "¿Cuánto vale…?", "¿Qué valen…?" y "vale la caja" siguen detectándose como precio.

= 1.17.1 =
* Sin promesas de contacto falsas: si la IA dice en el chat que la consulta "ha quedado registrada" o que "un asesor te escribirá" sin que el visitante haya enviado el formulario, el servidor quita esa frase, ofrece enviar la consulta y abre el formulario. Antes, algunos visitantes esperaban una respuesta que nunca llegaba porque no se había creado el lead.
* Buscador de catálogo más preciso con frases reales: las palabras de conversación ("venden", "tenéis", "hola") ya no vacían la búsqueda; las palabras obligatorias se eligen entre las que existen en el catálogo; se buscan parejas de palabras ("cinta transparente", "papel regalo") y medidas escritas con espacios ("100 x 70 mm"); plural y género coinciden ("plásticas" / "plástico").
* Nuevo ajuste "Vocabulario del cliente" (Ajustes → WooCommerce): reglas "cómo lo dicen tus clientes => cómo se llama en tu catálogo" (p. ej. "envasadora, carnicería => vacío").
* Errores temporales del proveedor IA: ante saturación (503) se reintenta una vez y, si persiste o es un límite de cuota (429), se prueba un modelo de reserva en vez de responder con el mensaje genérico.
* La selección automática de modelo prefiere el recomendado y descarta versiones preview o de imagen/voz si el modelo configurado se retira.
* Compatibilidad: no cambia tablas ni ajustes existentes; el nuevo ajuste empieza vacío.

= 1.17.0 =
* Conservación de datos (RGPD): nuevos plazos en Ajustes → RGPD y datos para borrar automáticamente las conversaciones sin solicitud (y las búsquedas del chat) y las solicitudes comerciales con su conversación. Tarea diaria de WP-Cron en tandas acotadas; muestra la última limpieza y la próxima ejecución.
* Por defecto ambos plazos están a 0 (no se borra nada automáticamente): actualizar no cambia el comportamiento hasta que el administrador los configure.
* El texto sugerido para la política de privacidad incluye los plazos configurados.
* La tarea programada se retira al desactivar o desinstalar el plugin.

= 1.16.1 =
* Ajuste visual: Cloudflare Turnstile usa su tamaño flexible oficial dentro del formulario del chat, adaptándose al ancho disponible sin quedar cortado.
* Responsive: el formulario y sus burbujas ya no generan desplazamiento horizontal en ventanas estrechas.
* Compatibilidad: actualización solo de CSS/JavaScript; no modifica ni elimina ajustes, claves, leads, conversaciones o base de conocimiento.

= 1.16.0 =
* Entrega verificable: la IA ya no puede prometer que un asesor escribirá, contactará o revisará una consulta antes de que el visitante confirme el envío y el servidor registre el lead.
* Confirmación autoritativa: el mensaje final lo genera el servidor después de guardar el lead y comprobar el resultado de `wp_mail()`.
* Trazabilidad: cada lead guarda si el aviso quedó pendiente, fue aceptado por WordPress o falló, junto con la fecha y el motivo interno; el detalle del lead lo muestra al administrador.
* Fallo seguro: si el correo automático falla, el visitante recibe un mensaje honesto; el lead permanece guardado y recuperable desde el panel.
* Conversación completa: los mensajes de la sesión se vinculan al lead y la confirmación server-side queda registrada en el histórico.
* Privacidad y UX: la IA no repite el email completo ni vuelve a pedir datos ya disponibles; el formulario habla de “enviar la consulta”, no de una promesa de contacto.
* Compatibilidad: migración aditiva de tres columnas; conserva todos los ajustes, claves, leads, conversaciones y base de conocimiento existentes.

= 1.15.0 =
* Nuevo: exportación de conversaciones en CSV, agrupada por conversación o detallada mensaje a mensaje.
* Análisis de contenido: el formato agrupado incluye preguntas, respuestas, intenciones, enlaces recomendados y transcripción completa para detectar carencias y crear nuevas entradas de base de conocimiento.
* Privacidad: las sesiones se exportan con un identificador seudónimo y nombre/email se excluyen por defecto; solo se incluyen mediante una opción explícita.
* Filtros: permite limitar el corpus por fechas y exportar una conversación concreta desde su histórico.
* Seguridad y rendimiento: nonce + `manage_options`, protección contra CSV injection y lectura por lotes para historiales grandes.
* Compatibilidad: no cambia el esquema de base de datos ni sobrescribe ajustes, claves, leads, conversaciones o base de conocimiento existentes.

= 1.14.0 =
* Precisión comercial: las preguntas de seguimiento breves conservan el producto de los turnos anteriores (por ejemplo, tras preguntar por cintas, “¿qué formatos y precios hay?” sigue buscando cintas).
* Búsqueda contextual: normaliza variantes y errores habituales como “presintar”/“precintar”, usa nombre, SKU, categoría y atributos, y exige coincidencias temáticas suficientes para evitar mezclar cintas con impresoras u otros productos.
* Respuesta verificable: cuando el cliente pide precios, formatos, unidades u opciones, el servidor responde con productos reales del catálogo aunque la IA falle o se despiste; nunca sustituye datos disponibles por “no tengo acceso”.
* Precio correcto: las tarjetas y respuestas usan el precio público mostrado por WooCommerce, respetando impuestos, ofertas y rangos de productos variables; ya no usan el precio bruto interno.
* Formato visible: las tarjetas pueden mostrar cantidades detectadas en el nombre o atributos, como “36 cintas” o “72 rollos”.
* Enlaces más estrictos: los enlaces de la base de conocimiento deben ser relevantes para el tema completo; una coincidencia genérica aislada ya no basta.
* Calidad de release: el empaquetador ejecuta una regresión comercial automática que cubre contexto, erratas, ranking, impuestos, formatos y enlaces.
* Compatibilidad: no cambia el esquema de base de datos ni sobrescribe ajustes, claves, leads, conversaciones o base de conocimiento existentes.

= 1.13.0 =
* Seguridad de costes: nuevos topes diarios configurables de consultas IA por IP y para todo el sitio, además de los límites de ventana y sesión existentes.
* Seguridad de proxy: CF-Connecting-IP solo se acepta desde las redes oficiales de Cloudflare; X-Forwarded-For solo desde proxies confiables y se recorre de forma resistente a valores falsos antepuestos. Se añade el filtro `supubot_trusted_proxy_cidrs` para alojamientos con redes propias.
* Integridad de leads: score, resumen IA, transcripción y datos de producto se reconstruyen o resuelven en el servidor y se ligan a sesión + hash de IP. El navegador ya no puede convertir un lead en "alta", inventar un resumen interno ni falsificar SKU/categoría/nombre de producto.
* Caché: si el nonce REST ha caducado, el widget obtiene uno nuevo por AJAX y reintenta una sola vez, evitando falsos errores 403 en páginas cacheadas.
* Privacidad: texto sugerido para la política de privacidad y compatibilidad con los exportadores/borradores nativos de datos personales de WordPress. Las URLs de origen se guardan sin query ni fragmento y solo si pertenecen al sitio.
* Secretos: las claves de OpenAI, Gemini y Turnstile se pueden eliminar expresamente desde Ajustes. Turnstile activado sin clave secreta falla de forma segura y bloquea el formulario.
* Nota: no cambia el esquema de base de datos y se conservan todos los ajustes y datos existentes.

= 1.12.0 =
* Nuevo (marca blanca real): el diagnóstico local de respaldo (lo que el bot pregunta cuando la IA no responde) ya no lleva el vocabulario del sector etiquetas incrustado en el código. Ahora se configura por cliente en Ajustes → Cliente: "Temas del sector" (una línea por tema: "palabras,clave :: pregunta") y "Pregunta genérica" para cuando ningún tema coincide. La detección de presupuesto/precio sigue integrada, es común a todos los sectores.
* Nuevo (validación al guardar): el "Modelo manual" de IA se valida contra los modelos vivos de la cuenta también al pulsar Guardar (antes solo con el botón "Validar", que era opcional). Un nombre inexistente NO se aplica: se conserva el modelo anterior y se avisa con claridad. Si la lista no se puede consultar (sin clave o sin red), el guardado no se bloquea.
* Mejora (rendimiento): la base de conocimiento se consulta UNA vez por mensaje del chat (antes dos veces: una para el resumen y otra para los enlaces).
* Cambio: los valores internos de intención pasan a ser neutros (producto|presupuesto|soporte|otro); los antiguos del sector etiquetas se siguen aceptando por compatibilidad. Las columnas del CSV "Modelo de impresora" y "Tipo de etiqueta/material" pasan a "Modelo / equipo" y "Tipo de material / producto".
* Nota: las conversaciones y datos existentes no se ven afectados; no hay migración de base de datos.

= 1.11.3 =
* Seguridad (auditoría): los buscadores de catálogo del chat (tarjetas de producto y "Sugerir producto del catálogo") ya no pueden recomendar productos ocultos del catálogo ni protegidos por contraseña. Aplican el mismo criterio de visibilidad pública que /product-context (endurecido en 1.11.1); antes solo comprobaban que el producto estuviera publicado.
* Seguridad (auditoría): el email de aviso de nuevo lead sanea todos los campos escritos por el visitante (empresa, producto, resumen) antes de componer el mensaje. Antes viajaban crudos al buzón del comercial.
* Fix (auditoría): el identificador de sesión del chat (lo genera el navegador) se recorta al tamaño real de la columna en base de datos; en MySQL en modo estricto, un valor más largo hacía fallar el guardado del mensaje en silencio.
* Compatibilidad (auditoría): soporte de los modelos razonadores de OpenAI (o1/o3/o4, gpt-5…): usan `max_completion_tokens` (rechazan `max_tokens`), sin temperatura personalizada, con más margen de tokens y tiempo de espera ampliado. Mismo trato que ya recibían los Gemini 3.x "thinking" desde 1.10.1. Afecta al chat y a "Probar conexión IA".
* Compatibilidad (auditoría): declaración oficial de compatibilidad con HPOS (pedidos de alto rendimiento de WooCommerce). El acceso a pedidos ya era compatible (wc_get_orders); ahora WooCommerce deja de marcar el plugin como incompatible.

= 1.11.2 =
* Mejora: la pestaña Anti-spam de Ajustes incluye ahora instrucciones paso a paso para configurar Cloudflare Turnstile, con enlaces directos al panel de Cloudflare y a la guía oficial, y una descripción de qué hace cada límite (mensajes por IP/ventana, por sesión, leads por IP/día). Avisa de que sin la clave secreta Turnstile no bloquea aunque esté activado. Solo textos de ayuda; sin cambios de comportamiento.

= 1.11.1 =
* Seguridad: el endpoint /product-context ya no expone productos sin publicar. Ahora exige nonce válido y solo devuelve productos publicados y visibles públicamente (rechaza borradores, privados, protegidos por contraseña u ocultos del catálogo).
* RGPD/datos: "Borrar todos los leads" elimina también sus conversaciones asociadas (antes quedaban con datos personales); las conversaciones anónimas se conservan. Si el borrado no se completa, avisa con honestidad (error o borrado parcial) en vez de dar falso éxito. uninstall.php borra también la tabla de búsquedas (supubot_searches) cuando no se conservan datos.
* Fix: el mensaje del usuario se enviaba dos veces a la IA (una en el historial y otra como mensaje actual), alterando respuestas y duplicando coste de tokens. Ahora viaja una sola vez.
* Fix: las URLs recomendadas por el asistente se guardan saneadas por separado en formato JSON (antes se concatenaban y podían corromperse) y la columna link_url pasa de VARCHAR(255) a TEXT. La migración solo se marca como hecha si se verifica (columna presente y de tipo TEXT); si falla, se reintenta. El histórico de Conversaciones lee tanto el formato nuevo como el antiguo.

= 1.11.0 =
* Fix (importante): el bot ya no puede mandar a una URL del propio dominio que no exista (404). Antes, si la IA escribía en el texto un enlace de tu dominio con una ruta inventada (p. ej. .../ficha-tecnica/), el servidor lo aceptaba solo por ser del mismo dominio. Ahora, además de ser del dominio, la página debe existir y estar publicada (se verifica contra la base de datos con url_to_postid); si no, no se muestra el botón. Los enlaces de la base de conocimiento y las tarjetas de producto ya usaban URLs reales y no se ven afectados.
* Nuevo: en Admin → Conversaciones, cada respuesta del asistente muestra ahora la(s) URL(s) que recomendó (botón-enlace y/o tarjetas de producto), clicables, para poder auditar adónde llevó cada enlace y detectar cualquier 404. Se guarda una columna nueva `link_url` en la tabla de conversaciones (migración automática, no toca datos existentes).

= 1.10.2 =
* Fix: el precio en las tarjetas de producto del chat mostraba las entidades HTML sin decodificar ("&euro;&nbsp;325,00") en vez de "€ 325,00". Ahora se decodifican antes de enviarlas al widget.

= 1.10.1 =
* Fix: compatibilidad con los modelos Gemini 3.x (gemini-3.5-flash, gemini-3.1-flash-lite, etc.). Estos modelos "razonan" (thinking) antes de responder y, en modo no-streaming, no devolvían nada hasta terminar: superaban el límite de tiempo del plugin y provocaban el fallback ("Gracias por tu consulta…") en cada mensaje. Ahora, para Gemini 3.x, se fija el razonamiento en nivel "low" (rápido y con calidad), la temperatura en 1.0 (recomendación oficial de Google para Gemini 3; 0.2 causaba comportamiento inesperado) y se amplían el margen de tokens y el tiempo de espera. Afecta tanto al chat como a "Probar conexión IA".
* Fix: los modelos recomendados de emergencia para Gemini pasan de la serie 1.5 (retirada por Google) a modelos 3.x vivos (gemini-3.1-flash-lite / gemini-3.5-flash). Ya no se cae a un modelo inexistente cuando no se puede consultar la lista en vivo.
* Nota: la vía normal sigue siendo el descubrimiento dinámico de modelos (botón "Consultar modelos disponibles"); estos valores solo actúan como reserva.

= 1.10.0 =
* Nuevo: descubrimiento automático de modelos IA. Botón "Consultar modelos disponibles" (Ajustes → Inteligencia Artificial) que consulta al proveedor, con tu clave y desde el servidor, qué modelos puede usar tu cuenta y muestra en un desplegable SOLO los compatibles (generateContent en Gemini; chat en OpenAI). Ya no hay que adivinar nombres de modelo.
* Nuevo: "Selección automática recomendada" (activada por defecto). El plugin elige un modelo compatible y, si tu proveedor retira el que usabas, cambia solo a otro válido tanto al probar la conexión como en tiempo de ejecución. Pensado para usuarios no técnicos.
* Nuevo: modo avanzado "Introducir modelo manualmente" con validación real: antes de aplicar un nombre escrito a mano se comprueba contra los modelos vivos de tu cuenta; si no existe o no es compatible, no se usa.
* Mejora: "Probar conexión" ahora verifica las cuatro cosas — clave válida, modelo disponible, compatibilidad con generateContent y respuesta real del proveedor — con mensajes claros en español.
* Mejora: se indica en todo momento "el modelo que se usará realmente".
* Interno: los nombres de modelo fijos en código pasan a ser solo un fallback de emergencia (cuando no hay red/clave). La vía normal es 100% dinámica. La clave API se sigue usando solo en el servidor; nunca se expone en el frontend ni en logs/errores.

= 1.9.0 =
* Nuevo: buscador de catálogo para la IA (Ajustes → WooCommerce → "Buscador de productos para la IA", activado por defecto). Con cada consulta el servidor busca productos publicados que encajen (nombre, SKU, categoría) y se los pasa a la IA con precio y disponibilidad reales. La IA solo puede recomendar productos de esa lista: nunca inventa nombres, precios ni enlaces. Acceso de solo lectura, vía wc_get_products, igual que cualquier visitante de la tienda.
* Nuevo: tarjetas de producto en el chat (foto, nombre, precio y disponibilidad) cuando la IA recomienda productos del catálogo, con enlace directo a la ficha.
* Nuevo: registro de búsquedas sin resultado y panel en el Dashboard ("Qué buscan y no encuentran") para detectar demanda no cubierta por el catálogo.
* Mejora: el matcher de catálogo ahora tolera plurales/singulares (p. ej. "etiquetas" encuentra "etiqueta") y reintenta por palabras clave si la búsqueda literal no da resultados.
* Mejora: si la IA recomendó un producto durante la charla y el cliente deja sus datos, el lead se precarga con ese producto como "producto consultado".

= 1.8.1 =
* Marca blanca 100%: eliminadas las plantillas de demo de clientes concretos. Quedan solo las plantillas genéricas ("ecommerce genérica" y "vaciar configuración").
* Valores por defecto neutros: una instalación nueva arranca sin datos de ningún cliente (empresa vacía, asistente "Asistente Comercial", mensajes genéricos, colores neutros azul/verde). Las instalaciones existentes NO cambian: su configuración vive en la base de datos del sitio y las actualizaciones no la tocan.

= 1.8.0 =
* Nuevo: "Conservar datos al desinstalar" (Ajustes → RGPD y datos, ACTIVADO por defecto). Actualizar o reinstalar el plugin nunca ha borrado nada; ahora tampoco lo hace BORRARLO desde WordPress: leads, conversaciones, base de conocimiento y ajustes sobreviven para una futura reinstalación. Para un borrado total real hay que desmarcar el ajuste primero y luego borrar el plugin. En instalaciones donde el ajuste no exista, ante la duda NUNCA se borra.
* Mejora: pantalla de Base de conocimiento rediseñada a ancho completo (adiós a las dos columnas). Formulario plegable arriba ("➕ Nueva entrada"; se abre solo al editar), barra de filtros con búsqueda (título/contenido/categoría), filtro por categoría y por estado (activas/inactivas), contador de entradas, sugerencias de categoría al escribir (datalist), badges de categoría clicables (filtran al pulsar), columna que indica si la entrada tiene enlace (🔗), estado Activa/Inactiva con badge y filas inactivas atenuadas.

= 1.7.1 =
* Fix: el bot ya no vuelve a pedir nombre y email a quien ya se identificó en el gate o al empezar el chat. La IA recibe un bloque "visitante identificado" con sus datos y la instrucción de no pedirlos de nuevo (si un asesor debe contactar, dice que escribirá a su email).
* Mejora: a los visitantes sin sesión iniciada la IA ya no les manda a "Mi cuenta → pedidos" como si fueran a ver sus pedidos (tendrían que iniciar sesión, o compraron como invitado). Orden correcto: email de confirmación primero; si no, asesor que lo localiza con su email.
* Mejora: los botones-enlace del chat hacia el propio dominio se abren en la MISMA pestaña (la conversación persiste y se restaura al navegar); los enlaces externos siguen abriéndose en pestaña nueva.

= 1.7.0 =
* Nuevo: identidad en conversaciones. Cada mensaje guarda quién habló (nombre y email del gate o del primer mensaje, y si hay sesión WordPress iniciada, los datos verificados de la cuenta, que tienen prioridad). Antes solo se sabía la identidad si el visitante enviaba el formulario de lead.
* Admin → Conversaciones: columna "Cliente" en el listado (nombre + email clicable; "Anónimo" si no se conoce). En el detalle, cabecera con cliente, email y enlace a su perfil de usuario si está registrado; los mensajes del visitante muestran su nombre en vez de "Usuario".
* Base de datos: columnas nuevas `visitor_name`, `visitor_email` y `user_id` en la tabla de conversaciones (migración automática, no toca datos existentes; las conversaciones antiguas siguen como anónimas).

= 1.6.0 =
* Nuevo: pedidos del cliente registrado. Si el usuario tiene sesión iniciada en WordPress, el bot ve sus últimos 3 pedidos (número, fecha, total y estado) y puede responder directamente a "no encuentro el número de pedido para la transferencia". Solo servidor: cada usuario ve únicamente SUS pedidos (mismo acceso que "Mi cuenta"); los visitantes sin sesión nunca acceden a datos de pedidos.
* Nuevo: capa determinista de pedidos. Si el cliente registrado pregunta por su pedido y la respuesta de la IA no contiene ninguno de sus números reales (IA caída o despistada), el servidor responde con el dato exacto de WooCommerce. Nunca inventa números.
* Nuevo: ajuste "Pedidos del cliente registrado" (Ajustes → WooCommerce, `wc_order_lookup`, activado por defecto) para activar/desactivar la función por cliente.
* Prompt: la IA sabe que el cliente registrado no tiene pedidos en su cuenta (pudo comprar como invitado) y ofrece dejar los datos para que un asesor lo localice.

= 1.5.3 =
* Fix: coherencia de medidas también en los enlaces de la base de conocimiento (y en el enlace que elige la IA). Antes, pedir "etiquetas 100x65" podía sacar el botón de una entrada 100x70 porque compartían palabras genéricas ("etiquetas"). Ahora, si el cliente indica una medida, la entrada o su URL debe contenerla (también invertida: 100x65 ≡ 65x100) o se descarta. Misma regla que ya aplicaba el buscador de catálogo WooCommerce desde 1.3.2. Las consultas sin medida no cambian.

= 1.5.2 =
* Fix: solo un punto verde de "activo" en la cabecera (sobre el avatar). Antes salían dos: uno en el avatar y otro en la línea de estado.
* Fix móvil definitivo (zoom/desborde al escribir en iPhone): la regla de 16px de los campos se movía a un bloque que los temas Integrado/Minimal anulaban por especificidad (redefinen 14px). Ahora vive al final del CSS con máxima prioridad y cubre también tablets táctiles. El panel a pantalla completa usa width:100% en vez de 100vw (en Android 100vw incluye la barra de scroll y desbordaba).
* Nuevo: "Horario de atención" en Ajustes → Widget (ej. "L-V 9:00–18:00"). Se muestra en la cabecera del chat con icono de reloj, bajo la línea de estado. Vacío = no se muestra.

= 1.5.1 =
* Revisión de estabilidad previa a producción (solo fixes, sin features):
  * El placeholder del área de escritura ya no dice "Completa tus datos…" cuando la conversación está terminada: ahora indica "Conversación finalizada." (tras Terminar, tras enviar el lead con sesión única y al restaurar una conversación terminada).
  * Si el usuario pulsa "Terminar" mientras la IA está "pensando", el botón Enviar ya no se reactiva al llegar la respuesta (tampoco si falla la red).
  * El mini-formulario del gate ya no puede desbloquear el chat si la conversación se terminó con el gate abierto.
  * La confirmación de "lead enviado" se guarda en el historial: ahora sobrevive a la navegación entre páginas.

= 1.5.0 =
* **Fix móvil:** iOS hacía zoom (y desbordaba el layout) al escribir porque los campos tenían fuente menor de 16px. En móvil, el área de escritura y los campos del formulario van ahora a 16px, y la barra de entrada respeta el safe-area.
* **FAB rediseñado (3 estilos, Ajustes → Widget):** "Icono con texto debajo" (círculo + etiqueta pastilla que se adapta al texto, moderno y compacto), "Solo icono" y "Solo texto". Nuevo campo para **subir una imagen de icono** propia con el selector de medios de WordPress (vacío → logo → icono por defecto).
* **Movimiento de atención:** si el visitante no abre el chat, el FAB hace un pequeño saludo cada ~9 segundos (se detiene al abrir; respeta prefers-reduced-motion).
* **Botón "Terminar" para el cliente** en la cabecera: cierra la conversación con despedida. Nuevo ajuste **"Una conversación por sesión"**: al terminar (o al enviar el formulario), el chat queda cerrado hasta que el visitante cierre la pestaña y vuelva; desactivado, puede empezar una conversación nueva al momento.
* **Cabecera con presencia:** avatar del asesor (subible desde Ajustes; vacío → logo) con punto verde "activo" y línea de estado editable bajo el nombre ("En línea · 24/7" por defecto), con latido sutil.

= 1.4.0 =
* **Datos antes de chatear (opcional):** nuevo ajuste "Pedir nombre y email antes de poder chatear". Con él activo, el chat queda bloqueado hasta que el visitante rellena un mini-formulario (nombre + email, con texto RGPD); después se desbloquea y esos datos precargan el formulario de lead.
* **Límite de consultas por conversación (opcional):** campo numérico en Ajustes (0 = sin límite). Al alcanzarlo, el bot avisa de que las consultas están limitadas y ofrece dos salidas que abren el formulario: hablar con asesor o pedir presupuesto. Pedir un humano sigue funcionando siempre.
* **Usuario logueado identificado:** si el visitante tiene sesión en WordPress, el bot le saluda por su nombre, se salta la petición de nombre (y el gate) y precarga nombre + email en el formulario.
* **Botón flotante con texto:** el FAB ahora puede ser una pastilla compacta con icono + texto ("Asesor online" por defecto, editable en Ajustes). Vacío = icono redondo clásico. Mantiene animación, temas y posición.

= 1.3.3 =
* Endurecimiento de seguridad (auditoría completa):
  * El botón-enlace ya no puede apuntar fuera: si la IA escribe una URL en el texto, se extrae y valida EN EL SERVIDOR contra la whitelist (enlaces de la KB o el propio dominio). Una inyección de prompt ya no puede hacer que el widget muestre un botón a una web externa; el frontend nunca crea botones desde URLs del texto.
  * Rate limit anti-abuso real: la IP ya no se toma de cabeceras falseables (X-Forwarded-For / CF-Connecting-IP) salvo que la conexión venga de un proxy inverso legítimo (IP privada). Evita rotar IPs ficticias para saltarse los límites y disparar el gasto de la API. Nuevo filtro `supubot_client_ip` para configuraciones de proxy particulares.
  * El visitante ya no puede fijar `importe_estimado` desde el navegador (dato de negocio: lo pone el comercial en el admin).
  * El escape del widget ahora también neutraliza comillas (endurecimiento de atributos HTML).
  * `/product-context` respeta el ajuste de widget desactivado.

= 1.3.2 =
* Control y precisión de la sugerencia de productos de WooCommerce (corrige sugerencias absurdas):
  * Nuevo ajuste **"Sugerir producto del catálogo"** (Ajustes → WooCommerce), DESACTIVADO por defecto. Con él apagado, el bot solo ofrece los enlaces que tú pongas en la Base de conocimiento (control total). Actívalo cuando el catálogo esté bien nombrado.
  * Matching mucho más estricto: si el cliente menciona una medida (p. ej. 100x70), solo se ofrecen productos con ESA medida; uno con otra medida (55x8) se descarta. Ya no basta una sola palabra suelta (umbral alto) y se elimina la sugerencia de "categoría más parecida", que producía resultados sin relación (p. ej. "Máquinas de aire").

= 1.3.1 =
* Enlaces a producto/categoría de WooCommerce: cuando ni la IA ni la base de conocimiento aportan un enlace, el bot busca en el catálogo real (wc_get_products + categorías) el producto o la categoría más relevante para la consulta y lo ofrece como botón. Matching conservador por tokens (las medidas/modelos como "100x70" o "4420TN" pesan más); si la relación es débil, muestra un aviso bajo el botón ("puede que no sea exactamente lo que buscas; dime más detalles"). Nunca inventa productos ni precios: solo enlaza a lo que existe y está publicado.
* Prioridad de enlaces: (1) el que decide la IA, (2) entrada de la base de conocimiento que casa, (3) producto/categoría de WooCommerce. El primero que aplica gana.

= 1.3.0.1 =
* Fix importante de los enlaces de la KB: el botón dependía de que la IA rellenara el campo `link`, y a veces lo olvidaba (mencionaba «el botón de abajo» sin que saliera) o derivaba a un asesor aunque existiera un producto/enlace que respondía la consulta (p. ej. una medida 100x70). Ahora, si la IA no devuelve enlace, el backend busca de forma determinista en la base de conocimiento la entrada con URL que casa con el mensaje del cliente y adjunta el botón automáticamente. Los tokens con dígitos (medidas, modelos) pesan más y los saludos genéricos no disparan enlaces.
* El prompt ahora insiste en ayudar con el enlace útil en lugar de derivar a un asesor o a presupuesto por defecto.

= 1.3.0 =
* Base de conocimiento **editable**: botón "Editar" en cada entrada (carga la entrada en el formulario, guarda cambios). Antes solo se podía añadir o eliminar.
* **Borrado completo de datos, sin dejar restos:**
  * Leads: eliminar un lead borra también su conversación asociada. Botón "Eliminar" en el listado y en el detalle, y "Borrar TODOS los leads".
  * Conversaciones: eliminar una sesión, y "Borrar TODAS las conversaciones".
  * Base de conocimiento: eliminar entrada y "Borrar TODA la base de conocimiento".
  * Todas las acciones destructivas piden confirmación y usan nonce + permiso `manage_options`.
* **uninstall.php**: al borrar el plugin desde WordPress se eliminan las 3 tablas, las opciones y los transients (compatible multisitio). No queda ningún rastro en la base de datos.
* **Animación del icono flotante (FAB)**: entrada suave con micro-rebote, flotación discreta en reposo y salida al abrir el chat. CSS puro, sin librerías (sin Lottie, respeta la regla de ligereza). Respeta `prefers-reduced-motion`.

= 1.2.1.1 =
* Fix de los enlaces de la KB: cuando la IA escribía la URL dentro del texto (enlace markdown o URL suelta) en vez de en el campo `link`, no salía el botón y se veía el markdown crudo. Ahora (1) el prompt prohíbe escribir URLs en la respuesta y obliga a usar el campo `link`; y (2) el frontend tiene una red de seguridad: si aun así la URL aparece en el texto, la extrae, pinta el botón y limpia el texto.

= 1.2.1 =
* Enlaces desde la base de conocimiento: si una entrada de la KB contiene una URL, la IA puede ofrecerla como botón clicable en el chat cuando sea útil para la consulta. El backend extrae las URLs y las pasa como recursos; solo se muestra un enlace que EXISTA en la KB (whitelist "verificar, no inventar") — la IA nunca inventa enlaces. El botón abre en pestaña nueva (rel noopener).
* Ajustes reorganizados en pestañas horizontales nativas de WordPress (Cliente · Widget · Inteligencia Artificial · WooCommerce · Anti-spam · RGPD · Plantillas). Sin librerías; un solo formulario, guardar sigue enviando todos los campos. La pestaña activa se recuerda en el hash de la URL.
* (Las tarjetas de producto WooCommerce se trasladan a 1.2.2.)

= 1.2.0 =
* Inteligencia comercial dirigida por el prompt/backend (no una máquina de estados en JS). La IA decide la estrategia; el frontend renderiza y aplica un guard de seguridad ligero.
* Nuevo prompt comercial: máximo 1 pregunta principal por respuesta, aporta valor antes de preguntar, diagnostica antes de recomendar, prohíbe inventar precios/stock/compatibilidades/productos, prioriza la base de conocimiento y capta leads como consecuencia natural (nunca abrasivo).
* JSON de la IA enriquecido: `stage` (saludo/exploración/diagnóstico/recomendación/presupuesto/captación_suave/humano) como etiqueta informativa, `next_action` (responder/pedir_dato/cta_suave/mostrar_formulario/pasar_asesor) y `advisor_summary` estructurado (necesidad, producto/categoría, datos conocidos, datos que faltan, urgencia, recomendación, siguiente acción, oportunidad).
* Reglas de captación refinadas: el formulario aparece solo si la IA lo indica (next_action) o hay interés alto confirmado con contexto suficiente; nunca en una primera consulta genérica, comparando, con fallback o faltando un dato técnico.
* CTAs suaves con tope de 2 por respuesta, y la salida a asesor solo se añade en fases avanzadas.
* Copy del formulario configurable desde Ajustes ("Mensaje antes del formulario") con un default no agresivo: "te dejo la consulta preparada para un asesor".
* Fallback más prudente: si la IA falla, diagnóstico local sin forzar la captación.
* Margen de +300 tokens también en Gemini (evita truncado del JSON más largo → fallback falso).

= 1.1.8 =
* Sistema de 3 temas visuales seleccionables desde Ajustes → Diseño del widget: "Integrado" (hereda fuente del body, cabecera blanca, burbujas en gris neutro), "Marca" (colores de marca completos, estilo actual mejorado) y "Minimal Pro" (blanco y grises, color solo en detalles; ideal para webs corporativas). Por defecto: Integrado.
* Clase CSS aplicada en el root del widget (.supubot-theme-brand / -integrated / -minimal) para aislamiento total sin afectar al tema de WordPress.
* Reset de aislamiento: los botones e inputs del widget ya no heredan estilos globales de temas WordPress/Elementor.
* FAB más premium: shadow de doble capa, transición transform+shadow en hover (ya no filter). Panel: radio 16 px, shadow de mayor profundidad.
* Mejoras generales: burbujas con radio 14 px y line-height 1.5, chips más modernos (font-weight 500, gap más ajustado), inputs con borde 1.5px y focus state explícito, input-bar con flex-shrink:0.

= 1.1.7 =
* detectIntent() amplía vocabulario real: pegatinas, adhesivos, rollos, bobinas, consumibles, transfer, etiquetadora (→ impresora), "cuánto cuesta/vale" (→ presupuesto). "Cinta adhesiva" sigue siendo precinto.
* Indicador de pensamiento animado: tres puntos que laten dentro de una burbuja (antes "…" estático), unificado en typingRow().
* Pausa natural también al pedir asesor (formulario ya no salta de golpe) y en el diagnóstico local si la red falla al instante (el indicador ya no parpadea).

= 1.1.6 =
* Fix importante: el límite de tokens de la IA no dejaba margen para el envoltorio JSON; con respuestas largas el JSON se truncaba y el bot caía al mensaje genérico de fallback aunque la IA respondiera bien. Ahora se añade margen (+300 tokens).
* Seguridad: neutralizada la inyección de fórmulas CSV en la exportación (campos del visitante que empiezan por =, +, -, @).
* Seguridad: la clave API de Gemini viaja por header (x-goog-api-key) en lugar de en la URL, para que no quede en logs de servidores/proxies.

= 1.1.5 =
* Persistencia de conversación entre páginas: el historial, nombre y contexto se guardan en sessionStorage y se restauran al volver al widget en cualquier página de la misma pestaña.

= 1.1.4 =
* Efecto typewriter: el texto del bot aparece letra a letra (velocidad adaptativa 10-28 ms/carácter). Chips y formulario aparecen al terminar de escribir, no antes.

= 1.1.3 =
* Tras capturar el nombre: sin botones predefinidos instantáneos; el bot responde con delay natural y espera que el cliente escriba su consulta.

= 1.1.2 =
* Botón "Probar conexión IA" en Ajustes: valida clave y modelo con una llamada real, muestra OK o error exacto del proveedor.
* Avatar/icono del widget: si hay logo configurado rellena todo el círculo (object-fit:cover, overflow:hidden). Sin logo muestra icono sparkles por defecto.
* Saludo inicial fusionado en un solo mensaje con indicador de escritura antes de aparecer.
* Retardo de respuesta proporcional a la longitud del texto (800-2500 ms) para experiencia más natural.
* Formulario de lead automático: umbral subido a 4 turnos con lead_score alta (antes 2 turnos con any score).

= 1.1.1 =
* Flujo conversacional: las intenciones comerciales iniciales (etiquetas, impresora, ribbon, precinto, bolsas, presupuesto) generan una pregunta de diagnóstico local y ya no abren el formulario de golpe.
* Diagnóstico local por intención, determinista, funciona aunque la IA falle o devuelva fallback.
* Formulario mínimo (nombre, email, teléfono); solo aparece al pedir humano o tras contexto suficiente.
* Control de colores del widget: 6 variables (principal, secundario, texto sobre cada fondo, fondo y texto de hover).
* Hover seguro: fondo y texto de hover independientes; hover solo con puntero real (@media hover) para evitar el estado pegajoso en móvil.

= 1.1.0 =
* Rediseño del widget de chat (FAB, avatares, chips-bloque, formulario en burbuja, pantalla completa en móvil).
* Nuevo flujo conversacional: pide el nombre de forma natural, conversa primero y solo muestra el formulario cuando hay intención clara de lead o el usuario pide contacto humano.
* Formulario de lead mínimo (nombre, email, teléfono) con el resto del contexto en la transcripción y el resumen de la IA.
* Corrección de contraste y del hover pegajoso en móvil en botones/chips.
* Sin cambios de backend, endpoints ni base de datos.

= 1.0.0 =
* Versión inicial: chat IA multi-cliente, captura y gestión de leads, base de conocimiento, exportación CSV, anti-spam, personalización de widget y ajustes.
