// IA — 3-column intelligence center

// =================== LEFT ===================
const IA_NAV = [
  { id: 'hot',    icon: 'flame',    label: 'Leads quentes',   prompt: 'Me liste os leads quentes em ordem de prioridade de fechamento e o que fazer com cada um.' },
  { id: 'crm',    icon: 'trending', label: 'Análise do CRM',  prompt: 'Faça uma análise completa do meu funil CRM: identifique os principais bottlenecks e oportunidades.' },
  { id: 'msgs',   icon: 'msgs',     label: 'Mensagens',       prompt: 'Resuma o estado das minhas conversas de WhatsApp. Quais contatos precisam de atenção urgente?' },
  { id: 'report', icon: 'chart',    label: 'Relatórios',      prompt: 'Gere um relatório de vendas da semana atual com as principais métricas do funil.' },
  { id: 'agenda', icon: 'cal',      label: 'Agenda',          prompt: 'Organize minha agenda: quais leads priorizar para contato hoje e em qual horário.' },
  { id: 'auto',   icon: 'flow',     label: 'Automações',      prompt: 'Sugira automações de WhatsApp para melhorar meu funil: follow-ups, boas-vindas e reativação.' },
];

function IALeft({ search, onSearch, conversations, activeId, onSelectConv, onNewConversation, onSend, onClose, onDeleteConv }) {
  const [showSearch,     setShowSearch]     = React.useState(false);
  const [confirmId,      setConfirmId]      = React.useState(null);
  const searchRef = React.useRef(null);

  React.useEffect(() => {
    if (showSearch) searchRef.current?.focus();
    else onSearch('');
  }, [showSearch]);

  const filtered = (conversations || []).filter(c =>
    !search || c.title.toLowerCase().includes(search.toLowerCase())
  );

  return (
    <aside className="ia-left">
      {/* Topbar */}
      <div className="ia-left-topbar">
        <span className="ia-left-brand">Horos AI</span>
        <div className="ia-left-topbar-icons">
          <button className="icon-btn" title="Pesquisar" onClick={() => setShowSearch(s => !s)}>
            <Icon name="search" size={15} stroke={1.8} />
          </button>
          <button className="icon-btn ia-close-btn" title="Fechar painel" onClick={onClose}>
            <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
              <rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18"/>
            </svg>
          </button>
        </div>
      </div>

      {/* Search input (toggleable) */}
      {showSearch && (
        <div className="ia-left-search">
          <Icon name="search" size={13} />
          <input ref={searchRef} value={search} onChange={e => onSearch(e.target.value)}
                 placeholder="Pesquisar conversas…" />
        </div>
      )}

      {/* Nova conversa */}
      <button className="ia-new-conv-btn" onClick={onNewConversation}>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z"/>
        </svg>
        Nova conversa
      </button>

      {/* Menu de atalhos */}
      <nav className="ia-left-nav">
        {IA_NAV.map(item => (
          <button key={item.id} className="ia-nav-item" onClick={() => onSend(item.prompt)}>
            <span className="ia-nav-icon"><Icon name={item.icon} size={16} stroke={1.8} /></span>
            <span className="ia-nav-label">{item.label}</span>
          </button>
        ))}
      </nav>

      {/* Histórico */}
      <div className="ia-left-hist-section">
        <div className="ia-hist-section-label">Recente</div>
        {filtered.length > 0
          ? filtered.map(conv => (
              <div key={conv.id} className="ia-hist-item-wrap">
                <button className={`ia-hist-item ${activeId === conv.id ? 'active' : ''}`}
                        onClick={() => onSelectConv(conv.id)}>
                  <span className="ia-hist-title">{conv.title}</span>
                  <span className="ia-hist-time">{conv.time}</span>
                </button>
                <button className="ia-hist-del" title="Apagar conversa"
                        onClick={e => { e.stopPropagation(); setConfirmId(conv.id); }}>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"/>
                  </svg>
                </button>
              </div>
            ))
          : <p className="ia-hist-empty-msg">{search ? 'Nenhum resultado.' : 'Nenhuma conversa ainda.'}</p>
        }

        {/* Modal de confirmação de exclusão */}
        {confirmId && (
          <div className="ia-del-overlay" onClick={() => setConfirmId(null)}>
            <div className="ia-del-modal" onClick={e => e.stopPropagation()}>
              <div className="ia-del-icon">
                <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M3 6h18M8 6V4h8v2M19 6l-1 14H6L5 6"/>
                </svg>
              </div>
              <p className="ia-del-title">Apagar conversa?</p>
              <p className="ia-del-sub">Essa ação não pode ser desfeita.</p>
              <div className="ia-del-actions">
                <button className="ia-del-cancel" onClick={() => setConfirmId(null)}>Cancelar</button>
                <button className="ia-del-confirm" onClick={() => { onDeleteConv(confirmId); setConfirmId(null); }}>Apagar</button>
              </div>
            </div>
          </div>
        )}
      </div>
    </aside>
  );
}

// =================== CENTER ===================
function AiOrb({ size = 36, animated = true }) {
  return (
    <span className={`ia-orb-lg ${animated ? 'animated' : ''}`} style={{ width: size, height: size }}>
      <span className="ia-orb-aura" />
      <span className="ia-orb-aura two" />
      <Icon name="sparkles" size={Math.round(size * 0.4)} stroke={1.8} />
    </span>
  );
}

function ChatHead({ leftOpen, onToggleLeft }) {
  if (leftOpen) return null;
  return (
    <div className="ia-chat-head ia-chat-head--slim">
      <button className="icon-btn" title="Mostrar histórico" onClick={onToggleLeft}>
        <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <rect x="3" y="3" width="18" height="18" rx="2"/><path d="M9 3v18"/>
        </svg>
      </button>
    </div>
  );
}

// rich block renderers
function renderInline(text) {
  return text.split(/\*\*([^*]+)\*\*/g).map((p, i) => i % 2 ? <b key={i}>{p}</b> : p);
}

function TextBlock({ text, refs }) {
  if (window.HorosRichText) return <HorosRichText text={text} refs={refs} className="ia-text-block ia-rich" />;
  const lines = text.split('\n');
  return (
    <div className="ia-text-block">
      {lines.map((line, li) => {
        if (!line.trim()) return <div key={li} className="ia-text-gap" />;
        const isBullet = /^[-•]\s/.test(line.trimStart());
        const raw = isBullet ? line.replace(/^[\s\-•]+/, '') : line;
        if (isBullet) return (
          <div key={li} className="ia-text-li">
            <span className="ia-text-dot" />
            <span>{renderInline(raw)}</span>
          </div>
        );
        return <p key={li} className="ia-text">{renderInline(raw)}</p>;
      })}
    </div>
  );
}

function OppCard({ o }) {
  const map = {
    hot:   { color: '#ff5a4e', bg: 'rgba(255,90,78,0.12)',  border: 'rgba(255,90,78,0.22)' },
    warn:  { color: '#f5b544', bg: 'rgba(245,181,68,0.12)', border: 'rgba(245,181,68,0.22)' },
    up:    { color: '#34d399', bg: 'rgba(52,211,153,0.12)', border: 'rgba(52,211,153,0.22)' },
    match: { color: '#c084fc', bg: 'rgba(168,85,247,0.12)', border: 'rgba(168,85,247,0.22)' },
  };
  const m = map[o.kind];
  return (
    <div className="ia-opp" style={{ '--opp-color': m.color, '--opp-bg': m.bg, '--opp-border': m.border }}>
      <div className="ia-opp-top">
        {o.avatar ? (
          <div className="lead-avatar" style={{ background: `linear-gradient(135deg, ${o.avatar.palette[0]}, ${o.avatar.palette[1]})`, width: 32, height: 32, fontSize: 11.5 }}>
            {o.avatar.initials}
          </div>
        ) : (
          <span className="ia-opp-icon"><Icon name={o.icon} size={14} stroke={2} /></span>
        )}
        <div className="ia-opp-meta">
          <span className="ia-opp-name">{o.name}</span>
          <span className="ia-opp-headline"><Icon name={o.icon} size={11} stroke={2} /> {o.headline}</span>
        </div>
      </div>
      <span className="ia-opp-detail">{o.meta}</span>
      <div className="ia-opp-actions">
        <button className="btn-soft"><Icon name="bolt" size={11} stroke={2} /> {o.action.primary}</button>
        {o.action.secondary && <button className="ghost-btn">{o.action.secondary} <Icon name="arrRight" size={11} stroke={2} /></button>}
      </div>
    </div>
  );
}

function OppCards({ items }) {
  return (
    <div className="ia-opp-grid">
      {items.map((o, i) => <OppCard key={i} o={o} />)}
    </div>
  );
}

function PriorityTable({ items }) {
  return (
    <div className="ia-table-wrap">
      <table className="ia-table">
        <thead>
          <tr>
            <th style={{ width: 32 }}>#</th>
            <th>Cliente</th>
            <th>Motivo</th>
            <th>Próx. janela</th>
            <th style={{ width: 56 }}>Score</th>
            <th style={{ width: 32 }}></th>
          </tr>
        </thead>
        <tbody>
          {items.map(it => (
            <tr key={it.rank}>
              <td><span className="ia-rank">{it.rank}</span></td>
              <td>
                <div className="cell-name">
                  <div className="avatar" style={{ background: `linear-gradient(135deg, ${it.palette[0]}, ${it.palette[1]})`, width: 26, height: 26, fontSize: 10 }}>
                    {it.initials}
                  </div>
                  <span className="name">{it.name}</span>
                </div>
              </td>
              <td><span className="ia-reason">{it.reason}</span></td>
              <td><span className={`action-when ${it.urgency ? `due-${it.urgency}` : ''}`}>{it.when}</span></td>
              <td>
                <div className="score-cell" style={{ gap: 6 }}>
                  <ScoreRing score={it.score} />
                  <span className="score-num">{it.score}</span>
                </div>
              </td>
              <td>
                <button className="icon-btn" style={{ width: 24, height: 24 }}>
                  <Icon name="arrRight" size={12} stroke={2} />
                </button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

function Callout({ block }) {
  const tones = {
    hot:  { color: '#ff5a4e', bg: 'rgba(255,90,78,0.10)',  border: 'rgba(255,90,78,0.28)' },
    warn: { color: '#f5b544', bg: 'rgba(245,181,68,0.10)', border: 'rgba(245,181,68,0.28)' },
    ok:   { color: '#34d399', bg: 'rgba(52,211,153,0.10)', border: 'rgba(52,211,153,0.28)' },
  };
  const m = tones[block.tone] || tones.hot;
  return (
    <div className="ia-callout" style={{ '--c-color': m.color, '--c-bg': m.bg, '--c-border': m.border }}>
      <div className="ia-callout-head">
        <span className="ia-callout-icon"><Icon name={block.icon} size={12} stroke={2} /></span>
        <span className="ia-callout-title">{block.title}</span>
      </div>
      <p className="ia-callout-body">{block.body}</p>
      {block.action && (
        <button className="ia-callout-action">
          <Icon name={block.action.icon} size={12} stroke={2} />
          {block.action.label}
        </button>
      )}
    </div>
  );
}

function MiniChart({ block }) {
  const { bars, labels, peakIdx, title, note } = block;
  const max = Math.max(...bars);
  return (
    <div className="ia-chart">
      <div className="ia-chart-head">
        <span className="ia-chart-title">{title}</span>
        <span className="ia-chart-peak">
          <Icon name="trending" size={11} stroke={2} />
          Pico: {labels[peakIdx]}
        </span>
      </div>
      <div className="ia-chart-body">
        {bars.map((v, i) => (
          <div key={i} className="ia-bar-col">
            <div className={`ia-bar ${i === peakIdx ? 'peak' : ''}`} style={{ height: `${(v / max) * 100}%` }}>
              {i === peakIdx && <span className="ia-bar-value">{v}%</span>}
            </div>
            <span className="ia-bar-label">{labels[i]}</span>
          </div>
        ))}
      </div>
      <div className="ia-chart-note"><Icon name="sparkles" size={10} stroke={2} /> {note}</div>
    </div>
  );
}

function AudioPlayer({ src }) {
  const [playing, setPlaying] = React.useState(false);
  const [current, setCurrent] = React.useState(0);
  const [dur,     setDur]     = React.useState(0);
  const aRef = React.useRef(null);

  const toggle = () => {
    const a = aRef.current; if (!a) return;
    if (playing) { a.pause(); setPlaying(false); }
    else { a.play().then(() => setPlaying(true)).catch(() => {}); }
  };
  const fmt = s => { if (!s || isNaN(s)) return '0:00'; return `${Math.floor(s/60)}:${String(Math.floor(s%60)).padStart(2,'0')}`; };
  const progress = dur > 0 ? current / dur : 0;
  const BARS = Array.from({ length: 28 }, (_, i) => 20 + Math.abs(Math.sin(i*0.9)*40 + Math.cos(i*1.7)*20));

  return (
    <div className="ia-audio-player">
      <audio ref={aRef} src={src}
             onTimeUpdate={() => setCurrent(aRef.current?.currentTime || 0)}
             onLoadedMetadata={() => setDur(aRef.current?.duration || 0)}
             onEnded={() => { setPlaying(false); setCurrent(0); }} />
      <button className="ia-audio-play" onClick={toggle}>
        {playing
          ? <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></svg>
          : <svg width="11" height="11" viewBox="0 0 24 24" fill="currentColor"><polygon points="5,3 19,12 5,21"/></svg>}
      </button>
      <div className="ia-audio-wave">
        {BARS.map((h, i) => (
          <div key={i} className={`ia-audio-bar${i/BARS.length <= progress ? ' played' : ''}`}
               style={{ height: `${h}%` }} />
        ))}
      </div>
      <span className="ia-audio-time">{fmt(playing ? current : dur)}</span>
    </div>
  );
}

function IaMsgFile({ block }) {
  const ext = (block.name || 'arquivo').split('.').pop().toUpperCase().slice(0, 6);
  return (
    <div className="ia-msg-file">
      <div className="ia-msg-file-icon">
        <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
          <polyline points="14 2 14 8 20 8"/>
        </svg>
      </div>
      <div className="ia-msg-file-meta">
        <span className="ia-msg-file-name">{block.name}</span>
        <span className="ia-msg-file-ext">{ext}</span>
      </div>
    </div>
  );
}

function AiBlocks({ blocks }) {
  return (
    <>
      {(blocks || []).map((b, i) => {
        if (b.kind === 'image')         return <img key={i} src={b.url} alt={b.name} className="ia-msg-img" />;
        if (b.kind === 'video')         return <video key={i} src={b.url} controls className="ia-msg-video" />;
        if (b.kind === 'audio')         return <AudioPlayer key={i} src={b.url} />;
        if (b.kind === 'file')          return <IaMsgFile key={i} block={b} />;
        if (b.kind === 'text')          return <TextBlock key={i} text={b.text} refs={b.refs} />;
        if (b.kind === 'oppCards')      return <OppCards key={i} items={b.items} />;
        if (b.kind === 'priorityTable') return <PriorityTable key={i} items={b.items} />;
        if (b.kind === 'callout')       return <Callout key={i} block={b} />;
        if (b.kind === 'miniChart')     return <MiniChart key={i} block={b} />;
        return null;
      })}
    </>
  );
}

// =================== PENSANDO — mascote do Horos (horos-mascot.js) ===================
// Enquanto a IA responde o mascote "trabalha": Pensando/Buscando = olhos procurando + órbita ·
// Analisando = olhos fechados + órbita · Escrevendo = falando. Ao terminar: pulinho feliz + "Pronto".
const IA_THINK_STEPS = [['Pensando', 'thinking'], ['Buscando', 'thinking'], ['Analisando', 'loading'], ['Escrevendo', 'talking']];

function IAThinking({ done }) {
  const [lab, setLab] = React.useState({ i: 0, cur: IA_THINK_STEPS[0][0], prev: null, n: 0 });

  React.useEffect(() => {
    if (done) { setLab(l => ({ ...l, cur: 'Pronto', prev: l.cur, n: l.n + 1 })); return; }
    const timer = setInterval(() => setLab(l => {
      const i = (l.i + 1) % IA_THINK_STEPS.length;
      return { i, cur: IA_THINK_STEPS[i][0], prev: l.cur, n: l.n + 1 };
    }), 1400);
    return () => clearInterval(timer);
  }, [done]);

  const inner = (t) => t === 'Pronto'
    ? <span className="ia-think-done">{t}</span>
    : <><span className="ia-think-t">{t}</span><span className="ia-think-dots" aria-hidden="true"><i /><i /><i /></span></>;

  return (
    <div className={`ia-think${done ? ' is-done' : ''}`} role="status" aria-live="polite" aria-label={done ? 'Resposta pronta' : 'A IA está pensando'}>
      <div className="ia-think-stage">
        <div className="ia-think-halo" aria-hidden="true" />
        <horos-mascot size="88" state={done ? 'done' : IA_THINK_STEPS[lab.i][1]} aria-hidden="true" />
      </div>
      <div className="ia-think-status" aria-hidden="true">
        {lab.prev !== null && <span key={'p' + lab.n} className="ia-think-lab out">{inner(lab.prev)}</span>}
        <span key={'c' + lab.n} className="ia-think-lab in">{inner(lab.cur)}</span>
      </div>
    </div>
  );
}

// Mascote grande da tela vazia: clique → reage
const IA_MASCOT_REACTIONS = ['happy', 'wink', 'excited', 'surprised', 'confident'];
function IAEmptyMascot() {
  const ref = React.useRef(null);
  React.useEffect(() => {
    const t = setTimeout(() => ref.current?.react?.('wink', 1300), 700);
    return () => clearTimeout(t);
  }, []);
  return (
    <button type="button" className="ia-mascot-hero" title="Oi! Sou o assistente do Horos"
            onClick={() => ref.current?.react?.(IA_MASCOT_REACTIONS[Math.floor(Math.random() * IA_MASCOT_REACTIONS.length)], 1600)}>
      <horos-mascot ref={ref} size="112" />
    </button>
  );
}

function TypingIndicator() {
  return (
    <div className="ia-msg ia-msg--ai">
      <div className="ia-msg__ai">
        <div className="ia-typing-dots"><span /><span /><span /></div>
      </div>
    </div>
  );
}

function ChatBody({ thread, loading }) {
  const endRef = React.useRef(null);
  // Quando a resposta chega, o orbe ainda mostra "Pronto" (~1,1 s) antes da resposta aparecer
  const [resolving, setResolving] = React.useState(false);
  const prevLoading = React.useRef(loading);
  React.useEffect(() => {
    const was = prevLoading.current;
    prevLoading.current = loading;
    if (was && !loading) {
      setResolving(true);
      const t = setTimeout(() => setResolving(false), 1150);
      return () => clearTimeout(t);
    }
    if (loading) setResolving(false);
  }, [loading]);
  const hideLast = resolving && thread.length > 0 && thread[thread.length - 1].from === 'ai';
  const shown = hideLast ? thread.slice(0, -1) : thread;

  React.useEffect(() => {
    endRef.current?.scrollIntoView({ behavior: 'smooth' });
  }, [shown.length, loading, resolving]);

  if (!thread.length && !loading) {
    return (
      <div className="ia-chat-body ia-chat-empty">
        <IAEmptyMascot />
        <p className="ia-empty-title">Sempre por perto, pra te ajudar.</p>
        <p className="ia-empty-sub">Pergunte sobre seus leads, funil, prioridades ou peça um resumo do dia.</p>
      </div>
    );
  }

  return (
    <div className="ia-chat-body">
      {shown.map((m, i) => (
        <div key={i} className={`ia-msg ia-msg--${m.from}${i === shown.length - 1 && m.from === 'ai' && !loading ? ' ia-msg--fresh' : ''}`}>
          {m.from === 'user'
            ? <div className="ia-msg__bubble"><AiBlocks blocks={m.blocks} /></div>
            : <div className="ia-msg__ai">
                <div className="ia-msg__who"><horos-mascot size="22" float="off" aria-hidden="true" /> Horos</div>
                <AiBlocks blocks={m.blocks} />
              </div>
          }
          <span className="ia-msg__time">{m.time}</span>
        </div>
      ))}
      {(loading || resolving) && <IAThinking key="think" done={!loading} />}
      <div ref={endRef} />
    </div>
  );
}

// =================== SUGESTÕES (adaptação do "Suggestions" do nexus-ui) ===================
// Mesma API do original — Suggestions · SuggestionList · Suggestion · SuggestionPanel
// (+ Header/Title/Close/Content) — sem Tailwind/Radix: classes .nx-* em ia-styles.css.
// Variantes do chip: filled (padrão) · outline · ghost. `highlight` apaga as palavras do tema.
const NxSuggestionsCtx = React.createContext({});

function Suggestions({ className = '', onSelect, children, ...props }) {
  return (
    <NxSuggestionsCtx.Provider value={{ onSelect }}>
      <div data-slot="suggestions" role="group" aria-label="Sugestões" className={`nx-suggestions ${className}`} {...props}>{children}</div>
    </NxSuggestionsCtx.Provider>
  );
}

function SuggestionList({ className = '', orientation = 'horizontal', ...props }) {
  return <div data-slot="suggestion-list" role="group" className={`nx-sugg-list ${orientation} ${className}`} {...props} />;
}

function nxHighlight(text, terms) {
  const list = (Array.isArray(terms) ? terms : [terms]).filter(Boolean);
  if (!list.length) return text;
  const esc = list.map(t => t.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'));
  const re = new RegExp(`(${esc.join('|')})`, 'gi');
  return text.split(re).map((part, i) =>
    esc.some(e => new RegExp(`^${e}$`, 'i').test(part))
      ? <span key={i} className="nx-hl">{part}</span>
      : <span key={i}>{part}</span>);
}

function Suggestion({ className = '', value, variant = 'filled', highlight, onClick, children, active, ...props }) {
  const { onSelect } = React.useContext(NxSuggestionsCtx);
  const text = value ?? (typeof children === 'string' ? children : '');
  const rendered = highlight && typeof children === 'string' ? nxHighlight(children, highlight) : children;
  return (
    <button type="button" data-slot="suggestion"
      className={`nx-sugg nx-${variant}${active ? ' active' : ''} ${className}`}
      onClick={(e) => { onClick && onClick(e); if (text && onSelect) onSelect(text); }} {...props}>
      {rendered}
    </button>
  );
}

const NX_FOCUSABLE = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
const NxPanelCtx = React.createContext(null);

// Painel que sai de trás do campo de mensagem. Esc fecha, Tab fica preso dentro, foca o 1º item ao abrir.
function SuggestionPanel({ className = '', open = true, onOpenChange, children, ...props }) {
  const ref = React.useRef(null);
  const [mounted, setMounted] = React.useState(open);
  React.useEffect(() => { if (open) setMounted(true); }, [open]);

  React.useEffect(() => {
    if (!open) return;
    const k = (e) => { if (e.key === 'Escape') { e.stopPropagation(); onOpenChange && onOpenChange(false); } };
    window.addEventListener('keydown', k);
    return () => window.removeEventListener('keydown', k);
  }, [open, onOpenChange]);

  React.useEffect(() => {
    if (!open || !ref.current) return;
    const f = ref.current.querySelectorAll(NX_FOCUSABLE);
    const first = Array.from(f).find(el => el.dataset.slot === 'suggestion') || f[0];
    if (first) first.focus({ preventScroll: true });
  }, [open, mounted]);

  const onKeyDown = (e) => {
    if (e.key !== 'Tab' || !ref.current) return;
    const f = Array.from(ref.current.querySelectorAll(NX_FOCUSABLE));
    if (!f.length) return;
    const first = f[0], last = f[f.length - 1];
    if (e.shiftKey && document.activeElement === first) { e.preventDefault(); last.focus(); }
    else if (!e.shiftKey && document.activeElement === last) { e.preventDefault(); first.focus(); }
  };

  if (!mounted) return null;
  return (
    <div ref={ref} data-slot="suggestion-panel" role="dialog" aria-label="Painel de sugestões"
      data-state={open ? 'open' : 'closed'} className={`nx-panel ${className}`} onKeyDown={onKeyDown}
      onAnimationEnd={(e) => { if (e.animationName === 'nxPanelOut' && !open) setMounted(false); }} {...props}>
      <NxPanelCtx.Provider value={{ onOpenChange }}>{children}</NxPanelCtx.Provider>
    </div>
  );
}

function SuggestionPanelHeader({ className = '', ...props }) { return <div data-slot="suggestion-panel-header" className={`nx-panel-head ${className}`} {...props} />; }
function SuggestionPanelTitle({ className = '', ...props }) { return <div data-slot="suggestion-panel-title" className={`nx-panel-title ${className}`} {...props} />; }
function SuggestionPanelClose({ className = '', onClick, ...props }) {
  const ctx = React.useContext(NxPanelCtx);
  return (
    <button type="button" data-slot="suggestion-panel-close" aria-label="Fechar sugestões" title="Fechar (Esc)"
      className={`nx-panel-close ${className}`} onClick={(e) => { ctx && ctx.onOpenChange && ctx.onOpenChange(false); onClick && onClick(e); }} {...props} />
  );
}
function SuggestionPanelContent({ className = '', ...props }) { return <div data-slot="suggestion-panel-content" className={`nx-panel-content ${className}`} {...props} />; }

// Uso na tela de IA: chips de tema abaixo do campo; o tema abre o painel (atrás do campo) com as perguntas.
// Temas mudam com o ramo da empresa (workspaces.segment): ex.: "Financiamento" só no imobiliário.
const iaGroupsOf = (segment) => (window.iaSuggestionGroups ? window.iaSuggestionGroups(segment) : (window.IA_SUGGESTION_GROUPS || []));
function IASuggestionPanel({ groupId, open, onClose, onPick, disabled }) {
  const segment = window.useHorosSegment ? window.useHorosSegment() : 'imobiliario';
  const group = iaGroupsOf(segment).find(g => g.id === groupId);
  if (!group) return null;
  return (
    <SuggestionPanel open={open} onOpenChange={(o) => { if (!o) onClose(); }}>
      <SuggestionPanelHeader>
        <SuggestionPanelTitle><Icon name={group.icon} size={15} stroke={1.8} /> {group.label}</SuggestionPanelTitle>
        <SuggestionPanelClose><Icon name="close" size={15} stroke={2} /></SuggestionPanelClose>
      </SuggestionPanelHeader>
      <SuggestionPanelContent>
        <Suggestions onSelect={onPick}>
          <SuggestionList orientation="vertical">
            {group.items.map(q => (
              <Suggestion key={q} variant="ghost" highlight={group.highlight} disabled={disabled}>{q}</Suggestion>
            ))}
          </SuggestionList>
        </Suggestions>
      </SuggestionPanelContent>
    </SuggestionPanel>
  );
}

function IASuggestionRow({ openId, onToggle, disabled }) {
  const segment = window.useHorosSegment ? window.useHorosSegment() : 'imobiliario';
  const groups = iaGroupsOf(segment);
  return (
    <Suggestions className="ia-sugg-row">
      <SuggestionList>
        {groups.map(g => (
          <Suggestion key={g.id} variant="filled" active={openId === g.id} disabled={disabled}
            aria-expanded={openId === g.id} onClick={() => onToggle(g.id)}>
            <Icon name={g.icon} size={15} stroke={1.8} /> {g.label}
          </Suggestion>
        ))}
      </SuggestionList>
    </Suggestions>
  );
}

function ChatInput({ draft, setDraft, onSend, loading }) {
  const [pending,    setPending]    = React.useState(null);
  const [recording,  setRecording]  = React.useState(false);
  const [transcript, setTranscript] = React.useState('');
  const [attachOpen, setAttachOpen] = React.useState(false);
  const recognitionRef = React.useRef(null);
  const recordingRef   = React.useRef(false);
  const photoRef  = React.useRef(null);
  const docRef    = React.useRef(null);
  const attachRef = React.useRef(null);
  const inputRef  = React.useRef(null);
  const [sgOpen, setSgOpen] = React.useState(null);   // tema aberto no painel de sugestões
  const [sgLast, setSgLast] = React.useState(null);   // último tema (mantém o painel durante a animação de saída)
  const toggleSg = (id) => { setSgOpen(o => o === id ? null : id); setSgLast(id); };
  const closeSg = () => { setSgOpen(null); requestAnimationFrame(() => inputRef.current?.focus()); };
  const pickSg = (text) => { setDraft(text); closeSg(); };

  React.useEffect(() => { recordingRef.current = recording; }, [recording]);

  React.useEffect(() => {
    if (!attachOpen) return;
    const h = e => { if (!attachRef.current?.contains(e.target)) setAttachOpen(false); };
    document.addEventListener('mousedown', h);
    return () => document.removeEventListener('mousedown', h);
  }, [attachOpen]);

  const handleKey = e => {
    if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(); }
  };

  function handleSubmit() {
    if (loading) return;
    if (pending) {
      const caption   = draft.trim();
      const kindLabel = pending.kind === 'image' ? 'Imagem' : 'Arquivo';
      onSend({
        text: caption || `${kindLabel}: ${pending.file.name}`,
        blocks: [
          { kind: pending.kind, url: pending.url, name: pending.file.name },
          ...(caption ? [{ kind: 'text', text: caption }] : []),
        ],
        fileData: pending.base64 ? { base64: pending.base64, mimeType: pending.mimeType, name: pending.file.name } : null,
      });
      setDraft('');
      setPending(null);
      return;
    }
    const text = draft.trim();
    if (!text) return;
    setDraft('');
    onSend(text);
  }

  function handleFile(e, forceKind) {
    const file = e.target.files?.[0];
    if (!file) return;
    const kind = forceKind === 'file' ? 'file' : file.type.startsWith('image/') ? 'image' : 'file';
    const url  = URL.createObjectURL(file);
    const reader = new FileReader();
    reader.onload = ev => {
      const base64 = ev.target.result.split(',')[1];
      setPending({ file, url, kind, base64, mimeType: file.type });
    };
    reader.readAsDataURL(file);
    e.target.value = '';
    setAttachOpen(false);
  }

  function startRecording() {
    const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SR) { alert('Reconhecimento de voz não disponível neste navegador. Use Chrome ou Edge.'); return; }
    const recognition = new SR();
    recognition.lang = 'pt-BR';
    recognition.continuous = true;
    recognition.interimResults = true;
    recognition.onresult = event => {
      let text = '';
      for (let i = 0; i < event.results.length; i++) text += event.results[i][0].transcript;
      setTranscript(text);
    };
    recognition.onerror = e => {
      if (e.error !== 'aborted') { recordingRef.current = false; setRecording(false); setTranscript(''); }
    };
    recognition.onend = () => {
      if (recordingRef.current) { try { recognition.start(); } catch {} }
    };
    recognition.start();
    recognitionRef.current = recognition;
    setRecording(true);
    setTranscript('');
  }

  function cancelRecording() {
    recordingRef.current = false;
    recognitionRef.current?.abort();
    recognitionRef.current = null;
    setRecording(false);
    setTranscript('');
  }

  function sendTranscript() {
    recordingRef.current = false;
    recognitionRef.current?.stop();
    recognitionRef.current = null;
    const text = transcript.trim();
    setRecording(false);
    setTranscript('');
    if (text) onSend(text);
  }

  const canSend = !loading && (draft.trim() || pending);

  if (recording) {
    return (
      <div className="ia-input-wrap">
        <div className="ia-rec-bar">
          <div className="ia-rec-body">
            {transcript
              ? <span className="ia-rec-transcript">{transcript}</span>
              : <span className="ia-rec-dots" />
            }
            <div className="ia-rec-waveform">
              {Array.from({ length: 14 }, (_, i) => (
                <div key={i} className="ia-rec-wbar"
                     style={{ animationDelay: `${(i * 0.07).toFixed(2)}s` }} />
              ))}
            </div>
          </div>
          <button className="ia-rec-x" onClick={cancelRecording} title="Cancelar">
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
              <path d="M18 6 6 18M6 6l12 12"/>
            </svg>
          </button>
          <button className="ia-rec-check" onClick={sendTranscript} title="Enviar" disabled={!transcript.trim()}>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <polyline points="20 6 9 17 4 12"/>
            </svg>
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className="ia-input-wrap">
      {pending && (
        <div className="ia-pending-wrap">
          {pending.kind === 'image' && <img src={pending.url} alt={pending.file.name} className="ia-pending-thumb" />}
          {pending.kind === 'video' && <video src={pending.url} className="ia-pending-thumb" />}
          {pending.kind === 'file'  && (
            <div className="ia-pending-file">
              <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                <polyline points="14 2 14 8 20 8"/>
              </svg>
              <span>{pending.file.name}</span>
            </div>
          )}
          <button className="ia-pending-remove" onClick={() => setPending(null)}>
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <path d="M18 6 6 18M6 6l12 12"/>
            </svg>
          </button>
        </div>
      )}

      <div className="ia-input-box">
      <IASuggestionPanel groupId={sgLast} open={!!sgOpen} onClose={closeSg} onPick={pickSg} disabled={loading} />
      <div className="ia-input">
        <input ref={photoRef} type="file" style={{ display: 'none' }}
               accept="image/*" onChange={e => handleFile(e)} />
        <input ref={docRef} type="file" style={{ display: 'none' }}
               accept=".pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.txt,.csv,.zip,.rar"
               onChange={e => handleFile(e, 'file')} />

        {/* + attach */}
        <div ref={attachRef} style={{ position: 'relative', flexShrink: 0 }}>
          <button className="ia-inp-plus" onClick={() => setAttachOpen(o => !o)} disabled={loading || !!pending}>
            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
              <path d="M12 5v14M5 12h14"/>
            </svg>
          </button>
          {attachOpen && (
            <div className="ia-attach-menu">
              <button className="ia-attach-opt" onClick={() => photoRef.current?.click()}>
                <span className="ia-attach-opt-icon" style={{ background: 'rgba(99,102,241,0.14)', color: '#818cf8' }}>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                    <rect x="3" y="3" width="18" height="18" rx="2"/><circle cx="8.5" cy="8.5" r="1.5"/>
                    <polyline points="21 15 16 10 5 21"/>
                  </svg>
                </span>
                Foto
              </button>
              <button className="ia-attach-opt" onClick={() => docRef.current?.click()}>
                <span className="ia-attach-opt-icon" style={{ background: 'rgba(31,147,255,0.14)', color: '#60b8ff' }}>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
                    <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/>
                    <polyline points="14 2 14 8 20 8"/>
                  </svg>
                </span>
                Documento
              </button>
            </div>
          )}
        </div>

        <input ref={inputRef} value={draft} onChange={e => setDraft(e.target.value)} onKeyDown={handleKey}
               disabled={loading} placeholder="Pergunte qualquer coisa…" />

        {/* Mic */}
        <button className="ia-inp-mic" onClick={startRecording} disabled={loading || !!pending}
                title="Gravar áudio">
          <svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
            <rect x="9" y="3" width="6" height="12" rx="3"/>
            <path d="M5 11a7 7 0 0 0 14 0M12 18v3"/>
          </svg>
        </button>

        {/* Send circle — always rendered, dimmed when empty */}
        <button className={`ia-inp-send${canSend ? ' ia-inp-send--on' : ''}`}
                onClick={handleSubmit} disabled={!canSend} title="Enviar">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
            <line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/>
          </svg>
        </button>
      </div>
      </div>

      <IASuggestionRow openId={sgOpen} onToggle={toggleSg} disabled={loading} />
    </div>
  );
}

// =================== RIGHT ===================
function IARight({ insights, suggActions, daySummary, onSend, loadingInsights, onClose }) {
  const insightMeta = {
    hot:   { color: '#ff5a4e', bg: 'rgba(255,90,78,0.14)' },
    warn:  { color: '#f5b544', bg: 'rgba(245,181,68,0.14)' },
    up:    { color: '#34d399', bg: 'rgba(52,211,153,0.14)' },
    money: { color: '#c084fc', bg: 'rgba(168,85,247,0.14)' },
  };

  const today = new Date();
  const dateStr = today.toLocaleDateString('pt-BR', { day: 'numeric', month: 'short' }).replace('.', '');

  const shownInsights   = insights   || IA_INSIGHTS;
  const shownActions    = suggActions || IA_SUGG_ACTIONS;
  const shownDaySummary = daySummary  || IA_DAY_SUMMARY;

  return (
    <aside className="ia-right">
      <div className="ia-right-close-bar">
        <span>Painel IA</span>
        <button className="icon-btn ia-close-btn" title="Fechar painel" onClick={onClose}>
          <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round">
            <path d="M18 6 6 18M6 6l12 12"/>
          </svg>
        </button>
      </div>
      <div className="ia-right-section">
        <div className="ia-right-head">
          <h3>Insights IA</h3>
          {loadingInsights
            ? <span style={{ fontSize: 10, opacity: 0.5 }}>carregando…</span>
            : <span className="ia-live"><span className="pulse-dot" /> ao vivo</span>
          }
        </div>
        <div className="ia-insights-stack">
          {shownInsights.map((ins, i) => {
            const m = insightMeta[ins.kind] || insightMeta.money;
            return (
              <div key={i} className="ia-insight-card">
                <span className="ia-insight-icon" style={{ color: m.color, background: m.bg }}>
                  <Icon name={ins.icon} size={13} stroke={1.8} />
                </span>
                <div className="ia-insight-body">
                  <span className="ia-insight-title">{ins.title}</span>
                  <div className="ia-insight-row">
                    <span className="ia-insight-value">{ins.value}</span>
                    <span className="ia-insight-sub">{ins.sub}</span>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      </div>

      <div className="ia-right-section">
        <div className="ia-right-head">
          <h3>Ações sugeridas</h3>
        </div>
        <div className="ia-actions-stack">
          {shownActions.map((a, i) => (
            <button key={i} className="ia-action-row"
                    onClick={() => a.prompt && onSend && onSend(a.prompt)}>
              <span className="ia-action-icon"><Icon name={a.icon} size={12} stroke={1.8} /></span>
              <span className="ia-action-label">{a.label}</span>
              <span className="ia-action-meta">{a.meta}</span>
              <Icon name="arrRight" size={11} stroke={2} />
            </button>
          ))}
        </div>
      </div>

      <div className="ia-right-section">
        <div className="ia-right-head">
          <h3>Resumo do dia</h3>
          <span className="ia-right-date">Hoje · {dateStr}</span>
        </div>
        <div className="ia-day-grid">
          {shownDaySummary.map((d, i) => (
            <div key={i} className={`ia-day-card tone-${d.tone}`}>
              <span className="ia-day-value">{d.value}</span>
              <span className="ia-day-label">{d.label}</span>
            </div>
          ))}
        </div>
      </div>
    </aside>
  );
}

function lsGet(key, fallback) {
  try { const v = localStorage.getItem(key); return v ? JSON.parse(v) : fallback; } catch { return fallback; }
}
function lsSave(key, val) {
  try { localStorage.setItem(key, JSON.stringify(val)); } catch {}
}

// =================== PAGE ===================
function IAPage() {
  // Chaves por usuário — impede vazamento de histórico entre contas no mesmo browser
  const _iaUid     = (window.HOROS_USER && window.HOROS_USER.id) || 'anon';
  const LS_CONVS   = `horos-ia-conversations-${_iaUid}`;
  const LS_THREAD  = `horos-ia-thread-${_iaUid}`;
  const LS_HISTORY = `horos-ia-history-${_iaUid}`;
  const LS_ACTIVE  = `horos-ia-active-${_iaUid}`;

  const [search,         setSearch]         = React.useState('');
  const [thread,         setThread]         = React.useState(() => lsGet(LS_THREAD, []));
  const [history,        setHistory]        = React.useState(() => lsGet(LS_HISTORY, []));
  const [loading,        setLoading]        = React.useState(false);
  const [draft,          setDraft]          = React.useState('');
  // A conversa atual fica SEMPRE no histórico (desde a 1ª mensagem), marcada como ativa
  const [conversations,  setConversations]  = React.useState(() => {
    const list = lsGet(LS_CONVS, []);
    const act = lsGet(LS_ACTIVE, null);
    const th = lsGet(LS_THREAD, []);
    if (th.length && !(act && list.some(c => c.id === act))) {
      // conversa aberta de antes desta versão: entra no histórico
      const firstUser = th.find(m => m.from === 'user');
      const id = `conv-${Date.now()}`;
      lsSave(LS_ACTIVE, id);
      return [{ id, title: (firstUser?.blocks?.[0]?.text || 'Conversa').slice(0, 44), time: firstUser?.time || '', thread: th, history: lsGet(LS_HISTORY, []) }, ...list];
    }
    return list;
  });
  const [activeConvId,   setActiveConvId]   = React.useState(() => {
    const act = lsGet(LS_ACTIVE, null);
    return act && lsGet(LS_THREAD, []).length ? act : null;
  });
  const [leftOpen,       setLeftOpen]       = React.useState(true);
  const activeRef = React.useRef(activeConvId);
  activeRef.current = activeConvId;

  React.useEffect(() => { lsSave(LS_CONVS, conversations); }, [conversations]);
  React.useEffect(() => { lsSave(LS_THREAD, thread); },      [thread]);
  React.useEffect(() => { lsSave(LS_HISTORY, history); },    [history]);
  React.useEffect(() => { lsSave(LS_ACTIVE, activeConvId); }, [activeConvId]);
  React.useEffect(() => { localStorage.setItem('horos-tour-visited-ia', '1'); window.dispatchEvent(new CustomEvent('horos:tour-check', { detail: { step: 'ia' } })); }, []);

  // Mantém a conversa ativa do histórico igual ao que está na tela
  React.useEffect(() => {
    if (!activeConvId || !thread.length) return;
    setConversations(prev => prev.map(c => c.id === activeConvId ? { ...c, thread, history } : c));
  }, [thread, history, activeConvId]);

  function fmtNow() {
    const d = new Date();
    return `${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`;
  }

  function handleNewConversation() {
    setThread([]);
    setHistory([]);
    setActiveConvId(null);
    setDraft('');
    lsSave(LS_THREAD, []);
    lsSave(LS_HISTORY, []);
  }

  function handleDeleteConv(id) {
    setConversations(prev => prev.filter(c => c.id !== id));
    if (activeConvId === id) {
      setThread([]);
      setHistory([]);
      setActiveConvId(null);
    }
  }

  function handleSelectConv(id) {
    if (id === activeConvId) return;
    const conv = conversations.find(c => c.id === id);
    if (!conv) return;
    setThread(conv.thread || []);
    setHistory(conv.history || []);
    setActiveConvId(id);
  }

  async function handleSend(input) {
    const isObj       = input !== null && typeof input === 'object';
    const apiText     = isObj ? input.text   : input;
    const extraBlocks = isObj ? (input.blocks   || []) : [];
    const fileData    = isObj ? (input.fileData || null) : null;

    if (!apiText?.trim() && !extraBlocks.length) return;
    if (loading) return;

    const userMsg = {
      from: 'user',
      time: fmtNow(),
      blocks: [...extraBlocks, ...(apiText?.trim() ? [{ kind: 'text', text: apiText.trim() }] : [])],
    };

    // 1ª mensagem: a conversa já entra no histórico, selecionada; nas seguintes sobe para o topo
    let convId = activeConvId;
    if (!convId) {
      convId = `conv-${Date.now()}`;
      const title = (apiText?.trim() || extraBlocks.map(b => b.name || b.kind).join(', ') || 'Conversa').slice(0, 44);
      setConversations(prev => [{ id: convId, title, time: userMsg.time, thread: [userMsg], history }, ...prev]);
      setActiveConvId(convId);
    } else {
      setConversations(prev => {
        const c = prev.find(x => x.id === convId);
        return c ? [{ ...c, time: userMsg.time }, ...prev.filter(x => x.id !== convId)] : prev;
      });
    }
    setThread(prev => [...prev, userMsg]);
    setLoading(true);

    const msgForApi = apiText?.trim() || extraBlocks.map(b => b.name || b.kind).join(', ');

    // Resposta vai para a conversa certa mesmo se a pessoa trocou de conversa enquanto esperava
    const deliver = (aiMsg, hist) => {
      if (activeRef.current === convId) {
        setThread(prev => [...prev, aiMsg]);
        if (hist) setHistory(prev => [...prev, ...hist]);
      } else {
        setConversations(prev => prev.map(c => c.id === convId
          ? { ...c, thread: [...(c.thread || []), aiMsg], history: hist ? [...(c.history || []), ...hist] : c.history }
          : c));
      }
    };

    try {
      const token = window.horosToken ? await window.horosToken() : (window.HOROS_SESSION || {}).access_token;
      const res = await fetch('/api/intelligence/broker-chat', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...(token ? { Authorization: `Bearer ${token}` } : {}) },
        body: JSON.stringify({ message: msgForApi, history, fileData }),
      });
      const data = await res.json();
      const aiText = data.ok && data.text ? data.text : 'Desculpe, ocorreu um erro. Tente novamente.';
      deliver({ from: 'ai', time: fmtNow(), blocks: [{ kind: 'text', text: aiText, refs: data.refs || [] }] },
        [{ role: 'user', content: msgForApi }, { role: 'assistant', content: aiText }]);
    } catch {
      deliver({ from: 'ai', time: fmtNow(), blocks: [{ kind: 'text', text: 'Não consegui conectar com o servidor. Verifique sua conexão.' }] }, null);
    } finally {
      setLoading(false);
    }
  }

  const gridCols = leftOpen ? '296px minmax(0,1fr)' : 'minmax(0,1fr)';

  return (
    <div className="ia-shell" style={{ gridTemplateColumns: gridCols }}>
      {leftOpen && (
        <IALeft
          search={search}
          onSearch={setSearch}
          conversations={conversations}
          activeId={activeConvId}
          onSelectConv={handleSelectConv}
          onNewConversation={handleNewConversation}
          onSend={handleSend}
          onClose={() => setLeftOpen(false)}
          onDeleteConv={handleDeleteConv}
        />
      )}

      <main className="ia-center">
        <ChatHead
          leftOpen={leftOpen}
          onToggleLeft={() => setLeftOpen(true)}
        />
        <ChatBody thread={thread} loading={loading} />
        <ChatInput draft={draft} setDraft={setDraft} onSend={handleSend} loading={loading} />
      </main>
    </div>
  );
}

window.IAPage = IAPage;
