// Tela: Disparos — campanhas de WhatsApp com templates verificados pela Meta

const dspHeaders = () => { const t = localStorage.getItem('ezza_token'); return { 'Content-Type':'application/json', ...(t?{'Authorization':`Bearer ${t}`}:{}) }; };

const DSP_STATUS = {
  APPROVED: { label: 'Aprovado',   bg: 'oklch(0.94 0.06 150)', fg: 'oklch(0.35 0.13 155)' },
  PENDING:  { label: 'Em análise', bg: 'oklch(0.96 0.08 90)',  fg: 'oklch(0.45 0.12 80)'  },
  REJECTED: { label: 'Recusado',   bg: 'oklch(0.94 0.06 20)',  fg: 'oklch(0.45 0.16 25)'  },
};

const DSP_PUBLICOS = [
  { id: 'contatos',      label: 'Todos os contatos' },
  { id: 'leads_abertos', label: 'Leads em aberto (não fechados)' },
  { id: 'leads_quentes', label: 'Só leads QUENTES 🔥' },
  { id: 'leads',         label: 'Segmentar leads (etapa, temperatura, vendedor)' },
];
// Etapas do funil — mesmos slugs do pipeline
const DSP_ETAPAS = [
  { id: '',                 label: 'Todas as etapas abertas' },
  { id: 'novo-lead',        label: 'Novo lead' },
  { id: 'contato-feito',    label: 'Contato feito' },
  { id: 'em-andamento',     label: 'Em andamento' },
  { id: 'proposta-enviada', label: 'Proposta enviada' },
  { id: 'fechado',          label: 'Fechado' },
];

// Biblioteca de modelos prontos — o cliente escolhe, personaliza e manda pra verificação
const DSP_MODELOS = [
  { id: 'boas_vindas',   rotulo: '👋 Boas-vindas',    cat: 'UTILITY',
    texto: 'Oi {{1}}! Que bom ter você com a gente 😊 Seu cadastro foi confirmado. Qualquer dúvida é só responder essa mensagem que a nossa equipe te ajuda!' },
  { id: 'promocao',      rotulo: '🏷️ Promoção',       cat: 'MARKETING',
    texto: 'Oi {{1}}! Temos uma condição especial essa semana: [DESCREVA A OFERTA AQUI]. Válida até [DATA]. Quer aproveitar? É só responder essa mensagem!' },
  { id: 'reengajamento', rotulo: '🔄 Reengajamento',  cat: 'MARKETING',
    texto: 'Oi {{1}}, tudo bem? Faz um tempinho que a gente não se fala! Temos novidades que podem te interessar. Quer dar uma olhada? Responde aqui que eu te conto 😊' },
  { id: 'aviso_pedido',  rotulo: '📦 Aviso de pedido', cat: 'UTILITY',
    texto: 'Oi {{1}}! Passando pra avisar que seu pedido foi atualizado: [STATUS]. Qualquer dúvida é só chamar por aqui!' },
  { id: 'agradecimento', rotulo: '💚 Agradecimento',   cat: 'MARKETING',
    texto: 'Oi {{1}}! Passando só pra agradecer pela confiança 💚 Se precisar de qualquer coisa, estamos por aqui. Indique a gente pra um amigo e os dois ganham [BENEFÍCIO]!' },
];

function NovoTemplateModal({ onClose, onCreated }) {
  const [nome, setNome] = React.useState('');
  const [cat, setCat] = React.useState('MARKETING');
  const [texto, setTexto] = React.useState('');
  const [midia, setMidia] = React.useState(null);      // File do anexo (imagem/vídeo)
  const [midiaPrev, setMidiaPrev] = React.useState(null); // object URL pra preview
  const [busy, setBusy] = React.useState(false);
  const [rodape, setRodape] = React.useState('');
  const [botoes, setBotoes] = React.useState([]);   // [{tipo, texto, url?, telefone?}]
  const midiaRef = React.useRef(null);
  const addBotao = () => setBotoes(b => [...b, { tipo:'QUICK_REPLY', texto:'' }]);
  const removerBotao = (i) => setBotoes(b => b.filter((_, j) => j !== i));
  const mudarBotao = (i, patch) => setBotoes(b => b.map((x, j) => j === i ? { ...x, ...patch } : x));
  const toast = useToast();
  const usarModelo = (m) => { setNome(m.id); setCat(m.cat); setTexto(m.texto); };
  const escolherMidia = (e) => {
    const f = e.target.files && e.target.files[0]; e.target.value = '';
    if (!f) return;
    if (f.size > 16*1024*1024) { toast('Anexo muito grande (máx 16 MB)', { kind: 'err' }); return; }
    setMidia(f); setMidiaPrev({ url: URL.createObjectURL(f), tipo: f.type.startsWith('video/') ? 'video' : f.type.startsWith('image/') ? 'imagem' : 'arquivo', nome: f.name });
  };
  const removerMidia = () => { setMidia(null); setMidiaPrev(null); };
  // Botao sem texto nao vai pra Meta: ela recusa o template inteiro.
  const botoesValidos = () => botoes.filter(b => (b.texto || '').trim());
  const enviar = async () => {
    if (busy) return;
    setBusy(true);
    try {
      let r;
      if (midia) {
        // multipart quando há anexo de mídia no cabeçalho
        const fd = new FormData();
        fd.append('nome', nome); fd.append('categoria', cat); fd.append('texto', texto); fd.append('midia', midia);
        fd.append('rodape', rodape); fd.append('botoes', JSON.stringify(botoesValidos()));
        const t = localStorage.getItem('ezza_token');
        r = await fetch('/api/whatsapp/templates', { method: 'POST', headers: { ...(t?{'Authorization':`Bearer ${t}`}:{}) }, body: fd });
      } else {
        r = await fetch('/api/whatsapp/templates', { method: 'POST', headers: dspHeaders(), body: JSON.stringify({ nome, categoria: cat, texto, rodape, botoes: botoesValidos() }) });
      }
      const d = await r.json();
      if (d.ok) { toast('Template enviado pra verificação da Meta ✓ (aprovação leva de minutos a 48h)', { duration: 5000 }); onCreated && onCreated(); onClose(); }
      else toast(d.error || 'Meta recusou', { kind: 'err', duration: 5000 });
    } catch (e) { toast('Erro de conexão', { kind: 'err' }); }
    setBusy(false);
  };
  return (
    <div className="modal-wrap" onClick={onClose}>
      <div className="card modal-card" onClick={e=>e.stopPropagation()} style={{width:560}}>
        <div className="modal-head">
          <div><div className="modal-title">Novo <em>template</em></div>
          <div className="modal-sub muted">Vai pra fila de verificação da Meta antes de poder ser usado</div></div>
          <div className="mini-btn" onClick={onClose}>{ICN.x}</div>
        </div>
        <div className="field" style={{marginBottom:12}}>
          <label className="field-lbl">Comece por um modelo pronto (opcional)</label>
          <div className="row" style={{gap:6, flexWrap:'wrap'}}>
            {DSP_MODELOS.map(m => (
              <span key={m.id} className="pill" onClick={()=>usarModelo(m)} style={{cursor:'default', fontSize:11.5}}>{m.rotulo}</span>
            ))}
          </div>
        </div>
        <div className="field" style={{marginBottom:12}}>
          <label className="field-lbl">Nome interno (minúsculas, sem espaço)</label>
          <input className="ezz-input" placeholder="promocao_inverno" value={nome} onChange={e=>setNome(e.target.value)} />
        </div>
        <div className="field" style={{marginBottom:12}}>
          <label className="field-lbl">Categoria</label>
          <div className="row" style={{gap:6}}>
            {[['MARKETING','Marketing (promoções, reengajamento)'],['UTILITY','Utilidade (avisos de pedido, confirmações)']].map(([id,lbl])=>(
              <span key={id} className={`pill ${cat===id?'pill-dark':''}`} onClick={()=>setCat(id)} style={{cursor:'default', fontSize:11.5}}>{lbl}</span>
            ))}
          </div>
        </div>
        <div className="field" style={{marginBottom:12}}>
          <label className="field-lbl">Anexo de mídia no cabeçalho (opcional)</label>
          <input ref={midiaRef} type="file" accept="image/jpeg,image/png,video/mp4,application/pdf" style={{display:'none'}} onChange={escolherMidia} />
          {!midiaPrev ? (
            <div className="tpl-midia-drop" onClick={()=>midiaRef.current && midiaRef.current.click()}>
              <span style={{display:'inline-flex'}}>{ICN.upload || '📎'}</span>
              <span>Anexar imagem, vídeo ou PDF <span className="muted">(vira o cabeçalho do template)</span></span>
            </div>
          ) : (
            <div className="tpl-midia-prev">
              {midiaPrev.tipo==='imagem'
                ? <img src={midiaPrev.url} alt="" />
                : <div className="tpl-midia-ic">{midiaPrev.tipo==='video' ? '🎬' : '📄'}</div>}
              <div className="col" style={{flex:1, minWidth:0}}>
                <div style={{fontSize:12.5, fontWeight:600, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>{midiaPrev.nome}</div>
                <div className="muted" style={{fontSize:11}}>{midiaPrev.tipo} · cabeçalho do template</div>
              </div>
              <button className="btn-ghost btn-sm" onClick={removerMidia}>Remover</button>
            </div>
          )}
        </div>
        <div className="field" style={{marginBottom:6}}>
          <label className="field-lbl">Texto da mensagem</label>
          <textarea className="ezz-input" rows={5} value={texto} onChange={e=>setTexto(e.target.value)}
            placeholder={'Oi {{1}}! Temos uma condição especial essa semana...\n\nUse {{1}} onde entra o NOME do contato.'}
            style={{resize:'vertical', minHeight:110}} />
        </div>
        {/* RODAPÉ — linha discreta abaixo do texto, teto de 60 pela Meta */}
        <div className="field" style={{marginBottom:12}}>
          <label className="field-lbl">
            Rodapé (opcional)
            <span className="tpl-contador" style={{color: rodape.length > 60 ? 'var(--danger)' : 'var(--ink-faint)'}}>
              {rodape.length}/60
            </span>
          </label>
          <input className="ezz-input" maxLength={70} value={rodape}
            onChange={e=>setRodape(e.target.value)}
            placeholder="Ex: Exclusivo para o atacado" />
        </div>

        {/* BOTÕES — é o "Quero adquirir!" que aparece embaixo da mensagem */}
        <div className="field" style={{marginBottom:12}}>
          <label className="field-lbl">Botões (opcional)</label>

          {botoes.length === 0 && (
            <div className="muted" style={{fontSize:11.5, marginBottom:8}}>
              Aparecem embaixo da mensagem. O cliente toca e já responde, sem digitar.
            </div>
          )}

          {botoes.map((bt, i) => (
            <div key={i} className="tpl-btn-cartao">
              {/* Tipo em seletor segmentado: sao 3 opcoes fixas, e o <select>
                  nativo abria aquele menu do navegador que nao aceita estilo. */}
              <div className="tpl-btn-topo">
                <div className="tpl-seg">
                  {[['QUICK_REPLY','Resposta'],['URL','Link'],['PHONE_NUMBER','Ligar']].map(([id,rot]) => (
                    <button key={id} type="button"
                      className={'tpl-seg-op' + (bt.tipo === id ? ' on' : '')}
                      onClick={()=>mudarBotao(i, { tipo: id })}>{rot}</button>
                  ))}
                </div>
                <button className="tpl-btn-x" title="Remover botão" onClick={()=>removerBotao(i)}>×</button>
              </div>
              <div className="tpl-btn-campos">
                <input className="ezz-input" maxLength={25}
                  value={bt.texto} onChange={e=>mudarBotao(i, { texto: e.target.value })}
                  placeholder="Texto do botão, ex: Quero adquirir!" />
                {bt.tipo === 'URL' && (
                  <input className="ezz-input" value={bt.url || ''}
                    onChange={e=>mudarBotao(i, { url: e.target.value })}
                    placeholder="https://..." />
                )}
                {bt.tipo === 'PHONE_NUMBER' && (
                  <input className="ezz-input" value={bt.telefone || ''}
                    onChange={e=>mudarBotao(i, { telefone: e.target.value })}
                    placeholder="DDD + número" />
                )}
              </div>
            </div>
          ))}

          {botoes.length < 3 && (
            <button className="tpl-btn-add" onClick={addBotao}>+ Adicionar botão</button>
          )}
        </div>

        {/* Prévia do que o cliente vai ver — inclui rodapé e botões */}
        {(texto.trim() || botoes.some(b=>b.texto.trim())) && (
          <div className="field" style={{marginBottom:12}}>
            <label className="field-lbl">Como o cliente vai ver</label>
            <div className="dsp-balao">
              {texto.replace(/\{\{1\}\}/g, '‹nome›') || '...'}
              {rodape.trim() && <div className="dsp-balao-rodape">{rodape}</div>}
            </div>
            {botoes.filter(b=>b.texto.trim()).map((b,i)=>(
              <div key={i} className="tpl-btn-prev">{b.texto}</div>
            ))}
          </div>
        )}

        <div className="muted" style={{fontSize:11.5, lineHeight:1.5, marginBottom:14}}>
          Regras da Meta: a variável {'{{1}}'} não pode ser a primeira nem a última coisa do texto · nada de links encurtados · aprovação leva de minutos a 48h.
        </div>
        <div className="modal-actions">
          <button className="btn-ghost" onClick={onClose}>Cancelar</button>
          <button className="btn-primary" disabled={busy || !nome.trim() || !texto.trim()} onClick={enviar}>{busy?'Enviando…':'Enviar pra verificação'}</button>
        </div>
      </div>
    </div>
  );
}

function Disparos() {
  const [tpls, setTpls] = React.useState([]);
  const [configurado, setConfigurado] = React.useState(true);
  const [loading, setLoading] = React.useState(true);
  const [showNovo, setShowNovo] = React.useState(false);
  const [tplSel, setTplSel] = React.useState('');
  const [publico, setPublico] = React.useState('contatos');
  const [fEtapa, setFEtapa] = React.useState('');
  const [fTemp, setFTemp]   = React.useState('');
  const [fDono, setFDono]   = React.useState('');
  const [equipe, setEquipe] = React.useState([]);
  const [fTag, setFTag] = React.useState('');
  const [tags, setTags] = React.useState([]);
  const [progresso, setProgresso] = React.useState(null);   // {enviados,total,status}
  const [numTeste, setNumTeste] = React.useState('');
  const [testando, setTestando] = React.useState(false);
  const [apagando, setApagando] = React.useState('');   // nome do template sendo apagado
  const [previa, setPrevia] = React.useState(null);   // {total, custo, exemplos}
  const [disparando, setDisparando] = React.useState(false);
  const [resultado, setResultado] = React.useState(null);
  const [historico, setHistorico] = React.useState([]);
  const toast = useToast();

  const carregar = () => {
    setLoading(true);
    fetch('/api/whatsapp/templates', { headers: dspHeaders() })
      .then(r=>r.json())
      .then(d=>{ if(d.ok){ setTpls(d.templates||[]); setConfigurado(d.configurado!==false); } else toast(d.error||'Erro ao consultar a Meta',{kind:'err'}); })
      .catch(()=>{})
      .finally(()=>setLoading(false));
    fetch('/api/disparos', { headers: dspHeaders() })
      .then(r=>r.json()).then(d=>{ if(d.ok) setHistorico(d.disparos||[]); }).catch(()=>{});
    fetch('/api/equipe', { headers: dspHeaders() })
      .then(r=>r.json()).then(d=>{ if(d.ok) setEquipe(d.equipe||[]); }).catch(()=>{});
    fetch('/api/tags', { headers: dspHeaders() })
      .then(r=>r.json()).then(d=>{ if(d.ok) setTags(d.tags||[]); }).catch(()=>{});
  };
  React.useEffect(() => { carregar(); }, []);

  const aprovados = tpls.filter(t => t.status === 'APPROVED');
  const tpl = tpls.find(t => t.name === tplSel);

  const calcularPrevia = async () => {
    setPrevia(null); setResultado(null);
    try {
      const r = await fetch('/api/whatsapp/disparo', { method:'POST', headers: dspHeaders(),
        body: JSON.stringify({ template: tplSel, params: tpl?.params||0, publico, ...filtrosAtivos(), simular: 1 }) });
      const d = await r.json();
      if (d.ok) setPrevia(d);
      else toast(d.error || 'Erro na prévia', { kind: 'err', duration: 4000 });
    } catch (e) { toast('Erro de conexão', { kind: 'err' }); }
  };

  // Só manda os filtros quando o público é "segmentar leads" — senão o backend
  // aplicaria filtro em cima de "todos os contatos" sem o usuário perceber.
  const filtrosAtivos = () => publico === 'leads'
    ? { etapa: fEtapa || '', temp: fTemp || '', usuarioId: fDono || '', tagId: fTag || '' }
    : (publico === 'contatos' && fTag ? { tagId: fTag } : {});

  // Apaga o modelo NA META. Irreversivel: a Meta trava o nome por 30 dias, por
  // isso o aviso e explicito e modelo APROVADO ainda exige digitar o nome.
  const apagarTemplate = async (t) => {
    if (apagando) return;
    const aprovado = t.status === 'APPROVED';
    const aviso = 'Apagar o modelo "' + t.name + '"?' + '\n\n' +
      'Isso APAGA NA META, nao so aqui. Nao tem desfazer.' + '\n' +
      'A Meta bloqueia esse nome por 30 DIAS: nao da pra criar outro igual nesse periodo.' +
      (aprovado ? '\n\n' + 'Este modelo esta APROVADO e pode estar em uso.' : '');
    if (!window.confirm(aviso)) return;
    if (aprovado) {
      const digitado = window.prompt('Confirme digitando o nome do modelo:' + '\n\n' + t.name);
      if (digitado === null) return;
      if (digitado.trim() !== t.name) { toast('O nome nao confere. Nada foi apagado.', { kind:'err' }); return; }
    }
    setApagando(t.name);
    try {
      const qs = t.id ? ('?id=' + encodeURIComponent(t.id)) : '';
      const r = await fetch('/api/whatsapp/templates/' + encodeURIComponent(t.name) + qs,
        { method:'DELETE', headers: dspHeaders() });
      const d = await r.json();
      if (d.ok) { toast('Modelo "' + t.name + '" apagado'); carregar(); }
      else toast(d.error || 'Nao consegui apagar', { kind:'err', duration: 6000 });
    } catch (e) { toast('Erro de conexao', { kind:'err' }); }
    setApagando('');
  };

  // Manda o template pra UM numero, sem tocar na base. Todo disparo de verdade
  // deveria passar por aqui antes.
  const enviarTeste = async () => {
    const n = numTeste.replace(/\D/g, '');
    if (!tplSel) { toast('Escolha um template primeiro', { kind: 'err' }); return; }
    if (n.length < 10) { toast('Informe DDD + número, ex: 11988887777', { kind: 'err' }); return; }
    if (testando) return;
    setTestando(true);
    try {
      const r = await fetch('/api/whatsapp/disparo', { method:'POST', headers: dspHeaders(),
        body: JSON.stringify({ template: tplSel, params: tpl?.params||0, numeroTeste: n }) });
      const d = await r.json();
      if (d.ok && d.enviados > 0) toast(`Teste enviado para ${n} ✓ Confira no WhatsApp.`, { duration: 6000 });
      else if (d.ok) toast('A Meta recusou: ' + (d.erro_exemplo || 'verifique o template'), { kind: 'err', duration: 7000 });
      else toast(d.error || 'Erro no teste', { kind: 'err', duration: 6000 });
      carregar();
    } catch (e) { toast('Erro de conexão', { kind: 'err' }); }
    setTestando(false);
  };

  const disparar = async () => {
    if (disparando || !previa) return;
    setDisparando(true); setProgresso(null);
    try {
      const r = await fetch('/api/whatsapp/disparo', { method:'POST', headers: dspHeaders(),
        body: JSON.stringify({ template: tplSel, params: tpl?.params||0, publico, ...filtrosAtivos() }) });
      let d = await r.json();
      if (!d.ok) { toast(d.error || 'Erro no disparo', { kind: 'err', duration: 5000 }); setDisparando(false); return; }

      // O envio vai em lotes: segue chamando até acabar a fila. Se a aba fechar,
      // o cron do servidor termina sozinho — nada fica pela metade.
      setProgresso({ enviados: d.enviados, total: d.total, status: d.status });
      let guarda = 0;
      while (d.status !== 'concluido' && d.status !== 'erro' && guarda++ < 40) {
        const rc = await fetch(`/api/whatsapp/disparo/${d.disparoId}`, { method:'POST', headers: dspHeaders() });
        const dc = await rc.json();
        if (!dc.ok) break;
        d = { ...d, ...dc };
        setProgresso({ enviados: d.enviados, total: d.total, status: d.status });
      }
      setResultado(d); setPrevia(null); setProgresso(null);
      toast(`Disparo concluído: ${d.enviados} enviados${d.falhas?`, ${d.falhas} falhas`:''}`, { duration: 5000 });
      carregar();
    } catch (e) {
      toast('Conexão caiu — o servidor termina o envio sozinho em até 2 min', { kind: 'err', duration: 6000 });
    }
    setDisparando(false);
  };

  const fmtD = (iso) => { try { const d=new Date(String(iso).replace(' ','T')); return d.toLocaleDateString('pt-BR')+' '+d.toLocaleTimeString('pt-BR',{hour:'2-digit',minute:'2-digit'}); } catch(e){ return ''; } };

  return (
    <>
      <PageHead title={<>Disparos <em>WhatsApp</em></>} subtitle="Campanhas com templates verificados pela Meta"
        right={<button className="btn-primary" onClick={()=>setShowNovo(true)}>{ICN.plus} Novo template</button>} />

      {!configurado && (
        <div className="card" style={{marginBottom:14, padding:'16px 20px', fontSize:13}}>
          ⚠️ WhatsApp/WABA ainda não configurados para esta conta. Fale com o suporte da Ezza pra ativar.
        </div>
      )}

      <div className="dsp-grid">
        {/* ── Novo disparo ── */}
        <div className="card">
          <div className="card-head"><div className="card-title">Novo disparo</div></div>

          {/* PASSO 1 — o que enviar. Lista de cartoes no lugar do <select>:
              o dropdown nativo nao aceita estilo (aquele azul do navegador) e
              escondia o que importa — status e conteudo do modelo. */}
          <div className="dsp-passo">
            <div className="dsp-passo-cab">
              <span className="dsp-passo-num">1</span>
              <div>
                <div className="dsp-passo-tit">O que enviar</div>
                <div className="dsp-passo-sub">Só modelos aprovados pela Meta podem sair</div>
              </div>
            </div>

            {tpls.length === 0 && (
              <div className="muted" style={{fontSize:12.5}}>Nenhum modelo ainda.</div>
            )}

            <div className="dsp-esc">
              {tpls.map(t => {
                const st = DSP_STATUS[t.status] || { label: t.status, bg: 'oklch(0.95 0.01 250)', fg: 'var(--ink-muted)' };
                const ok = t.status === 'APPROVED';
                const sel = tplSel === t.name;
                return (
                  <button key={t.name} type="button" disabled={!ok}
                    className={'dsp-esc-item' + (sel ? ' on' : '')}
                    onClick={() => { setTplSel(t.name); setPrevia(null); setResultado(null); }}>
                    <span className="dsp-esc-radio" />
                    <span className="dsp-esc-corpo">
                      <span className="dsp-esc-nome">{t.name}</span>
                      <span className="dsp-esc-desc">{(t.body || '').slice(0, 70)}{(t.body || '').length > 70 ? '…' : ''}</span>
                    </span>
                    <span className="dsp-esc-selo" style={{background:st.bg, color:st.fg}}>{st.label}</span>
                  </button>
                );
              })}
            </div>

            {/* Prévia em forma de balão: é assim que o cliente vai ver */}
            {tpl && (
              <div className="dsp-balao-wrap">
                <div className="dsp-balao">
                  {tpl.body.replace(/\{\{1\}\}/g, '‹nome do contato›')}
                  {tpl.rodape && <div className="dsp-balao-rodape">{tpl.rodape}</div>}
                </div>
                {Array.isArray(tpl.botoes) && tpl.botoes.map((bt,i) => (
                  <div key={i} className="tpl-btn-prev">{bt}</div>
                ))}
                <div className="dsp-balao-nota muted">Assim que o contato vai receber</div>
              </div>
            )}
          </div>

          {/* PASSO 2 — para quem */}
          <div className="dsp-passo">
            <div className="dsp-passo-cab">
              <span className="dsp-passo-num">2</span>
              <div>
                <div className="dsp-passo-tit">Para quem</div>
                <div className="dsp-passo-sub">Escolha o grupo e, se quiser, refine</div>
              </div>
            </div>
            {/* 4 opcoes fixas nao precisam de dropdown: em cartao a pessoa ve
                todas de uma vez e entende a diferenca sem abrir nada. */}
            <div className="dsp-esc">
              {DSP_PUBLICOS.map(pb => (
                <button key={pb.id} type="button"
                  className={'dsp-esc-item' + (publico === pb.id ? ' on' : '')}
                  onClick={() => { setPublico(pb.id); setPrevia(null); setResultado(null); }}>
                  <span className="dsp-esc-radio" />
                  <span className="dsp-esc-corpo">
                    <span className="dsp-esc-nome">{pb.label}</span>
                  </span>
                </button>
              ))}
            </div>

            {publico === 'contatos' && tags.length > 0 && (
              <div className="dsp-sub-campo">
                <label className="field-lbl">Filtrar por etiqueta (opcional)</label>
                {/* Chips no lugar do <select>: etiqueta TEM COR, e a cor e o que a
                    vendedora reconhece de relance no pipeline. Num dropdown nativo
                    a cor se perde e tudo vira texto igual. */}
                <div className="dsp-chips">
                  <button type="button"
                    className={'dsp-chip dsp-chip-todos' + (fTag === '' ? ' on' : '')}
                    onClick={()=>{ setFTag(''); setPrevia(null); setResultado(null); }}>
                    Todos, sem filtrar
                  </button>
                  {/* Soma leads + contatos: etiqueta colada no pipeline conta como
                      'lead', e o backend casa pelo telefone. Antes exibia so a contagem
                      de 'contato', que era sempre 0 e parecia etiqueta vazia. */}
                  {tags.map(t => {
                    const n = (t.leads || 0) + (t.contatos || 0);
                    return (
                      <button key={t.id} type="button"
                        className={'dsp-chip dsp-chip-' + (t.cor || 'lav') + (String(fTag) === String(t.id) ? ' on' : '')}
                        disabled={n === 0}
                        title={n === 0 ? 'Nenhum contato com esta etiqueta' : t.nome + ': ' + n}
                        onClick={()=>{ setFTag(String(t.id)); setPrevia(null); setResultado(null); }}>
                        {t.nome}<span className="dsp-chip-n">{n}</span>
                      </button>
                    );
                  })}
                </div>
              </div>
            )}

            {/* Filtros finos — só quando o público é "segmentar leads" */}
            {publico === 'leads' && (
              <div className="dsp-seg">
                <div className="dsp-seg-tit">Refinar o público</div>
                <div className="dsp-seg-campos">
                  <div className="field">
                    <label className="field-lbl">Etapa do funil</label>
                    <select className="ezz-input" value={fEtapa} onChange={e=>{setFEtapa(e.target.value); setPrevia(null); setResultado(null);}}>
                      {DSP_ETAPAS.map(x => <option key={x.id} value={x.id}>{x.label}</option>)}
                    </select>
                  </div>
                  <div className="field">
                    <label className="field-lbl">Temperatura</label>
                    <select className="ezz-input" value={fTemp} onChange={e=>{setFTemp(e.target.value); setPrevia(null); setResultado(null);}}>
                      <option value="">Todas</option>
                      <option value="frio">Frio</option>
                      <option value="morno">Morno</option>
                      <option value="quente">Quente</option>
                    </select>
                  </div>
                  <div className="field">
                    <label className="field-lbl">Etiqueta</label>
                    <select className="ezz-input" value={fTag} onChange={e=>{setFTag(e.target.value); setPrevia(null); setResultado(null);}}>
                      <option value="">Qualquer etiqueta</option>
                      {tags.map(t => <option key={t.id} value={t.id}>{t.nome} ({t.leads})</option>)}
                    </select>
                  </div>
                  <div className="field">
                    <label className="field-lbl">Responsável</label>
                    <select className="ezz-input" value={fDono} onChange={e=>{setFDono(e.target.value); setPrevia(null); setResultado(null);}}>
                      <option value="">Qualquer vendedor</option>
                      {equipe.map(m => <option key={m.id} value={m.id}>{m.nome}</option>)}
                    </select>
                  </div>
                </div>
                <div className="dsp-seg-dica muted">
                  Clique em <b>Calcular prévia</b> pra ver quantas pessoas entram nesse recorte antes de gastar.
                </div>
              </div>
            )}
          </div>

          {/* Teste em um número antes de gastar com a base */}
          <div className="dsp-teste">
            <div className="dsp-passo-cab" style={{marginBottom:10}}>
              <span className="dsp-passo-num dsp-passo-num-op">3</span>
              <div>
                <div className="dsp-passo-tit">Testar antes <span className="dsp-opcional">opcional</span></div>
                <div className="dsp-passo-sub">Manda pra um número só, sem tocar na base</div>
              </div>
            </div>
            <div className="row" style={{gap:8, alignItems:'stretch'}}>
              <input className="ezz-input" style={{flex:1}} value={numTeste}
                onChange={e=>setNumTeste(e.target.value)}
                placeholder="DDD + número, ex: 11988887777" />
              <button className="btn-sec" disabled={!tplSel || testando} onClick={enviarTeste}
                title={!tplSel ? 'Escolha um modelo no passo 1 primeiro' : 'Manda o modelo so pra esse numero'}>
                {ICN.send || ICN.bolt}
                <span>{testando ? 'Enviando…' : 'Enviar teste'}</span>
              </button>
            </div>
            <div className="dsp-teste-dica muted">
              {!tplSel ? 'Escolha um modelo no passo 1 pra liberar o teste.' : 'Custa R$ 0,33 e nao toca na base.'}
            </div>
          </div>

          {!previa && !resultado && (
            <button className="btn-primary" style={{width:'100%', justifyContent:'center'}} disabled={!tplSel} onClick={calcularPrevia}>
              Calcular prévia e custo
            </button>
          )}

          {progresso && (
            <div className="dsp-prog">
              <div className="dsp-prog-top">
                <span>Enviando… {progresso.enviados} de {progresso.total}</span>
                <span>{Math.round((progresso.enviados / Math.max(1, progresso.total)) * 100)}%</span>
              </div>
              <div className="dsp-prog-bar">
                <div className="dsp-prog-fill" style={{width: `${(progresso.enviados / Math.max(1, progresso.total)) * 100}%`}} />
              </div>
              <div className="dsp-prog-nota muted">
                Pode fechar a aba — o servidor termina o envio sozinho.
              </div>
            </div>
          )}

          {previa && (
            <div style={{border:'1px solid oklch(0.88 0.03 295)', background:'oklch(0.97 0.015 295)', borderRadius:14, padding:'14px 16px'}}>
              <div style={{fontSize:13.5, fontWeight:700, marginBottom:6}}>Prévia do disparo</div>
              <div style={{fontSize:12.5, lineHeight:1.7}}>
                Destinatários: <b>{previa.total}</b><br/>
                Custo estimado (Meta): <b>R$ {Number(previa.custo).toFixed(2).replace('.',',')}</b> <span className="muted">(~R$ 0,33/msg)</span><br/>
                {previa.exemplos && <span className="muted" style={{fontSize:11.5}}>Ex.: {previa.exemplos.slice(0,3).join(' · ')}</span>}
              </div>
              <div className="row" style={{gap:8, marginTop:12}}>
                <button className="btn-ghost" onClick={()=>setPrevia(null)}>Cancelar</button>
                <button className="btn-primary" style={{flex:1, justifyContent:'center'}} disabled={disparando} onClick={disparar}>
                  {disparando ? 'Disparando…' : `Disparar para ${previa.total} agora`}
                </button>
              </div>
            </div>
          )}

          {resultado && (
            <div style={{border:'1px solid oklch(0.85 0.06 150)', background:'oklch(0.96 0.04 150)', borderRadius:14, padding:'14px 16px', fontSize:12.5, lineHeight:1.7}}>
              ✅ <b>{resultado.enviados}</b> enviados de {resultado.total} · custo ~<b>R$ {Number(resultado.custo).toFixed(2).replace('.',',')}</b>
              {resultado.falhas > 0 && <><br/>⚠️ {resultado.falhas} falha(s){resultado.erro_exemplo ? ` — ex.: ${resultado.erro_exemplo}` : ''}</>}
            </div>
          )}
        </div>

        {/* ── Templates ── */}
        <div className="card">
          <div className="card-head">
            <div className="card-title">Meus templates</div>
            <ActionBtn icon={ICN.refresh} title="Atualizar status" size="icon" onClick={carregar} />
          </div>
          {loading && <div className="muted" style={{fontSize:13, padding:'12px 0'}}>Consultando a Meta…</div>}
          {!loading && tpls.length === 0 && (
            <div className="muted" style={{fontSize:13, padding:'12px 0'}}>Nenhum template ainda. Crie o primeiro — a Meta verifica e libera pro disparo.</div>
          )}
          <div className="col" style={{gap:10}}>
            {tpls.map(t => {
              const st = DSP_STATUS[t.status] || { label: t.status, bg: 'oklch(0.95 0.01 250)', fg: 'var(--ink-muted)' };
              return (
                <div key={t.name} style={{border:'1px solid var(--ink-line)', borderRadius:14, padding:'12px 14px'}}>
                  <div className="row" style={{justifyContent:'space-between', gap:8, marginBottom:6, flexWrap:'wrap'}}>
                    <span style={{fontSize:13, fontWeight:700, fontFamily:'var(--font-mono)', minWidth:0, overflow:'hidden', textOverflow:'ellipsis'}}>{t.name}</span>
                    {/* selo e ação andam juntos na direita — antes o selo ficava
                        solto no meio quando entrou o terceiro elemento */}
                    <div className="row" style={{gap:8, flexShrink:0}}>
                    <span style={{fontSize:10.5, fontWeight:700, padding:'3px 10px', borderRadius:999, background:st.bg, color:st.fg, whiteSpace:'nowrap'}}>{st.label}</span>
                    <button className="dsp-tpl-del" title="Apagar este modelo na Meta"
                      disabled={apagando === t.name}
                      onClick={() => apagarTemplate(t)}>
                      {ICN.trash}<span>{apagando === t.name ? 'Apagando…' : 'Apagar'}</span>
                    </button>
                    </div>
                  </div>
                  {/* Texto à ESQUERDA, mídia à DIREITA (pedido do Daniel 06/08).
                      Antes a imagem ficava full-width em cima e ficava achatada;
                      na coluna lateral ela aparece inteira e o texto respira. */}
                  {(() => {
                    // Cópia local (template criado aqui) ou o exemplo que a própria Meta devolve
                    const src = t.midia_url || t.header_proxy;   // proxy do nosso dominio
                    const ehVideo = t.midia_tipo === 'video' || t.header_tipo === 'VIDEO';
                    const temMidia = src && t.header_tipo !== 'DOCUMENT';
                    const aviso = !temMidia && t.header_tipo && t.header_tipo !== 'TEXT'
                      ? (t.header_tipo === 'DOCUMENT' ? '📄 Tem documento no cabeçalho' : '🖼 Tem mídia no cabeçalho')
                      : null;

                    const texto = (
                      <div className="dsp-tpl-texto">
                        {t.header_texto && <div className="dsp-tpl-htexto">{t.header_texto}</div>}
                        {/* Texto completo — antes cortava em 2 linhas e a vendedora não via a mensagem toda */}
                        <div className="dsp-tpl-body">{t.body}</div>
                        {t.rodape && <div className="dsp-tpl-rodape muted">{t.rodape}</div>}
                        {Array.isArray(t.botoes) && t.botoes.length > 0 && (
                          <div className="dsp-tpl-btns">
                            {t.botoes.map((bt,i) => <span key={i} className="dsp-tpl-btn">{bt}</span>)}
                          </div>
                        )}
                      </div>
                    );

                    // Sem mídia: o texto ocupa a largura toda, sem coluna vazia do lado.
                    if (!temMidia && !aviso) return texto;

                    return (
                      <div className="dsp-tpl-split">
                        {texto}
                        <div className="dsp-tpl-lado">
                          {temMidia
                            ? <TplMidia src={src} video={ehVideo} className="dsp-tpl-img" />
                            : <div className="dsp-tpl-semimg">{aviso}</div>}
                        </div>
                      </div>
                    );
                  })()}
                  <div className="muted" style={{fontSize:10.5, marginTop:6}}>{t.category === 'MARKETING' ? 'Marketing' : 'Utilidade'} · {t.language}</div>
                </div>
              );
            })}
          </div>
        </div>
      </div>

      {/* ── Histórico ── */}
      <div className="card" style={{marginTop:14}}>
        <div className="card-head"><div className="card-title">Histórico de disparos</div></div>
        {historico.length === 0 && <div className="muted" style={{fontSize:13}}>Nenhum disparo ainda.</div>}
        <div className="col" style={{gap:8}}>
          {historico.map(h => (
            <div key={h.id} className="row" style={{justifyContent:'space-between', gap:10, fontSize:12.5, padding:'10px 12px', border:'1px solid var(--ink-line)', borderRadius:12, flexWrap:'wrap'}}>
              <span style={{fontFamily:'var(--font-mono)', fontWeight:700}}>{h.template}</span>
              <span className="muted">{(DSP_PUBLICOS.find(p=>p.id===h.publico)||{}).label || h.publico}</span>
              <span><b>{h.enviados}</b>/{h.total} enviados{Number(h.falhas)>0?` · ${h.falhas} falhas`:''}</span>
              <span className="muted">R$ {Number(h.custo_estimado).toFixed(2).replace('.',',')}</span>
              <span className="muted">{fmtD(h.criado_em)}</span>
            </div>
          ))}
        </div>
      </div>

      {showNovo && <NovoTemplateModal onClose={()=>setShowNovo(false)} onCreated={carregar} />}

      <style>{`
        /* ── Passos do "Novo disparo" ───────────────────────────────────────
           Antes eram 3 selects idênticos empilhados, sem hierarquia: nada dizia
           o que era decisão principal e o que era refinamento. Agora cada etapa
           é um bloco numerado, e o teste fica claramente opcional. */
        /* Seletor em cartao (modelo e publico). Substitui o <select> nativo, que
           nao aceita estilo -- era aquele dropdown azul do navegador -- e obrigava
           a abrir pra ver as opcoes. */
        /* Chips de etiqueta. O <select> nativo transformava tudo em texto igual e
           jogava fora a COR, que e justamente como a vendedora reconhece a etiqueta
           no pipeline. Etiqueta sem ninguem marcado fica desabilitada. */
        .dsp-chips { display: flex; flex-wrap: wrap; gap: 6px; }
        .dsp-chip { display: inline-flex; align-items: center; gap: 6px;
          font-family: inherit; font-size: 12px; font-weight: 600; cursor: pointer;
          padding: 6px 11px; border-radius: 999px; border: 1.5px solid transparent;
          transition: border-color .15s, box-shadow .15s, opacity .15s; }
        .dsp-chip:disabled { opacity: .38; cursor: not-allowed; }
        .dsp-chip.on { border-color: currentColor;
          box-shadow: 0 0 0 3px oklch(0.55 0.19 285 / 0.10); }
        .dsp-chip-n { font-size: 10.5px; font-weight: 700; opacity: .65;
          padding-left: 5px; border-left: 1px solid currentColor; }
        .dsp-chip-todos { background: oklch(0.95 0.01 260); color: var(--ink-soft); }
        .dsp-chip-lav { background: oklch(0.93 0.05 300); color: oklch(0.40 0.15 300); }
        .dsp-chip-blue { background: oklch(0.93 0.05 250); color: oklch(0.38 0.14 250); }
        .dsp-chip-mint { background: oklch(0.93 0.06 155); color: oklch(0.35 0.13 155); }
        .dsp-chip-yellow { background: oklch(0.95 0.07 85); color: oklch(0.42 0.12 75); }
        .dsp-chip-pink { background: oklch(0.93 0.05 350); color: oklch(0.40 0.14 350); }
        .dsp-chip-red { background: oklch(0.94 0.06 25); color: oklch(0.44 0.16 25); }

        .dsp-esc { display: flex; flex-direction: column; gap: 6px; max-height: 260px;
          overflow-y: auto; padding-right: 2px; }
        .dsp-esc-item { display: flex; align-items: center; gap: 10px; width: 100%;
          text-align: left; font-family: inherit; cursor: pointer;
          padding: 10px 12px; border-radius: 11px; background: #fff;
          border: 1px solid oklch(0.92 0.01 260);
          transition: border-color .15s, background .15s, box-shadow .15s; }
        .dsp-esc-item:hover:not(:disabled) { border-color: oklch(0.78 0.07 285);
          background: oklch(0.99 0.006 285); }
        .dsp-esc-item.on { border-color: oklch(0.55 0.19 285);
          background: oklch(0.985 0.012 285);
          box-shadow: 0 0 0 3px oklch(0.55 0.19 285 / 0.10); }
        .dsp-esc-item:disabled { opacity: .5; cursor: not-allowed; }
        .dsp-esc-radio { flex-shrink: 0; width: 16px; height: 16px; border-radius: 50%;
          border: 2px solid oklch(0.82 0.02 260); position: relative; }
        .dsp-esc-item.on .dsp-esc-radio { border-color: oklch(0.55 0.19 285); }
        .dsp-esc-item.on .dsp-esc-radio::after { content: ''; position: absolute;
          inset: 2px; border-radius: 50%; background: oklch(0.55 0.19 285); }
        .dsp-esc-corpo { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
        .dsp-esc-nome { font-size: 13px; font-weight: 600; color: var(--ink);
          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .dsp-esc-desc { font-size: 11px; color: var(--ink-muted);
          overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
        .dsp-esc-selo { flex-shrink: 0; font-size: 10px; font-weight: 700;
          padding: 3px 9px; border-radius: 999px; white-space: nowrap; }

        .dsp-passo { border: 1px solid oklch(0.93 0.01 260); border-radius: 14px;
          padding: 14px 16px; margin-bottom: 12px; background: #fff; }
        .dsp-passo-cab { display: flex; align-items: flex-start; gap: 10px; margin-bottom: 11px; }
        .dsp-passo-num { flex-shrink: 0; width: 24px; height: 24px; border-radius: 50%;
          background: oklch(0.55 0.19 285); color: #fff; font-size: 12.5px; font-weight: 700;
          display: grid; place-items: center; margin-top: 1px; }
        .dsp-passo-num-op { background: oklch(0.88 0.02 260); color: oklch(0.45 0.02 260); }
        .dsp-passo-tit { font-size: 14px; font-weight: 700; letter-spacing: -0.01em;
          display: flex; align-items: center; gap: 7px; }
        .dsp-passo-sub { font-size: 11.5px; color: var(--ink-muted); margin-top: 1px; }
        .dsp-opcional { font-size: 9.5px; font-weight: 700; text-transform: uppercase;
          letter-spacing: 0.06em; padding: 2px 7px; border-radius: 999px;
          background: oklch(0.94 0.01 260); color: var(--ink-muted); }
        .dsp-sub-campo { margin-top: 11px; padding-top: 11px;
          border-top: 1px dashed oklch(0.92 0.01 260); }

        /* Prévia como balão de WhatsApp: a vendedora entende na hora que aquilo
           é o que o cliente vai ver, sem precisar de legenda. */
        .dsp-balao-wrap { margin-top: 12px; }
        .dsp-balao { background: oklch(0.94 0.06 150); border-radius: 12px 12px 12px 3px;
          padding: 11px 13px; font-size: 12.5px; line-height: 1.55; white-space: pre-wrap;
          color: oklch(0.28 0.03 155); max-width: 92%; }
        .dsp-balao-rodape { margin-top: 7px; font-size: 11px; font-style: italic; opacity: .75; }
        .dsp-balao-nota { font-size: 10.5px; margin-top: 5px; }

        /* Segmentação do público (etapa / temperatura / responsável) */
        .dsp-seg { background: oklch(0.975 0.012 285); border: 1px solid oklch(0.91 0.03 285);
          border-radius: 14px; padding: 13px 15px; margin-bottom: 14px; }
        .dsp-seg-tit { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em;
          color: oklch(0.45 0.14 285); margin-bottom: 10px; }
        .dsp-seg-campos { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
        .dsp-seg-dica { font-size: 11.5px; line-height: 1.45; margin-top: 10px; }
        /* Progresso do envio em lotes */
        .dsp-prog { background: oklch(0.97 0.02 250); border: 1px solid oklch(0.90 0.03 250);
          border-radius: 14px; padding: 13px 15px; margin-bottom: 12px; }
        .dsp-prog-top { display: flex; justify-content: space-between; font-size: 12.5px; font-weight: 600; margin-bottom: 8px; }
        .dsp-prog-bar { height: 7px; border-radius: 99px; background: oklch(0.92 0.02 250); overflow: hidden; }
        .dsp-prog-fill { height: 100%; border-radius: 99px; background: oklch(0.62 0.16 250); transition: width .3s ease; }
        .dsp-prog-nota { font-size: 11px; margin-top: 8px; }
        @media (max-width: 720px) { .dsp-seg-campos { grid-template-columns: 1fr; } }
        /* Prévia do template: texto na ESQUERDA, mídia na DIREITA. A coluna da
           imagem é fixa pra não encolher quando o texto é longo. */
        .dsp-tpl-split { display: grid; grid-template-columns: 1fr 210px; gap: 14px;
          align-items: start; margin-top: 8px; }
        .dsp-tpl-texto { min-width: 0; }   /* sem isso o texto força a coluna e espreme a foto */
        .dsp-tpl-lado { position: sticky; top: 8px; }
        /* object-fit contain (era cover): mostra a foto INTEIRA sem cortar as
           bordas — era a queixa de "não dá pra ver a foto direito". */
        .dsp-tpl-img { display: block; width: 100%; max-height: 260px; object-fit: contain;
          border-radius: 10px; background: oklch(0.95 0.01 250); }
        .dsp-tpl-semimg { font-size: 11.5px; padding: 7px 10px; border-radius: 9px;
          background: oklch(0.96 0.015 250); }
        /* No celular não cabe lado a lado: vira uma coluna, com a imagem embaixo
           do texto (a mensagem é o que importa ler primeiro). */
        @media (max-width: 640px) {
          .dsp-tpl-split { grid-template-columns: 1fr; }
          .dsp-tpl-lado { position: static; }
          .dsp-tpl-img { max-height: 200px; }
        }
        /* Apagar modelo: discreto por padrao, vermelho no hover. Acao destrutiva
           e irreversivel (a Meta trava o nome por 30 dias), entao nao deve competir
           visualmente com o resto do card. */
        .dsp-tpl-del { display: inline-flex; align-items: center; gap: 5px;
          border: 1px solid oklch(0.90 0.01 260); background: #fff; color: var(--ink-muted);
          font: inherit; font-size: 11.5px; font-weight: 600; line-height: 1;
          padding: 5px 10px; border-radius: 8px; cursor: pointer; white-space: nowrap;
          transition: color .15s, border-color .15s, background .15s; }
        .dsp-tpl-del svg { width: 13px; height: 13px; }
        .dsp-tpl-del:hover:not(:disabled) { color: oklch(0.50 0.20 25);
          border-color: oklch(0.80 0.10 25); background: oklch(0.97 0.03 25); }
        .dsp-tpl-del:disabled { opacity: .45; cursor: default; }
        .dsp-tpl-htexto { font-size: 12.5px; font-weight: 700; margin-bottom: 4px; }
        .dsp-tpl-body { font-size: 12.5px; line-height: 1.55; color: var(--ink-soft); white-space: pre-wrap; }
        .dsp-tpl-rodape { font-size: 11px; margin-top: 6px; font-style: italic; }
        .dsp-tpl-btns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
        .dsp-tpl-btn { font-size: 11px; font-weight: 600; padding: 4px 10px; border-radius: 8px;
          background: oklch(0.96 0.02 250); color: oklch(0.48 0.10 250); }
        .dsp-teste { background: oklch(0.975 0.015 200); border: 1px solid oklch(0.90 0.04 200);
          border-radius: 14px; padding: 13px 15px; margin-bottom: 14px; }
        .dsp-teste-tit { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.07em;
          color: oklch(0.42 0.10 210); margin-bottom: 9px; }
        .dsp-teste-dica { font-size: 11.5px; line-height: 1.45; margin-top: 8px; }
        .dsp-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 14px; }
        @media (max-width: 768px) { .dsp-grid { grid-template-columns: 1fr; } }
        /* Botoes do template (o "Quero adquirir!" que aparece pro cliente) */
        .tpl-contador { float: right; font-weight: 500; font-size: 10.5px; }
        /* Cada botao do template vira um cartao proprio: com tipo, texto e (as
           vezes) link/telefone na mesma linha, ficava apertado demais. */
        .tpl-btn-cartao { border: 1px solid oklch(0.92 0.01 260); border-radius: 11px;
          padding: 9px 10px; margin-bottom: 7px; background: oklch(0.99 0.004 260); }
        .tpl-btn-topo { display: flex; align-items: center; justify-content: space-between;
          gap: 8px; margin-bottom: 7px; }
        .tpl-btn-campos { display: flex; flex-direction: column; gap: 6px; }
        .tpl-btn-campos .ezz-input { font-size: 12.5px; }
        /* Seletor segmentado: 3 opcoes fixas ficam melhor lado a lado que num
           dropdown -- some o menu nativo do navegador. */
        .tpl-seg { display: inline-flex; background: oklch(0.94 0.01 260);
          border-radius: 9px; padding: 2px; gap: 2px; }
        .tpl-seg-op { font-family: inherit; font-size: 11.5px; font-weight: 600;
          padding: 5px 12px; border-radius: 7px; border: none; background: transparent;
          color: var(--ink-muted); cursor: pointer; transition: background .15s, color .15s; }
        .tpl-seg-op:hover:not(.on) { color: var(--ink); }
        .tpl-seg-op.on { background: #fff; color: oklch(0.45 0.17 285);
          box-shadow: 0 1px 2px rgba(0,0,0,.08); }
        .tpl-btn-x { border: none; background: transparent; color: var(--ink-muted);
          font-size: 17px; line-height: 1; cursor: pointer; padding: 0 4px; flex-shrink: 0; }
        .tpl-btn-x:hover { color: oklch(0.55 0.20 25); }
        .tpl-btn-add { width: 100%; padding: 8px; font-size: 12px; font-weight: 600;
          color: var(--ink-muted); background: transparent; cursor: pointer; font-family: inherit;
          border: 1px dashed oklch(0.85 0.02 260); border-radius: 9px; }
        .tpl-btn-add:hover { color: var(--ink); border-color: oklch(0.72 0.09 285);
          background: oklch(0.98 0.01 285); }
        /* Previa do botao: imita o botao real do WhatsApp */
        .tpl-btn-prev { margin-top: 4px; padding: 8px; border-radius: 8px; text-align: center;
          font-size: 12.5px; font-weight: 600; color: oklch(0.45 0.14 230);
          background: #fff; border: 1px solid oklch(0.90 0.01 260); max-width: 92%; }
        .tpl-midia-drop { display:flex; align-items:center; gap:10px; padding:14px; border:1.5px dashed oklch(0.86 0.02 255); border-radius:12px; cursor:pointer; font-size:12.5px; color:var(--ink-soft); background:oklch(0.98 0.005 255); }
        .tpl-midia-drop:hover { border-color:oklch(0.7 0.12 285); background:oklch(0.97 0.02 285); }
        .tpl-midia-drop svg { width:18px; height:18px; }
        .tpl-midia-prev { display:flex; align-items:center; gap:12px; padding:10px; border:0.5px solid oklch(0.9 0.01 255); border-radius:12px; background:white; }
        .tpl-midia-prev img { width:52px; height:52px; border-radius:10px; object-fit:cover; }
        .tpl-midia-ic { width:52px; height:52px; border-radius:10px; background:oklch(0.95 0.02 285); display:grid; place-items:center; font-size:22px; }
      `}</style>
    </>
  );
}

Object.assign(window, { Disparos });
