<?php /* views/pages/funis.php */ 

require_once __DIR__ . '/components/tutorial.php';



?>
<style>

/* Oculta o bloco "Fim" da paleta */
button[data-type="fim"] {
  display: none !important;
}

  /* cores por tipo */
  .theme-texto   { --c:#4f46e5; --cbg:#eef2ff; }   /* indigo */
  .theme-esperar { --c:#f59e0b; --cbg:#fff7ed; }   /* amber  */
  .theme-imagem  { --c:#0ea5e9; --cbg:#f0f9ff; }   /* sky    */
  .theme-audio   { --c:#a855f7; --cbg:#faf5ff; }   /* purple */
  .theme-pdf     { --c:#10b981; --cbg:#ecfdf5; }   /* emerald*/
  .theme-video   { --c:#ef4444; --cbg:#fef2f2; }   /* red    */
  .theme-fim     { --c:#64748b; --cbg:#f8fafc; }   /* slate  */

  /* paleta */
  .paletteItem{border:2px solid var(--c);background:#fff;border-radius:.75rem;transition:transform .06s,box-shadow .12s,background .12s}
  .paletteItem:hover{background:var(--cbg);transform:translateY(-1px);box-shadow:0 2px 6px rgba(0,0,0,.06)}
  .paletteItem .title{color:var(--c)}

  /* blocos */
  .blockItem{border:2px solid var(--c);border-radius:.75rem;background:#fff;transition:box-shadow .12s}
  .blockItem .header{background:var(--cbg)}
  .blockItem .dot{width:.5rem;height:.5rem;background:var(--c);border-radius:9999px}
  .blockItem.collapsed .cfg{display:none}
  .blockItem .badge{background:var(--c);color:#fff;font-size:.7rem;border-radius:9999px;padding:.1rem .45rem}
  .dragging{opacity:.6}
  .dnd-placeholder{border:2px dashed #93c5fd;background:#eff6ff;height:58px;border-radius:.5rem;margin:6px 0}

  /* chips de resumo */
  .chip{display:inline-flex;align-items:center;gap:.4rem;font-size:.78rem;background:#f3f4f6;border:1px solid #e5e7eb;border-radius:9999px;padding:.25rem .6rem}
  .chip svg{width:14px;height:14px}

  /* toast */
  #toast{position:fixed;right:14px;bottom:14px;z-index:60;display:none}
  #toast .t{background:#111827;color:#fff;border-radius:.6rem;padding:.6rem .8rem;box-shadow:0 6px 24px rgba(0,0,0,.18)}
</style>







<!-- Em qualquer lugar do HTML: -->
<?= tutorial_component([
  'id'     => 'funis',
  'title'  => 'Como usar Funis',
  'button' => 'Ver tutorial de Funis',
  'video'  => 'https://youtu.be/QT8qHkq6hls',
  'spotlight' => true // se não quiser holofote aqui
]); ?>









<div class="p-6">
  <h1 class="text-2xl font-semibold mb-4">Funil de Prospecção</h1>

  <div class="grid grid-cols-1 lg:grid-cols-3 gap-6">
    <!-- Paleta -->
    <div class="bg-white rounded-lg p-4 shadow lg:col-span-1">
      <h2 class="text-lg font-medium mb-1">Blocos</h2>
      <p class="text-xs text-gray-500 mb-3">Arraste para a área do funil →</p>

      <div id="palette" class="grid grid-cols-2 gap-3">
        <button draggable="true" data-type="texto"   class="paletteItem theme-texto px-3 py-2 text-left"><div class="title font-medium">Enviar texto</div><div class="text-xs text-gray-500">mensagem com placeholders</div></button>
        <button draggable="true" data-type="esperar" class="paletteItem theme-esperar px-3 py-2 text-left"><div class="title font-medium">Esperar</div><div class="text-xs text-gray-500">intervalo em segundos</div></button>
        <button draggable="true" data-type="imagem"  class="paletteItem theme-imagem px-3 py-2 text-left"><div class="title font-medium">Enviar imagem</div><div class="text-xs text-gray-500">upload ou URL</div></button>
        <button draggable="true" data-type="audio"   class="paletteItem theme-audio px-3 py-2 text-left"><div class="title font-medium">Enviar áudio</div><div class="text-xs text-gray-500">upload ou URL</div></button>
        <button draggable="true" data-type="pdf"     class="paletteItem theme-pdf px-3 py-2 text-left"><div class="title font-medium">Enviar PDF</div><div class="text-xs text-gray-500">upload ou URL</div></button>
        <button draggable="true" data-type="video"   class="paletteItem theme-video px-3 py-2 text-left"><div class="title font-medium">Enviar vídeo</div><div class="text-xs text-gray-500">upload ou URL</div></button>
        <button draggable="true" data-type="fim"     class="paletteItem theme-fim px-3 py-2 text-left"><div class="title font-medium">Fim</div><div class="text-xs text-gray-500">encerrar sequência</div></button>
      </div>

      <hr class="my-4">
      <div class="space-y-2">
        <label class="block text-sm mb-1">Nome do funil</label>
        <input id="fNome" type="text" class="w-full rounded border px-3 py-2" placeholder="Ex: Sequência inicial">
      </div>

      <div class="mt-4 flex items-center gap-2">
        <button id="btnSave" class="rounded bg-indigo-600 text-white px-4 py-2">Salvar rascunho</button>
        <button id="btnPublish" class="rounded bg-emerald-600 text-white px-4 py-2">Publicar</button>
      </div>
      <div class="mt-2 text-sm text-gray-500" id="msg"></div>
    </div>

    <!-- Canvas -->
    <div class="bg-white rounded-lg p-4 shadow lg:col-span-2">
      <div class="flex items-center justify-between mb-3">
        <h2 class="text-lg font-medium">Canvas do funil</h2>
        <div class="flex items-center gap-2">
          <span id="sumSteps" class="chip" title="Total de blocos">
            <svg viewBox="0 0 24 24" fill="currentColor"><path d="M3 5h18v2H3V5zm0 6h12v2H3v-2zm0 6h18v2H3v-2z"/></svg>
            <b>0</b> blocos
          </span>
          <span id="sumTime" class="chip" title="Soma dos 'Esperar'">
            <svg viewBox="0 0 24 24" fill="currentColor"><path d="M12 1a11 11 0 1 0 11 11A11.012 11.012 0 0 0 12 1Zm1 11.59 4.3 4.3-1.42 1.42L11 13V6h2Z"/></svg>
            ~ <b>0s</b>
          </span>
          <button id="btnAddTexto" class="rounded border px-3 py-1.5 text-sm">+ Texto</button>
          <button id="btnAddEsperar" class="rounded border px-3 py-1.5 text-sm">+ Esperar</button>
        </div>
      </div>

      <div id="canvas" class="min-h-[220px] rounded-lg border p-3 bg-gray-50" aria-label="Área para arrastar e ordenar os blocos do funil">
        <div class="text-center text-gray-500 text-sm py-16 empty-hint">Arraste itens da biblioteca para cá ou use os botões “+”</div>
      </div>

      <div class="mt-4 text-xs text-gray-500">Dica: clique no título do bloco para **abrir/fechar**. Use <kbd>Alt</kbd> + <kbd>↑</kbd>/<kbd>↓</kbd> para reordenar; <kbd>Delete</kbd> remove.</div>
    </div>
  </div>

  <!-- Lista -->
  <div class="mt-6 bg-white rounded-lg p-4 shadow">
    <div class="flex items-center justify-between mb-3">
      <h2 class="text-lg font-medium">Meus funis</h2>
      <button id="btnReload" class="rounded bg-gray-800 text-white px-3 py-1.5 text-sm">Atualizar</button>
    </div>
    <div class="overflow-x-auto">
      <table class="min-w-full text-sm">
        <thead>
          <tr class="text-left border-b"><th class="py-2 pr-3">Nome</th><th class="py-2 pr-3">Status</th><th class="py-2 pr-3">Versão</th><th class="py-2">Ações</th></tr>
        </thead>
        <tbody id="tbodyFunis"></tbody>
      </table>
    </div>
  </div>
</div>

<div id="toast"><div class="t" id="toastMsg"></div></div>

<script>
(function(){
  const API_FUNIS='api/funis.php', API_UPLOAD='api/upload.php';
  let editingId=null;

  const canvas=document.getElementById('canvas');
  const fNome=document.getElementById('fNome');
  const msg=document.getElementById('msg');
  const sumSteps=document.getElementById('sumSteps').querySelector('b');
  const sumTime=document.getElementById('sumTime').querySelector('b');

  const THEME={texto:'theme-texto',esperar:'theme-esperar',imagem:'theme-imagem',audio:'theme-audio',pdf:'theme-pdf',video:'theme-video',fim:'theme-fim'};
  const uid = ()=>'b'+Math.random().toString(36).slice(2,9);
  const esc = s=>String(s||'').replaceAll('&','&amp;').replaceAll('<','&lt;').replaceAll('"','&quot;');

  function toast(s){ const t=document.getElementById('toast'); const m=document.getElementById('toastMsg'); m.textContent=s; t.style.display='block'; setTimeout(()=>t.style.display='none',1800); }

  async function fetchJSON(url,opts={}){ const r=await fetch(url,{credentials:'same-origin',...opts}); const t=await r.text(); let j; try{j=JSON.parse(t)}catch{} return j&&r.ok?j:{ok:false,error:j?.error||t||'Falha'}; }

  function fileName(u){ try{const p=new URL(u);return decodeURIComponent(p.pathname.split('/').pop()||'arquivo');}catch{const i=(u||'').lastIndexOf('/');return decodeURIComponent((i>=0?u.slice(i+1):u)||'arquivo');} }

  // === leitura / escrita ===
  function readSequence(){
    const out=[];
    canvas.querySelectorAll('.blockItem').forEach((el,i)=>{
      const tipo=el.dataset.type, s={tipo};
      if(tipo==='texto') s.conteudo=el.querySelector('.fConteudo').value||'';
      else if(tipo==='esperar') s.segundos=parseInt(el.querySelector('.fSeg').value||'0',10)||0;
      else if(['imagem','audio','pdf','video'].includes(tipo)){ s.url=el.querySelector('.fUrl').value||''; s.legenda=el.querySelector('.fLegenda')?.value||''; }
      out.push(s);
    });
    return out;
  }
  function blockToData(el){
    const tipo=el.dataset.type, s={};
    if(tipo==='texto') s.conteudo=el.querySelector('.fConteudo').value||'';
    if(tipo==='esperar') s.segundos=parseInt(el.querySelector('.fSeg').value||'0',10)||0;
    if(['imagem','audio','pdf','video'].includes(tipo)){ s.url=el.querySelector('.fUrl').value||''; s.legenda=el.querySelector('.fLegenda')?.value||''; }
    return s;
  }

  // === Preview mídia ===
  function renderMediaPreview(el){
    const type=el.dataset.type, url=el.querySelector('.fUrl').value.trim();
    const prev=el.querySelector('.preview'), btnOpen=el.querySelector('.btnOpen'), btnClear=el.querySelector('.btnClear');
    btnOpen.disabled=!url; btnClear.disabled=!url;
    if(!url){ prev.innerHTML=`<div class="text-xs text-gray-500">Nenhum arquivo. Faça o upload ou cole um link.</div>`; return; }
    if(type==='imagem') prev.innerHTML=`<img src="${esc(url)}" alt="pré-visualização" class="max-h-28 rounded border">`;
    else if(type==='audio') prev.innerHTML=`<audio controls src="${esc(url)}" class="w-full"></audio>`;
    else if(type==='pdf') prev.innerHTML=`<div class="flex items-center gap-2 text-sm"><svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-emerald-600" viewBox="0 0 24 24" fill="currentColor"><path d="M6 2h7l5 5v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2z"/><path class="text-white" d="M14 2v6h6"/></svg><span class="truncate max-w-[320px]">${esc(fileName(url))}</span><a href="${esc(url)}" target="_blank" download class="rounded border px-2 py-1 text-xs">Baixar PDF</a></div>`;
    else if(type==='video') prev.innerHTML=`<div class="flex items-center gap-2 text-sm"><svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-red-500" viewBox="0 0 24 24" fill="currentColor"><path d="M17 10.5V6a2 2 0 0 0-2-2H3v16h12a2 2 0 0 0 2-2v-4.5l4 4v-11l-4 4z"/></svg><span class="truncate max-w-[320px]">${esc(fileName(url))}</span><a href="${esc(url)}" target="_blank" download class="rounded border px-2 py-1 text-xs">Baixar vídeo</a></div>`;
  }

  // === criação de bloco ===
  function createBlock(type,data={}){
    const id=uid(), themeClass=THEME[type]||'theme-fim';
    const titleMap={texto:'Enviar texto',esperar:'Esperar',imagem:'Enviar imagem',audio:'Enviar áudio',pdf:'Enviar PDF',video:'Enviar vídeo',fim:'Fim'};
    const def = type==='texto'?{conteudo:''}
              : type==='esperar'?{segundos:(typeof data.segundos==='number'?data.segundos:60)}
              : ['imagem','audio','pdf','video'].includes(type)?{url:'',legenda:''}:{};
    const value={...def,...data};

    const el=document.createElement('div');
    el.className=`blockItem ${themeClass} group p-0 shadow-sm mb-2`;
    el.dataset.id=id; el.dataset.type=type; el.tabIndex=0; el.draggable=true;

    el.innerHTML=`
      <div class="header flex items-center gap-2 px-3 py-2 rounded-t-lg">
        <span class="badge" data-role="idx">1</span>
        <div class="cursor-grab active:cursor-grabbing text-gray-400" draggable="true" data-role="handle" title="Arraste">
          <svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" viewBox="0 0 24 24" fill="currentColor">
            <circle cx="5" cy="7" r="1"/><circle cx="5" cy="12" r="1"/><circle cx="5" cy="17" r="1"/>
            <circle cx="9" cy="7" r="1"/><circle cx="9" cy="12" r="1"/><circle cx="9" cy="17" r="1"/>
          </svg>
        </div>
        <span class="dot"></span>
        <button class="toggle font-medium text-left" style="flex:1;outline:none">${titleMap[type]||type}</button>
        <div class="ml-auto flex items-center gap-1 opacity-0 group-hover:opacity-100 transition">
          <button class="btnDup text-xs rounded border px-2 py-1" title="Duplicar">dup</button>
          <button class="btnDel text-xs rounded bg-rose-600 text-white px-2 py-1" title="Remover">rem</button>
        </div>
      </div>
      <div class="cfg px-3 py-3"></div>`;

    const cfg=el.querySelector('.cfg');
    if(type==='texto'){
      cfg.innerHTML=`<label class="block text-sm mb-1">Conteúdo</label>
        <textarea class="fConteudo w-full rounded border px-3 py-2" rows="3">${esc(value.conteudo)}</textarea>`;
    }else if(type==='esperar'){
      cfg.innerHTML=`<label class="block text-sm mb-1">Intervalo (segundos)</label>
        <input class="fSeg w-full rounded border px-3 py-2" type="number" min="0" step="1" value="${value.segundos??60}">
        <p class="text-xs text-gray-500 mt-1">Tempo entre este bloco e o próximo.</p>`;
    }else if(['imagem','audio','pdf','video'].includes(type)){
      const accept= type==='imagem'?'image/*': type==='audio'?'audio/*': type==='pdf'?'application/pdf':'video/*';
      cfg.innerHTML=`
        <div class="flex items-center gap-2 mb-2">
          <button type="button" class="btnUpload rounded border px-3 py-2 text-sm">Upload</button>
          <button type="button" class="btnPaste rounded border px-3 py-2 text-sm">Colar URL</button>
          <button type="button" class="btnOpen rounded border px-3 py-2 text-sm" ${value.url?'':'disabled'}>Abrir</button>
          <button type="button" class="btnClear rounded border px-3 py-2 text-sm" ${value.url?'':'disabled'}>Remover</button>
        </div>
        <input class="fUrl hidden" value="${esc(value.url)}">
        <div class="preview mb-2"></div>
        <label class="block text-sm mt-1 mb-1">Legenda (opcional)</label>
        <input class="fLegenda w-full rounded border px-3 py-2" value="${esc(value.legenda)}">
        <p class="text-xs text-gray-500 mt-2">Limite: 50MB. Tipos aceitos: ${accept.replaceAll('*','')}</p>`;
      const btnUpload=cfg.querySelector('.btnUpload'), btnPaste=cfg.querySelector('.btnPaste'), btnOpen=cfg.querySelector('.btnOpen'), btnClear=cfg.querySelector('.btnClear'), inputUrl=cfg.querySelector('.fUrl');
      const doRender=()=>{renderMediaPreview(el); scheduleAutosave();};
      btnUpload.addEventListener('click',async()=>{
        const fi=document.createElement('input'); fi.type='file'; fi.accept=accept;
        fi.onchange=async()=>{
          if(!fi.files||!fi.files[0])return;
          btnUpload.disabled=true; const old=btnUpload.textContent; btnUpload.textContent='Enviando...';
          const fd=new FormData(); fd.append('file',fi.files[0]); fd.append('kind',type==='pdf'?'pdf':(type==='imagem'?'imagem':(type==='audio'?'audio':'video')));
          try{const r=await fetch(API_UPLOAD,{method:'POST',body:fd,credentials:'same-origin'}); const j=await r.json();
            if(j.ok){ inputUrl.value=j.public_url||j.signed_url||''; doRender(); toast('Arquivo enviado'); }
            else alert((j.error||'Falha ao enviar')+(j.status?' ['+j.status+']':''));}
          catch{ alert('Erro de rede'); }
          btnUpload.disabled=false; btnUpload.textContent=old;
        };
        fi.click();
      });
      btnPaste.addEventListener('click',()=>{ const u=prompt('Cole a URL pública do arquivo:'); if(!u)return; inputUrl.value=u.trim(); doRender(); });
      btnOpen.addEventListener('click',()=>{ const u=inputUrl.value.trim(); if(u) window.open(u,'_blank'); });
      btnClear.addEventListener('click',()=>{ inputUrl.value=''; doRender(); });
      renderMediaPreview(el);
    }else{
      cfg.innerHTML=`<p class="text-xs text-gray-500">Este passo encerra a sequência.</p>`;
    }

    // colapsar
    el.querySelector('.toggle').addEventListener('click',()=>{ el.classList.toggle('collapsed'); });

    // duplicar/remover
    el.querySelector('.btnDel').addEventListener('click',()=>{ el.remove(); renumber(); scheduleAutosave(); });
    el.querySelector('.btnDup').addEventListener('click',()=>{ const clone=createBlock(type,blockToData(el)); el.after(clone); renumber(); scheduleAutosave(); });

    // teclado: Alt+↑/↓ reordena; Delete remove
    el.addEventListener('keydown',e=>{
      if(e.altKey && (e.key==='ArrowUp'||e.key==='ArrowDown')){ e.preventDefault();
        const trg = e.key==='ArrowUp'? el.previousElementSibling : el.nextElementSibling;
        if(trg && trg.classList.contains('blockItem')){ (e.key==='ArrowUp'?canvas.insertBefore(el,trg):canvas.insertBefore(trg,el)); renumber(); scheduleAutosave(); }
      }else if(e.key==='Delete'){ e.preventDefault(); el.remove(); renumber(); scheduleAutosave(); }
    });

    // qualquer mudança aciona autosave/summary
    el.addEventListener('input',()=>{ scheduleAutosave(); });

    setupBlockDnD(el);
    return el;
  }

  // === util: UI ===
  function toggleEmptyHint(){ const hint=canvas.querySelector('.empty-hint'); if(!hint)return; hint.style.display=canvas.querySelector('.blockItem')?'none':''; }
  function addBlock(type,data){ const b=createBlock(type,data); canvas.appendChild(b); renumber(); toggleEmptyHint(); return b; }
  function clearCanvas(){ canvas.innerHTML=`<div class="text-center text-gray-500 text-sm py-16 empty-hint">Arraste itens da biblioteca para cá ou use os botões “+”</div>`; updateSummary(); }

  function renumber(){ let i=1; canvas.querySelectorAll('.blockItem [data-role="idx"]').forEach(b=>b.textContent=i++); updateSummary(); }

  function updateSummary(){
    const blocks=canvas.querySelectorAll('.blockItem').length;
    sumSteps.textContent=blocks;
    let secs=0; canvas.querySelectorAll('.blockItem[data-type="esperar"] .fSeg').forEach(i=>{ const v=parseInt(i.value||'0',10)||0; secs+=v; });
    sumTime.textContent = secs<60 ? `${secs}s` : `${Math.floor(secs/60)}m${secs%60?(' '+(secs%60)+'s'):''}`;
  }

  // === Drag & Drop ===
  let dragEl=null, placeholder=null;
  function setupBlockDnD(el){
    const handle=el.querySelector('[data-role="handle"]')||el;
    handle.addEventListener('dragstart',ev=>{
      dragEl=el; el.classList.add('dragging'); ev.dataTransfer.effectAllowed='move';
      ev.dataTransfer.setData('text/plain',el.dataset.id);
      placeholder=document.createElement('div'); placeholder.className='dnd-placeholder';
      setTimeout(()=>{ el.style.display='none'; },0);
    });
    handle.addEventListener('dragend',()=>{
      if(placeholder&&placeholder.parentNode) placeholder.replaceWith(dragEl);
      dragEl.classList.remove('dragging'); dragEl.style.display=''; dragEl=null; placeholder=null; renumber(); scheduleAutosave();
    });
  }
  function before(a,b){ b.parentNode.insertBefore(a,b); }
  function after(a,b){ b.parentNode.insertBefore(a,b.nextSibling); }
  function closestBlock(el){ return el?.closest?.('.blockItem')||null; }

  canvas.addEventListener('dragover',ev=>{
    ev.preventDefault();
    const target=closestBlock(ev.target);
    if(!placeholder) return;
    if(!target){ if(canvas.lastElementChild!==placeholder) canvas.appendChild(placeholder); return; }
    const box=target.getBoundingClientRect(); const halfway=(ev.clientY-box.top)<box.height/2;
    if(halfway) before(placeholder,target); else after(placeholder,target);
  });
  canvas.addEventListener('drop',ev=>{
    ev.preventDefault();
    const paletteType=ev.dataTransfer.getData('text/type');
    if(paletteType){ const b=addBlock(paletteType); if(placeholder&&placeholder.parentNode) placeholder.replaceWith(b); return; }
    if(dragEl&&placeholder&&placeholder.parentNode) placeholder.replaceWith(dragEl);
  });

  // Paleta arrasta tipo
  document.getElementById('palette').querySelectorAll('.paletteItem').forEach(it=>{
    it.addEventListener('dragstart',ev=>{ ev.dataTransfer.setData('text/type',it.dataset.type); ev.dataTransfer.effectAllowed='copy'; });
  });

  // atalhos botões
  document.getElementById('btnAddTexto').addEventListener('click',()=> addBlock('texto'));
  document.getElementById('btnAddEsperar').addEventListener('click',()=> addBlock('esperar'));

  // === Autosave (debounce 1.2s) ===
  let autosaveTimer=null;
  function scheduleAutosave(){ updateSummary(); clearTimeout(autosaveTimer); autosaveTimer=setTimeout(saveDraft,1200); }
  fNome.addEventListener('input',scheduleAutosave);

  // === Persistência ===
  async function saveDraft(){
    const payload={id:editingId,nome:fNome.value||'',sequencia:readSequence()};
    msg.textContent='Salvando...';
    const j=await fetchJSON(`${API_FUNIS}?action=save`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});
    msg.textContent=j.ok?'Rascunho salvo.':('Erro: '+(j.error||'Falha'));
    if(j.ok){ if(j.id&&!editingId) editingId=j.id; toast('Rascunho salvo'); }
    await loadList();
  }

  function validateSequence(seq){
    const issues=[];
    seq.forEach((s,i)=>{
      const n=i+1;
      if(s.tipo==='texto' && !s.conteudo?.trim()) issues.push(`#${n}: texto vazio`);
      if(s.tipo==='esperar' && (s.segundos==null || s.segundos<0)) issues.push(`#${n}: esperar inválido`);
      if(['imagem','audio','pdf','video'].includes(s.tipo) && !s.url?.trim()) issues.push(`#${n}: ${s.tipo} sem URL`);
    });
    return issues;
  }

  async function publish(){
    if(!editingId){ msg.textContent='Salve primeiro o rascunho.'; return; }
    const seq=readSequence(); const problems=validateSequence(seq);
    if(problems.length){ alert('Corrija antes de publicar:\n- '+problems.join('\n- ')); return; }
    msg.textContent='Publicando...';
    const body=new URLSearchParams({id:editingId});
    const j=await fetchJSON(`${API_FUNIS}?action=publish`,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body});
    msg.textContent=j.ok?`Publicado v${j.versao}.`:('Erro: '+(j.error||'Falha'));
    if(j.ok) toast('Publicado!');
    await loadList();
  }
  document.getElementById('btnSave').addEventListener('click',saveDraft);
  document.getElementById('btnPublish').addEventListener('click',publish);

  // Lista
  async function loadList(){
    const tb=document.getElementById('tbodyFunis');
    const j=await fetchJSON(`${API_FUNIS}?action=list&_=${Date.now()}`);
    if(!j.ok){ tb.innerHTML=`<tr><td class="py-3" colspan="4">${j.error}</td></tr>`; return; }
    tb.innerHTML=(j.data||[]).map(f=>`
      <tr class="border-b">
        <td class="py-2 pr-3">${f.nome}</td>
        <td class="py-2 pr-3">${f.status}</td>
        <td class="py-2 pr-3">${f.versao}</td>
        <td class="py-2">
          <button class="actEdit px-2 py-1 rounded border" data-id="${f.id}">Editar</button>
          <button class="actDel px-2 py-1 rounded bg-rose-600 text-white ml-1" data-id="${f.id}">Excluir</button>
        </td>
      </tr>`).join('') || '<tr><td class="py-3" colspan="4">Nenhum funil</td></tr>';

    tb.querySelectorAll('.actEdit').forEach(b=>b.addEventListener('click',async()=>{
      const id=b.getAttribute('data-id');
      const g=await fetchJSON(`${API_FUNIS}?action=get&id=${encodeURIComponent(id)}`);
      if(!g.ok){ msg.textContent='Erro: '+(g.error||'Falha'); return; }
      editingId=g.data.id; fNome.value=g.data.nome||''; clearCanvas();
      const seq=Array.isArray(g.data.sequencia)?g.data.sequencia:(JSON.parse(g.data.sequencia||'[]')||[]);
      seq.forEach(s=> addBlock(s.tipo,s));
      msg.textContent='Rascunho carregado.'; toast('Rascunho carregado');
    }));

    tb.querySelectorAll('.actDel').forEach(b=>b.addEventListener('click',async()=>{
      if(!confirm('Excluir este funil?')) return;
      const id=b.getAttribute('data-id'); const body=new URLSearchParams({id});
      const r=await fetchJSON(`${API_FUNIS}?action=delete`,{method:'POST',headers:{'Content-Type':'application/x-www-form-urlencoded'},body});
      if(!r.ok) alert(r.error||'Falha');
      if(editingId===id){ editingId=null; fNome.value=''; clearCanvas(); }
      await loadList();
    }));
  }
  document.getElementById('btnReload').addEventListener('click',loadList);

  // boot
  clearCanvas(); addBlock('texto'); loadList();
})();
</script>
