/* ─────────────────────────────────────────────────────────────
   BotLauncher · widget flotante (abajo-derecha)
   · Cara del bot (mascota newGalaxIA) + botones WhatsApp / Instagram.
   · Al tocar el bot abre un CHAT REAL contra el cerebro (POST /api/chat).
   · Contrato único /api/chat — atendido por proxy local (dev) o Worker CF (prod).
   · Capta contacto con form-backstop cuando el bot deriva (lead siempre alcanzable).
   ───────────────────────────────────────────────────────────── */
const { useState, useEffect, useRef } = React;

const NG_WA = 'https://wa.me/59892499463?text=' +
  encodeURIComponent('¡Hola! Quiero saber cómo pueden ayudar a mi negocio con IA.');
const NG_GREETING = '¡Hola! 👋 Soy Galaxia. Contame qué hacés y dónde se te va el tiempo, y te muestro qué podríamos automatizar.';

// Endpoint único: mismo origen (proxy local en dev, Worker de Cloudflare en prod).
const CHAT_ENDPOINT = '/api/chat';

// Turnstile (anti-bot de Cloudflare). Site key pública (atada a newgalaxia.com).
// Se activa SOLO en el dominio real (no en localhost, donde la key no valida).
const NG_TURNSTILE_SITEKEY = '0x4AAAAAADuBmFi2Im0SFA7W';
const NG_TURNSTILE_ON = !!NG_TURNSTILE_SITEKEY && !/^(localhost|127\.0\.0\.1|\[::1\])$/.test(location.hostname);

// Anclas reales de la web (allowlist). El bot menciona estas; las render como chips.
const ANCHORS = {
  '#agente': 'Ver la demo',
  '#lo-que-resuelve': 'Lo que resuelve',
  '#inteligencia-operativa': 'Inteligencia operativa',
  '#problema': 'El problema',
  '#creaciones': 'Casos reales',
  '#proceso': 'Cómo trabajamos',
  '#empleados-ia': 'Empleados IA',
  '#quienes-somos': 'Quiénes somos',
  '#faq': 'Preguntas frecuentes',
  '#contacto': 'Contacto',
};

// Clave de sesión por visitante (rol de "teléfono" en el cerebro). Persiste contexto.
function getSessionId() {
  try {
    let id = localStorage.getItem('ng_chat_session');
    if (!id) {
      id = (crypto.randomUUID ? crypto.randomUUID() : 'ng-' + Date.now() + '-' + Math.random().toString(36).slice(2));
      localStorage.setItem('ng_chat_session', id);
    }
    return id;
  } catch (e) {
    return 'ng-mem-' + Date.now();
  }
}

// Detecta anclas válidas en el texto del bot (para los chips de navegación).
function chipsFromText(text) {
  const found = [];
  for (const key of Object.keys(ANCHORS)) {
    if (text.includes(key) && !found.includes(key)) found.push(key);
  }
  return found;
}

// Limpia los tokens crudos (#ancla, asteriscos de markdown) del texto visible.
function cleanReply(text) {
  let t = text || '';
  for (const key of Object.keys(ANCHORS)) {
    // saca "→ `#ancla`", "(#ancla)", "#ancla" sueltos
    t = t.split('`' + key + '`').join('').split(key).join('');
  }
  t = t.replace(/\*\*(.*?)\*\*/g, '$1').replace(/\*(.*?)\*/g, '$1'); // markdown light
  t = t.replace(/[ \t]+→[ \t]*$/gm, '').replace(/\(\s*\)/g, '').replace(/[ \t]{2,}/g, ' ');
  return t.replace(/\n{3,}/g, '\n\n').trim();
}

function WhatsAppGlyph({ size = 22 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 32 32" fill="currentColor" aria-hidden="true">
      <path d="M16 3.06c-7.13 0-12.92 5.79-12.92 12.92 0 2.28.6 4.5 1.74 6.46L3 29l4.74-1.74a12.86 12.86 0 0 0 6.26 1.6h.01c7.13 0 12.92-5.79 12.92-12.92S23.13 3.06 16 3.06Zm7.56 18.25c-.32.9-1.87 1.72-2.57 1.77-.66.05-1.49.29-4.85-1.02-4.07-1.6-6.67-5.74-6.87-6.01-.2-.27-1.65-2.19-1.65-4.18 0-1.99 1.04-2.97 1.41-3.37.37-.4.81-.5 1.08-.5l.78.01c.25.01.59-.09.92.7.32.78 1.1 2.69 1.2 2.88.1.2.16.43.03.7-.13.27-.2.43-.39.66l-.59.69c-.2.2-.4.42-.17.81.23.4 1.03 1.7 2.21 2.75 1.52 1.36 2.8 1.78 3.2 1.98.4.2.63.16.86-.1.23-.27.99-1.15 1.25-1.55.26-.4.53-.33.89-.2.36.13 2.28 1.08 2.67 1.27.39.2.65.3.74.46.1.16.1.93-.22 1.83Z" />
    </svg>
  );
}

function InstagramGlyph({ size = 22 }) {
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" aria-hidden="true">
      <rect x="3" y="3" width="18" height="18" rx="5.2" />
      <circle cx="12" cy="12" r="4.2" />
      <circle cx="17.2" cy="6.8" r="1.15" fill="currentColor" stroke="none" />
    </svg>
  );
}

function BotAvatar({ size = 7 }) {
  return (
    <span className={`size-${size} rounded-full overflow-hidden flex-none`}
      style={{ background: 'rgba(51,194,234,0.15)', border: '1px solid rgba(51,194,234,0.4)' }}>
      <img src="assets/ngbot-icon.png" alt="" className="w-full h-full" style={{ objectFit: 'cover' }} />
    </span>
  );
}

function BotLauncher() {
  const [open, setOpen] = useState(false);
  const [hint, setHint] = useState(false);
  const [messages, setMessages] = useState([]); // {role:'user'|'bot', text, chips?}
  const [input, setInput] = useState('');
  const [sending, setSending] = useState(false);
  const [error, setError] = useState('');
  const [contactCaptured, setContactCaptured] = useState(false);
  const [showContactForm, setShowContactForm] = useState(false);
  const [cName, setCName] = useState('');
  const [cContact, setCContact] = useState('');
  const [closed, setClosed] = useState(false); // charla cerrada (derivada/pausada) → ofrecer reinicio
  const [recording, setRecording] = useState(false); // grabando nota de voz
  const [recSecs, setRecSecs] = useState(0);
  const [tsError, setTsError] = useState(false); // Turnstile falló → salida amable + WhatsApp

  const sessionRef = useRef(null);
  const scrollRef = useRef(null);
  const turnstileRef = useRef(''); // token de Turnstile (vacío si está desactivado)
  const widgetIdRef = useRef(null); // id del widget de Turnstile (para reset)
  const mediaRecRef = useRef(null);
  const chunksRef = useRef([]);
  const recTimerRef = useRef(null);
  if (sessionRef.current === null) sessionRef.current = getSessionId();

  // Reinicia la conversación: sesión nueva (uuid nuevo) + estado limpio.
  function reset() {
    try { localStorage.removeItem('ng_chat_session'); } catch (_) {}
    sessionRef.current = getSessionId();
    setMessages([{ role: 'bot', text: NG_GREETING }]);
    setClosed(false); setContactCaptured(false); setShowContactForm(false);
    setCName(''); setCContact(''); setError('');
  }

  // Saludo (burbuja) una sola vez.
  useEffect(() => {
    const t = setTimeout(() => setHint(true), 1800);
    return () => clearTimeout(t);
  }, []);

  // Semilla del chat al abrir por primera vez.
  useEffect(() => {
    if (open && messages.length === 0) {
      setMessages([{ role: 'bot', text: NG_GREETING }]);
    }
  }, [open]);

  // Turnstile (anti-bot): si hay site key, carga el script y renderiza el widget
  // invisible una vez (al abrir el panel). Guarda el token en turnstileRef.
  useEffect(() => {
    if (!open || !NG_TURNSTILE_ON) return;
    function render() {
      if (!window.turnstile) return;
      const el = document.getElementById('ng-turnstile');
      if (!el || el.dataset.rendered) return;
      el.dataset.rendered = '1';
      widgetIdRef.current = window.turnstile.render(el, {
        sitekey: NG_TURNSTILE_SITEKEY,
        size: 'flexible',        // se adapta al ancho del chat (compacto)
        appearance: 'interaction-only', // invisible si pasa solo; solo aparece si requiere clic
        retry: 'auto',
        'refresh-expired': 'auto',
        callback: (t) => { turnstileRef.current = t; setTsError(false); },
        'error-callback': () => { turnstileRef.current = ''; setTsError(true); },
        'expired-callback': () => { turnstileRef.current = ''; },
      });
    }
    if (window.turnstile) { render(); return; }
    const id = 'cf-turnstile-script';
    if (!document.getElementById(id)) {
      const s = document.createElement('script');
      s.id = id; s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
      s.async = true; s.defer = true; s.onload = render;
      document.head.appendChild(s);
    } else { render(); }
  }, [open]);

  // Auto-scroll al último mensaje.
  useEffect(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [messages, sending, showContactForm]);

  async function postChat(extra) {
    const resp = await fetch(CHAT_ENDPOINT, {
      method: 'POST',
      headers: { 'content-type': 'application/json' },
      body: JSON.stringify({ sessionId: sessionRef.current, turnstileToken: turnstileRef.current || undefined, ...extra }),
    });
    if (!resp.ok) {
      let msg = 'No pude responder ahora.', code = '';
      try { const e = await resp.json(); if (e) { msg = e.error || msg; code = e.code || ''; } } catch (_) {}
      const err = new Error(msg); err.code = code; throw err;
    }
    return resp.json();
  }

  // Aplica la respuesta del cerebro al chat (común a texto y audio).
  function applyReply(out) {
    const replyRaw = out.reply || '';
    const cleaned = cleanReply(replyRaw);
    if (cleaned) {
      setMessages((m) => [...m, { role: 'bot', text: cleaned, chips: chipsFromText(replyRaw) }]);
    } else {
      // Reply vacío = el motor mutó la sesión (ya derivada/pausada). En vez de
      // dejar el chat "mudo", marcamos la charla cerrada y ofrecemos reiniciar.
      setClosed(true);
    }
    // Backstop de contacto: el motor puede derivar (incluido pedido de humano)
    // sin que el LLM haya pedido el contacto. En web no hay teléfono → form.
    if (out.derivo && !contactCaptured) setShowContactForm(true);
  }

  async function send(textRaw) {
    const texto = (textRaw == null ? input : textRaw).trim();
    if (!texto || sending) return;
    setError('');
    setInput('');
    setMessages((m) => [...m, { role: 'user', text: texto }]);
    setSending(true);
    try { applyReply(await postChat({ texto, messageType: 'text' })); }
    catch (e) { if (e.code === 'turnstile_failed') setTsError(true); else setError(e.message || 'Se cortó la conexión, probá de nuevo.'); }
    finally { setSending(false); }
  }

  // Manda una nota de voz: la transcribe el cerebro (STT) y sigue como si fuera texto.
  async function sendAudio(base64, mime) {
    if (sending) return;
    setError('');
    setMessages((m) => [...m, { role: 'user', text: '🎤 Nota de voz' }]);
    setSending(true);
    try { applyReply(await postChat({ audio_base64: base64, audio_mime: mime, messageType: 'audio' })); }
    catch (e) { if (e.code === 'turnstile_failed') setTsError(true); else setError(e.message || 'No pude procesar el audio, probá de nuevo.'); }
    finally { setSending(false); }
  }

  const REC_MAX_SECS = 45; // el motor topea el body ~256KB → notas de voz cortas
  function blobToBase64(blob) {
    return new Promise((resolve, reject) => {
      const r = new FileReader();
      r.onloadend = () => resolve(String(r.result).split(',')[1] || '');
      r.onerror = reject;
      r.readAsDataURL(blob);
    });
  }
  async function startRec() {
    if (recording || sending || closed || showContactForm) return;
    setError('');
    if (!navigator.mediaDevices || !window.MediaRecorder) { setError('Tu navegador no soporta grabar audio.'); return; }
    let stream;
    try { stream = await navigator.mediaDevices.getUserMedia({ audio: true }); }
    catch (_) { setError('No pude usar el micrófono. Revisá los permisos del navegador.'); return; }
    const mime = MediaRecorder.isTypeSupported('audio/webm;codecs=opus') ? 'audio/webm;codecs=opus'
      : (MediaRecorder.isTypeSupported('audio/ogg;codecs=opus') ? 'audio/ogg;codecs=opus' : '');
    const mr = new MediaRecorder(stream, mime ? { mimeType: mime, audioBitsPerSecond: 24000 } : {});
    chunksRef.current = [];
    mr.ondataavailable = (e) => { if (e.data && e.data.size) chunksRef.current.push(e.data); };
    mr.onstop = async () => {
      stream.getTracks().forEach((t) => t.stop());
      clearInterval(recTimerRef.current);
      if (mr._cancelled) return;
      const blob = new Blob(chunksRef.current, { type: mr.mimeType || 'audio/webm' });
      if (blob.size < 900) { setError('El audio salió muy corto 🎧 probá de nuevo.'); return; }
      const b64 = await blobToBase64(blob);
      if (b64.length > 240 * 1024) { setError('El audio es muy largo, grabá algo más corto 🎧'); return; }
      sendAudio(b64, mr.mimeType || 'audio/webm');
    };
    mediaRecRef.current = mr;
    mr.start();
    setRecording(true); setRecSecs(0);
    let secs = 0;
    recTimerRef.current = setInterval(() => { secs += 1; setRecSecs(secs); if (secs >= REC_MAX_SECS) stopRec(); }, 1000);
  }
  function stopRec() {
    const mr = mediaRecRef.current;
    if (mr && mr.state !== 'inactive') mr.stop();
    setRecording(false);
    clearInterval(recTimerRef.current);
  }
  function cancelRec() {
    const mr = mediaRecRef.current;
    if (mr) { mr._cancelled = true; if (mr.state !== 'inactive') mr.stop(); }
    setRecording(false); setRecSecs(0);
    clearInterval(recTimerRef.current);
  }

  // Reintenta la verificación de Turnstile (re-lanza el desafío).
  function retryTurnstile() {
    setTsError(false); setError('');
    try { if (window.turnstile && widgetIdRef.current != null) window.turnstile.reset(widgetIdRef.current); } catch (_) {}
  }

  async function submitContact(ev) {
    if (ev) ev.preventDefault();
    const name = cName.trim();
    const contact = cContact.trim();
    if (!name || !contact || sending) return;
    setContactCaptured(true);
    setShowContactForm(false);
    setCName(''); setCContact('');
    // Lo mando como un turno más para que el handoff/email lo incluya.
    await send(`Mi nombre es ${name} y mi contacto es ${contact}.`);
    // Captado el contacto + ya derivado → la charla queda cerrada (el equipo sigue).
    // Evita el loop de "ya te pasé al equipo" repetido si el visitante sigue escribiendo.
    setClosed(true);
  }

  function goToAnchor(anchor) {
    const id = anchor.replace('#', '');
    const el = document.getElementById(id);
    if (el) { el.scrollIntoView({ behavior: 'smooth', block: 'start' }); setOpen(false); }
    else { window.location.hash = anchor; }
  }

  function onKeyDown(e) {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); send(); }
  }

  return (
    <div className="fixed z-[80] right-4 bottom-4 md:right-6 md:bottom-6 flex flex-col items-end gap-3">
      {/* Burbuja de saludo */}
      {hint && !open && (
        <div className="ng-bot-hint relative max-w-[250px] glass-strong rounded-2xl rounded-br-sm px-4 py-3 shadow-[0_18px_40px_-18px_rgba(0,0,0,0.7)]">
          <button type="button" aria-label="Cerrar"
            onClick={() => setHint(false)}
            className="absolute -top-2 -right-2 size-6 rounded-full flex items-center justify-center text-ink/80 hover:text-ink"
            style={{ background: 'rgba(8,10,16,0.92)', border: '1px solid rgba(244,241,234,0.18)' }}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18" /></svg>
          </button>
          <button type="button" onClick={() => { setOpen(true); setHint(false); }} className="text-left">
            <p className="text-[13.5px] leading-[1.45] text-ink/92">{NG_GREETING}</p>
          </button>
        </div>
      )}

      {/* Panel de chat real */}
      {open && (
        <div className="ng-bot-panel w-[300px] sm:w-[350px] rounded-2xl overflow-hidden card-solid-2 flex flex-col"
          style={{ boxShadow: '0 30px 70px -25px rgba(0,0,0,0.85), 0 0 0 1px rgba(51,194,234,0.18)', height: 'min(70vh, 540px)' }}>
          {/* header */}
          <div className="flex items-center gap-3 px-4 py-3 flex-none" style={{ background: 'linear-gradient(120deg, rgba(51,194,234,0.18), rgba(158,123,255,0.12)), rgba(10,12,18,0.96)', borderBottom: '1px solid rgba(244,241,234,0.08)' }}>
            <span className="size-9 rounded-full overflow-hidden flex-none" style={{ background: 'radial-gradient(circle at 50% 35%, rgba(51,194,234,0.35), rgba(10,12,18,0.9))', border: '1px solid rgba(51,194,234,0.5)' }}>
              <img src="assets/ngbot-icon.png" alt="" className="w-full h-full" style={{ objectFit: 'cover' }} />
            </span>
            <div className="flex-1 min-w-0">
              <div className="text-[13.5px] font-medium text-ink leading-tight">Galaxia</div>
              <div className="text-[11px] text-ink/60 flex items-center gap-1.5">
                <span className="size-1.5 rounded-full" style={{ background: '#50D2A0' }} /> en línea
              </div>
            </div>
            <button type="button" aria-label="Empezar de nuevo" title="Empezar de nuevo" onClick={reset}
              className="size-7 rounded-full flex items-center justify-center text-ink/65 hover:text-ink">
              <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.1" strokeLinecap="round" strokeLinejoin="round"><path d="M3 12a9 9 0 1 0 3-6.7L3 8" /><path d="M3 3v5h5" /></svg>
            </button>
            <button type="button" aria-label="Cerrar" onClick={() => setOpen(false)}
              className="size-7 rounded-full flex items-center justify-center text-ink/75 hover:text-ink">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18" /></svg>
            </button>
          </div>

          {/* historial */}
          <div ref={scrollRef} className="flex-1 overflow-y-auto px-4 py-4 flex flex-col gap-3 ng-chat-scroll" style={{ background: 'rgba(8,10,14,0.6)' }}>
            {messages.map((m, i) => (
              m.role === 'user' ? (
                <div key={i} className="self-end max-w-[82%] rounded-2xl rounded-br-sm px-3.5 py-2.5 text-[13.5px] leading-[1.5] whitespace-pre-wrap"
                  style={{ background: 'rgba(51,194,234,0.16)', border: '1px solid rgba(51,194,234,0.28)', color: '#EAF7FE' }}>
                  {m.text}
                </div>
              ) : (
                <div key={i} className="flex gap-2.5 items-end self-start max-w-[92%]">
                  <BotAvatar size={7} />
                  <div className="min-w-0">
                    <div className="rounded-2xl rounded-bl-sm px-3.5 py-2.5 text-[13.5px] leading-[1.5] text-ink/92 whitespace-pre-wrap"
                      style={{ background: 'rgba(244,241,234,0.06)', border: '1px solid rgba(244,241,234,0.10)' }}>
                      {m.text}
                    </div>
                    {m.chips && m.chips.length > 0 && (
                      <div className="flex flex-wrap gap-1.5 mt-1.5">
                        {m.chips.map((c) => (
                          <button key={c} type="button" onClick={() => goToAnchor(c)}
                            className="text-[11.5px] rounded-full px-2.5 py-1 text-cyan hover:text-ink transition-colors"
                            style={{ background: 'rgba(51,194,234,0.10)', border: '1px solid rgba(51,194,234,0.32)' }}>
                            {ANCHORS[c]} →
                          </button>
                        ))}
                      </div>
                    )}
                  </div>
                </div>
              )
            ))}

            {sending && (
              <div className="flex gap-2.5 items-end self-start">
                <BotAvatar size={7} />
                <div className="rounded-2xl rounded-bl-sm px-3.5 py-3 ng-typing" style={{ background: 'rgba(244,241,234,0.06)', border: '1px solid rgba(244,241,234,0.10)' }}>
                  <span /><span /><span />
                </div>
              </div>
            )}

            {/* form de contacto (backstop) */}
            {showContactForm && (
              <form onSubmit={submitContact} className="self-stretch rounded-xl p-3 mt-1 flex flex-col gap-2"
                style={{ background: 'rgba(158,123,255,0.08)', border: '1px solid rgba(158,123,255,0.30)' }}>
                <div className="text-[12.5px] text-ink/85 leading-snug">Dejame tus datos así el equipo te contacta 👇</div>
                <input value={cName} onChange={(e) => setCName(e.target.value)} placeholder="Tu nombre" maxLength={80}
                  className="rounded-lg px-3 py-2 text-[13px] text-ink bg-transparent outline-none"
                  style={{ background: 'rgba(8,10,14,0.7)', border: '1px solid rgba(244,241,234,0.14)' }} />
                <input value={cContact} onChange={(e) => setCContact(e.target.value)} placeholder="Email o WhatsApp" maxLength={120}
                  className="rounded-lg px-3 py-2 text-[13px] text-ink bg-transparent outline-none"
                  style={{ background: 'rgba(8,10,14,0.7)', border: '1px solid rgba(244,241,234,0.14)' }} />
                <button type="submit" disabled={!cName.trim() || !cContact.trim()}
                  className="btn-cta rounded-lg px-4 py-2 text-[13px] font-medium disabled:opacity-50"
                  style={{ background: 'linear-gradient(120deg, #33C2EA, #9E7BFF)', color: '#06121a' }}>
                  Enviar mis datos
                </button>
              </form>
            )}

            {error && <div className="self-start text-[12px] text-amber/90 px-1">{error}</div>}

            {/* Charla cerrada (derivada/pausada): cartel claro + reinicio, en vez de quedar muda. */}
            {closed && (
              <div className="self-stretch rounded-xl p-3 mt-1 text-center flex flex-col gap-2"
                style={{ background: 'rgba(51,194,234,0.07)', border: '1px solid rgba(51,194,234,0.22)' }}>
                <div className="text-[12.5px] text-ink/80 leading-snug">Esta consulta ya quedó con el equipo 🙌 Te van a contactar. ¿Querés empezar otra?</div>
                <button type="button" onClick={reset}
                  className="btn-cta rounded-lg px-4 py-2 text-[13px] font-medium self-center"
                  style={{ background: 'linear-gradient(120deg, #33C2EA, #9E7BFF)', color: '#06121a' }}>
                  Empezar otra consulta
                </button>
              </div>
            )}

            {/* Turnstile: contenedor compacto, se adapta al ancho del chat (solo dominio real). */}
            {NG_TURNSTILE_ON && <div id="ng-turnstile" className="self-stretch ng-turnstile-box" />}

            {/* Si Turnstile falla, salida amable: reintentar o WhatsApp — nunca queda trabado. */}
            {tsError && (
              <div className="self-stretch rounded-xl p-3 mt-1 flex flex-col gap-2"
                style={{ background: 'rgba(242,178,92,0.10)', border: '1px solid rgba(242,178,92,0.35)' }}>
                <div className="text-[12.5px] text-ink/85 leading-snug">No pudimos verificar tu navegador 🤖 Reintentá, o escribinos por WhatsApp y te atendemos igual.</div>
                <div className="flex gap-2">
                  <button type="button" onClick={retryTurnstile}
                    className="flex-1 rounded-lg px-3 py-1.5 text-[12.5px] font-medium text-cyan"
                    style={{ background: 'rgba(51,194,234,0.12)', border: '1px solid rgba(51,194,234,0.35)' }}>
                    Reintentar
                  </button>
                  <a href={NG_WA} target="_blank" rel="noopener noreferrer"
                    className="flex-1 rounded-lg px-3 py-1.5 text-[12.5px] font-medium inline-flex items-center justify-center gap-1.5"
                    style={{ background: '#25D366', color: '#06251a' }}>
                    <WhatsAppGlyph size={14} /> WhatsApp
                  </a>
                </div>
              </div>
            )}
          </div>

          {/* input */}
          <div className="px-3 py-2.5 flex-none flex items-end gap-2" style={{ background: 'rgba(10,12,18,0.96)', borderTop: '1px solid rgba(244,241,234,0.08)' }}>
            {recording ? (
              <div className="flex-1 flex items-center gap-2.5 rounded-xl px-3 py-2" style={{ background: 'rgba(158,123,255,0.12)', border: '1px solid rgba(158,123,255,0.35)' }}>
                <button type="button" aria-label="Cancelar grabación" onClick={cancelRec} className="text-ink/70 hover:text-ink flex-none">
                  <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><path d="M6 6l12 12M18 6L6 18" /></svg>
                </button>
                <span className="size-2.5 rounded-full ng-rec-dot flex-none" style={{ background: '#F2607A' }} />
                <span className="text-[12.5px] text-ink/85 flex-1 tabular-nums">Grabando… {Math.floor(recSecs / 60)}:{String(recSecs % 60).padStart(2, '0')}</span>
                <button type="button" aria-label="Enviar audio" onClick={stopRec}
                  className="size-9 rounded-full flex-none flex items-center justify-center"
                  style={{ background: 'linear-gradient(120deg, #33C2EA, #9E7BFF)', color: '#06121a' }}>
                  <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7Z" /></svg>
                </button>
              </div>
            ) : (
              <>
                <textarea value={input} onChange={(e) => setInput(e.target.value)} onKeyDown={onKeyDown}
                  rows={1} placeholder={closed ? 'Tocá "Empezar otra consulta"…' : (showContactForm ? 'Completá tus datos arriba 👆' : 'Escribí o mandá un audio…')} maxLength={2000} disabled={closed || showContactForm}
                  className="flex-1 resize-none rounded-xl px-3 py-2 text-[13.5px] text-ink bg-transparent outline-none ng-chat-input disabled:opacity-50"
                  style={{ background: 'rgba(8,10,14,0.7)', border: '1px solid rgba(244,241,234,0.12)', maxHeight: '88px' }} />
                {input.trim() ? (
                  <button type="button" aria-label="Enviar" onClick={() => send()} disabled={sending || closed || showContactForm}
                    className="size-9 rounded-full flex-none flex items-center justify-center disabled:opacity-40 transition-opacity"
                    style={{ background: 'linear-gradient(120deg, #33C2EA, #9E7BFF)', color: '#06121a' }}>
                    <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round"><path d="M22 2L11 13M22 2l-7 20-4-9-9-4 20-7Z" /></svg>
                  </button>
                ) : (
                  <button type="button" aria-label="Grabar audio" title="Mandá una nota de voz" onClick={startRec} disabled={sending || closed || showContactForm}
                    className="size-9 rounded-full flex-none flex items-center justify-center disabled:opacity-40 transition-opacity"
                    style={{ background: 'rgba(158,123,255,0.18)', border: '1px solid rgba(158,123,255,0.4)', color: '#C9B8FF' }}>
                    <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2a3 3 0 0 0-3 3v6a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" /><path d="M19 10v1a7 7 0 0 1-14 0v-1M12 18v4" /></svg>
                  </button>
                )}
              </>
            )}
          </div>

          {/* fallback WhatsApp, discreto */}
          <a href={NG_WA} target="_blank" rel="noopener noreferrer"
            className="flex-none text-[11px] text-ink/55 hover:text-ink/85 text-center py-1.5 transition-colors"
            style={{ background: 'rgba(10,12,18,0.96)', borderTop: '1px solid rgba(244,241,234,0.05)' }}>
            ¿Preferís WhatsApp? Escribinos directo
          </a>
        </div>
      )}

      {/* Botones flotantes: Galaxia · Instagram · WhatsApp */}
      <div className="flex flex-col items-center gap-3">
        <button type="button" aria-label={open ? 'Cerrar asistente' : 'Abrir asistente'}
          onClick={() => { setOpen((o) => !o); setHint(false); }}
          className="ng-fab ng-fab-bot relative size-12">
          <span aria-hidden="true" className="absolute inset-0 rounded-full ng-bot-pulse" />
          <span className="relative block w-full h-full rounded-full overflow-hidden">
            <img src="assets/ngbot-icon.png" alt="Asistente newGalaxIA"
              className="w-full h-full" style={{ objectFit: 'cover', transform: 'scale(1.06)' }} />
          </span>
        </button>
        <a href="https://instagram.com/new_galaxia" target="_blank" rel="noopener noreferrer" aria-label="Seguinos en Instagram"
          className="ng-fab size-12 rounded-full flex items-center justify-center text-white shadow-[0_12px_30px_-10px_rgba(214,41,118,0.6)]"
          style={{ background: 'radial-gradient(circle at 30% 110%, #FEDA77 0%, #F58529 18%, #DD2A7B 48%, #8134AF 72%, #515BD4 100%)' }}>
          <InstagramGlyph size={22} />
        </a>
        <a href={NG_WA} target="_blank" rel="noopener noreferrer" aria-label="Escribinos por WhatsApp"
          className="ng-fab size-12 rounded-full flex items-center justify-center text-white shadow-[0_12px_30px_-10px_rgba(37,211,102,0.7)]"
          style={{ background: '#25D366' }}>
          <WhatsAppGlyph size={24} />
        </a>
      </div>

      <style>{`
        .ng-fab{ transition: transform .3s cubic-bezier(.65,0,.35,1), box-shadow .3s ease; }
        .ng-fab:hover{ transform: translateY(-3px) scale(1.05); }
        .ng-fab-bot{ background: transparent; filter: drop-shadow(0 10px 22px rgba(51,194,234,0.55)); }
        .ng-bot-pulse{ box-shadow: 0 0 0 0 rgba(51,194,234,0.5); animation: ng-bot-pulse 2.6s cubic-bezier(0.4,0,0.6,1) infinite; }
        @keyframes ng-bot-pulse{ 0%{ box-shadow:0 0 0 0 rgba(51,194,234,0.5);} 70%{ box-shadow:0 0 0 14px rgba(51,194,234,0);} 100%{ box-shadow:0 0 0 0 rgba(51,194,234,0);} }
        .ng-bot-hint{ animation: ng-bot-pop .4s cubic-bezier(.16,1,.3,1) both; }
        .ng-bot-panel{ animation: ng-bot-pop .32s cubic-bezier(.16,1,.3,1) both; }
        @keyframes ng-bot-pop{ from{ opacity:0; transform: translateY(8px) scale(.96);} to{ opacity:1; transform:none;} }
        .ng-chat-scroll::-webkit-scrollbar{ width:6px; } .ng-chat-scroll::-webkit-scrollbar-thumb{ background:rgba(244,241,234,0.14); border-radius:3px; }
        .ng-typing{ display:inline-flex; gap:4px; align-items:center; }
        .ng-typing span{ width:6px; height:6px; border-radius:50%; background:rgba(244,241,234,0.55); animation: ng-typing 1.2s infinite ease-in-out; }
        .ng-typing span:nth-child(2){ animation-delay:.18s; } .ng-typing span:nth-child(3){ animation-delay:.36s; }
        @keyframes ng-typing{ 0%,60%,100%{ transform:translateY(0); opacity:.5; } 30%{ transform:translateY(-4px); opacity:1; } }
        .ng-rec-dot{ animation: ng-rec 1.1s ease-in-out infinite; }
        @keyframes ng-rec{ 0%,100%{ opacity:1; } 50%{ opacity:.3; } }
        .ng-turnstile-box{ margin:2px 0; }
        .ng-turnstile-box:empty{ display:none; }
        .ng-turnstile-box iframe{ max-width:100% !important; }
        @media (prefers-reduced-motion: reduce){ .ng-bot-pulse,.ng-bot-hint,.ng-bot-panel,.ng-typing span,.ng-rec-dot{ animation:none; } }
      `}</style>
    </div>
  );
}

window.BotLauncher = BotLauncher;
