<?php // views/pages/agente-atendimento.php
require_once __DIR__ . '/../../app/csrf.php';
require_once __DIR__ . '/components/tutorial.php';
$csrf = htmlspecialchars(csrf_token(), ENT_QUOTES, 'UTF-8');

/** Seed do prompt (será convertido p/ tokens no load) */
$defaultPrompt = <<<TXT
Insira seu prompt aqui. Confira o tutorial no topo da página e visite também nossa área de dicas para acessar modelos prontos e sugestões de prompts.

TXT;
?>

<!-- Tutorial -->
<!-- Tutorial -->
<div class="mb-4 sm:mb-6">
  <?= tutorial_component([
    'id' => 'agente-atendimentos',
    'title' => 'Como usar Agente de Atendimentos',
    'button' => 'Ver tutorial Agente de Atendimento',
    'video' => 'https://youtu.be/rv_7j_mHChc',
    'spotlight' => true
  ]); ?>
  

</div>



<style>
#refreshMediaTags {
  display: none !important;
}


  /* Oculta o botão "usar no prompt" na Minha biblioteca */
  #libList .btnInsert {
    display: none !important;
  }

  #btnInsertAgendaChip,
  #btnInsertNumeroChip,
  #btnInsertGrupoChip {
    display: none !important;
  }

  /* Botão "Ver Prompt" dentro do popup (só nesta página) */
  #btnVerPrompt {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    margin-top: 24px; /* espaçamento abaixo do vídeo */
    padding: .7rem 1.1rem;
    border-radius: .75rem;
    border: 1px solid #4f46e5;
    background: linear-gradient(135deg,#6366f1 0%,#4f46e5 100%);
    color: #fff;
    font-size: .9rem;
    font-weight: 700;
    box-shadow: 0 6px 18px rgba(79,70,229,.18);
    transition: transform .15s ease, box-shadow .15s ease, opacity .15s ease;
    text-decoration: none;
  }
  #btnVerPrompt:hover { transform: translateY(-1px); box-shadow: 0 10px 24px rgba(79,70,229,.25); }
  #btnVerPrompt:active { transform: translateY(0); }
</style>

<script>
(function () {
  const BTN_ID = 'btnVerPrompt';
  const TUTORIAL_TITLE = 'Como usar Agente de Atendimentos';
  const DRIVE_LINK = 'https://docs.google.com/document/d/1er7O8skfpoBq7kFTwycgnhBrM3GxMVxulvMUy-BnO7Q/edit?usp=sharing'; // <-- coloque seu link do Drive

  // Checagem de visibilidade robusta
  function isVisible(el) {
    if (!el) return false;
    const cs = getComputedStyle(el);
    if (cs.display === 'none' || cs.visibility === 'hidden' || Number(cs.opacity) === 0) return false;
    const rect = el.getBoundingClientRect();
    return rect.width > 0 && rect.height > 0;
  }

  // Encontra um "modal" cujo texto contenha o título
  function findOpenTutorialModal() {
    const pools = [
      '[role="dialog"]',
      '.modal, .dialog, .ReactModal__Content',
      '.fixed.inset-0',               // tailwind patterns
      '[class*="modal"], [class*="Dialog"], [class*="Overlay"]'
    ].join(',');

    const candidates = Array.from(document.querySelectorAll(pools))
      .filter(isVisible)
      .filter(el => (el.innerText || '').includes(TUTORIAL_TITLE));

    return candidates[candidates.length - 1] || null;
  }

  function injectButton(modal) {
    if (!modal || modal.querySelector('#' + BTN_ID)) return;

    // Tenta localizar vídeo/iframe
    const videoEl =
      modal.querySelector('iframe, video') ||
      modal.querySelector('.video, .video-wrapper iframe, .video-wrapper video');

    // Cria botão
    const btn = document.createElement('a');
    btn.id = BTN_ID;
    btn.href = DRIVE_LINK;
    btn.target = '_blank';
    btn.rel = 'noopener noreferrer';
    btn.textContent = '📝 Ver Prompt';

    // 1) Preferência: logo abaixo do vídeo
    if (videoEl && videoEl.parentElement) {
      videoEl.parentElement.appendChild(btn);
      return;
    }

    // 2) Fallback: acima do botão "Fechar"
    const closeByText = Array.from(modal.querySelectorAll('button, [role="button"]'))
      .find(b => (b.textContent || '').trim().toLowerCase() === 'fechar');
    if (closeByText && closeByText.parentElement) {
      closeByText.parentElement.insertBefore(btn, closeByText);
      return;
    }

    // 3) Último recurso: final do conteúdo do modal
    (modal.querySelector('.modal-content, .content, .p-6, .p-4') || modal).appendChild(btn);
  }

  // Observa o DOM e tenta injetar quando o modal abrir
  const mo = new MutationObserver(() => {
    const modal = findOpenTutorialModal();
    if (modal) injectButton(modal);
  });
  mo.observe(document.body, { childList: true, subtree: true });

  // Tenta injetar em cliques (quando abre)
  document.addEventListener('click', () => {
    setTimeout(() => {
      const modal = findOpenTutorialModal();
      if (modal) injectButton(modal);
    }, 100);
  });

  // Tentativas iniciais
  const tryNow = () => {
    const modal = findOpenTutorialModal();
    if (modal) injectButton(modal);
  };
  window.addEventListener('load', () => setTimeout(tryNow, 200));
  setTimeout(tryNow, 400);
})();
</script>





















<!-- Card: Config do agente -->
<div class="rounded-xl border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 p-6">
  <div class="flex items-center justify-between mb-4">
    <div>
      <h2 class="text-xl font-semibold">Agente de Atendimento</h2>
      <p class="text-sm text-gray-500 dark:text-gray-400">
        Defina o prompt base usado pelo seu agente de atendimento.
      </p>
    </div>
    <span id="saveBadge" class="hidden text-xs px-2 py-1 rounded bg-emerald-100 text-emerald-800">Salvo</span>
  </div>

  <!-- Barra de mídias como tags -->
<!-- Barra de mídias como tags (STICKY) -->
<div id="mediaStickyContainer" class="mb-3">
  <div id="mediaTagsWrapper">
    <div class="flex items-center justify-between mb-1">
      <div class="text-sm font-medium">Minhas Ferramentas</div>
      <button id="refreshMediaTags" class="rounded border px-2 py-1 text-xs">Atualizar</button>
    </div>
<div class="flex flex-wrap gap-2 items-center">
<button id="chipAgendaTop"
        class="tag-chip btn"
        draggable="true"            
        style="background: linear-gradient(135deg,#6366f1 0%,#4f46e5 100%); border-color:#4f46e5; color:#fff"
        title="Inserir agenda">
  <span>🗓️</span><span class="tag-id">Agenda</span></button>


<button id="chipNumeroTop"
        class="tag-chip btn"
        draggable="true"
        style="background: linear-gradient(135deg,#14b8a6 0%,#0d9488 100%); border-color:#0d9488; color:#fff"
        title="Inserir número para falar com humano">
  <span>👤</span><span class="tag-id">Falar com uma pessoa</span>
</button>

<button id="chipGrupoTop"
        class="tag-chip btn"
        draggable="true"
        style="background: linear-gradient(135deg,#f59e0b 0%,#d97706 100%); border-color:#d97706; color:#fff"
        title="Inserir grupo para falar com humano">
  <span>👥</span><span class="tag-id">Avisar no Grupo</span>
</button>


  <div id="mediaTags" class="flex flex-wrap gap-2"></div>
</div>
    <p class="text-[11px] text-gray-500 mt-1">
      Como usar: Arraste a ferramenta para o local correto no seu prompt.
    </p>
  </div>
</div>

<style>

/* Esconde a linha do URL na lista da biblioteca */
#libList .flex-1 > div:nth-child(2){
  display: none !important;
}

/* Na Minha biblioteca, oculte a 2ª linha (URL) e a 3ª linha (tipo • data) */
#libList .flex-1 > div:nth-child(2),
#libList .flex-1 > div:nth-child(3){
  display: none !important;
}


/* ===== STICKY BEHAVIOR ===== */
#mediaStickyContainer {
  position: relative;
}

#mediaTagsWrapper {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

#mediaTagsWrapper.is-sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 40;
  background: rgba(255, 255, 255, 0.98);
  backdrop-filter: blur(12px);
  border-bottom: 1px solid #e5e7eb;
  padding: 1rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
  animation: slideDown 0.3s ease-out;
}

.dark #mediaTagsWrapper.is-sticky {
  background: rgba(11, 15, 26, 0.98);
  border-bottom-color: #374151;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

@keyframes slideDown {
  from {
    transform: translateY(-100%);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

#mediaStickyContainer.has-placeholder::before {
  content: '';
  display: block;
  height: var(--placeholder-height, 0px);
}




/* Desliga a linha azul de drop */
.drop-indicator { display: none !important; }

/* ===== CHIPS (acima) - CORES VIBRANTES ===== */
.tag-chip {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: .82rem;
  font-weight: 600;
  border-radius: 9999px;
  padding: .4rem .75rem;
  border: 2px solid transparent;
  cursor: grab;
  transition: all 0.2s ease;
  box-shadow: 0 2px 4px rgba(0,0,0,.1);
}
.tag-chip:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0,0,0,.15);
}
.tag-chip:active {
  cursor: grabbing;
  transform: scale(0.98);
}
.tag-id {
  font-family: ui-monospace, monospace;
  font-size: .78rem;
}

/* CORES VIBRANTES POR TIPO */
.tag-image {
  background: linear-gradient(135deg, #10b981 0%, #059669 100%);
  border-color: #059669;
  color: #ffffff;
}
.tag-video {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
  border-color: #dc2626;
  color: #ffffff;
}
.tag-audio {
  background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
  border-color: #7c3aed;
  color: #ffffff;
}
.tag-pdf {
  background: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%);
  border-color: #0891b2;
  color: #ffffff;
}
.tag-file {
  background: linear-gradient(135deg, #64748b 0%, #475569 100%);
  border-color: #475569;
  color: #ffffff;
}

/* Editor contenteditable */
.prompt-editor {
  min-height: 260px;
  border: 2px solid #d1d5db;
  border-radius: .5rem;
  padding: .75rem;
  outline: none;
  white-space: pre-wrap;
  position: relative;
}
.dark .prompt-editor {
  border-color: #374151;
  background: #0b0f1a;
}
.prompt-editor:focus {
  border-color: #818cf8;
  box-shadow: 0 0 0 3px rgba(99, 102, 241, .15);
}
.prompt-placeholder {
  color: #94a3b8;
}

/* Drop indicator - linha que mostra onde vai cair */
.drop-indicator {
  position: absolute;
  height: 3px;
  background: #818cf8;
  border-radius: 2px;
  pointer-events: none;
  z-index: 100;
  box-shadow: 0 0 8px rgba(129, 140, 248, 0.6);
  transition: all 0.1s ease;
}

/* Editor em modo drag-over */
.prompt-editor.drag-over {
  border-color: #818cf8;
  background: rgba(129, 140, 248, 0.05);
}

/* ===== TOKENS DENTRO DO PROMPT (super destaque) ===== */
.media-token {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .3rem .8rem;
  border-radius: 9999px;
  border: 3px solid transparent;
  font-weight: 800;
  font-size: 1.05rem;
  line-height: 1;
  vertical-align: middle;
  color: #fff;
  box-shadow: 0 3px 6px rgba(0,0,0,.18);
  transform: translateY(-1px);
  cursor: move;
  transition: all 0.2s ease;
}
.media-token:hover {
  transform: translateY(-3px) scale(1.05);
  box-shadow: 0 5px 12px rgba(0,0,0,.25);
}
.media-token[contenteditable="false"] {
  user-select: none;
}
.media-token.dragging {
  opacity: 0.5;
  cursor: grabbing;
}

.media-token .icon {
  font-size: 1.15rem;
  line-height: 1;
}
.media-token .label {
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
  font-size: .95rem;
  letter-spacing: .2px;
}

/* CORES CHAPADAS POR TIPO */
.media-token[data-type="image"] {
  background: linear-gradient(135deg, #22c55e 0%, #16a34a 100%);
  border-color: #16a34a;
}



.media-token[data-type="humano_numero"] {
  background: linear-gradient(135deg,#14b8a6 0%,#0d9488 100%);
  border-color:#0d9488;
}
.media-token[data-type="humano_grupo"] {
  background: linear-gradient(135deg,#f59e0b 0%,#d97706 100%);
  border-color:#d97706;
}



.media-token[data-type="video"] {
  background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%);
  border-color: #dc2626;
}

.media-token[data-type="agenda"] {
  background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
  border-color: #4f46e5;
}

.media-token[data-type="audio"] {
  background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);
  border-color: #7c3aed;
}
.media-token[data-type="pdf"] {
  background: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%);
  border-color: #0891b2;
}
.media-token[data-type="file"] {
  background: linear-gradient(135deg, #64748b 0%, #475569 100%);
  border-color: #475569;
}

.media-token:focus-visible {
  outline: 3px solid #ffffff;
  outline-offset: 2px;
}
.dark .media-token:focus-visible {
  outline: 3px solid #0b0f1a;
  outline-offset: 2px;
}

/* Slash menu */
.slash-menu {
  position: absolute;
  z-index: 50;
  min-width: 260px;
  max-height: 240px;
  overflow: auto;
  background: #fff;
  border: 1px solid #e5e7eb;
  border-radius: .6rem;
  box-shadow: 0 8px 24px rgba(0,0,0,.08);
}
.dark .slash-menu {
  background: #0b0f1a;
  border-color: #1f2937;
}
.slash-item {
  display: flex;
  align-items: center;
  gap: .6rem;
  padding: .45rem .65rem;
  font-size: .85rem;
  cursor: pointer;
}
.slash-item:hover,
.slash-item.active {
  background: #f1f5f9;
}
.dark .slash-item:hover,
.dark .slash-item.active {
  background: #0f172a;
}
.slash-id {
  font-family: ui-monospace, monospace;
  font-size: .78rem;
  opacity: .9;
}
.slash-type {
  font-size: .72rem;
  opacity: .7;
}





/* ===== SEÇÕES COM DESTAQUE VISUAL ===== */
.section-card {
  border: 2px solid var(--section-border, #e5e7eb); /* slate-200 */
  border-radius: 1rem;
  padding: 1.25rem;
  background: var(--section-bg, #fff);
  position: relative;
  margin-top: 2rem; /* separação vertical entre seções */
}

.section-card::before {
  content: "";
  position: absolute;
  left: -2px;
  top: 0;
  bottom: 0;
  width: 6px;                  /* barrinha de cor na lateral */
  border-radius: 1rem 0 0 1rem;
  background: var(--section-accent, #c7d2fe); /* indigo-200 */
}

.dark .section-card {
  --section-border: #374151;   /* slate-700 */
  --section-bg: #0b0f1a;
}

/* Variações de cor p/ diferenciar as seções */
.section-primary {
  --section-accent: #2ec8cf; /* indigo-300 */
}

.section-secondary {
  --section-accent: #cbd5e1; /* slate-300 */
}

/* Cabeçalho da seção */
.section-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: .75rem;
}
.section-title {
  font-size: 1.125rem; font-weight: 700;
}
.section-subtitle {
  font-size: .875rem; color: #6b7280;
}
.dark .section-subtitle { color: #9ca3af; }

.section-spacer {
  height: .75rem;
}

/* Mais respiro entre cards internos */
.section-grid > * { margin-top: .5rem; }






/* Variação para o bloco de Pausa/Contador */
.section-tertiary {
  --section-accent: #86efac; /* emerald-300 */
}


/* ===== [NOVO] Contador com cor de alerta ===== */
#countWrap.count-warn #count { color: #d97706; font-weight: 700; }
#countWrap.count-danger #count { color: #dc2626; font-weight: 800; }
.dark #countWrap.count-warn #count { color: #fbbf24; }
.dark #countWrap.count-danger #count { color: #f87171; }

/* ===== [NOVO] Modelos de prompt (cards) ===== */
.pm-card {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; padding: 10px 14px;
  border: 1.5px solid #e5e7eb; border-radius: 12px;
  background: #fff; transition: all .15s;
}
.dark .pm-card { background:#0b0f1a; border-color:#1f2937; }
.pm-card:hover { border-color:#a5b4fc; box-shadow:0 2px 8px rgba(99,102,241,.1); }
.pm-card.is-active {
  border-color:#6366f1;
  background: rgba(99,102,241,.06);
}
.dark .pm-card.is-active { background: rgba(99,102,241,.15); }
.pm-card .pm-info { min-width:0; flex:1; }
.pm-card .pm-name {
  font-weight:600; font-size:.9rem;
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
}
.pm-card .pm-meta { font-size:.72rem; color:#6b7280; margin-top:2px; }
.dark .pm-card .pm-meta { color:#9ca3af; }
.pm-badge-active {
  display:inline-flex; align-items:center; gap:4px;
  font-size:.68rem; font-weight:700;
  background:#6366f1; color:#fff;
  padding:2px 8px; border-radius:9999px;
  margin-left:6px;
}
.pm-card .pm-actions { display:flex; align-items:center; gap:6px; flex-shrink:0; flex-wrap:wrap; justify-content:flex-end; }
.pm-btn-use {
  font-size:.78rem; font-weight:600;
  background:#6366f1; color:#fff;
  border:none; border-radius:8px;
  padding:6px 14px; cursor:pointer; transition:background .15s;
}
.pm-btn-use:hover { background:#4f46e5; }
.pm-btn-use:disabled { opacity:.5; cursor:default; }
.pm-btn-edit {
  font-size:.78rem; font-weight:600;
  background:#fff; color:#4f46e5;
  border:1px solid #c7d2fe; border-radius:8px;
  padding:6px 14px; cursor:pointer; transition:all .15s;
}
.pm-btn-edit:hover { background:#eef2ff; border-color:#a5b4fc; }
.dark .pm-btn-edit { background:transparent; color:#a5b4fc; border-color:#374151; }
.dark .pm-btn-edit:hover { background:rgba(99,102,241,.12); }
.pm-btn-del {
  font-size:.78rem;
  background:transparent; color:#9ca3af;
  border:1px solid #e5e7eb; border-radius:8px;
  padding:6px 10px; cursor:pointer; transition:all .15s;
}
.pm-btn-del:hover { color:#dc2626; border-color:#fca5a5; background:#fef2f2; }
.dark .pm-btn-del { border-color:#374151; }
.dark .pm-btn-del:hover { background:rgba(220,38,38,.12); }

/* Botões de ícone (renomear / baixar) */
.pm-btn-icon {
  display:inline-flex; align-items:center; justify-content:center;
  width:30px; height:30px;
  background:transparent; color:#9ca3af;
  border:1px solid #e5e7eb; border-radius:8px;
  cursor:pointer; transition:all .15s;
  flex-shrink:0;
}
.pm-btn-icon svg { width:14px; height:14px; }
.pm-btn-icon:hover { color:#4f46e5; border-color:#a5b4fc; background:#eef2ff; }
.dark .pm-btn-icon { border-color:#374151; }
.dark .pm-btn-icon:hover { color:#a5b4fc; background:rgba(99,102,241,.12); }

/* Modal renomear */
.pm-rename-overlay {
  position:fixed; inset:0; background:rgba(2,6,23,.62);
  backdrop-filter:blur(6px);
  display:none; align-items:center; justify-content:center;
  z-index:1150; padding:18px;
}
.pm-rename-overlay[aria-hidden="false"] { display:flex; }
.pm-rename-card {
  width:min(560px,94vw); border-radius:18px; overflow:hidden;
  background:rgba(255,255,255,.96); border:1px solid rgba(255,255,255,.45);
  box-shadow:0 30px 80px rgba(0,0,0,.45);
}
.dark .pm-rename-card { background:rgba(11,15,26,.96); border-color:rgba(148,163,184,.18); }
.pm-rename-head {
  display:flex; align-items:center; justify-content:space-between;
  padding:14px 16px;
  background:linear-gradient(135deg,rgba(99,102,241,.16),rgba(79,70,229,.06));
  border-bottom:1px solid rgba(148,163,184,.22);
}
.pm-rename-title { font-weight:800; font-size:1rem; }
.pm-rename-body { padding:16px; }
.pm-rename-label { font-size:.78rem; font-weight:700; color:#475569; margin-bottom:6px; display:block; }
.dark .pm-rename-label { color:#cbd5e1; }
.pm-rename-input {
  width:100%; border-radius:12px; border:1px solid rgba(148,163,184,.4);
  background:#fff; padding:.7rem .8rem; font-size:.95rem; font-weight:600;
  outline:none; color:#0b0f1a; transition:border-color .15s, box-shadow .15s;
}
.dark .pm-rename-input { background:#0b0f1a; color:#e5e7eb; border-color:rgba(148,163,184,.25); }
.pm-rename-input:focus { border-color:#6366f1; box-shadow:0 0 0 4px rgba(99,102,241,.18); }
.pm-rename-preview {
  margin-top:12px; max-height:180px; overflow:auto;
  border-radius:12px; border:1px solid rgba(148,163,184,.3);
  background:#f8fafc; padding:.7rem .8rem;
  font-size:.78rem; line-height:1.45; color:#475569;
  white-space:pre-wrap; word-break:break-word;
}
.dark .pm-rename-preview { background:#0f172a; color:#94a3b8; border-color:rgba(148,163,184,.18); }
.pm-rename-err { margin-top:10px; font-size:.85rem; color:#e11d48; font-weight:700; display:none; }
.pm-rename-foot {
  padding:14px 16px; border-top:1px solid rgba(148,163,184,.22);
  display:flex; justify-content:flex-end; gap:10px;
}
.pm-rename-btn {
  border-radius:12px; padding:.65rem 1rem; font-weight:800; font-size:.9rem;
  border:1px solid transparent; cursor:pointer; transition:transform .15s, box-shadow .15s;
}
.pm-rename-btn:hover { transform:translateY(-1px); }
.pm-rename-ghost { background:transparent; border-color:rgba(148,163,184,.4); color:#1e293b; }
.dark .pm-rename-ghost { color:#e2e8f0; border-color:rgba(148,163,184,.22); }
.pm-rename-primary {
  background:linear-gradient(135deg,#6366f1 0%,#4f46e5 100%); color:#fff;
  box-shadow:0 10px 24px rgba(79,70,229,.3);
}
.pm-rename-primary:disabled { opacity:.6; cursor:not-allowed; transform:none; }




</style>

  <div class="space-y-3 relative">

    <!-- ====================================================== -->
    <!-- ===== TELA A: LISTA DE MODELOS (principal) ========== -->
    <!-- ====================================================== -->
    <section id="crudListView" class="section-card section-primary">
      <div class="section-header">
        <div>
          <div class="section-title">📚 Prompts do agente</div>
          <div class="section-subtitle">
            Crie e gerencie seus prompts. O que estiver <strong>Em uso</strong> é o que o agente responde. Clique em <strong>Ativar</strong> para colocar um prompt no ar.
          </div>
        </div>
        <div class="flex items-center gap-2">
          <button id="btnImportModel" type="button"
            class="rounded-lg border border-indigo-200 dark:border-indigo-800 bg-white dark:bg-gray-900 hover:bg-indigo-50 dark:hover:bg-gray-800 text-indigo-600 dark:text-indigo-400 px-3.5 py-2 text-xs font-medium transition inline-flex items-center gap-1.5"
            title="Importar um prompt a partir de um arquivo .json">
            <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M4 16v2a2 2 0 002 2h12a2 2 0 002-2v-2M12 4v12m0-12l-4 4m4-4l4 4"/></svg>
            Importar
          </button>
          <button id="btnNewModel" type="button"
            class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-3.5 py-2 text-xs font-medium transition inline-flex items-center gap-1.5">
            <svg class="w-3.5 h-3.5" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M12 5v14m-7-7h14"/></svg>
            Novo prompt
          </button>
        </div>
      </div>

      <div class="section-spacer"></div>

      <div id="modelsList" class="grid gap-2">
        <div class="text-xs text-gray-500">Carregando prompts...</div>
      </div>

      <input id="inpImportModel" type="file" accept="application/json,.json" class="hidden">
    </section>

    <!-- ====================================================== -->
    <!-- ===== TELA B: EDITOR (abre só ao Novo/Editar) ======= -->
    <!-- ====================================================== -->
    <div id="crudEditorView" class="hidden">

      <!-- Cabeçalho do editor com Voltar / Salvar -->
      <div class="flex items-center justify-between mb-4 p-3 rounded-lg border border-indigo-200 dark:border-indigo-800 bg-indigo-50/60 dark:bg-indigo-950/40">
        <div class="flex items-center gap-3 min-w-0">
          <button id="btnEditorBack" type="button"
            class="rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-900 px-3 py-1.5 text-sm inline-flex items-center gap-1.5 hover:bg-gray-50 dark:hover:bg-gray-800">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M15 18l-6-6 6-6"/></svg>
            Voltar
          </button>
          <div class="min-w-0">
            <div id="editorTitle" class="text-sm font-semibold truncate">Novo prompt</div>
            <div id="editorSubtitle" class="text-xs text-gray-500 dark:text-gray-400 truncate">Preencha o prompt e clique em Salvar</div>
          </div>
        </div>
        <div class="flex items-center gap-2 flex-shrink-0">
          <button id="btnEditorSave" type="button"
            class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-1.5 text-sm font-semibold inline-flex items-center gap-1.5">
            <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M5 13l4 4L19 7"/></svg>
            Salvar
          </button>
        </div>
      </div>

      <label class="block text-sm font-medium mb-2">Conteúdo do prompt</label>

      <div class="mb-3">
        <button id="btnClearMemory"
          class="inline-flex items-center gap-2 rounded-lg
                 bg-rose-600 hover:bg-rose-700
                 text-white px-4 py-2 text-sm font-semibold
                 shadow-md hover:shadow-lg transition-all">
          🧹 Limpar memória do agente para testes
        </button>
      </div>

      <!-- Editor visível (mostra símbolo) -->
      <div id="promptEditor"
           class="prompt-editor"
           contenteditable="true"
           spellcheck="false"
           data-placeholder="Escreva aqui as instruções do seu agente (tom de voz, escopo, exemplos, restrições, etc)."></div>

      <!-- Armazena o prompt serializado real (com as frases) -->
      <textarea id="prompt" class="hidden" rows="1"><?= htmlspecialchars($defaultPrompt, ENT_QUOTES, 'UTF-8') ?></textarea>

      <!-- Menu flutuante do "/" -->
      <div id="slashMenu" class="slash-menu hidden"></div>

      <!-- Barra de status -->
      <div class="flex items-center justify-between my-4 p-3 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-800">
        <div id="countWrap" class="text-sm text-gray-600 dark:text-gray-400">
          <span id="count">0</span>/8000 caracteres
          <span id="autosaveStatus" class="ml-3 text-xs font-medium inline-flex items-center gap-1"></span>
        </div>
        <div class="flex gap-2">
          <button id="btnReset" class="rounded-lg border border-gray-300 dark:border-gray-700 px-3 py-1.5 text-sm">Limpar editor</button>
        </div>
      </div>

      <!-- ===== Pausa após interação humana ===== -->
      <section id="sec-pausa" class="section-card section-tertiary">
        <div class="section-header">
          <div>
            <div class="section-title">Pausa após interação humana</div>
            <div class="section-subtitle">Controle quando o agente retoma automaticamente após sua intervenção.</div>
          </div>
        </div>

        <div class="section-spacer"></div>

        <div>
          <label for="tempoSet" class="block text-sm mb-1">
            Pausar o Agente de IA após interação humana por
          </label>
          <div class="flex items-center gap-2">
            <input id="tempoSet" type="number" min="0" step="1" inputmode="numeric"
              class="w-28 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-950 px-3 py-2 outline-none focus:ring-2 focus:ring-indigo-500"
              placeholder="12">
            <span class="text-sm text-gray-600 dark:text-gray-400">minutos</span>
          </div>

          <div class="mt-3 flex items-start gap-2">
            <input id="definitivo" type="checkbox"
              class="mt-0.5 h-4 w-4 rounded border-gray-300 dark:border-gray-700 text-indigo-600 focus:ring-indigo-500">
            <label for="definitivo" class="text-sm">
              Pausa definitiva
              <span class="text-gray-500 dark:text-gray-400">
                (não reativa automaticamente. Para limpar memórias fixas, basta gerar uma nova conexão na aba <strong>Conexões</strong>.)
              </span>
            </label>
          </div>

          <p class="mt-2 text-xs text-gray-500 dark:text-gray-400">
            💡 Dica: defina <strong>0</strong> para não pausar. Se marcar <strong>Pausa definitiva</strong>, o agente não voltará a responder automaticamente após sua interação.
          </p>
        </div>
      </section>

    </div><!-- /crudEditorView -->

  </div>
</div>
<!-- FIM Card: Config do agente -->

<!-- ===== Biblioteca / Upload ===== -->
<div class="rounded-xl border border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-900 p-6 mt-6">
  
  
  
  
  
  <!-- ===== Itens padrões ===== -->
<!-- ===== SEÇÕES: Itens padrões + Uploads ===== -->
<div class="space-y-10">

  <!-- ===== SEÇÃO 1: ITENS PADRÕES ===== -->
  <section id="sec-itens-padroes" class="section-card section-primary">
    <div class="section-header">
      <div>
        <div class="section-title">Itens padrões</div>
        <div class="section-subtitle">Use estes itens como tokens no prompt. (Agenda, Número falar com humano, Grupo falar com humano)</div>
      </div>
    </div>

    <div class="section-spacer"></div>

    <div class="space-y-4 section-grid">
      <!-- Agenda pública -->
      <div class="rounded-lg border border-gray-200 dark:border-gray-800 p-4">
        <div class="flex items-center justify-between mb-2">
          <div class="flex items-center gap-2">
            <span class="text-lg">🗓️</span>
            <div>
              <div class="text-sm font-semibold">Agenda</div>
              <div class="text-xs text-gray-500 dark:text-gray-400">
                Defina o link público da sua agenda e insira no prompt como um token visual.
              </div>
            </div>
          </div>
          <button id="btnInsertAgendaChip" class="rounded border px-3 py-1.5 text-xs">
            inserir no prompt
          </button>
        </div>

        <label class="block text-sm mb-1">Link da agenda (https://...)</label>
        <div class="flex gap-2">
          <input id="agendaLink" type="url"
            class="flex-1 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-950 px-3 py-2 text-sm"
            placeholder="https://cal.com/seu-usuario | https://calendar.app... | etc">
          <button id="btnSaveAgenda" class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 text-sm">
            Salvar agenda
          </button>
          <span id="agendaMsg" class="text-xs text-emerald-600 hidden self-center">URL salva com sucesso.</span>
        </div>


      </div>

      <!-- Número para falar com humano -->
      <div class="rounded-lg border border-gray-200 dark:border-gray-800 p-4">
        <div class="flex items-center justify-between mb-2">
          <div class="flex items-center gap-2">
            <span class="text-lg">👤</span>
            <div>
              <div class="text-sm font-semibold">Número falar com humano</div>
              <div class="text-xs text-gray-500 dark:text-gray-400">
                Insira no formato <b>55DDD99999999</b>. Use como token no prompt.
              </div>
            </div>
          </div>
          <button id="btnInsertNumeroChip" class="rounded border px-3 py-1.5 text-xs">
            inserir no prompt
          </button>
        </div>

        <label class="block text-sm mb-1">Número (ex.: 5511999999999)</label>
        <div class="flex gap-2">
          <input id="numeroHumano" type="text"
            class="flex-1 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-950 px-3 py-2 text-sm"
            placeholder="55DDD99999999">
          <button id="btnSaveNumeroGrupo" class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 text-sm">
            Salvar
          </button>
          <span id="numeroMsg" class="text-xs text-emerald-600 hidden self-center">Número salvo.</span>
        </div>


      </div>

      <!-- Grupo para falar com humano -->
      <div class="rounded-lg border border-gray-200 dark:border-gray-800 p-4">
        <div class="flex items-center justify-between mb-2">
          <div class="flex items-center gap-2">
            <span class="text-lg">👥</span>
            <div>
              <div class="text-sm font-semibold">Grupo falar com humano</div>
              <div class="text-xs text-gray-500 dark:text-gray-400">
                Insira o ID do grupo (ex.: <code>1234567890-123456@g.us</code>). Use como token no prompt.
              </div>
            </div>
          </div>
          <button id="btnInsertGrupoChip" class="rounded border px-3 py-1.5 text-xs">
            inserir no prompt
          </button>
<button id="btnGrupoTutorial" type="button"
  class="rounded bg-violet-600 hover:bg-violet-700 text-white px-3 py-1.5 text-xs">
  Ver tutorial
</button>


        </div>

        <label class="block text-sm mb-1">ID do grupo</label>
        <div class="flex gap-2">
          <input id="grupoHumano" type="text"
            class="flex-1 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-950 px-3 py-2 text-sm"
            placeholder="1234567890-123456@g.us">
          <button id="btnSaveGrupoNumero" class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 text-sm">
            Salvar
          </button>
          <span id="grupoMsg" class="text-xs text-emerald-600 hidden self-center">Grupo salvo.</span>
        </div>


      </div>
    </div>
  </section>

  <!-- ===== SEÇÃO 2: UPLOADS DE MÍDIA ===== -->
  <section id="sec-uploads" class="section-card section-secondary">
    <div class="section-header">
      <div>
        <div class="section-title">Uploads de mídia do agente</div>
        <div class="section-subtitle">Envie arquivos e gere tokens para usar no prompt.</div>
      </div>
      <span id="libCountBadge" class="text-xs px-2 py-1 rounded bg-gray-100 dark:bg-gray-800">0 itens</span>
    </div>

    <div class="section-spacer"></div>

    <div class="grid md:grid-cols-2 gap-4">
      <!-- Novo upload -->
      <div class="rounded-lg border border-gray-200 dark:border-gray-800 p-4">
        <h3 class="text-sm font-semibold mb-3">Novo upload</h3>
        <label class="block text-sm mb-1">Arquivo</label>
        <input id="inpFile" type="file" class="w-full text-sm mb-3">
        <label class="block text-sm mb-1">Nome/ID da mídia</label>
        <input id="inpName" type="text"
          class="w-full rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-950 px-3 py-2 text-sm"
          placeholder="ex.: video_demo1">
        <p class="text-xs text-gray-500 dark:text-gray-400 mt-1">
          Regras: minúsculas, sem acentos, sem espaços. Permitido <code>a-z 0-9 _ -</code>.
        </p>
        <div class="mt-4 flex items-center gap-2">
          <button id="btnUploadSave" class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 text-sm">
            Enviar e salvar
          </button>
          <span id="upMsg" class="text-xs text-gray-500"></span>
        </div>
      </div>

      <!-- Minha biblioteca -->
      <div class="rounded-lg border border-gray-200 dark:border-gray-800 p-4">
        <div class="flex items-center justify-between">
          <h3 class="text-sm font-semibold">Minha biblioteca</h3>
          <button id="btnReloadLib" class="rounded border px-3 py-1.5 text-xs">Atualizar</button>
        </div>
        <div id="libList" class="mt-3 space-y-2 text-sm"></div>
      </div>
    </div>
  </section>

</div>


<script>
const API = 'api/agent_atendimento.php';
const API_UPLOAD = 'api/upload.php';
const CSRF = '<?= $csrf ?>';
const DEFAULT_PROMPT = <?= json_encode($defaultPrompt, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) ?>;

/* ===== Elements ===== */
const agendaMsg = document.getElementById('agendaMsg');
const numeroInput = document.getElementById('numeroHumano');
const grupoInput  = document.getElementById('grupoHumano');
const btnSaveNumeroGrupo = document.getElementById('btnSaveNumeroGrupo') || document.getElementById('btnSaveGrupoNumero');
const btnInsertNumeroChip = document.getElementById('btnInsertNumeroChip');
const btnInsertGrupoChip  = document.getElementById('btnInsertGrupoChip');
const chipNumeroTop = document.getElementById('chipNumeroTop');
const chipGrupoTop  = document.getElementById('chipGrupoTop');
const numeroMsg = document.getElementById('numeroMsg');
const grupoMsg  = document.getElementById('grupoMsg');


const editor = document.getElementById('promptEditor');
const ta = document.getElementById('prompt');
const count = document.getElementById('count');
const countWrap = document.getElementById('countWrap');
const autosaveStatus = document.getElementById('autosaveStatus');
const btnReset = document.getElementById('btnReset');
const saveBadge = document.getElementById('saveBadge');
const inpTempo = document.getElementById('tempoSet');
const chkDefinitivo = document.getElementById('definitivo');
const mediaTags = document.getElementById('mediaTags');
const refreshMediaTags = document.getElementById('refreshMediaTags');
const slashMenu = document.getElementById('slashMenu');
const inpFile = document.getElementById('inpFile');
const inpName = document.getElementById('inpName');
const btnUploadSave = document.getElementById('btnUploadSave');
const upMsg = document.getElementById('upMsg');
const libList = document.getElementById('libList');
const libCountBadge = document.getElementById('libCountBadge');
const btnReloadLib = document.getElementById('btnReloadLib');
const agendaLinkInput = document.getElementById('agendaLink');
const btnSaveAgenda = document.getElementById('btnSaveAgenda');
const btnInsertAgendaChip = document.getElementById('btnInsertAgendaChip');
const chipAgendaTop = document.getElementById('chipAgendaTop');

/* ===== CRUD de prompts ===== */
const modelsList     = document.getElementById('modelsList');
const crudListView   = document.getElementById('crudListView');
const crudEditorView = document.getElementById('crudEditorView');
const btnNewModel    = document.getElementById('btnNewModel');
const btnEditorBack  = document.getElementById('btnEditorBack');
const btnEditorSave  = document.getElementById('btnEditorSave');
const editorTitle    = document.getElementById('editorTitle');
const editorSubtitle = document.getElementById('editorSubtitle');

/* Estado do editor CRUD:
   - editingModelId: id do modelo aberto no editor (null = "Novo prompt")
   - editorDirty: houve alteração desde que abriu/salvou (controla aviso de sair)
   - suppressDirty: trava o "dirty" durante cargas programáticas
   Não há autosave: salvar é explícito pelo botão Salvar.
*/
let editingModelId = null;
let editorDirty = false;
let suppressDirty = false;

function setAutosaveStatus(state, extra) {
  if (!autosaveStatus) return;
  if (state === 'pending') {
    autosaveStatus.textContent = '● Alterações não salvas';
    autosaveStatus.className = 'ml-3 text-xs font-medium inline-flex items-center gap-1 text-amber-600 dark:text-amber-400';
  } else if (state === 'saved') {
    autosaveStatus.textContent = '✓ Salvo';
    autosaveStatus.className = 'ml-3 text-xs font-medium inline-flex items-center gap-1 text-emerald-600 dark:text-emerald-400';
  } else if (state === 'error') {
    autosaveStatus.textContent = '⚠ ' + (extra || 'Falha ao salvar');
    autosaveStatus.className = 'ml-3 text-xs font-medium inline-flex items-center gap-1 text-rose-600 dark:text-rose-400';
  } else {
    autosaveStatus.textContent = '';
    autosaveStatus.className = 'ml-3 text-xs font-medium inline-flex items-center gap-1';
  }
}

// markDirty: chamado pelos vários pontos do editor (digitar, soltar
// chip, etc). No CRUD só marca que há alteração não salva.
function markDirty() {
  if (suppressDirty) return;
  if (!editorDirty) {
    editorDirty = true;
    setAutosaveStatus('pending');
  }
}

// clearDirty: estado "sem alterações pendentes" (após salvar/abrir).
function clearDirty() {
  editorDirty = false;
  setAutosaveStatus('clear');
}

// Compat: alguns pontos antigos chamam flushAutosave(); no CRUD
// não faz nada (não há autosave).
function flushAutosave() { /* CRUD: salvar é explícito */ }

// Aviso ao sair com edição não salva (só quando o editor está aberto).
window.addEventListener('beforeunload', (e) => {
  if (!crudEditorView.classList.contains('hidden') && editorDirty) {
    e.preventDefault();
    e.returnValue = '';
  }
});




/* ===== Helpers ===== */
function showSaved() {
  saveBadge.classList.remove('hidden');
  setTimeout(() => saveBadge.classList.add('hidden'), 1800);
}

function lockTempoByDefinitivo() {
  if (chkDefinitivo.checked) {
    inpTempo.disabled = true;
    inpTempo.classList.add('opacity-60', 'cursor-not-allowed');
  } else {
    inpTempo.disabled = false;
    inpTempo.classList.remove('opacity-60', 'cursor-not-allowed');
  }
}

function isEmptyValue(v) {
  return !(typeof v === 'string' && v.trim().length > 0);
}

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

/* ======= Frase real e regex (SERIALIZAÇÃO) ======= */
function realPhraseFromId(id) {
  const found = (CURRENT_MEDIA || []).find(m => m.id === id);
  const url = found ? found.url : '';
  return `envie o link no seu output: ${url}`;
}

const REAL_PHRASE_RE = /envie o link no seu output:\s*(https?:\/\/\S+)/gi;
const LEGACY_MEDIA_RE = /\[MEDIA:([a-z0-9_-]+)(?:\s+"[^"]*")?\]/gi;

/* ======= Estado ======= */
let CURRENT_MEDIA = [];
let dropIndicator = null;
let draggedToken = null;


/* ======= AGENDA (padrão) ======= */
let AGENDA_LINK = '';


let NUMERO_HUMANO = '';
let GRUPO_HUMANO  = '';


function ensureGus(value) {
  const v = (value || '').trim();
  if (!v) return '';
  return /@g\.us$/i.test(v) ? v : `${v}@g.us`;
}


function realNumeroPhrase(num) {
  return `Avise no grupo do link: ${ensureGus(num)} (obrigatório soltar esse link com @g.us no seu output)`;
}
function realGrupoPhrase(id) {
  return `Avise no grupo do link: ${ensureGus(id)} (obrigatório soltar esse link com @g.us no seu output)`;
}

// Regex unificado: captura tanto número (só dígitos) quanto grupo (já com @g.us)
// O grupo de captura pega o "identificador" antes do @g.us OU os dígitos puros
const REAL_NUMERO_RE = /Avise no grupo do link:\s*(\d{12,15})@g\.us\s*\(obrigatório soltar esse link com @g\.us no seu output\)/gi;
const REAL_GRUPO_RE  = /Avise no grupo do link:\s*([\w\-]+@g\.us)\s*\(obrigatório soltar esse link com @g\.us no seu output\)/gi;


function realAgendaPhrase(url) {
  return `acionar tool envia_agenda com url: ${url}`;
}
const REAL_AGENDA_RE = /acionar tool envia_agenda com url:\s*(\S+)/gi;




/* ======= Chips (acima) ======= */
function typeClass(t) {
  return t === 'image' ? 'tag-image' : 
         t === 'video' ? 'tag-video' : 
         t === 'audio' ? 'tag-audio' : 
         t === 'pdf' ? 'tag-pdf' : 'tag-file';
}

function chipHTML(it) {
  const icon = it.type === 'image' ? '🖼️' : 
               it.type === 'video' ? '🎬' : 
               it.type === 'audio' ? '🎧' : 
               it.type === 'pdf' ? '📄' : '📦';
  return `<button class="tag-chip btn ${typeClass(it.type)}" draggable="true" data-id="${it.id}" data-type="${it.type}" title="Inserir mídia ${it.id}">
     <span>${icon}</span><span class="tag-id">${it.id}</span>
  </button>`;
}

function renderMediaChips(list) {
  CURRENT_MEDIA = Array.isArray(list) ? list : [];
  mediaTags.innerHTML = CURRENT_MEDIA.length ? 
    CURRENT_MEDIA.map(chipHTML).join('') : 
    '<div class="text-xs text-gray-500">Sem mídias. Envie na seção abaixo.</div>';
  
  mediaTags.querySelectorAll('.tag-chip').forEach(btn => {
    btn.addEventListener('click', () => insertTokenAtCaret(btn.dataset.id, btn.dataset.type));
    btn.addEventListener('dragstart', ev => {
      ev.dataTransfer.setData('text/x-media-id', btn.dataset.id);
      ev.dataTransfer.setData('text/x-media-type', btn.dataset.type || 'file');
      ev.dataTransfer.effectAllowed = 'copy';
    });
  });
}



/* ============================================================
   CRUD DE PROMPTS
   - Tela A (lista): cards com Ativar/Editar/Renomear/Baixar/Excluir
   - Tela B (editor): abre só ao Novo/Editar; Salvar explícito
   ============================================================ */
let MODELS_CACHE = [];

function tempoLabel(tempo, definitivo) {
  if (definitivo) return 'Pausa definitiva';
  const t = Number(tempo);
  if (!t || t <= 0) return 'Sem pausa';
  return `Pausa ${t} min`;
}

function escapeHtml(s) {
  return (s || '').replace(/[&<>"']/g, m => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":"&#39;"}[m]));
}

/* ---------- Alternância Lista <-> Editor ---------- */
function showListView() {
  crudEditorView.classList.add('hidden');
  crudListView.classList.remove('hidden');
  editingModelId = null;
  clearDirty();
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

function showEditorView() {
  crudListView.classList.add('hidden');
  crudEditorView.classList.remove('hidden');
  window.scrollTo({ top: 0, behavior: 'smooth' });
}

/* ---------- Lista (Tela A) ---------- */
function renderModels(list, meta) {
  MODELS_CACHE = Array.isArray(list) ? list : [];
  meta = meta || {};

  if (!MODELS_CACHE.length) {
    // Empty-state ESPECIAL: usuário tem prompt antigo (sistema pré-CRUD)
    // que ainda não foi migrado. Mostra botão "Restaurar meu prompt anterior".
    if (meta.needs_migration) {
      const preview = (meta.legacy_preview || '').trim();
      const previewHtml = preview
        ? `<div class="mt-3 mb-4 max-w-md mx-auto text-left text-xs text-gray-600 dark:text-gray-300 bg-gray-50 dark:bg-gray-800 border border-gray-200 dark:border-gray-700 rounded-lg p-3">
             <div class="font-semibold mb-1">Prévia do prompt encontrado:</div>
             <div class="whitespace-pre-wrap break-words opacity-90">${escapeHtml(preview)}${preview.length >= 200 ? '…' : ''}</div>
           </div>`
        : '';

      // se a tentativa automática deixou erro registrado, mostra discreto
      const errHtml = meta.migration_error
        ? `<div class="mt-3 text-[11px] text-amber-700 dark:text-amber-400 max-w-md mx-auto">
             Detalhe técnico: ${escapeHtml(meta.migration_error)}
           </div>`
        : '';

      modelsList.innerHTML = `
        <div class="text-center py-8 px-4">
          <div class="text-4xl mb-3">🔄</div>
          <div class="text-sm font-semibold mb-1">Encontramos um prompt seu do sistema anterior</div>
          <div class="text-xs text-gray-500 dark:text-gray-400 mb-1">
            Clique abaixo para restaurá-lo como seu primeiro prompt já ativo.
          </div>
          ${previewHtml}
          <div class="flex flex-wrap items-center justify-center gap-2 mt-3">
            <button id="btnRestoreLegacy"
              class="rounded-lg bg-emerald-600 hover:bg-emerald-700 text-white px-4 py-2 text-sm font-semibold inline-flex items-center gap-1.5">
              <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M3 12a9 9 0 109-9"/><path d="M3 4v5h5"/></svg>
              Restaurar meu prompt anterior
            </button>
            <button id="btnEmptyNew"
              class="rounded-lg border border-gray-300 dark:border-gray-700 px-4 py-2 text-sm inline-flex items-center gap-1.5">
              Criar do zero
            </button>
          </div>
          ${errHtml}
        </div>`;

      document.getElementById('btnRestoreLegacy')?.addEventListener('click', restoreLegacyPrompt);
      document.getElementById('btnEmptyNew')?.addEventListener('click', () => openEditorNew());
      return;
    }

    // Empty-state padrão: conta nova de verdade
    modelsList.innerHTML = `
      <div class="text-center py-10 px-4">
        <div class="text-4xl mb-3">📝</div>
        <div class="text-sm font-semibold mb-1">Você ainda não tem nenhum prompt</div>
        <div class="text-xs text-gray-500 dark:text-gray-400 mb-4">Crie seu primeiro prompt para o agente começar a responder.</div>
        <button id="btnEmptyNew" class="rounded-lg bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 text-sm font-medium inline-flex items-center gap-1.5">
          <svg class="w-4 h-4" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M12 5v14m-7-7h14"/></svg>
          Criar primeiro prompt
        </button>
      </div>`;
    document.getElementById('btnEmptyNew')?.addEventListener('click', () => openEditorNew());
    return;
  }

  modelsList.innerHTML = MODELS_CACHE.map(m => {
    const active = m.is_active === true;
    return `
      <div class="pm-card ${active ? 'is-active' : ''}" data-id="${m.id}">
        <div class="pm-info">
          <div class="pm-name">
            ${escapeHtml(m.model_name)}
            ${active ? '<span class="pm-badge-active">✓ Em uso</span>' : ''}
          </div>
          <div class="pm-meta">${escapeHtml(tempoLabel(m.tempo_de_set, m.definitivo))}</div>
        </div>
        <div class="pm-actions">
          <button class="pm-btn-icon pm-btn-rename" data-id="${m.id}" title="Renomear" aria-label="Renomear">
            <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/><path d="M18.5 2.5a2.12 2.12 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/></svg>
          </button>
          <button class="pm-btn-icon pm-btn-export" data-id="${m.id}" title="Baixar (.json)" aria-label="Baixar">
            <svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><path d="M7 10l5 5 5-5"/><path d="M12 15V3"/></svg>
          </button>
          <button class="pm-btn-del" data-id="${m.id}" title="Excluir">Excluir</button>
          <button class="pm-btn-edit" data-id="${m.id}">Editar</button>
          <button class="pm-btn-use" data-id="${m.id}" ${active ? 'disabled' : ''}>
            ${active ? 'Em uso' : 'Ativar'}
          </button>
        </div>
      </div>`;
  }).join('');

  modelsList.querySelectorAll('.pm-btn-use').forEach(b =>
    b.addEventListener('click', () => activateModel(parseInt(b.dataset.id, 10))));
  modelsList.querySelectorAll('.pm-btn-edit').forEach(b =>
    b.addEventListener('click', () => openEditorEdit(parseInt(b.dataset.id, 10))));
  modelsList.querySelectorAll('.pm-btn-del').forEach(b =>
    b.addEventListener('click', () => deleteModel(parseInt(b.dataset.id, 10))));
  modelsList.querySelectorAll('.pm-btn-rename').forEach(b =>
    b.addEventListener('click', () => openRenameModal(parseInt(b.dataset.id, 10))));
  modelsList.querySelectorAll('.pm-btn-export').forEach(b =>
    b.addEventListener('click', () => exportModel(parseInt(b.dataset.id, 10))));
}

async function loadModels() {
  const d = await fetchJSON(`${API}?action=models_list&_=${Date.now()}`);
  if (d.ok) {
    renderModels(d.data || [], {
      needs_migration: !!d.needs_migration,
      legacy_preview:  d.legacy_preview  || '',
      migration_error: d.migration_error || '',
    });
  } else {
    modelsList.innerHTML = `<div class="text-xs text-rose-600">Falha ao carregar prompts.</div>`;
  }
}

/* ---------- Restaurar prompt legado (botão do empty-state) ---------- */
async function restoreLegacyPrompt() {
  const btn = document.getElementById('btnRestoreLegacy');
  if (!btn) return;
  const old = btn.innerHTML;
  btn.disabled = true;
  btn.textContent = 'Restaurando...';

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);

  let r = await fetchJSON(`${API}?action=models_migrate_now`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });
  // 25P02: backend já limpou, tenta de novo 1x
  if (!r.ok && /25P02|conex[ãa]o estava ocupada|transaction is aborted/i.test(r.error || '')) {
    await new Promise(res => setTimeout(res, 350));
    r = await fetchJSON(`${API}?action=models_migrate_now`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: fd
    });
  }

  btn.disabled = false;
  btn.innerHTML = old;

  if (!r.ok) {
    alert(r.error || 'Falha ao restaurar o prompt anterior.');
    return;
  }

  // sucesso: recarrega a lista (agora deve mostrar o modelo migrado)
  await loadModels();
}

/* ---------- Ativar (vira o que o agente roda) ---------- */
async function activateModel(id) {
  if (!id) return;
  const model = MODELS_CACHE.find(m => m.id === id);
  const nome = model ? model.model_name : 'este prompt';

  if (!confirm(`Ativar o prompt "${nome}"?\n\nO agente passará a responder com este prompt imediatamente.`)) {
    return;
  }

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);
  fd.append('id', String(id));

  let r = await fetchJSON(`${API}?action=models_use`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });
  if (!r.ok && /25P02|conex[ãa]o estava ocupada|transaction is aborted/i.test(r.error || '')) {
    await new Promise(res => setTimeout(res, 350));
    r = await fetchJSON(`${API}?action=models_use`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: fd
    });
  }
  if (!r.ok) { alert(r.error || 'Falha ao ativar o prompt'); return; }

  await loadModels();
}

/* ---------- Excluir ---------- */
async function deleteModel(id) {
  if (!id) return;
  const model = MODELS_CACHE.find(m => m.id === id);
  const nome = model ? model.model_name : 'este prompt';
  if (model && model.is_active) {
    alert(`"${nome}" está Em uso. Ative outro prompt antes de excluir este.`);
    return;
  }
  if (!confirm(`Excluir o prompt "${nome}"? Esta ação não pode ser desfeita.`)) return;

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);
  fd.append('id', String(id));

  const r = await fetchJSON(`${API}?action=models_delete`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });
  if (!r.ok) { alert(r.error || 'Falha ao excluir'); return; }
  await loadModels();
}

/* ---------- Abrir editor: NOVO ---------- */
function openEditorNew() {
  editingModelId = null;
  editorTitle.textContent = 'Novo prompt';
  editorSubtitle.textContent = 'Escreva o prompt e clique em Salvar';

  suppressDirty = true;
  // tenta usar a lista de mídias já carregada; senão segue vazio
  deserializeToEditor(DEFAULT_PROMPT);
  ta.value = DEFAULT_PROMPT;
  chkDefinitivo.checked = false;
  inpTempo.value = '12';
  lockTempoByDefinitivo();
  updateCount();
  suppressDirty = false;

  clearDirty();
  showEditorView();
}

/* ---------- Abrir editor: EDITAR existente ---------- */
async function openEditorEdit(id) {
  if (!id) return;
  const meta = MODELS_CACHE.find(m => m.id === id);

  // garante mídias atualizadas ANTES de desserializar (chips corretos)
  try {
    const ml = await fetchJSON(`${API}?action=media_list&_=${Date.now()}`);
    if (ml.ok) CURRENT_MEDIA = ml.data || [];
  } catch (e) {}

  // busca o conteúdo completo do modelo
  const d = await fetchJSON(`${API}?action=models_export&id=${id}&_=${Date.now()}`);
  if (!d.ok || !d.model) { alert(d.error || 'Falha ao abrir o prompt'); return; }

  editingModelId = id;
  editorTitle.textContent = 'Editar: ' + (meta ? meta.model_name : d.model.model_name);
  editorSubtitle.textContent = (meta && meta.is_active)
    ? 'Este prompt está Em uso — salvar aplica no agente na hora'
    : 'Edite e clique em Salvar';

  suppressDirty = true;
  const promptText = !isEmptyValue(d.model.prompt_text) ? d.model.prompt_text : DEFAULT_PROMPT;
  ta.value = promptText;
  deserializeToEditor(promptText);

  const definitivo = !!d.model.definitivo;
  chkDefinitivo.checked = definitivo;
  if (!definitivo) {
    const t = Number.isFinite(d.model.tempo_de_set) ? d.model.tempo_de_set : 12;
    inpTempo.value = String(t);
  } else if (!inpTempo.value) {
    inpTempo.value = '12';
  }
  lockTempoByDefinitivo();
  updateCount();
  suppressDirty = false;

  clearDirty();
  showEditorView();
}

/* ---------- Salvar (botão explícito do editor) ---------- */
btnEditorSave.addEventListener('click', async () => {
  ta.value = serializeEditor();
  const promptAtual = (ta.value || '').trim();
  if (!promptAtual) {
    alert('O prompt está vazio. Escreva o conteúdo antes de salvar.');
    return;
  }

  const old = btnEditorSave.innerHTML;
  btnEditorSave.disabled = true;
  btnEditorSave.textContent = 'Salvando...';

  let r;
  if (editingModelId == null) {
    // NOVO: pede nome e cria
    const nome = prompt('Nome do prompt (ex.: "Clínicas médicas"):', '');
    if (nome == null) {
      btnEditorSave.disabled = false;
      btnEditorSave.innerHTML = old;
      return;
    }
    const nomeTrim = nome.trim();
    if (!nomeTrim) {
      alert('Informe um nome para o prompt.');
      btnEditorSave.disabled = false;
      btnEditorSave.innerHTML = old;
      return;
    }
    const fd = new URLSearchParams();
    fd.append('csrf', CSRF);
    fd.append('model_name', nomeTrim);
    fd.append('prompt', ta.value || '');
    fd.append('definitivo', chkDefinitivo.checked ? '1' : '');
    if (!chkDefinitivo.checked) fd.append('tempo_de_set', inpTempo.value || '12');

    r = await fetchJSON(`${API}?action=models_save`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: fd
    });
  } else {
    // EDITAR existente
    const fd = new URLSearchParams();
    fd.append('csrf', CSRF);
    fd.append('id', String(editingModelId));
    fd.append('prompt', ta.value || '');
    fd.append('definitivo', chkDefinitivo.checked ? '1' : '');
    if (!chkDefinitivo.checked) fd.append('tempo_de_set', inpTempo.value || '12');

    r = await fetchJSON(`${API}?action=models_update`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: fd
    });
    if (!r.ok && /25P02|conex[ãa]o estava ocupada|transaction is aborted/i.test(r.error || '')) {
      await new Promise(res => setTimeout(res, 350));
      r = await fetchJSON(`${API}?action=models_update`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
        body: fd
      });
    }
  }

  btnEditorSave.disabled = false;
  btnEditorSave.innerHTML = old;

  if (!r || !r.ok) { alert((r && r.error) || 'Falha ao salvar'); return; }

  clearDirty();
  await loadModels();
  showListView();
});

/* ---------- Voltar (descarta edição) ---------- */
btnEditorBack.addEventListener('click', () => {
  if (editorDirty) {
    if (!confirm('Você tem alterações não salvas. Sair sem salvar?')) return;
  }
  showListView();
});

btnNewModel.addEventListener('click', () => openEditorNew());

/* ---------- Renomear (modal com preview) ---------- */
let RENAME_MODEL_ID = null;

async function openRenameModal(id) {
  if (!id) return;
  const model = MODELS_CACHE.find(m => m.id === id);
  RENAME_MODEL_ID = id;

  const overlay = document.getElementById('pmRenameModal');
  const inp     = document.getElementById('pmRenameInput');
  const prev    = document.getElementById('pmRenamePreview');
  const err     = document.getElementById('pmRenameErr');

  err.style.display = 'none';
  err.textContent = '';
  inp.value = model ? model.model_name : '';
  prev.textContent = 'Carregando prévia do prompt...';

  overlay.setAttribute('aria-hidden', 'false');
  document.body.style.overflow = 'hidden';
  setTimeout(() => { inp.focus(); inp.select(); }, 50);

  const d = await fetchJSON(`${API}?action=models_export&id=${id}&_=${Date.now()}`);
  if (d.ok && d.model) {
    const txt = (d.model.prompt_text || '').trim();
    prev.textContent = txt ? txt.slice(0, 1200) + (txt.length > 1200 ? '\n\n[...]' : '') : '(prompt vazio)';
  } else {
    prev.textContent = '(não foi possível carregar a prévia)';
  }
}

function closeRenameModal() {
  const overlay = document.getElementById('pmRenameModal');
  overlay.setAttribute('aria-hidden', 'true');
  document.body.style.overflow = '';
  RENAME_MODEL_ID = null;
}

async function confirmRename() {
  const inp = document.getElementById('pmRenameInput');
  const err = document.getElementById('pmRenameErr');
  const btn = document.getElementById('pmRenameConfirm');
  const nome = (inp.value || '').trim();

  err.style.display = 'none';
  if (!nome) {
    err.textContent = 'Informe um nome para o prompt.';
    err.style.display = '';
    return;
  }
  if (!RENAME_MODEL_ID) return;

  const old = btn.textContent;
  btn.disabled = true;
  btn.textContent = 'Salvando...';

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);
  fd.append('id', String(RENAME_MODEL_ID));
  fd.append('model_name', nome);

  const r = await fetchJSON(`${API}?action=models_rename`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });

  btn.disabled = false;
  btn.textContent = old;

  if (!r.ok) {
    err.textContent = r.error || 'Falha ao renomear';
    err.style.display = '';
    return;
  }

  closeRenameModal();
  await loadModels();
}

/* ---------- Baixar 1 prompt (.json) ---------- */
async function exportModel(id) {
  if (!id) return;
  const d = await fetchJSON(`${API}?action=models_export&id=${id}&_=${Date.now()}`);
  if (!d.ok || !d.model) { alert(d.error || 'Falha ao baixar o prompt'); return; }

  const payload = {
    _evolua_export: 'prompt_model_v1',
    exported_at: new Date().toISOString(),
    model: {
      model_name:   d.model.model_name,
      prompt_text:  d.model.prompt_text,
      tempo_de_set: d.model.tempo_de_set,
      definitivo:   d.model.definitivo
    }
  };

  const safeName = (d.model.model_name || 'prompt')
    .toLowerCase()
    .normalize('NFD').replace(/[\u0300-\u036f]/g, '')
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '') || 'prompt';

  const blob = new Blob([JSON.stringify(payload, null, 2)], { type: 'application/json' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `prompt-${safeName}.json`;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  setTimeout(() => URL.revokeObjectURL(url), 1500);
}

/* ---------- Importar 1 prompt (.json) ---------- */
const btnImportModel = document.getElementById('btnImportModel');
const inpImportModel = document.getElementById('inpImportModel');

btnImportModel?.addEventListener('click', () => inpImportModel.click());

inpImportModel?.addEventListener('change', async () => {
  const file = inpImportModel.files && inpImportModel.files[0];
  if (!file) return;

  let text = '';
  try {
    text = await file.text();
  } catch (e) {
    alert('Não foi possível ler o arquivo.');
    inpImportModel.value = '';
    return;
  }

  try {
    JSON.parse(text);
  } catch (e) {
    alert('Arquivo inválido: não é um JSON válido.');
    inpImportModel.value = '';
    return;
  }

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);
  fd.append('payload', text);

  const old = btnImportModel.innerHTML;
  btnImportModel.disabled = true;
  btnImportModel.textContent = 'Importando...';

  const r = await fetchJSON(`${API}?action=models_import`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });

  btnImportModel.disabled = false;
  btnImportModel.innerHTML = old;
  inpImportModel.value = '';

  if (!r.ok) { alert(r.error || 'Falha ao importar o prompt'); return; }

  await loadModels();

  const nome = r.model ? r.model.model_name : 'prompt';
  if (r.renamed) {
    alert(`Prompt importado como "${nome}" (já existia um com o nome original, então renomeei para não sobrescrever).`);
  } else {
    alert(`Prompt "${nome}" importado com sucesso!`);
  }
});


// 1) Trocar o rótulo VISUAL do token de número humano
function createNumeroToken() {
  if (!NUMERO_HUMANO) { alert('Defina o número antes de inserir o token.'); return null; }
  const span = document.createElement('span');
  span.className = 'media-token';
  span.setAttribute('data-id', 'numero_humano');
  span.setAttribute('data-type', 'humano_numero');
  span.setAttribute('data-real', realNumeroPhrase(NUMERO_HUMANO)); // <-- mantém a frase real
  span.setAttribute('contenteditable', 'false');
  span.setAttribute('draggable', 'true');
  span.title = `Número: ${NUMERO_HUMANO}`;

  const icon = document.createElement('span'); icon.className='icon';  icon.textContent = '👤';
  const label= document.createElement('span'); label.className='label';
  label.textContent = 'Falar com uma pessoa'; // <-- rótulo amigável
  span.append(icon, label);

  span.addEventListener('dragstart', (ev)=>{ draggedToken=span; span.classList.add('dragging'); ev.dataTransfer.effectAllowed='move'; ev.dataTransfer.setData('text/x-token-id','numero_humano'); ev.dataTransfer.setData('text/x-token-type','humano_numero'); });
  span.addEventListener('dragend', ()=>{ span.classList.remove('dragging'); draggedToken=null; hideDropIndicator(); });
  return span;
}


// 2) Trocar o rótulo VISUAL do token de grupo humano
function createGrupoToken() {
  if (!GRUPO_HUMANO) { alert('Defina o grupo antes de inserir o token.'); return null; }
  const span = document.createElement('span');
  span.className = 'media-token';
  span.setAttribute('data-id', 'grupo_humano');
  span.setAttribute('data-type', 'humano_grupo');
  span.setAttribute('data-real', realGrupoPhrase(GRUPO_HUMANO)); // <-- mantém a frase real
  span.setAttribute('contenteditable', 'false');
  span.setAttribute('draggable', 'true');
  span.title = `Grupo: ${GRUPO_HUMANO}`;

  const icon = document.createElement('span'); icon.className='icon';  icon.textContent = '👥';
  const label= document.createElement('span'); label.className='label';
  label.textContent = 'Avisar no Grupo'; // <-- rótulo amigável
  span.append(icon, label);

  span.addEventListener('dragstart', (ev)=>{ draggedToken=span; span.classList.add('dragging'); ev.dataTransfer.effectAllowed='move'; ev.dataTransfer.setData('text/x-token-id','grupo_humano'); ev.dataTransfer.setData('text/x-token-type','humano_grupo'); });
  span.addEventListener('dragend', ()=>{ span.classList.remove('dragging'); draggedToken=null; hideDropIndicator(); });
  return span;
}








function createAgendaToken() {
  if (!AGENDA_LINK) {
    alert('Defina o link da agenda antes de inserir o token.');
    return null;
  }
  const span = document.createElement('span');
  span.className = 'media-token';
  span.setAttribute('data-id', 'agenda');
  span.setAttribute('data-type', 'agenda');
  span.setAttribute('data-real', realAgendaPhrase(AGENDA_LINK));
  span.setAttribute('contenteditable', 'false');
  span.setAttribute('draggable', 'true');
  span.title = `Agenda: ${AGENDA_LINK}`;

  const icon = document.createElement('span');
  icon.className = 'icon';
  icon.textContent = '🗓️';

  const label = document.createElement('span');
  label.className = 'label';
  label.textContent = 'agenda';

  span.appendChild(icon);
  span.appendChild(label);

  span.addEventListener('dragstart', (ev) => {
    draggedToken = span;
    span.classList.add('dragging');
    ev.dataTransfer.effectAllowed = 'move';
    ev.dataTransfer.setData('text/x-token-id', 'agenda');
    ev.dataTransfer.setData('text/x-token-type', 'agenda');
  });
  span.addEventListener('dragend', () => {
    span.classList.remove('dragging');
    draggedToken = null;
    hideDropIndicator();
  });

  return span;
}


// === Eventos dos botões de agenda ===
btnSaveAgenda.addEventListener('click', async () => {
  const link = (agendaLinkInput.value || '').trim();
  if (link && !/^https?:\/\//i.test(link)) {
    alert('Informe uma URL válida iniciando com http:// ou https://');
    return;
  }

  // estado de carregamento (opcional)
  const oldLabel = btnSaveAgenda.textContent;
  btnSaveAgenda.disabled = true;
  btnSaveAgenda.textContent = 'Salvando...';
  agendaMsg?.classList.add('hidden'); // limpa msg anterior

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);
  fd.append('link', link);

  const r = await fetchJSON(`${API}?action=agenda_save`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });

  btnSaveAgenda.disabled = false;
  btnSaveAgenda.textContent = oldLabel;

  if (!r.ok) {
    // feedback de erro
    if (agendaMsg) {
      agendaMsg.textContent = r.error || 'Falha ao salvar agenda';
      agendaMsg.classList.remove('text-emerald-600');
      agendaMsg.classList.add('text-rose-600');
      agendaMsg.classList.remove('hidden');
      setTimeout(() => agendaMsg.classList.add('hidden'), 3000);
    } else {
      alert(r.error || 'Falha ao salvar agenda');
    }
    return;
  }

  AGENDA_LINK = (r.agenda_link || '').trim();

  // re-render tokens e contador
  suppressDirty = true;
  deserializeToEditor(serializeEditor());
  updateCount();
  suppressDirty = false;
  showSaved();

  // ✅ sucesso
  if (agendaMsg) {
    agendaMsg.textContent = 'URL salva com sucesso.';
    agendaMsg.classList.remove('text-rose-600');
    agendaMsg.classList.add('text-emerald-600');
    agendaMsg.classList.remove('hidden');
    setTimeout(() => agendaMsg.classList.add('hidden'), 2500);
  }
});



async function salvarNumeroGrupo(which, btn) {
  const numero = (numeroInput?.value || '').trim();
  const grupo  = (grupoInput ?.value || '').trim();

  if (which === 'numero' && numero && !/^55\d{10,13}$/.test(numero)) {
    alert('Informe o número no formato 55DDD99999999');
    return;
  }

  // feedback do botão clicado
  const oldLabel = btn?.textContent;
  if (btn) { btn.disabled = true; btn.textContent = 'Salvando...'; }

  const fd = new URLSearchParams();
  fd.append('csrf', CSRF);
  fd.append('numero', numero);
  fd.append('grupo',  grupo);

  const r = await fetchJSON(`${API}?action=falarhumano_save`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
    body: fd
  });

  if (btn) { btn.disabled = false; btn.textContent = oldLabel; }

  if (!r.ok) {
    const span = (which === 'numero') ? numeroMsg : grupoMsg;
    if (span) {
      span.textContent = r.error || 'Falha ao salvar';
      span.classList.remove('text-emerald-600');
      span.classList.add('text-rose-600');
      span.classList.remove('hidden');
      setTimeout(()=> span.classList.add('hidden'), 3000);
    } else {
      alert(r.error || 'Falha ao salvar');
    }
    return;
  }

  NUMERO_HUMANO = (r.numero_falar_humano || '').trim();
  GRUPO_HUMANO  = (r.grupo_falar_humano  || '').trim();

  // re-render pra atualizar tokens existentes
  suppressDirty = true;
  deserializeToEditor(serializeEditor());
  updateCount();
  suppressDirty = false;
  showSaved();

  // esconder a outra mensagem, se estiver visível
  if (which === 'numero' && grupoMsg) grupoMsg.classList.add('hidden');
  if (which === 'grupo'  && numeroMsg) numeroMsg.classList.add('hidden');

  // mostrar só a mensagem do campo clicado
  const okSpan = (which === 'numero') ? numeroMsg : grupoMsg;
  if (okSpan) {
    okSpan.textContent = (which === 'numero') ? 'Número salvo.' : 'Grupo salvo.';
    okSpan.classList.remove('text-rose-600');
    okSpan.classList.add('text-emerald-600');
    okSpan.classList.remove('hidden');
    setTimeout(()=> okSpan.classList.add('hidden'), 2500);
  }
}


document.getElementById('btnSaveNumeroGrupo')?.addEventListener('click', (e) => salvarNumeroGrupo('numero', e.currentTarget));
document.getElementById('btnSaveGrupoNumero')?.addEventListener('click', (e) => salvarNumeroGrupo('grupo',  e.currentTarget));








/* ======= Drop Indicator (linha visual) ======= */
function createDropIndicator() {
  if (!dropIndicator) {
    dropIndicator = document.createElement('div');
    dropIndicator.className = 'drop-indicator';
    dropIndicator.style.display = 'none';
    editor.parentElement.appendChild(dropIndicator);
  }
  return dropIndicator;
}

function showDropIndicator(x, y) {
  const indicator = createDropIndicator();
  const editorRect = editor.getBoundingClientRect();
  
  indicator.style.left = `${editorRect.left}px`;
  indicator.style.top = `${y}px`;
  indicator.style.width = `${editorRect.width}px`;
  indicator.style.display = 'block';
}

function hideDropIndicator() {
  if (dropIndicator) {
    dropIndicator.style.display = 'none';
  }
}

/* ======= Editor: utilitários de caret ======= */
function placeCaretAfter(node) {
  const range = document.createRange();
  const sel = window.getSelection();
  range.setStartAfter(node);
  range.collapse(true);
  sel.removeAllRanges();
  sel.addRange(range);
}

function insertNodeAtCaret(node) {
  const sel = window.getSelection();
  if (!sel || !sel.rangeCount) {
    editor.appendChild(node);
    placeCaretAfter(node);
    return;
  }
  const range = sel.getRangeAt(0);
  range.deleteContents();
  range.insertNode(node);
  placeCaretAfter(node);
}

function getCaretPosition(clientX, clientY) {
  let range, textNode, offset;
  
  if (document.caretPositionFromPoint) {
    const pos = document.caretPositionFromPoint(clientX, clientY);
    if (pos) {
      textNode = pos.offsetNode;
      offset = pos.offset;
    }
  } else if (document.caretRangeFromPoint) {
    range = document.caretRangeFromPoint(clientX, clientY);
    if (range) {
      textNode = range.startContainer;
      offset = range.startOffset;
    }
  }
  
  return { textNode, offset, range };
}

/* ======= Criação de token visual ======= */
function iconFromType(t) {
  if (t === 'agenda') return '🗓️';
  if (t === 'humano_numero') return '👤';
  if (t === 'humano_grupo')  return '👥';
  return t === 'image' ? '🖼️' :
         t === 'video' ? '🎬' :
         t === 'audio' ? '🎧' :
         t === 'pdf'   ? '📄' : '📦';
}



function createMediaToken(id, type = 'file', explicitUrl = '') {
  const span = document.createElement('span');
  span.className = 'media-token';

  // [FIX] Resolve a frase real de forma robusta:
  // 1) tenta achar a mídia pelo id em CURRENT_MEDIA
  // 2) se não achar mas veio uma URL explícita (caso de modelo
  //    importado/alternado antes da lista carregar), usa essa URL
  // Assim o data-real nunca fica sem URL e o save não perde o link.
  const foundById = (CURRENT_MEDIA || []).find(m => m.id === id);
  let realUrl = foundById ? foundById.url : '';
  if (!realUrl && explicitUrl) realUrl = explicitUrl;
  // se o próprio id já é uma URL (token órfão), usa ele
  if (!realUrl && /^https?:\/\//i.test(id)) realUrl = id;

  const realPhrase = realUrl
    ? `envie o link no seu output: ${realUrl}`
    : realPhraseFromId(id);

  // label amigável: se o id for uma URL crua, mostra algo curto
  const labelText = /^https?:\/\//i.test(id)
    ? (foundById ? foundById.id : 'mídia')
    : id;

  span.setAttribute('data-id', id);
  span.setAttribute('data-type', type || 'file');
  span.setAttribute('data-real', realPhrase);
  span.setAttribute('contenteditable', 'false');
  span.setAttribute('draggable', 'true');
  span.title = `Mídia: ${labelText}`;

  const icon = document.createElement('span');
  icon.className = 'icon';
  icon.textContent = iconFromType(type || 'file');

  const label = document.createElement('span');
  label.className = 'label';
  label.textContent = labelText;

  span.appendChild(icon);
  span.appendChild(label);

  // Eventos de drag para tokens dentro do editor
  span.addEventListener('dragstart', (ev) => {
    draggedToken = span;
    span.classList.add('dragging');
    ev.dataTransfer.effectAllowed = 'move';
    ev.dataTransfer.setData('text/x-token-id', id);
    ev.dataTransfer.setData('text/x-token-type', type);
  });

  span.addEventListener('dragend', () => {
    span.classList.remove('dragging');
    draggedToken = null;
    hideDropIndicator();
  });

  return span;
}

/* ======= Inserções no editor ======= */
function insertTokenAtCaret(id, type = 'file') {
  const token = createMediaToken(id, type);
  insertNodeAtCaret(token);
  insertNodeAtCaret(document.createTextNode(' '));
  updateCount();
  markDirty();
}


function insertAgendaAtCaret() {
  const token = createAgendaToken();
  if (!token) return;
  insertNodeAtCaret(token);
  insertNodeAtCaret(document.createTextNode(' '));
  updateCount();
  markDirty();
}



function insertNumeroAtCaret() {
  const t = createNumeroToken();
  if (!t) return;
  insertNodeAtCaret(t);
  insertNodeAtCaret(document.createTextNode(' '));
  updateCount();
  markDirty();
}
function insertGrupoAtCaret()  {
  const t = createGrupoToken();
  if (!t) return;
  insertNodeAtCaret(t);
  insertNodeAtCaret(document.createTextNode(' '));
  updateCount();
  markDirty();
}

// Botões “inserir no prompt”
btnInsertNumeroChip?.addEventListener('click', insertNumeroAtCaret);
btnInsertGrupoChip ?.addEventListener('click', insertGrupoAtCaret);

// Chips fixos no topo
chipNumeroTop?.addEventListener('click', insertNumeroAtCaret);
chipGrupoTop ?.addEventListener('click', insertGrupoAtCaret);

// Drag dos chips (para soltar no editor)
chipNumeroTop?.addEventListener('dragstart', (ev) => {
  ev.dataTransfer.setData('text/x-media-id', 'numero_humano');
  ev.dataTransfer.setData('text/x-media-type', 'humano_numero');
  ev.dataTransfer.effectAllowed = 'copy';
});
chipGrupoTop?.addEventListener('dragstart', (ev) => {
  ev.dataTransfer.setData('text/x-media-id', 'grupo_humano');
  ev.dataTransfer.setData('text/x-media-type', 'humano_grupo');
  ev.dataTransfer.effectAllowed = 'copy';
});










function insertTokenAtPosition(id, type, clientX, clientY) {
  const pos = getCaretPosition(clientX, clientY);

const makeToken = () => {
  if (type === 'agenda')        return createAgendaToken();
  if (type === 'humano_numero') return createNumeroToken();
  if (type === 'humano_grupo')  return createGrupoToken();
  return createMediaToken(id, type);
};


  if (pos.textNode) {
    const range = document.createRange();
    range.setStart(pos.textNode, pos.offset);
    range.collapse(true);

    const token = makeToken();
    if (!token) return; // agenda sem link configurado
    range.insertNode(token);
    range.insertNode(document.createTextNode(' '));
    placeCaretAfter(token);
  } else {
    if (type === 'agenda') {
      const token = createAgendaToken();
      if (!token) return;
      insertNodeAtCaret(token);
    } else {
      insertTokenAtCaret(id, type);
    }
    insertNodeAtCaret(document.createTextNode(' '));
  }

  updateCount();
  markDirty();
}

/* ======= Drag & drop no editor (MELHORADO) ======= */
editor.addEventListener('dragover', (ev) => {
  ev.preventDefault();
  ev.dataTransfer.dropEffect = draggedToken ? 'move' : 'copy';
  
  editor.classList.add('drag-over');
  
  // Mostra indicador visual
  const pos = getCaretPosition(ev.clientX, ev.clientY);
  if (pos.textNode) {
    showDropIndicator(ev.clientX, ev.clientY);
  }
});

editor.addEventListener('dragleave', (ev) => {
  if (ev.target === editor) {
    editor.classList.remove('drag-over');
    hideDropIndicator();
  }
});

editor.addEventListener('drop', (ev) => {
  ev.preventDefault();
  editor.classList.remove('drag-over');
  hideDropIndicator();
  
  // Verifica se é um token sendo movido dentro do editor
  if (draggedToken) {
    const pos = getCaretPosition(ev.clientX, ev.clientY);
    
    if (pos.textNode) {
      const range = document.createRange();
      range.setStart(pos.textNode, pos.offset);
      range.collapse(true);
      
      // Remove o token da posição antiga
      const parent = draggedToken.parentNode;
      if (parent) {
        parent.removeChild(draggedToken);
      }
      
      // Insere na nova posição
      range.insertNode(draggedToken);
      range.insertNode(document.createTextNode(' '));
      placeCaretAfter(draggedToken);
    } else {
      editor.appendChild(draggedToken);
    }
    
    draggedToken = null;
  } else {
    // Token novo sendo arrastado dos chips
    const id = ev.dataTransfer.getData('text/x-media-id');
    const type = ev.dataTransfer.getData('text/x-media-type') || 'file';
    
    if (id) {
      insertTokenAtPosition(id, type, ev.clientX, ev.clientY);
    }
  }
  
  updateCount();
  markDirty();
});

/* ======= Placeholder no contenteditable ======= */
function clearPlaceholderFlags() {
  const ph = editor.dataset.placeholder || '';
  if (editor.getAttribute('data-showing-placeholder') === '1') {
    editor.classList.remove('prompt-placeholder');
    editor.removeAttribute('data-showing-placeholder');
    if (ph && editor.textContent.trim() === ph.trim()) {
      editor.textContent = '';
    }
  }
}

function togglePlaceholder() {
  if (!editor.textContent.trim() && !editor.querySelector('.media-token')) {
    const ph = editor.dataset.placeholder || '';
    editor.classList.add('prompt-placeholder');
    editor.setAttribute('data-showing-placeholder', '1');
    editor.textContent = ph;
  } else {
    clearPlaceholderFlags();
  }
}

editor.addEventListener('focus', () => {
  const ph = editor.dataset.placeholder || '';
  if (editor.getAttribute('data-showing-placeholder') === '1' && editor.textContent.trim() === ph.trim()) {
    clearPlaceholderFlags();
    editor.textContent = '';
  }
});

editor.addEventListener('blur', () => {
  togglePlaceholder();
});

/* ======= Serialização (editor -> texto real) ======= */
function serializeEditor() {
  const BLOCK_TAGS = /^(DIV|P|LI|UL|OL|H1|H2|H3|H4|H5|H6|PRE)$/;

  function walk(node) {
    if (node.nodeType === Node.TEXT_NODE) {
      // mantém o texto como está
      return node.nodeValue || '';
    }

    if (node.nodeType !== Node.ELEMENT_NODE) return '';

    // Tokens: mantém a frase real (sem tocar nas quebras)
    if (node.classList && node.classList.contains('media-token')) {
      return node.getAttribute('data-real') || '';
    }

    // <br> conta como uma quebra de linha
    if (node.tagName === 'BR') return '\n';

    // percorre filhos
    let out = '';
    node.childNodes.forEach(n => { out += walk(n); });

    // elementos de bloco viram uma quebra ao final
    if (BLOCK_TAGS.test(node.tagName || '')) {
      // evita duplicar \n se já terminar com quebra
      if (!out.endsWith('\n')) out += '\n';
    }

    return out;
  }

  // normaliza CRLF -> LF e retorna sem colapsar/truncar
  return walk(editor).replace(/\r\n?/g, '\n');
}

/* ======= [NOVO] Contagem VISUAL do prompt =======
   Conta o que o usuário vê: cada token = 1 caractere "visual"
   (em vez da frase real longa com URL embutida). O valor que
   vai pra API continua sendo o serializado real (ta.value). */
function visualLength() {
  // Clona o editor e troca cada .media-token por um caractere único
  let total = 0;
  function walk(node) {
    if (node.nodeType === Node.TEXT_NODE) {
      total += Array.from(node.nodeValue || '').length;
      return;
    }
    if (node.nodeType !== Node.ELEMENT_NODE) return;
    if (node.classList && node.classList.contains('media-token')) {
      total += 1; // token conta como 1 caractere visual
      return;
    }
    if (node.tagName === 'BR') { total += 1; return; }
    node.childNodes.forEach(walk);
    const BLOCK_TAGS = /^(DIV|P|LI|UL|OL|H1|H2|H3|H4|H5|H6|PRE)$/;
    if (BLOCK_TAGS.test(node.tagName || '')) total += 1;
  }
  walk(editor);
  return total;
}



/* ======= Desserialização (texto real -> editor com tokens) ======= */
function guessType(id) {
  const found = CURRENT_MEDIA.find(m => m.id === id);
  if (found) return found.type || 'file';
  // [FIX] token órfão (id == URL): deduz pelo final da URL
  if (/^https?:\/\//i.test(id)) {
    const u = id.toLowerCase().split('?')[0];
    if (/\.(png|jpe?g|webp|gif|bmp|svg)$/.test(u)) return 'image';
    if (/\.(mp4|mov|webm|m4v|avi|mkv)$/.test(u)) return 'video';
    if (/\.(mp3|wav|ogg|m4a|aac|flac)$/.test(u)) return 'audio';
    if (/\.pdf$/.test(u)) return 'pdf';
  }
  return 'file';
}

function deserializeToEditor(text) {
  clearPlaceholderFlags();
  editor.innerHTML = '';

  let normalized = (text || '');

  const parts = [];
  let lastIndex = 0;

  // [FIX] As regex REAL_* têm flag /g e guardam lastIndex interno.
  // Ao alternar entre modelos, esse estado residual embaralhava a
  // captura e o chip não era reconstruído (sumia). Zeramos antes de usar.
  REAL_AGENDA_RE.lastIndex = 0;
  REAL_NUMERO_RE.lastIndex = 0;
  REAL_GRUPO_RE.lastIndex  = 0;
  REAL_PHRASE_RE.lastIndex = 0;

  const COMBINED_RE = new RegExp(
    `${REAL_AGENDA_RE.source}|${REAL_NUMERO_RE.source}|${REAL_GRUPO_RE.source}|${REAL_PHRASE_RE.source}`,
    'gi'
  );
  COMBINED_RE.lastIndex = 0;

  normalized.replace(COMBINED_RE, (match, agendaUrl, numeroHumano, grupoHumano, mediaUrl, offset) => {
    if (offset > lastIndex) {
      parts.push({ type: 'text', value: normalized.slice(lastIndex, offset) });
    }
    if (agendaUrl) {
      parts.push({ type: 'agenda', url: agendaUrl });
    } else if (numeroHumano) {
      parts.push({ type: 'numero' });
    } else if (grupoHumano) {
      parts.push({ type: 'grupo' });
    } else if (mediaUrl) {
      const found = (CURRENT_MEDIA || []).find(m => m.url === mediaUrl);
      // [FIX] Se a mídia não está na lista carregada (ex.: lista ainda
      // não recarregou ao alternar modelos), ainda assim reconstrói um
      // token usando a própria URL como id — antes virava texto cru.
      parts.push({ type: 'token', id: found ? found.id : mediaUrl, url: mediaUrl });
    }
    lastIndex = offset + match.length;
    return match;
  });


  if (lastIndex < normalized.length) {
    parts.push({ type: 'text', value: normalized.slice(lastIndex) });
  }

parts.forEach(p => {
  if (p.type === 'text') {
    editor.appendChild(document.createTextNode(p.value));
  } else if (p.type === 'agenda') {
    if (AGENDA_LINK) {
      const t = createAgendaToken();
      if (t) { editor.appendChild(t); editor.appendChild(document.createTextNode(' ')); }
    } else {
      editor.appendChild(document.createTextNode(realAgendaPhrase(p.url) + ' '));
    }
  } else if (p.type === 'numero') {
    const t = createNumeroToken();
    if (t) { editor.appendChild(t); editor.appendChild(document.createTextNode(' ')); }
  } else if (p.type === 'grupo') {
    const t = createGrupoToken();
    if (t) { editor.appendChild(t); editor.appendChild(document.createTextNode(' ')); }
  } else {
    const t = createMediaToken(p.id, guessType(p.id), p.url || '');
    editor.appendChild(t); editor.appendChild(document.createTextNode(' '));
  }
});


  if (!parts.length) {
    editor.appendChild(document.createTextNode(normalized));
  }

  if (!editor.textContent.trim() && !editor.querySelector('.media-token')) {
    togglePlaceholder();
  } else {
    clearPlaceholderFlags();
  }
}



/* ======= Slash (/) autocomplete no contenteditable ======= */
let slashState = null;

function showSlashMenu(items, x, y) {
  if (!items.length) {
    hideSlashMenu();
    return;
  }
  slashMenu.innerHTML = items.map((it, i) => `<div class="slash-item ${i === 0 ? 'active' : ''}" data-id="${it.id}" data-type="${it.type}">
    <div>${iconFromType(it.type)}</div>
    <div class="slash-id">${it.id}</div>
    <div class="slash-type">(${it.type})</div>
  </div>`).join('');
  slashMenu.style.left = x + 'px';
  slashMenu.style.top = y + 'px';
  slashMenu.classList.remove('hidden');
  slashState = { ...slashState, items, active: 0 };
  slashMenu.querySelectorAll('.slash-item').forEach((el, idx) => {
    el.addEventListener('mouseenter', () => setActive(idx));
    el.addEventListener('mousedown', (e) => {
      e.preventDefault();
      pickSlash(idx);
    });
  });
}

function hideSlashMenu() {
  slashMenu.classList.add('hidden');
  slashState = null;
}

function setActive(idx) {
  slashMenu.querySelectorAll('.slash-item').forEach((el, i) => el.classList.toggle('active', i === idx));
  if (slashState) slashState.active = idx;
}

function caretClientRect() {
  const sel = window.getSelection();
  if (!sel || !sel.rangeCount) return null;
  const range = sel.getRangeAt(0).cloneRange();
  range.collapse(true);
  const rects = range.getClientRects();
  if (rects.length) return rects[0];
  const span = document.createElement('span');
  range.insertNode(span);
  const rect = span.getBoundingClientRect();
  span.parentNode.removeChild(span);
  return rect;
}

function openSlashIfNeeded() {
  const sel = window.getSelection();
  if (!sel || !sel.anchorNode) return hideSlashMenu();
  const node = sel.anchorNode;
  const text = (node.nodeType === Node.TEXT_NODE ? node.nodeValue : node.textContent) || '';
  const off = sel.anchorOffset;
  const before = text.slice(0, off);
  const lastSlash = before.lastIndexOf('/');
  if (lastSlash < 0) return hideSlashMenu();
  if (lastSlash > 0 && /\S/.test(before[lastSlash - 1])) return hideSlashMenu();
  const q = before.slice(lastSlash + 1).trim().toLowerCase();
const items = [
  ...(AGENDA_LINK   ? [{ id: 'agenda',        type: 'agenda' }] : []),
  ...(NUMERO_HUMANO ? [{ id: 'numero_humano', type: 'humano_numero' }] : []),
  ...(GRUPO_HUMANO  ? [{ id: 'grupo_humano',  type: 'humano_grupo'  }] : []),
  ...((CURRENT_MEDIA || []).filter(it => it.id.toLowerCase().includes(q)))
];

  const rect = caretClientRect();
  if (!rect) return hideSlashMenu();
  slashState = { anchorNode: node, anchorOffset: lastSlash, q, items, active: 0 };
  showSlashMenu(items, rect.left + window.scrollX, rect.bottom + window.scrollY + 6);
}

function replaceFromSlashPick(id, type) {
  const sel = window.getSelection();
  if (!slashState || !sel || !sel.rangeCount) return;
  const anchor = slashState.anchorNode;
  const startOffset = slashState.anchorOffset;
  const endOffset = sel.anchorOffset;
  const range = document.createRange();
  range.setStart(anchor, startOffset);
  range.setEnd(anchor, endOffset);
  range.deleteContents();

  let node;
if (id === 'agenda') {
  node = createAgendaToken();
} else if (id === 'numero_humano') {
  node = createNumeroToken();
} else if (id === 'grupo_humano') {
  node = createGrupoToken();
} else {
  node = createMediaToken(id, type || 'file');
}

  range.insertNode(node);
  placeCaretAfter(node);
  insertNodeAtCaret(document.createTextNode(' '));
  hideSlashMenu();
  updateCount();
  markDirty();
}


function pickSlash(idx) {
  const it = slashState.items[idx];
  replaceFromSlashPick(it.id, it.type || 'file');
}

document.addEventListener('keydown', (e) => {
  if (!slashState) return;
  if (['ArrowDown', 'ArrowUp', 'Enter', 'Tab', 'Escape'].includes(e.key)) {
    e.preventDefault();
    e.stopPropagation();
  }
  if (e.key === 'ArrowDown') setActive(Math.min(slashState.active + 1, slashState.items.length - 1));
  if (e.key === 'ArrowUp') setActive(Math.max(slashState.active - 1, 0));
  if (e.key === 'Enter' || e.key === 'Tab') pickSlash(slashState.active);
  if (e.key === 'Escape') hideSlashMenu();
});

document.addEventListener('click', (e) => {
  if (!slashMenu.contains(e.target)) hideSlashMenu();
});

editor.addEventListener('keyup', openSlashIfNeeded);
editor.addEventListener('mouseup', openSlashIfNeeded);

/* ======= Contagem ======= */
function updateCount() {
  if (editor.getAttribute('data-showing-placeholder') === '1') {
    ta.value = '';
    count.textContent = '0';
    applyCountColor(0);
    return;
  }
  // ta.value = serializado REAL (vai pra API) -> não muda comportamento de save
  ta.value = serializeEditor();
  // contador exibido = comprimento VISUAL (token = 1 char) -> menos confuso
  const visual = visualLength();
  count.textContent = visual;
  applyCountColor(visual);
}

/* [NOVO] Cor de alerta no contador */
function applyCountColor(n) {
  countWrap.classList.remove('count-warn', 'count-danger');
  if (n >= 7500) {
    countWrap.classList.add('count-danger');
  } else if (n >= 6500) {
    countWrap.classList.add('count-warn');
  }
}

/* ======= Normalizador de ID ======= */
function normalizeMediaId(s) {
  s = (s || '').toLowerCase();
  const map = { 'á': 'a', 'à': 'a', 'ã': 'a', 'â': 'a', 'ä': 'a', 'é': 'e', 'è': 'e', 'ê': 'e', 'ë': 'e', 'í': 'i', 'ì': 'i', 'î': 'i', 'ï': 'i', 'ó': 'o', 'ò': 'o', 'õ': 'o', 'ô': 'o', 'ö': 'o', 'ú': 'u', 'ù': 'u', 'û': 'u', 'ü': 'u', 'ç': 'c', 'ñ': 'n' };
  s = s.replace(/./g, ch => map[ch] ?? ch).replace(/\s+/g, '_').replace(/[^a-z0-9_-]+/g, '_').replace(/_+/g, '_').replace(/^[_-]+|[_-]+$/g, '');
  return s || 'midia';
}

inpName.addEventListener('input', () => {
  const pos = inpName.selectionStart;
  const norm = normalizeMediaId(inpName.value);
  if (norm !== inpName.value) {
    inpName.value = norm;
    inpName.selectionStart = inpName.selectionEnd = Math.min(pos, norm.length);
  }
});

/* ======= Upload helpers ======= */
function fileTypeFromInput(file) {
  if (!file || !file.type) return '';
  if (file.type.startsWith('image/')) return 'image';
  if (file.type.startsWith('video/')) return 'video';
  if (file.type.startsWith('audio/')) return 'audio';
  if (file.type === 'application/pdf') return 'pdf';
  return 'file';
}

/* ======= Biblioteca (lista) ======= */
function renderLibrary(items) {
  const arr = Array.isArray(items) ? items : [];
  libCountBadge.textContent = `${arr.length} ${arr.length === 1 ? 'item' : 'itens'}`;
  if (!arr.length) {
    libList.innerHTML = '<div class="text-xs text-gray-500">Nenhuma mídia cadastrada.</div>';
    return;
  }
  libList.innerHTML = arr.map(it => {
    const icon = iconFromType(it.type);
    const when = (it.created_at || '').toString().replace('T', ' ').replace('Z', '');
    return `<div class="flex items-center gap-2 border rounded-lg px-3 py-2">
      <div class="text-lg">${icon}</div>
      <div class="flex-1 min-w-0">
        <div class="font-mono text-xs truncate"><b>Ferramenta:</b> ${it.id}</div>
        <div class="text-xs text-gray-500 truncate">${it.url || ''}</div>
        <div class="text-[10px] text-gray-400 mt-0.5">${it.type || 'file'} • ${when}</div>
      </div>
      <div class="flex items-center gap-2">
        <button class="btnInsert text-xs rounded border px-2 py-1" data-id="${it.id}" data-type="${it.type}">usar no prompt</button>
        <a class="text-xs rounded border px-2 py-1" href="${it.url || '#'}" target="_blank">abrir</a>
        <button class="btnDel text-xs rounded bg-rose-600 text-white px-2 py-1" data-id="${it.id}">excluir</button>
      </div>
    </div>`;
  }).join('');
  libList.querySelectorAll('.btnInsert').forEach(b => b.addEventListener('click', () => insertTokenAtCaret(b.dataset.id, b.dataset.type || 'file')));
  libList.querySelectorAll('.btnDel').forEach(b => {
    b.addEventListener('click', async () => {
      if (!confirm('Excluir a mídia "' + b.dataset.id + '"?')) return;
      const fd = new URLSearchParams();
      fd.append('csrf', CSRF);
      fd.append('id', b.dataset.id);
      const r = await fetchJSON(`${API}?action=media_delete`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: fd });
      if (!r.ok) {
        alert(r.error || 'Falha');
        return;
      }
      const j = await fetchJSON(`${API}?action=media_list&_=${Date.now()}`);
      if (j.ok) {
        renderMediaChips(j.data || []);
        renderLibrary(j.data || []);
      }
    });
  });
}

/* ======= Carregar prompt + biblioteca ======= */
// Carrega o contexto que o editor precisa (agenda, número, grupo,
// biblioteca de mídias). NÃO mexe no editor — no CRUD o editor só
// abre via openEditorNew/openEditorEdit.
async function loadAgentContext() {
  const d = await fetchJSON(`${API}?action=get&_=${Date.now()}`);
  if (d.ok) {
    AGENDA_LINK = (d.agenda_link || '').trim();
    agendaLinkInput.value = AGENDA_LINK;

    NUMERO_HUMANO = (d.numero_falar_humano || '').trim();
    GRUPO_HUMANO  = (d.grupo_falar_humano  || '').trim();

    if (numeroInput) numeroInput.value = NUMERO_HUMANO;
    if (grupoInput)  grupoInput.value  = GRUPO_HUMANO;

    CURRENT_MEDIA = d.media_biblioteca || [];
    renderMediaChips(d.media_biblioteca || []);
    renderLibrary(d.media_biblioteca || []);

    if (!inpTempo.value) inpTempo.value = '12';
  } else {
    if (!inpTempo.value) inpTempo.value = '12';
    renderMediaChips([]);
    renderLibrary([]);
  }
}

refreshMediaTags.addEventListener('click', async () => {
  const j = await fetchJSON(`${API}?action=media_list&_=${Date.now()}`);
  if (j.ok) {
    renderMediaChips(j.data || []);
  }
});

/* ======= Mudanças no editor marcam "não salvo" (sem autosave) ======= */
// blur do editor: nada a fazer (salvar é pelo botão Salvar)

btnReset.addEventListener('click', () => {
  if (!confirm('Limpar o conteúdo do editor e voltar ao texto padrão?')) return;
  deserializeToEditor(DEFAULT_PROMPT);
  updateCount();
  markDirty();
});

/* Confirmação ao marcar Pausa definitiva */
chkDefinitivo.addEventListener('change', () => {
  if (chkDefinitivo.checked) {
    const ok = confirm(
      'Ativar PAUSA DEFINITIVA?\n\n' +
      'O agente NÃO voltará a responder automaticamente após uma interação humana. ' +
      'Para reativar, será necessário gerar uma nova conexão na aba Conexões.\n\n' +
      'Deseja continuar?'
    );
    if (!ok) {
      chkDefinitivo.checked = false;
      lockTempoByDefinitivo();
      return;
    }
  }
  lockTempoByDefinitivo();
  markDirty();
});

/* ======= Reagir a mudanças no editor ======= */
['keyup', 'input', 'paste', 'cut'].forEach(evt => {
  editor.addEventListener(evt, () => {
    if (editor.getAttribute('data-showing-placeholder') === '1') return;
    updateCount();
    markDirty();
  });
});

/* tempo manual também marca não salvo */
inpTempo.addEventListener('input', () => markDirty());

/* ======= Upload ======= */
btnUploadSave.addEventListener('click', async () => {
  const file = inpFile.files && inpFile.files[0];
  const rawName = inpName.value || '';
  const id = normalizeMediaId(rawName);
  if (!file) {
    alert('Selecione um arquivo.');
    return;
  }
  if (!id) {
    alert('Informe o nome/ID da mídia.');
    return;
  }
  btnUploadSave.disabled = true;
  const old = btnUploadSave.textContent;
  btnUploadSave.textContent = 'Enviando...';
  upMsg.textContent = '';
  const fd = new FormData();
  fd.append('file', file);
  const kind = fileTypeFromInput(file);
  fd.append('kind', kind === 'pdf' ? 'pdf' : (kind === 'image' ? 'imagem' : (kind === 'audio' ? 'audio' : (kind === 'video' ? 'video' : 'arquivo'))));
  let publicUrl = '';
  try {
    const r = await fetch(API_UPLOAD, { method: 'POST', body: fd, credentials: 'same-origin' });
    const j = await r.json();
    if (!r.ok || !j.ok) throw new Error((j && (j.error || j.status)) || 'Falha no upload');
    publicUrl = j.public_url || j.signed_url || '';
    if (!publicUrl) throw new Error('URL não retornada.');
  } catch (e) {
    alert('Erro no upload: ' + (e?.message || 'Falha'));
    btnUploadSave.disabled = false;
    btnUploadSave.textContent = old;
    return;
  }
  const reg = new URLSearchParams();
  reg.append('csrf', CSRF);
  reg.append('name', id);
  reg.append('url', publicUrl);
  reg.append('type', kind);
  const addResp = await fetchJSON(`${API}?action=media_add`, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: reg });
  btnUploadSave.disabled = false;
  btnUploadSave.textContent = old;
  if (!addResp.ok) {
    alert(addResp.error || 'Falha ao salvar na biblioteca');
    return;
  }
upMsg.textContent = 'Arquivo enviado e salvo como ID "' + id + '".';
  inpFile.value = '';

  const j = await fetchJSON(`${API}?action=media_list&_=${Date.now()}`);
  if (j.ok) {
    renderMediaChips(j.data || []);
    renderLibrary(j.data || []);
    setTimeout(() => showChipSpotlight(id), 150);
  }
});

btnReloadLib.addEventListener('click', async () => {
  const j = await fetchJSON(`${API}?action=media_list&_=${Date.now()}`);
  if (j.ok) {
    renderMediaChips(j.data || []);
    renderLibrary(j.data || []);
  }
});

// === Eventos dos botões de agenda ===
btnInsertAgendaChip.addEventListener('click', insertAgendaAtCaret);
chipAgendaTop.addEventListener('click', insertAgendaAtCaret);
// arrastar o chip "agenda" da barra superior
chipAgendaTop.addEventListener('dragstart', (ev) => {
  ev.dataTransfer.setData('text/x-media-id', 'agenda');
  ev.dataTransfer.setData('text/x-media-type', 'agenda');
  ev.dataTransfer.effectAllowed = 'copy';
});



/* ======= Sticky Media Tags ======= */
const mediaStickyContainer = document.getElementById('mediaStickyContainer');
const mediaTagsWrapper = document.getElementById('mediaTagsWrapper');
let originalTop = 0;
let wrapperHeight = 0;

function updateStickyBehavior() {
  const rect = mediaStickyContainer.getBoundingClientRect();
  const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
  
  if (!originalTop) {
    originalTop = rect.top + scrollTop;
    wrapperHeight = mediaTagsWrapper.offsetHeight;
  }
  
  if (scrollTop > originalTop) {
    // Ativar sticky
    if (!mediaTagsWrapper.classList.contains('is-sticky')) {
      mediaTagsWrapper.classList.add('is-sticky');
      mediaStickyContainer.classList.add('has-placeholder');
      mediaStickyContainer.style.setProperty('--placeholder-height', wrapperHeight + 'px');
    }
  } else {
    // Desativar sticky
    if (mediaTagsWrapper.classList.contains('is-sticky')) {
      mediaTagsWrapper.classList.remove('is-sticky');
      mediaStickyContainer.classList.remove('has-placeholder');
    }
  }
}

window.addEventListener('scroll', updateStickyBehavior);
window.addEventListener('resize', () => {
  originalTop = 0;
  updateStickyBehavior();
});



/* ======= LIMPAR MEMÓRIA (TESTES) ======= */
document.addEventListener('DOMContentLoaded', () => {
  const btnClearMemory = document.getElementById('btnClearMemory');
  const clearMemoryModal = document.getElementById('clearMemoryModal');
  const btnClearMemoryCloseX = document.getElementById('btnClearMemoryCloseX');
  const btnClearMemoryCancel = document.getElementById('btnClearMemoryCancel');
  const btnClearMemoryConfirm = document.getElementById('btnClearMemoryConfirm');
  const clearMemoryNumero = document.getElementById('clearMemoryNumero');
  const clearMemoryErr = document.getElementById('clearMemoryErr');

  const clearStepForm = document.getElementById('clearStepForm');
  const clearStepLoading = document.getElementById('clearStepLoading');
  const clearStepDone = document.getElementById('clearStepDone');

  if (!btnClearMemory || !clearMemoryModal) return;

  function showClearError(msg) {
    clearMemoryErr.textContent = msg || 'Erro';
    clearMemoryErr.style.display = '';
  }

  function validNumeroBR(v) {
    return /^55\d{10,13}$/.test((v || '').trim());
  }


  // ====== "Como usar" (tutorial do modal Limpar Memória) ======
  const CLEAR_MEM_TUTORIAL_URL = 'https://youtu.be/ONTfo7Oq5RA'; // <-- troque

  const btnComoUsar   = document.getElementById('btnClearMemoryComoUsar');
  const modalComoUsar = document.getElementById('clearMemoryComoUsarModal');
  const btnFecharTut  = document.getElementById('btnClearMemoryComoUsarFechar');
  const btnCloseXTut  = document.getElementById('btnClearMemoryComoUsarCloseX');
  const iframeTut     = document.getElementById('clearMemoryComoUsarIframe');

  function toEmbedUrl(url) {
    try {
      const u = new URL(url);
      if (u.hostname.includes('youtu.be')) return `https://www.youtube.com/embed/${u.pathname.slice(1)}?rel=0`;
      if (u.hostname.includes('youtube.com')) {
        const id = u.searchParams.get('v');
        if (id) return `https://www.youtube.com/embed/${id}?rel=0`;
      }
      return url;
    } catch { return url; }
  }

  function openComoUsar() {
    if (!modalComoUsar) return;
    iframeTut.src = toEmbedUrl(CLEAR_MEM_TUTORIAL_URL);
    modalComoUsar.setAttribute('aria-hidden', 'false');
    // mantém o body travado (já está travado pelo modal principal)
  }

  function closeComoUsar() {
    if (!modalComoUsar) return;
    modalComoUsar.setAttribute('aria-hidden', 'true');
    iframeTut.src = '';
  }

  btnComoUsar?.addEventListener('click', openComoUsar);
  btnFecharTut?.addEventListener('click', closeComoUsar);
  btnCloseXTut?.addEventListener('click', closeComoUsar);
  modalComoUsar?.addEventListener('click', (e) => { if (e.target === modalComoUsar) closeComoUsar(); });
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && modalComoUsar?.getAttribute('aria-hidden') === 'false') closeComoUsar();
  });

  // [NOVO] feedback estendido no loading do limpar memória
  let clearMemTimer = null;

function openClearMemoryModal() {
    clearStepForm.style.display = '';
    clearStepLoading.style.display = 'none';
    clearStepDone.style.display = 'none';
    clearMemoryErr.style.display = 'none';
    clearMemoryErr.textContent = '';

    btnClearMemoryConfirm.disabled = false;
    btnClearMemoryConfirm.style.display = '';
    btnClearMemoryConfirm.textContent = 'Limpar agora';
    isClearingMemory = false;

    clearMemoryNumero.value = (window.NUMERO_HUMANO || '').trim();
    clearMemoryModal.setAttribute('aria-hidden', 'false');
    document.body.style.overflow = 'hidden';
    setTimeout(() => clearMemoryNumero.focus(), 50);
  }


function digitsOnly(s){ return (s || '').replace(/\D+/g, ''); }

// Formata: (DD) 9 XXXX-XXXX ou (DD) XXXX-XXXX (detecta por quantidade)
function formatBRPhone(d) {
  d = digitsOnly(d);

  // aceita digitarem com 55 na frente também
  if (d.startsWith('55') && d.length >= 12) d = d.slice(2);

  // limita (2 DDD + 9 dígitos) = 11, ou (2 + 8) = 10
  d = d.slice(0, 11);

  const ddd = d.slice(0, 2);
  const rest = d.slice(2);

  if (!ddd) return '';
  if (rest.length === 0) return `(${ddd}`;

  // 11 dígitos -> móvel com 9
  if (rest.length > 8) {
    const p1 = rest.slice(0, 1);
    const p2 = rest.slice(1, 5);
    const p3 = rest.slice(5, 9);
    return `(${ddd}) ${p1} ${p2}${p3 ? '-' + p3 : ''}`.trim();
  }

  // 10 dígitos (ou incompleto) -> fixo/sem 9
  const a = rest.slice(0, 4);
  const b = rest.slice(4, 8);
  return `(${ddd}) ${a}${b ? '-' + b : ''}`.trim();
}

// Converte para formato de envio (55DDDXXXXXXXXX)
function toE164BR(d) {
  let x = digitsOnly(d);
  if (x.startsWith('55')) x = x.slice(2);
  x = x.slice(0, 11); // 10 ou 11
  if (x.length < 10) return ''; // inválido
  return '55' + x;
}

// Máscara ao digitar (mantém caret de forma aceitável sem muita complexidade)
clearMemoryNumero.addEventListener('input', (e) => {
  const before = e.target.value;
  const cursor = e.target.selectionStart || before.length;

  const formatted = formatBRPhone(before);
  e.target.value = formatted;

  // tenta manter cursor "aproximado"
  const diff = formatted.length - before.length;
  const newPos = Math.max(0, Math.min(formatted.length, cursor + diff));
  e.target.setSelectionRange(newPos, newPos);
});













  function closeClearMemoryModal() {
    clearMemoryModal.setAttribute('aria-hidden', 'true');
    document.body.style.overflow = '';
    if (clearMemTimer) { clearTimeout(clearMemTimer); clearMemTimer = null; }
  }

  btnClearMemory.addEventListener('click', openClearMemoryModal);
  btnClearMemoryCloseX?.addEventListener('click', closeClearMemoryModal);
  btnClearMemoryCancel?.addEventListener('click', closeClearMemoryModal);
  clearMemoryModal.addEventListener('click', (e) => { if (e.target === clearMemoryModal) closeClearMemoryModal(); });

  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && clearMemoryModal.getAttribute('aria-hidden') === 'false') {
      closeClearMemoryModal();
    }
  });

  btnClearMemoryConfirm?.addEventListener('click', async () => {
      if (isClearingMemory) return;
isClearingMemory = true;

const numeroFmt = (clearMemoryNumero.value || '').trim();
const numeroE164 = toE164BR(numeroFmt);

clearMemoryErr.style.display = 'none';
if (!numeroE164) {
  showClearError('Informe um número válido. Ex: (31) 9 9999-9999');
  isClearingMemory = false;
  return;
}


    // UI -> loading
    btnClearMemoryConfirm.disabled = true;
    const oldText = btnClearMemoryConfirm.textContent;
    btnClearMemoryConfirm.textContent = 'Limpando...';

    clearStepForm.style.display = 'none';
    clearStepDone.style.display = 'none';
    clearStepLoading.style.display = '';

    // [NOVO] após 4s, avisa que pode demorar
    const loadingSub = clearStepLoading.querySelector('.text-xs');
    if (clearMemTimer) clearTimeout(clearMemTimer);
    clearMemTimer = setTimeout(() => {
      if (loadingSub) loadingSub.textContent = 'Isso pode levar alguns segundos, aguarde...';
    }, 4000);

    const fd = new URLSearchParams();
    fd.append('csrf', CSRF);
    fd.append('numero', numeroE164);

    const r = await fetchJSON(`${API}?action=clear_memory`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
      body: fd
    });

    if (clearMemTimer) { clearTimeout(clearMemTimer); clearMemTimer = null; }

    btnClearMemoryConfirm.disabled = false;
    btnClearMemoryConfirm.textContent = oldText || 'Limpar agora';

    if (!r.ok) {
      clearStepLoading.style.display = 'none';
      clearStepForm.style.display = '';
      showClearError(r.error || 'Falha ao limpar memória');
      isClearingMemory = false;

      return;
    }

setTimeout(() => {
      clearStepLoading.style.display = 'none';
      clearStepDone.style.display = '';
      
      btnClearMemoryConfirm.disabled = true;
      btnClearMemoryConfirm.style.display = 'none';
      isClearingMemory = false;

    }, 900);
  });
});







/* ===== Spotlight no chip recém-adicionado ===== */
/* ===== Spotlight no chip recém-adicionado ===== */
/* ===== Spotlight no chip recém-adicionado ===== */
function showChipSpotlight(chipId) {
  let overlay = document.getElementById('chipSpotlightOverlay');
  if (!overlay) {
    overlay = document.createElement('div');
    overlay.id = 'chipSpotlightOverlay';
    document.body.appendChild(overlay);
  }

  const chip = mediaTags.querySelector(`[data-id="${chipId}"]`);
  if (!chip) return;

  chip.scrollIntoView({ behavior: 'smooth', block: 'nearest' });

  setTimeout(() => {
    const rect = chip.getBoundingClientRect();
    const vw = window.innerWidth;

    // Clone flutuante do chip
    let ghost = document.getElementById('chipSpotlightGhost');
    if (ghost) ghost.remove();
    ghost = chip.cloneNode(true);
    ghost.id = 'chipSpotlightGhost';
    ghost.style.cssText = `
      position: fixed !important;
      top: ${rect.top}px !important;
      left: ${rect.left}px !important;
      width: ${rect.width}px !important;
      height: ${rect.height}px !important;
      z-index: 1600 !important;
      pointer-events: none;
      margin: 0 !important;
      box-shadow: 0 0 0 6px rgba(255,255,255,.3), 0 0 40px rgba(255,255,255,.2), 0 8px 24px rgba(0,0,0,.4) !important;
      transform: scale(1.08) !important;
    `;
    document.body.appendChild(ghost);

    // Balão
    let balloon = document.getElementById('chipSpotlightBalloon');
    if (!balloon) {
      balloon = document.createElement('div');
      balloon.id = 'chipSpotlightBalloon';
      document.body.appendChild(balloon);
    }
    balloon.innerHTML = '🎉 Pronto! Arraste esse chip para o seu prompt';
    balloon.style.cssText = `
      position: fixed !important;
      z-index: 1700 !important;
      background: #ffffff !important;
      color: #0b0f1a !important;
      border-radius: 14px !important;
      padding: .75rem 1.2rem !important;
      font-size: .9rem !important;
      font-weight: 700 !important;
      box-shadow: 0 12px 40px rgba(0,0,0,.3) !important;
      white-space: nowrap !important;
      pointer-events: none !important;
      display: flex !important;
      align-items: center !important;
      gap: .5rem !important;
      opacity: 0 !important;
      transition: opacity .3s ease, transform .3s ease !important;
      transform: translateY(6px) !important;
    `;

    // Posiciona após render
    requestAnimationFrame(() => {
      const bw = balloon.offsetWidth || 300;
      const bh = balloon.offsetHeight || 44;
      const margin = 14;
      const goBelow = rect.top < 100;
      let top = goBelow ? rect.bottom + margin : rect.top - bh - margin;
      top = Math.max(8, Math.min(top, window.innerHeight - bh - 8));
      let left = rect.left + rect.width / 2 - bw / 2;
      left = Math.max(12, Math.min(left, vw - bw - 12));
      balloon.style.left = left + 'px';
      balloon.style.top = top + 'px';

      requestAnimationFrame(() => {
        balloon.style.opacity = '1';
        balloon.style.transform = 'translateY(0)';
      });
    });

    overlay.classList.add('show');

    function dismiss() {
      overlay.classList.remove('show');
      balloon.style.opacity = '0';
      balloon.style.display = 'none';
      ghost.remove();
      overlay.removeEventListener('click', dismiss);
    }
    overlay.addEventListener('click', dismiss);
    setTimeout(dismiss, 6000);

  }, 400);
}




/* ======= Boot ======= */
(async function bootCrud() {
  await loadAgentContext();   // agenda/numero/grupo/midias
  await loadModels();         // tela A (lista) é a inicial
  // editor (#crudEditorView) começa escondido até Novo/Editar
})();
</script>


<script>
    let isClearingMemory = false;

document.addEventListener('DOMContentLoaded', () => {
  // === Configurações do tutorial do GRUPO ===
  const GRUPO_TUTORIAL_URL = 'https://youtu.be/JKMlVyYK2_g';
  const GRUPO_CTA_URL      = 'https://drive.google.com/file/d/1YGmzia0dk9yLIqbpg0XEixj-Cd_zJNjy/view?usp=sharing';
  const GRUPO_CTA_LABEL    = 'Baixar Extensão ID Grupo';

  function toEmbedUrl(url) {
    try {
      const u = new URL(url);
      if (u.hostname.includes('youtu.be')) {
        return `https://www.youtube.com/embed/${u.pathname.slice(1)}?rel=0`;
      }
      if (u.hostname.includes('youtube.com')) {
        const id = u.searchParams.get('v');
        if (id) return `https://www.youtube.com/embed/${id}?rel=0`;
      }
      return url;
    } catch { return url; }
  }

  // pega os elementos APÓS o DOM estar pronto (modal já existe)
  const btnOpenGrupo   = document.getElementById('btnGrupoTutorial');
  const modalGrupo     = document.getElementById('grupoTutorialModal');
  const btnFechar      = document.getElementById('btnGrupoFechar');
  const btnCloseX      = document.getElementById('btnGrupoCloseX');
  const iframeGrupo    = document.getElementById('grupoTutorialIframe');
  const btnGrupoCTA    = document.getElementById('btnGrupoCTA');

  function openGrupoModal() {
    iframeGrupo.src = toEmbedUrl(GRUPO_TUTORIAL_URL);
    btnGrupoCTA.href = GRUPO_CTA_URL;
    btnGrupoCTA.textContent = GRUPO_CTA_LABEL;
    modalGrupo.setAttribute('aria-hidden', 'false');
    document.body.style.overflow = 'hidden';
  }

  function closeGrupoModal() {
    modalGrupo.setAttribute('aria-hidden', 'true');
    iframeGrupo.src = '';
    document.body.style.overflow = '';
  }

  btnOpenGrupo?.addEventListener('click', openGrupoModal);
  btnFechar?.addEventListener('click', closeGrupoModal);
  btnCloseX?.addEventListener('click', closeGrupoModal);
  modalGrupo?.addEventListener('click', (e) => { if (e.target === modalGrupo) closeGrupoModal(); });
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && modalGrupo?.getAttribute('aria-hidden') === 'false') closeGrupoModal();
  });
});



// === Modal de Dicas do Agente de Atendimento ===
document.addEventListener('DOMContentLoaded', () => {
  const DICAS_AGENTE_URL = 'https://youtu.be/EweR-yVgoG4';

  function toEmbedUrl(url) {
    try {
      const u = new URL(url);
      if (u.hostname.includes('youtu.be')) {
        return `https://www.youtube.com/embed/${u.pathname.slice(1)}?rel=0`;
      }
      if (u.hostname.includes('youtube.com')) {
        const id = u.searchParams.get('v');
        if (id) return `https://www.youtube.com/embed/${id}?rel=0`;
      }
      return url;
    } catch { return url; }
  }

  const btnOpenDicasAgente  = document.getElementById('btnDicasAgente');
  const modalDicasAgente    = document.getElementById('dicasAgenteModal');
  const btnDicasAgenteFechar = document.getElementById('btnDicasAgenteFechar');
  const btnDicasAgenteCloseX = document.getElementById('btnDicasAgenteCloseX');
  const iframeDicasAgente   = document.getElementById('dicasAgenteIframe');

  function openDicasAgenteModal() {
    iframeDicasAgente.src = toEmbedUrl(DICAS_AGENTE_URL);
    modalDicasAgente.setAttribute('aria-hidden', 'false');
    document.body.style.overflow = 'hidden';
  }

  function closeDicasAgenteModal() {
    modalDicasAgente.setAttribute('aria-hidden', 'true');
    iframeDicasAgente.src = '';
    document.body.style.overflow = '';
  }

  btnOpenDicasAgente?.addEventListener('click', openDicasAgenteModal);
  btnDicasAgenteFechar?.addEventListener('click', closeDicasAgenteModal);
  btnDicasAgenteCloseX?.addEventListener('click', closeDicasAgenteModal);
  modalDicasAgente?.addEventListener('click', (e) => { if (e.target === modalDicasAgente) closeDicasAgenteModal(); });
  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && modalDicasAgente?.getAttribute('aria-hidden') === 'false') closeDicasAgenteModal();
  });
});
</script>










<style>
  /* ===== Modal Pro (Clear Memory) ===== */
  .cm-overlay{
    position: fixed; inset: 0;
    background: rgba(2, 6, 23, .62);
    backdrop-filter: blur(6px);
    display: none;
    align-items: center;
    justify-content: center;
    z-index: 1100;
    padding: 18px;
  }
  .cm-overlay[aria-hidden="false"]{ display:flex; }

  .cm-card{
    width: min(560px, 94vw);
    border-radius: 18px;
    overflow: hidden;
    background: rgba(255,255,255,.92);
    border: 1px solid rgba(255,255,255,.45);
    box-shadow:
      0 30px 80px rgba(0,0,0,.45),
      0 1px 0 rgba(255,255,255,.3) inset;
    transform: translateY(8px) scale(.985);
    opacity: 0;
    animation: cmIn .18s ease-out forwards;
  }
  .dark .cm-card{
    background: rgba(11,15,26,.92);
    border-color: rgba(148,163,184,.18);
    box-shadow: 0 30px 80px rgba(0,0,0,.65);
  }
  @keyframes cmIn{
    to{ transform: translateY(0) scale(1); opacity:1; }
  }

  .cm-header{
    display:flex; align-items:center; justify-content:space-between;
    padding: 14px 16px;
    background: linear-gradient(135deg, rgba(99,102,241,.16), rgba(79,70,229,.06));
    border-bottom: 1px solid rgba(148,163,184,.22);
  }
  .dark .cm-header{
    border-bottom-color: rgba(148,163,184,.14);
    background: linear-gradient(135deg, rgba(99,102,241,.18), rgba(79,70,229,.08));
  }



.cm-helpbtn{
  margin-left: .6rem;
  padding: .32rem .75rem;
  border-radius: 999px;
  font-size: .75rem;
  font-weight: 800;
  border: 1px solid #f97316 !important;
  background: linear-gradient(135deg,#fb923c 0%, #f97316 100%) !important;
  color: #ffffff !important;
  box-shadow: 0 6px 16px rgba(249,115,22,.35);
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
}

.cm-helpbtn:hover{
  transform: translateY(-1px);
  box-shadow: 0 10px 22px rgba(249,115,22,.45);
}


.cm-helpbtn:active{
  transform: translateY(0);
}

.dark .cm-helpbtn{
  border-color: rgba(251,146,60,.4);
  box-shadow: 0 6px 16px rgba(249,115,22,.5);
}



  .cm-title{
    font-weight: 800;
    letter-spacing: .2px;
    display:flex; align-items:center; gap:.6rem;
    font-size: 1rem;
  }
  .cm-title .badge{
    font-size: .72rem;
    font-weight: 800;
    padding: .18rem .5rem;
    border-radius: 999px;
    background: rgba(244,63,94,.12);
    color: rgb(190, 18, 60);
    border: 1px solid rgba(244,63,94,.22);
  }
  .dark .cm-title .badge{
    color: rgb(253, 164, 175);
    border-color: rgba(244,63,94,.18);
    background: rgba(244,63,94,.10);
  }

  .cm-x{
    width: 36px; height: 36px;
    border-radius: 12px;
    border: 1px solid rgba(148,163,184,.35);
    background: rgba(255,255,255,.7);
    cursor: pointer;
    transition: transform .15s ease, background .15s ease;
  }
  .cm-x:hover{ transform: translateY(-1px); background: rgba(255,255,255,.95); }
  .dark .cm-x{
    background: rgba(11,15,26,.55);
    border-color: rgba(148,163,184,.22);
    color:#e5e7eb;
  }

  .cm-body{ padding: 16px; }
  .cm-sub{
    color: rgba(100,116,139,1);
    font-size: .92rem;
    margin-bottom: 12px;
    line-height: 1.35;
  }
  .dark .cm-sub{ color: rgba(156,163,175,1); }

  .cm-field{
    border-radius: 14px;
    border: 1px solid rgba(148,163,184,.35);
    background: rgba(255,255,255,.75);
    padding: 12px;
    transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
  }
  .dark .cm-field{
    background: rgba(11,15,26,.55);
    border-color: rgba(148,163,184,.20);
  }
  .cm-field:focus-within{
    border-color: rgba(99,102,241,.65);
    box-shadow: 0 0 0 4px rgba(99,102,241,.18);
  }

  .cm-label{
    font-size: .78rem;
    font-weight: 700;
    color: rgba(71,85,105,1);
    margin-bottom: 6px;
    display:block;
  }
  .dark .cm-label{ color: rgba(203,213,225,1); }

  .cm-input{
    width: 100%;
    outline: none;
    border: none;
    background: transparent;
    font-size: 1rem;
    font-weight: 700;
    letter-spacing: .3px;
    color: #0b0f1a;
  }
  .dark .cm-input{ color:#e5e7eb; }

  .cm-help{
    margin-top: 8px;
    font-size: .75rem;
    color: rgba(100,116,139,1);
  }
  .dark .cm-help{ color: rgba(156,163,175,1); }

  .cm-err{
    margin-top: 10px;
    font-size: .9rem;
    color: #e11d48;
    font-weight: 700;
    display:none;
  }

  .cm-footer{
    padding: 14px 16px 16px;
    border-top: 1px solid rgba(148,163,184,.22);
    display:flex;
    justify-content: flex-end;
    gap: 10px;
    background: rgba(255,255,255,.72);
  }
  .dark .cm-footer{
    border-top-color: rgba(148,163,184,.14);
    background: rgba(11,15,26,.50);
  }

  .cm-btn{
    border-radius: 14px;
    padding: .72rem 1rem;
    font-weight: 900;
    font-size: .92rem;
    letter-spacing: .2px;
    border: 1px solid transparent;
    cursor:pointer;
    transition: transform .15s ease, box-shadow .15s ease, opacity .15s ease;
    display:inline-flex;
    align-items:center;
    gap:.55rem;
    user-select: none;
  }
  .cm-btn:active{ transform: translateY(0); }
  .cm-btn:hover{ transform: translateY(-1px); }

  .cm-btn-ghost{
    background: transparent;
    border-color: rgba(148,163,184,.35);
    color: rgba(30,41,59,1);
  }
  .dark .cm-btn-ghost{
    border-color: rgba(148,163,184,.22);
    color: rgba(226,232,240,1);
  }

  .cm-btn-primary{
    background: linear-gradient(135deg,#6366f1 0%,#4f46e5 100%);
    color:#fff;
    box-shadow: 0 10px 24px rgba(79,70,229,.30);
  }
  .cm-btn-primary:disabled{
    opacity: .7;
    cursor:not-allowed;
    transform:none;
    box-shadow:none;
  }

  .cm-pill{
    width:10px; height:10px;
    border-radius:999px;
    background: rgba(34,197,94,1);
    box-shadow: 0 0 0 4px rgba(34,197,94,.18);
  }

  /* Loading row */
  .cm-loadingRow{
    display:flex; align-items:center; gap:12px;
    padding: 12px;
    border-radius: 14px;
    border: 1px dashed rgba(99,102,241,.45);
    background: rgba(99,102,241,.08);
  }
  .dark .cm-loadingRow{
    border-color: rgba(99,102,241,.35);
    background: rgba(99,102,241,.10);
  }

  /* Spinner upgrade */
  .cm-spinner{
    width: 34px; height: 34px;
    border: 4px solid rgba(99,102,241,.22);
    border-top-color: rgba(99,102,241,1);
    border-radius: 9999px;
    animation: cmSpin .9s linear infinite;
  }
  @keyframes cmSpin { to { transform: rotate(360deg); } }
  
  
  
  /* ===== Balão spotlight - BASE (estava faltando!) ===== */
.chip-spotlight-balloon {
  position: fixed;
  z-index: 1700;
  background: #ffffff;
  color: #0b0f1a;
  border-radius: 14px;
  padding: .75rem 1.2rem;
  font-size: .9rem;
  font-weight: 700;
  box-shadow: 0 12px 40px rgba(0,0,0,.3), 0 2px 8px rgba(0,0,0,.15);
  white-space: nowrap;
  pointer-events: none;
  display: none;
  align-items: center;
  gap: .5rem;
  opacity: 0;
  transform: translateY(6px);
  transition: opacity .3s ease, transform .3s ease;
}

.chip-spotlight-balloon.show {
  opacity: 1;
  transform: translateY(0);
}
  
  
  
  
  
  
  
  
  
  
  
  
  
</style>


<div id="clearMemoryModal" class="cm-overlay" aria-hidden="true" role="dialog" aria-modal="true">
  <div class="cm-card">
    <div class="cm-header">
      <div class="cm-title">
  🧹 Limpar memória do agente
<button id="btnClearMemoryComoUsar" 
        type="button" 
        class="cm-helpbtn bg-orange-500 hover:bg-orange-600 text-white border-orange-600">
  Como usar
</button>
</div>

      <button id="btnClearMemoryCloseX" class="cm-x" aria-label="Fechar">✕</button>
    </div>

    <div class="cm-body">
      <!-- ETAPA 1: FORM -->
      <div id="clearStepForm" class="fade-in">
        <div class="cm-sub">
          Digite o <b>número que está conversando com a IA</b>. Vamos resetar a conversa desse número.
        </div>

        <div class="cm-field">
          <label class="cm-label" for="clearMemoryNumero">WhatsApp de teste</label>
          <input id="clearMemoryNumero" type="tel" inputmode="numeric" autocomplete="tel"
                 class="cm-input" placeholder="(31) 9 9999-9999" />
        </div>

        <div id="clearMemoryErr" class="cm-err"></div>
      </div>

      <!-- ETAPA 2: LOADING -->
      <div id="clearStepLoading" class="fade-in" style="display:none;">
        <div class="cm-loadingRow">
          <div class="cm-spinner"></div>
          <div>
            <div class="text-sm font-semibold">Limpando a memória...</div>
            <div class="text-xs" style="opacity:.7; margin-top:2px;">Aguarde só um instante.</div>
          </div>
        </div>
      </div>

      <!-- ETAPA 3: SUCESSO -->
      <div id="clearStepDone" class="fade-in" style="display:none;">
        <div class="text-sm font-semibold" style="margin-bottom:8px; display:flex; align-items:center; gap:10px;">
          <span class="cm-pill"></span> ✅ Memória limpa com sucesso!
        </div>
        <div class="cm-sub" style="margin-bottom: 0;">
          Agora envie uma nova mensagem para o número da IA. O prompt/fluxo será reiniciado do zero.
        </div>
      </div>
    </div>

    <div class="cm-footer">
      <button id="btnClearMemoryCancel" class="cm-btn cm-btn-ghost">Fechar</button>
      <button id="btnClearMemoryConfirm" class="cm-btn cm-btn-primary">
        <span>Limpar agora</span>
      </button>
    </div>
  </div>
</div>



<div id="clearMemoryComoUsarModal" class="modal-overlay-grupo" aria-hidden="true" role="dialog" aria-modal="true">
  <div class="modal-content-grupo">
    <div class="modal-header-grupo">
      <div class="modal-title-grupo">Como usar “Limpar memória do agente”</div>
      <button id="btnClearMemoryComoUsarCloseX" aria-label="Fechar" class="rounded px-2 py-1">✕</button>
    </div>
    <div class="modal-body-grupo">
      <div class="video-wrap-grupo">
        <iframe id="clearMemoryComoUsarIframe"
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
          allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe>
      </div>
    </div>
    <div class="modal-footer-grupo">
      <button id="btnClearMemoryComoUsarFechar">Fechar</button>
    </div>
  </div>
</div>




<!-- ===== Modal: Renomear Modelo ===== -->
<div id="pmRenameModal" class="pm-rename-overlay" aria-hidden="true" role="dialog" aria-modal="true">
  <div class="pm-rename-card">
    <div class="pm-rename-head">
      <div class="pm-rename-title">✏️ Renomear modelo</div>
      <button id="pmRenameCloseX" class="cm-x" aria-label="Fechar">✕</button>
    </div>
    <div class="pm-rename-body">
      <label class="pm-rename-label" for="pmRenameInput">Novo nome do modelo</label>
      <input id="pmRenameInput" type="text" class="pm-rename-input" maxlength="150"
             placeholder="Ex.: Prompt clínicas médicas">

      <label class="pm-rename-label" style="margin-top:14px;">Prévia do prompt (somente leitura)</label>
      <div id="pmRenamePreview" class="pm-rename-preview">—</div>

      <div id="pmRenameErr" class="pm-rename-err"></div>
    </div>
    <div class="pm-rename-foot">
      <button id="pmRenameCancel" class="pm-rename-btn pm-rename-ghost">Cancelar</button>
      <button id="pmRenameConfirm" class="pm-rename-btn pm-rename-primary">Salvar nome</button>
    </div>
  </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
  const overlay = document.getElementById('pmRenameModal');
  const inp     = document.getElementById('pmRenameInput');

  document.getElementById('pmRenameCloseX')?.addEventListener('click', closeRenameModal);
  document.getElementById('pmRenameCancel')?.addEventListener('click', closeRenameModal);
  document.getElementById('pmRenameConfirm')?.addEventListener('click', confirmRename);

  overlay?.addEventListener('click', (e) => { if (e.target === overlay) closeRenameModal(); });

  inp?.addEventListener('keydown', (e) => {
    if (e.key === 'Enter') { e.preventDefault(); confirmRename(); }
  });

  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && overlay?.getAttribute('aria-hidden') === 'false') closeRenameModal();
  });
});
</script>


<!-- ===== Modal: Salvo com Sucesso ===== -->
<div id="modalSaveSuccess" class="cm-overlay" aria-hidden="true" role="dialog" aria-modal="true">
  <div class="cm-card">
    <div class="cm-header">
      <div class="cm-title">
        ✅ Configuração salva
      </div>
      <button id="btnSaveSuccessCloseX" class="cm-x" aria-label="Fechar">✕</button>
    </div>

    <div class="cm-body">
      <div class="cm-sub" style="font-size:1rem;">
        🎉 Seu agente foi salvo com sucesso!
      </div>
    </div>

    <div class="cm-footer">
      <button id="btnSaveSuccessOk" class="cm-btn cm-btn-primary">
        OK
      </button>
    </div>
  </div>
</div>

<script>
document.addEventListener('DOMContentLoaded', () => {
  const modalSaveSuccess = document.getElementById('modalSaveSuccess');
  const btnSaveSuccessOk = document.getElementById('btnSaveSuccessOk');
  const btnSaveSuccessCloseX = document.getElementById('btnSaveSuccessCloseX');

  function openSaveSuccessModal() {
    if (!modalSaveSuccess) return;
    modalSaveSuccess.setAttribute('aria-hidden', 'false');
    document.body.style.overflow = 'hidden';
  }

  function closeSaveSuccessModal() {
    if (!modalSaveSuccess) return;
    modalSaveSuccess.setAttribute('aria-hidden', 'true');
    document.body.style.overflow = '';
  }

  // deixa global pra você chamar de qualquer lugar
  window.openSaveSuccessModal = openSaveSuccessModal;

  btnSaveSuccessOk?.addEventListener('click', closeSaveSuccessModal);
  btnSaveSuccessCloseX?.addEventListener('click', closeSaveSuccessModal);

  modalSaveSuccess?.addEventListener('click', (e) => {
    if (e.target === modalSaveSuccess) closeSaveSuccessModal();
  });

  document.addEventListener('keydown', (e) => {
    if (e.key === 'Escape' && modalSaveSuccess?.getAttribute('aria-hidden') === 'false') {
      closeSaveSuccessModal();
    }
  });
});
</script>







<!-- ===== Modal: Tutorial Grupo falar com humano ===== -->
<style>
  .modal-overlay-grupo {
    position: fixed; inset: 0; background: rgba(0,0,0,.6); backdrop-filter: blur(2px);
    display: none; align-items: center; justify-content: center; z-index: 1200;
  }
  .modal-overlay-grupo[aria-hidden="false"] { display: flex; }
  .modal-content-grupo {
    width: min(920px, 92vw); background: #fff; color: #0b0f1a; border-radius: 12px;
    box-shadow: 0 20px 60px rgba(0,0,0,.35); overflow: hidden;
  }
  .dark .modal-content-grupo { background:#0b0f1a; color:#e5e7eb; }
  .modal-header-grupo {
    display:flex; align-items:center; justify-content:space-between;
    padding: 14px 18px; border-bottom: 1px solid rgba(0,0,0,.08);
  }
  .dark .modal-header-grupo { border-bottom-color: #1f2937; }
  .modal-title-grupo { font-weight:700; font-size: 1rem; }
  .modal-body-grupo { padding: 16px 18px 20px; }
  .video-wrap-grupo { position: relative; padding-bottom: 56.25%; height: 0; border-radius: 10px; overflow: hidden; }
  .video-wrap-grupo iframe, .video-wrap-grupo video {
    position:absolute; top:0; left:0; width:100%; height:100%; border:0;
  }
  .modal-footer-grupo {
    display:flex; gap:10px; justify-content:flex-end; align-items:center;
    padding: 12px 18px 18px;
  }
  #btnGrupoCTA {
    display:inline-flex; align-items:center; gap:.5rem;
    padding:.65rem 1rem; border-radius:.65rem; border:1px solid #4f46e5;
    background: linear-gradient(135deg,#6366f1 0%,#4f46e5 100%); color:#fff; font-weight:700;
    box-shadow: 0 8px 20px rgba(79,70,229,.25); text-decoration:none;
  }
  #btnGrupoCTA:hover { transform: translateY(-1px); }
  #btnGrupoFechar { padding:.55rem .9rem; border-radius:.5rem; border:1px solid #d1d5db; }
  .dark #btnGrupoFechar { border-color:#374151; }
  
  
  
  
  /* ===== Spotlight do chip recém-adicionado ===== */
#chipSpotlightOverlay {
  position: fixed;
  inset: 0;
  z-index: 1500;
  background: rgba(2, 6, 23, 0.72);
  backdrop-filter: blur(3px);
  opacity: 0;
  pointer-events: none;
  transition: opacity .35s ease;
}
#chipSpotlightOverlay.show {
  opacity: 1;
  pointer-events: auto;
}

/* O chip em destaque fica "acima" do overlay */
.chip-spotlight-active {
  position: relative;
  z-index: 1600 !important;
  box-shadow:
    0 0 0 6px rgba(255,255,255,.25),
    0 0 40px rgba(255,255,255,.18),
    0 8px 24px rgba(0,0,0,.35) !important;
  transform: translateY(-3px) scale(1.08) !important;
  transition: all .35s cubic-bezier(0.34, 1.56, 0.64, 1) !important;
  pointer-events: none;
}

/* Balão de mensagem acima do chip */
.chip-spotlight-balloon.balloon-above::after {
  content: '';
  position: absolute;
  bottom: -8px;
  left: 50%;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-bottom: none;
  border-top-color: #fff;
}

.chip-spotlight-balloon.balloon-below::after {
  content: '';
  position: absolute;
  top: -8px;
  left: 50%;
  transform: translateX(-50%);
  border: 8px solid transparent;
  border-top: none;
  border-bottom-color: #fff;
}
.chip-spotlight-balloon.show {
  opacity: 1;
  transform: translateY(0);
}
  
  
  
  
  
  
  
  
  
  
  
</style>

<div id="grupoTutorialModal" class="modal-overlay-grupo" aria-hidden="true" role="dialog" aria-modal="true">
  <div class="modal-content-grupo">
    <div class="modal-header-grupo">
      <div class="modal-title-grupo">Como configurar “Grupo falar com humano”</div>
      <button id="btnGrupoCloseX" aria-label="Fechar" class="rounded px-2 py-1">✕</button>
    </div>
    <div class="modal-body-grupo">
      <div class="video-wrap-grupo">
        <!-- O src é setado via JS para poder pausar ao fechar -->
        <iframe id="grupoTutorialIframe" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe>
      </div>
      <!-- botão abaixo do vídeo -->
      <div style="margin-top: 16px;">
        <a id="btnGrupoCTA" href="#" target="_blank" rel="noopener noreferrer">Abrir no YouTube</a>
      </div>
    </div>
    <div class="modal-footer-grupo">
      <button id="btnGrupoFechar">Fechar</button>
    </div>
  </div>
</div>

<!-- ===== Modal: Dicas Agente de Atendimento ===== -->
<div id="dicasAgenteModal" class="modal-overlay-grupo" aria-hidden="true" role="dialog" aria-modal="true">
  <div class="modal-content-grupo">
    <div class="modal-header-grupo">
      <div class="modal-title-grupo">Dicas para Agente de Atendimento</div>
      <button id="btnDicasAgenteCloseX" aria-label="Fechar" class="rounded px-2 py-1">✕</button>
    </div>
    <div class="modal-body-grupo">
      <div class="video-wrap-grupo">
        <iframe id="dicasAgenteIframe" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe>
      </div>
    </div>
    <div class="modal-footer-grupo">
      <button id="btnDicasAgenteFechar">Fechar</button>
    </div>
  </div>
</div>