// Configuração do Markdown parser personalizado com Highlight.js integrado
const renderer = new marked.Renderer();

// Função auxiliar para escapar caracteres HTML
function escapeHtml(text) {
  return text
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
}

// Função auxiliar para exibir alerta customizado e elegante (substitui o alert nativo)
function showCustomAlert(title, message) {
  return new Promise((resolve) => {
    const overlay = document.createElement('div');
    overlay.className = 'custom-dialog-overlay';
    
    overlay.innerHTML = `
      <div class="custom-dialog-card">
        <div class="custom-dialog-header">
          <span>🔔</span>
          <span>${escapeHtml(title)}</span>
        </div>
        <p class="custom-dialog-body">${escapeHtml(message)}</p>
        <div class="custom-dialog-footer">
          <button class="btn-dialog btn-dialog-confirm">OK</button>
        </div>
      </div>
    `;
    
    const btn = overlay.querySelector('.btn-dialog-confirm');
    btn.addEventListener('click', () => {
      overlay.remove();
      resolve();
    });
    
    document.body.appendChild(overlay);
  });
}

// Função auxiliar para exibir diálogo de confirmação elegante (substitui o confirm nativo)
function showCustomConfirm(title, message, isDanger = false) {
  return new Promise((resolve) => {
    const overlay = document.createElement('div');
    overlay.className = 'custom-dialog-overlay';
    
    overlay.innerHTML = `
      <div class="custom-dialog-card">
        <div class="custom-dialog-header">
          <span>${isDanger ? '⚠️' : '❓'}</span>
          <span>${escapeHtml(title)}</span>
        </div>
        <p class="custom-dialog-body">${escapeHtml(message)}</p>
        <div class="custom-dialog-footer">
          <button class="btn-dialog btn-dialog-cancel">Cancelar</button>
          <button class="btn-dialog ${isDanger ? 'btn-dialog-danger' : 'btn-dialog-confirm'}">${isDanger ? 'Excluir' : 'Confirmar'}</button>
        </div>
      </div>
    `;
    
    const btnCancel = overlay.querySelector('.btn-dialog-cancel');
    const btnConfirm = overlay.querySelector(isDanger ? '.btn-dialog-danger' : '.btn-dialog-confirm');
    
    btnCancel.addEventListener('click', () => {
      overlay.remove();
      resolve(false);
    });
    
    btnConfirm.addEventListener('click', () => {
      overlay.remove();
      resolve(true);
    });
    
    document.body.appendChild(overlay);
  });
}

// Função auxiliar para gerar nome de arquivo de download formatado como <nome_data_hora>.<extensao>
function getDownloadFileName(type, ext) {
  const now = new Date();
  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, '0');
  const day = String(now.getDate()).padStart(2, '0');
  const hours = String(now.getHours()).padStart(2, '0');
  const minutes = String(now.getMinutes()).padStart(2, '0');
  const seconds = String(now.getSeconds()).padStart(2, '0');
  return `${type}_${year}-${month}-${day}_${hours}-${minutes}-${seconds}.${ext}`;
}

renderer.code = function(code, language) {
  // Ajuste para lidar com as diferenças na assinatura do marked.js
  const codeContent = typeof code === 'object' ? code.text : code;
  const lang = (typeof code === 'object' ? code.lang : language) || 'txt';
  
  return `
    <div class="code-container">
      <div class="code-header">
        <span class="code-lang">${lang}</span>
        <button class="btn-copy-code" onclick="copyCode(this)">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H5.25m11.9-3.664A2.251 2.251 0 0 0 15 2.25h-3a2.251 2.251 0 0 0-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5M16.5 9h3.75c.621 0 1.125.504 1.125 1.125v8.25c0 .621-.504 1.125-1.125 1.125H16.5m-3-12h3m-3 3h3M13.5 14.25h3" />
          </svg>
          <span>Copiar</span>
        </button>
      </div>
      <pre><code class="hljs language-${lang}">${escapeHtml(codeContent)}</code></pre>
    </div>
  `;
};

marked.use({ renderer });

// Função global de copiar código para que funcione no onclick
window.copyCode = function(button) {
  const container = button.closest('.code-container');
  const codeElement = container.querySelector('code');
  const textToCopy = codeElement.textContent;

  navigator.clipboard.writeText(textToCopy).then(() => {
    const textSpan = button.querySelector('span');
    const originalText = textSpan.textContent;
    textSpan.textContent = 'Copiado!';
    button.style.color = 'var(--success)';
    
    setTimeout(() => {
      textSpan.textContent = originalText;
      button.style.color = '';
    }, 2000);
  }).catch(err => {
    console.error('Erro ao copiar código:', err);
  });
};

const initApp = () => {
  // Elementos do DOM
  const sidebar = document.getElementById('sidebar');
  const btnMenu = document.getElementById('btnMenu');
  const btnCloseSidebar = document.getElementById('btnCloseSidebar');
  const sidebarOverlay = document.getElementById('sidebarOverlay');
  
  const userInput = document.getElementById('userInput');
  const btnSend = document.getElementById('btnSend');
  const btnVoice = document.getElementById('btnVoice');
  const chatForm = document.getElementById('chatForm');
  const messagesContainer = document.getElementById('messagesContainer');
  const welcomeContainer = document.getElementById('welcomeContainer');
  const conversationList = document.getElementById('conversationList');
  
  const btnNewChat = document.getElementById('btnNewChat');
  const btnNewChatMobile = document.getElementById('btnNewChatMobile');
  const historyItems = document.getElementById('historyItems');
  const btnLogout = document.getElementById('btnLogout');
  const suggestionCards = document.querySelectorAll('.suggestion-card');
  const searchInput = document.getElementById('searchInput');
  const searchClear = document.getElementById('searchClear');
  const searchResultsHeader = document.getElementById('searchResultsHeader');
  const searchResultsCount = document.getElementById('searchResultsCount');
  const searchClearAll = document.getElementById('searchClearAll');
  const sidebarTags = document.getElementById('sidebarTags');

  // Configuração de Identidade do Agente (Kemily/Camila)
  const btnSettings = document.getElementById('btnSettings');
  const settingsModal = document.getElementById('settingsModal');
  const closeSettingsModal = document.getElementById('closeSettingsModal');
  const btnSaveSettings = document.getElementById('btnSaveSettings');
  const settingAgentName = document.getElementById('settingAgentName');
  const previewKemilyAvatar = document.getElementById('previewKemilyAvatar');
  const uploadKemilyAvatar = document.getElementById('uploadKemilyAvatar');
  const previewCamilaAvatar = document.getElementById('previewCamilaAvatar');
  const uploadCamilaAvatar = document.getElementById('uploadCamilaAvatar');
  const welcomeTitle = document.getElementById('welcomeTitle');
  const welcomeAvatarImg = document.getElementById('welcomeAvatarImg');
  const sidebarAvatarImg = document.getElementById('sidebarAvatarImg');
  const temperatureOptions = document.getElementById('temperatureOptions');
  const knowledgeList = document.getElementById('knowledgeList');
  const manualKnowledgeInput = document.getElementById('manualKnowledgeInput');
  const btnAddKnowledge = document.getElementById('btnAddKnowledge');

  window.agentConfig = {
    agentName: "Kemily",
    kemilyAvatarUrl: "assets/kemily.png",
    camilaAvatarUrl: "assets/camila_prof.png",
    temperaturePreset: 'equilibrado'
  };

  window.temperaturePresets = {
    tecnico: { value: 0.2, label: 'Técnico e Direto', description: 'Respostas curtas, objetivas, sem rodeios. Ideal para quando precisa só do essencial.' },
    equilibrado: { value: 0.6, label: 'Equilibrado', description: 'Bom para uso geral — nem muito curto, nem muito longo.' },
    detalhista: { value: 1.0, label: 'Detalhista e Falante', description: 'Respostas extensas, explicações completas, contextualização máxima. Ideal para estudo e revisão.' }
  };

  window.conhecimento = { facts: [], lastUpdated: null };

  // Carrega as configurações do servidor
  const loadAgentConfig = async () => {
    try {
      const res = await fetch('/api/agent-config');
      if (res.ok) {
        window.agentConfig = await res.json();
        updateAgentIdentityUI();
      }
    } catch (e) {
      console.error('Erro ao carregar configurações do agente:', e);
    }
  };

  const updateAgentIdentityUI = () => {
    if (welcomeTitle) {
      welcomeTitle.innerText = `Olá! Sou sua assistente virtual e me chamo ${window.agentConfig.agentName}. Como posso ajudar?`;
    }
    if (welcomeAvatarImg) {
      welcomeAvatarImg.src = window.agentConfig.kemilyAvatarUrl;
    }
    if (sidebarAvatarImg) {
      sidebarAvatarImg.src = window.agentConfig.camilaAvatarUrl;
    }
    if (settingAgentName) {
      settingAgentName.value = window.agentConfig.agentName;
    }
    if (previewKemilyAvatar) {
      previewKemilyAvatar.src = window.agentConfig.kemilyAvatarUrl;
    }
    if (previewCamilaAvatar) {
      previewCamilaAvatar.src = window.agentConfig.camilaAvatarUrl;
    }
    // Atualiza seleção de temperatura
    renderTemperatureOptions();
  };

  // Carregar presets de temperatura do servidor
  const loadTemperaturePresets = async () => {
    try {
      const res = await fetch('/api/temperature-presets');
      if (res.ok) {
        window.temperaturePresets = await res.json();
        renderTemperatureOptions();
      }
    } catch (e) {
      console.error('Erro ao carregar presets de temperatura:', e);
    }
  };

  // Renderizar opções de temperatura
  const renderTemperatureOptions = () => {
    if (!temperatureOptions) return;
    const preset = window.agentConfig.temperaturePreset || 'equilibrado';
    temperatureOptions.innerHTML = Object.entries(window.temperaturePresets).map(([key, t]) => `
      <label class="temperature-option ${preset === key ? 'selected' : ''}" data-preset="${key}">
        <input type="radio" name="temperature" value="${key}" ${preset === key ? 'checked' : ''}>
        <div class="temperature-option-content">
          <strong>${t.label}</strong>
          <span>${t.description}</span>
        </div>
      </label>
    `).join('');

    // Event listeners para as opções
    temperatureOptions.querySelectorAll('.temperature-option').forEach(opt => {
      opt.addEventListener('click', () => {
        temperatureOptions.querySelectorAll('.temperature-option').forEach(o => o.classList.remove('selected'));
        opt.classList.add('selected');
        opt.querySelector('input').checked = true;
      });
    });
  };

  // Carregar conhecimento do servidor
  const loadConhecimento = async () => {
    try {
      const res = await fetch('/api/conhecimento');
      if (res.ok) {
        window.conhecimento = await res.json();
        renderKnowledgeList();
      }
    } catch (e) {
      console.error('Erro ao carregar conhecimento:', e);
    }
  };

  // Renderizar lista de conhecimento
  const renderKnowledgeList = () => {
    if (!knowledgeList) return;
    if (!window.conhecimento.facts || window.conhecimento.facts.length === 0) {
      knowledgeList.innerHTML = '<p style="color: var(--text-muted); text-align: center; padding: 20px;">Nenhum conhecimento aprendido ainda. A assistente aprende automaticamente quando você ensinar algo novo!</p>';
      return;
    }
    knowledgeList.innerHTML = window.conhecimento.facts.map(f => `
      <div class="knowledge-item" data-id="${f.id}">
        <div class="knowledge-item-content" id="knowledge-content-${f.id}">
          <span class="knowledge-source">${f.source}</span>
          <p style="margin: 4px 0 0 0;">${f.content}</p>
          <small style="display: block; margin-top: 4px;">${new Date(f.addedAt).toLocaleDateString('pt-BR')}</small>
        </div>
        <div class="knowledge-actions" id="knowledge-actions-${f.id}" style="display: flex; gap: 4px; align-self: flex-start; margin-left: 8px;">
          <button class="knowledge-edit-btn" onclick="startEditKnowledge(${f.id})" title="Editar" style="background: none; border: none; color: var(--text-secondary); cursor: pointer; padding: 2px 4px; font-size: 0.9rem; transition: color 0.2s;">✏️</button>
          <button class="knowledge-delete-btn" onclick="deleteKnowledge(${f.id})" title="Excluir">×</button>
        </div>
      </div>
    `).join('');
  };

  // Iniciar edição de item de conhecimento
  window.startEditKnowledge = (id) => {
    const fact = window.conhecimento.facts.find(f => f.id === id);
    if (!fact) return;

    const contentDiv = document.getElementById(`knowledge-content-${id}`);
    const actionsDiv = document.getElementById(`knowledge-actions-${id}`);
    if (!contentDiv) return;

    if (actionsDiv) actionsDiv.style.display = 'none';

    contentDiv.innerHTML = `
      <span class="knowledge-source">${fact.source}</span>
      <textarea id="edit-textarea-${id}" style="width: 100%; min-height: 70px; padding: 8px; border-radius: 6px; border: 1px solid var(--brand-green); background: var(--bg-primary); color: var(--text-primary); font-family: var(--font-sans); font-size: 0.9rem; resize: vertical; margin: 6px 0; outline: none; box-shadow: 0 0 4px var(--brand-glow);">${fact.content}</textarea>
      <div style="display: flex; gap: 8px; margin-top: 4px;">
        <button onclick="saveEditKnowledge(${id})" style="background: var(--brand-green); border: none; color: white; padding: 4px 10px; border-radius: 6px; font-size: 0.75rem; cursor: pointer; font-weight: 500; transition: opacity 0.2s;">Salvar</button>
        <button onclick="renderKnowledgeList()" style="background: var(--bg-tertiary); border: none; color: var(--text-primary); padding: 4px 10px; border-radius: 6px; font-size: 0.75rem; cursor: pointer; font-weight: 500; transition: opacity 0.2s;">Cancelar</button>
      </div>
    `;

    const textarea = document.getElementById(`edit-textarea-${id}`);
    if (textarea) {
      textarea.focus();
      textarea.setSelectionRange(textarea.value.length, textarea.value.length);
    }
  };

  // Salvar edição de item de conhecimento
  window.saveEditKnowledge = async (id) => {
    const textarea = document.getElementById(`edit-textarea-${id}`);
    if (!textarea) return;
    const newContent = textarea.value.trim();
    if (!newContent) {
      alert('O conteúdo do conhecimento não pode ser vazio.');
      return;
    }

    try {
      const res = await fetch(`/api/conhecimento/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ content: newContent })
      });
      if (res.ok) {
        const fact = window.conhecimento.facts.find(f => f.id === id);
        if (fact) fact.content = newContent;
        renderKnowledgeList();
      } else {
        const err = await res.json();
        alert('Erro ao salvar conhecimento: ' + err.error);
      }
    } catch (e) {
      console.error('Erro ao atualizar conhecimento:', e);
      alert('Erro de conexão ao salvar conhecimento.');
    }
  };

  // Deletar item de conhecimento (função global para onclick)
  window.deleteKnowledge = async (id) => {
    if (!confirm('Deseja realmente remover este conhecimento aprendido?')) return;
    try {
      const res = await fetch(`/api/conhecimento/${id}`, { method: 'DELETE' });
      if (res.ok) {
        window.conhecimento.facts = window.conhecimento.facts.filter(f => f.id !== id);
        renderKnowledgeList();
      }
    } catch (e) {
      console.error('Erro ao deletar conhecimento:', e);
    }
  };

  // Adicionar conhecimento manualmente
  if (btnAddKnowledge) {
    btnAddKnowledge.addEventListener('click', async () => {
      const input = manualKnowledgeInput?.value.trim();
      if (!input) return;
      try {
        const res = await fetch('/api/conhecimento', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ fact: input, source: 'manual' })
        });
        if (res.ok) {
          const data = await res.json();
          if (data.added) {
            manualKnowledgeInput.value = '';
            await loadConhecimento();
          } else {
            alert('Esta informação já existe ou é similar a um conhecimento que a IA já possui.');
          }
        } else {
          alert('Erro ao salvar no servidor. Verifique sua conexão.');
        }
      } catch (e) {
        console.error('Erro ao adicionar conhecimento:', e);
        alert('Erro ao processar requisição.');
      }
    });
  }

  // Função para extrair knowledge tags da resposta da IA e enviar ao servidor
  window.extractAndSaveKnowledge = async (assistantMessage) => {
    if (!assistantMessage || !assistantMessage.includes('[KNOWLEDGE:')) return;
    try {
      await fetch('/api/conhecimento/extrair', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ message: assistantMessage })
      });
    } catch (e) {
      console.error('Erro ao extrair conhecimento:', e);
    }
  };

  // Variáveis temporárias para avatares (em base64 ou URLs novas)
  let newKemilyAvatarData = null;
  let newCamilaAvatarData = null;

  // Eventos do Modal
  if (btnSettings) {
    btnSettings.addEventListener('click', () => {
      newKemilyAvatarData = null;
      newCamilaAvatarData = null;
      if (settingAgentName) settingAgentName.value = window.agentConfig.agentName;
      if (previewKemilyAvatar) previewKemilyAvatar.src = window.agentConfig.kemilyAvatarUrl;
      if (previewCamilaAvatar) previewCamilaAvatar.src = window.agentConfig.camilaAvatarUrl;
      renderTemperatureOptions();
      loadConhecimento();
      settingsModal.style.display = 'flex';
    });
  }

  if (closeSettingsModal) {
    closeSettingsModal.addEventListener('click', () => {
      settingsModal.style.display = 'none';
    });
  }

  // Tab switching logic
  document.querySelectorAll('.settings-tab').forEach(tab => {
    tab.addEventListener('click', () => {
      document.querySelectorAll('.settings-tab').forEach(t => t.classList.remove('active'));
      document.querySelectorAll('.settings-tab-content').forEach(c => c.classList.remove('active'));
      tab.classList.add('active');
      const targetId = tab.dataset.tab;
      const targetContent = document.getElementById(targetId);
      if (targetContent) targetContent.classList.add('active');
    });
  });

  // Fechar clicando fora do modal-content
  if (settingsModal) {
    settingsModal.addEventListener('click', (e) => {
      if (e.target === settingsModal) {
        settingsModal.style.display = 'none';
      }
    });
  }

  // Previews de Imagem
  const handleAvatarFileSelect = (input, previewImg, callback) => {
    const file = input.files[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = (e) => {
        previewImg.src = e.target.result;
        callback(e.target.result);
      };
      reader.readAsDataURL(file);
    }
  };

  if (uploadKemilyAvatar) {
    uploadKemilyAvatar.addEventListener('change', () => {
      handleAvatarFileSelect(uploadKemilyAvatar, previewKemilyAvatar, (base64) => {
        newKemilyAvatarData = base64;
      });
    });
  }

  if (uploadCamilaAvatar) {
    uploadCamilaAvatar.addEventListener('change', () => {
      handleAvatarFileSelect(uploadCamilaAvatar, previewCamilaAvatar, (base64) => {
        newCamilaAvatarData = base64;
      });
    });
  }

  // Salvar Configurações
  if (btnSaveSettings) {
    btnSaveSettings.addEventListener('click', async () => {
      btnSaveSettings.disabled = true;
      btnSaveSettings.innerText = 'Salvando...';

      try {
        let kemilyUrl = window.agentConfig.kemilyAvatarUrl;
        let camilaUrl = window.agentConfig.camilaAvatarUrl;

        // Se houver novas imagens, faz upload
        if (newKemilyAvatarData) {
          const res = await fetch('/api/upload-avatar', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ avatarType: 'kemily', base64Data: newKemilyAvatarData })
          });
          if (res.ok) {
            const data = await res.json();
            kemilyUrl = data.url;
          }
        }

        if (newCamilaAvatarData) {
          const res = await fetch('/api/upload-avatar', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ avatarType: 'camila', base64Data: newCamilaAvatarData })
          });
          if (res.ok) {
            const data = await res.json();
            camilaUrl = data.url;
          }
        }

        // Envia as configurações gerais
        const selectedTempPreset = temperatureOptions?.querySelector('input[name="temperature"]:checked')?.value || 'equilibrado';
        const resConfig = await fetch('/api/agent-config', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            agentName: settingAgentName.value,
            kemilyAvatarUrl: kemilyUrl,
            camilaAvatarUrl: camilaUrl,
            temperaturePreset: selectedTempPreset
          })
        });

        if (resConfig.ok) {
          const result = await resConfig.json();
          window.agentConfig = result.config;
          updateAgentIdentityUI();
          settingsModal.style.display = 'none';
        } else {
          alert('Erro ao salvar as configurações.');
        }
      } catch (err) {
        console.error(err);
        alert('Ocorreu um erro ao salvar.');
      } finally {
        btnSaveSettings.disabled = false;
        btnSaveSettings.innerText = 'Salvar Configurações';
      }
    });
  }

  // Executa o carregamento inicial das configurações
  loadAgentConfig();

  // Variáveis de Estado
  let chats = JSON.parse(localStorage.getItem('camila_chats')) || [];
  // Migração: adicionar campos tags e pinned a chats antigos
  chats = chats.map(c => ({ ...c, tags: c.tags || [], pinned: c.pinned || false }));
  let currentChatId = localStorage.getItem('camila_current_chat_id') || null;
  let isGenerating = false;
  let searchQuery = '';
  let activeTag = 'all';
  let currentUtterance = null; // para controlar TTS em andamento

  // Variáveis de Reconhecimento de Voz
  let recognition = null;
  let isListening = false;
  let lastInputWasVoice = false; // Rastrear se a última mensagem veio do microfone

  // ==========================================================================
  // THEME TOGGLE — Claro/Escuro
  // ==========================================================================
  const btnThemeToggle = document.getElementById('btnThemeToggle');
  const iconThemeSun = document.getElementById('iconThemeSun');
  const iconThemeMoon = document.getElementById('iconThemeMoon');

  const applyTheme = (theme) => {
    document.documentElement.setAttribute('data-theme', theme);
    localStorage.setItem('camila_theme', theme);
    if (theme === 'light') {
      iconThemeSun.style.display = 'none';
      iconThemeMoon.style.display = 'block';
    } else {
      iconThemeSun.style.display = 'block';
      iconThemeMoon.style.display = 'none';
    }
  };

  // Init theme from localStorage or system preference
  const savedTheme = localStorage.getItem('camila_theme');
  if (savedTheme) {
    applyTheme(savedTheme);
  } else {
    // Default to dark
    applyTheme('dark');
  }

  btnThemeToggle.addEventListener('click', () => {
    const current = document.documentElement.getAttribute('data-theme') || 'dark';
    applyTheme(current === 'dark' ? 'light' : 'dark');
  });

  // ==========================================================================
  // BADGE DE MODELO DINÂMICO
  // ==========================================================================
  const modelBadgeText = document.getElementById('modelBadgeText');
  const updateModelBadge = async () => {
    try {
      const res = await fetch('/api/status');
      if (res.ok) {
        const data = await res.json();
        // Extrai nome abreviado do modelo (ex: "openai/gpt-4.1-nano" → "GPT-4.1 Nano")
        const modelName = data.model.split('/').pop();
        const formatted = modelName.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
        modelBadgeText.textContent = formatted;
      }
    } catch (e) {
      // Mantém texto padrão se falhar
    }
  };
  updateModelBadge();

  // ==========================================================================
  // MODAL DE TAGS & SIDEBAR TAGS
  // ==========================================================================
  const AVAILABLE_TAGS = [
    { id: 'relatorios', label: '📋 Relatórios' },
    { id: 'planejamento', label: '📝 Planejamento' },
    { id: 'mindlab', label: '🧠 Mind Lab' },
    { id: 'estudos', label: '📚 Estudos' },
    { id: 'htpc', label: '💻 HTPC' },
    { id: 'ata', label: '📝 ATA' },
    { id: 'sugestao', label: '💡 Sugestão' },
    { id: 'duvida', label: '❓ Dúvida' }
  ];
  const modalTagOverlay = document.getElementById('modalTagOverlay');
  const modalTagList = document.getElementById('modalTagList');
  const modalTagClose = document.getElementById('modalTagClose');
  const modalTagCancel = document.getElementById('modalTagCancel');
  const modalTagConfirm = document.getElementById('modalTagConfirm');
  let pendingTagAction = null; // { chatId, callback }
  let selectedTagsState = [];

  const openTagModal = (chatId, currentTags, callback) => {
    pendingTagAction = { chatId, callback };
    selectedTagsState = [...currentTags];
    renderTagModalList();
    modalTagOverlay.classList.add('active');
  };

  const closeTagModal = () => {
    modalTagOverlay.classList.remove('active');
    pendingTagAction = null;
  };

  const renderTagModalList = () => {
    modalTagList.innerHTML = AVAILABLE_TAGS.map(tag => `
      <div class="modal-tag-item ${selectedTagsState.includes(tag.id) ? 'selected' : ''}" data-tag="${tag.id}">
        <input type="checkbox" ${selectedTagsState.includes(tag.id) ? 'checked' : ''}>
        <span>${tag.label}</span>
      </div>
    `).join('');

    modalTagList.querySelectorAll('.modal-tag-item').forEach(item => {
      item.addEventListener('click', () => {
        const tag = item.dataset.tag;
        if (selectedTagsState.includes(tag)) {
          selectedTagsState = selectedTagsState.filter(t => t !== tag);
        } else {
          selectedTagsState.push(tag);
        }
        renderTagModalList();
      });
    });
  };

  const renderSidebarTags = () => {
    if (!sidebarTags) return;
    let tagsHtml = `<button class="tag-filter ${activeTag === 'all' ? 'active' : ''}" data-tag="all">Todas</button>`;
    tagsHtml += AVAILABLE_TAGS.map(tag => `
      <button class="tag-filter ${activeTag === tag.id ? 'active' : ''}" data-tag="${tag.id}">
        ${tag.label}
      </button>
    `).join('');
    sidebarTags.innerHTML = tagsHtml;
  };

  modalTagClose.addEventListener('click', closeTagModal);
  modalTagCancel.addEventListener('click', closeTagModal);
  modalTagOverlay.addEventListener('click', (e) => {
    if (e.target === modalTagOverlay) closeTagModal();
  });

  modalTagConfirm.addEventListener('click', () => {
    if (pendingTagAction) {
      pendingTagAction.callback(selectedTagsState);
    }
    closeTagModal();
  });

  // Expose globally for inline onclick handlers
  window.openTagModal = openTagModal;

  // ==========================================================================
  // CONTROLES DE INTERFACE & SIDEBAR
  // ==========================================================================

  const toggleSidebar = (open) => {
    if (open) {
      sidebar.classList.add('open');
    } else {
      sidebar.classList.remove('open');
    }
  };

  btnMenu.addEventListener('click', () => toggleSidebar(true));
  btnCloseSidebar.addEventListener('click', () => toggleSidebar(false));
  sidebarOverlay.addEventListener('click', () => toggleSidebar(false));

  // Redimensionamento automático do Input de Texto (textarea)
  userInput.addEventListener('input', () => {
    userInput.style.height = 'auto';
    userInput.style.height = (userInput.scrollHeight - 4) + 'px';
    
    // Habilitar ou desabilitar botão
    btnSend.disabled = userInput.value.trim() === '' || isGenerating;
  });

  // Prevenir comportamento padrão do Enter no textarea (enviar em vez de quebrar linha, Shift+Enter para nova linha)
  userInput.addEventListener('keydown', (e) => {
    if (e.key === 'Enter' && !e.shiftKey) {
      e.preventDefault();
      if (userInput.value.trim() !== '' && !isGenerating) {
        chatForm.requestSubmit();
      }
    }
  });

  // Busca no histórico
  searchInput.addEventListener('input', () => {
    searchQuery = searchInput.value;
    searchClear.style.display = searchQuery ? 'flex' : 'none';
    renderHistory();
  });

  searchClear.addEventListener('click', () => {
    searchInput.value = '';
    searchQuery = '';
    searchClear.style.display = 'none';
    renderHistory();
  });

  searchClearAll.addEventListener('click', () => {
    searchInput.value = '';
    searchQuery = '';
    searchClear.style.display = 'none';
    renderHistory();
  });

  // Alternar (expandir/recolher) as tags
  const btnToggleSidebarTags = document.getElementById('btnToggleSidebarTags');
  if (btnToggleSidebarTags && sidebarTags) {
    btnToggleSidebarTags.addEventListener('click', () => {
      if (sidebarTags.style.display === 'none') {
        sidebarTags.style.display = 'flex';
      } else {
        sidebarTags.style.display = 'none';
      }
    });
  }

  // Filtro por tags
  sidebarTags.addEventListener('click', (e) => {
    const tagBtn = e.target.closest('.tag-filter');
    if (!tagBtn) return;
    activeTag = tagBtn.dataset.tag;
    renderHistory();
  });

  // ==========================================================================
  // VOZ — WEB SPEECH API (ditado + conversa por voz)
  // ==========================================================================

  const initVoiceRecognition = () => {
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    if (!SpeechRecognition) {
      btnVoice.style.display = 'none';
      console.warn('SpeechRecognition não suportado neste navegador.');
      return;
    }

    recognition = new SpeechRecognition();
    recognition.lang = 'pt-BR';
    recognition.continuous = false;
    recognition.interimResults = false;
    recognition.maxAlternatives = 1;

    recognition.onresult = (event) => {
      const transcript = event.results[0][0].transcript;
      userInput.value = transcript;
      userInput.dispatchEvent(new Event('input'));
      setVoiceState(false);

      // Marca que o input veio do microfone para auto-responder por voz
      lastInputWasVoice = true;

      // Envia automaticamente a mensagem ditada
      if (transcript.trim()) {
        setTimeout(() => {
          chatForm.dispatchEvent(new Event('submit', { cancelable: true }));
        }, 300);
      }
    };

    recognition.onerror = (event) => {
      console.warn('Voice error:', event.error);
      setVoiceState(false);
    };

    recognition.onend = () => {
      setVoiceState(false);
    };
  };

  const setVoiceState = (listening) => {
    isListening = listening;
    if (listening) {
      btnVoice.classList.add('listening');
      btnVoice.setAttribute('title', 'Clique para parar de ouvir');
    } else {
      btnVoice.classList.remove('listening');
      btnVoice.setAttribute('title', 'Conversar por voz');
    }
  };

  btnVoice.addEventListener('click', () => {
    if (!recognition) return;
    if (isListening) {
      recognition.stop();
    } else {
      recognition.start();
      setVoiceState(true);
    }
  });

  // ==========================================================================
  // TTS — Speech Synthesis nativa (voz do navegador)
  // ==========================================================================

  // Selecionar melhor voz pt-BR disponível no dispositivo de forma dinâmica
  const getBestVoice = () => {
    const voices = window.speechSynthesis.getVoices();
    const ptBR = voices.filter(v => v.lang === 'pt-BR' || v.lang === 'pt_BR');
    if (ptBR.length === 0) {
      const pt = voices.filter(v => v.lang.startsWith('pt'));
      return pt[0] || null;
    }

    // 1. Microsoft Neural (Edge): Thalita, Francisca, Giovanna
    const msNeural = ptBR.find(v => /thalita|francisca|giovanna|natural|neural/i.test(v.name));
    if (msNeural) return msNeural;

    // 2. Google (Chrome/Android): vozes naturais
    const google = ptBR.find(v => /google/i.test(v.name));
    if (google) return google;

    // 3. Apple (Safari/iOS): Luciana é excelente
    const apple = ptBR.find(v => /luciana|fernanda/i.test(v.name));
    if (apple) return apple;

    // 4. Qualquer feminina
    const female = ptBR.find(v => /female|femin|maria|raquel|camila/i.test(v.name));
    if (female) return female;

    // 5. Primeira disponível
    return ptBR[0];
  };

  const resetSpeakBtnState = (btn) => {
    if (btn) {
      btn.classList.remove('speaking');
      const span = btn.querySelector('span');
      if (span) span.textContent = 'Ouvir';
    }
  };

  let currentSpeakingBtn = null;
  let currentAudio = null;
  let ttsFallbackTimeout = null;

  // Função auxiliar para parar qualquer áudio em andamento (tanto nativo quanto do backend)
  const stopAllSpeech = () => {
    // Parar áudio do backend
    if (currentAudio) {
      currentAudio.pause();
      currentAudio = null;
    }
    // Parar SpeechSynthesis nativo
    window.speechSynthesis.cancel();
    
    // Limpar timeouts pendentes
    if (ttsFallbackTimeout) {
      clearTimeout(ttsFallbackTimeout);
      ttsFallbackTimeout = null;
    }

    // Resetar estado do botão ativo anterior
    if (currentSpeakingBtn) {
      resetSpeakBtnState(currentSpeakingBtn);
      currentSpeakingBtn = null;
    }
  };

  const speakTextLocalFallback = (cleanText, btn) => {
    console.log('[TTS] Acionando fallback local (voz nativa do navegador)...');
    
    // Configura SpeechSynthesis nativo
    const utterance = new SpeechSynthesisUtterance(cleanText);
    utterance.lang = 'pt-BR';
    utterance.rate = 1.15;
    utterance.pitch = 1.0;

    const voice = getBestVoice();
    if (voice) utterance.voice = voice;

    utterance.onstart = () => {
      if (btn) {
        btn.classList.add('speaking');
        const span = btn.querySelector('span');
        if (span) span.textContent = 'Parar';
      }
    };

    const handleStop = (event) => {
      console.log('TTS nativo finalizado ou com erro:', event.type);
      if (currentSpeakingBtn === btn) {
        resetSpeakBtnState(btn);
        currentSpeakingBtn = null;
      }
    };

    utterance.onend = handleStop;
    utterance.onerror = handleStop;

    window.speechSynthesis.speak(utterance);
  };

  // Falar texto com reprodução híbrida (prioriza Opção A: MsEdgeTTS com fallback local)
  const speakText = async (text, btn) => {
    if (!text) return;

    // Se clicar no botão que já está ativo, para tudo e retorna
    if (currentSpeakingBtn === btn) {
      stopAllSpeech();
      return;
    }

    // Para qualquer reprodução anterior
    stopAllSpeech();

    currentSpeakingBtn = btn;

    // Limpar markdown e emojis antes de falar
    const clean = text
      .replace(/\p{Extended_Pictographic}/gu, '') // Remove emojis pictográficos (ex: ✍️, 📝, 🧒)
      .replace(/[\u{1F300}-\u{1F9FF}]|[\u{2700}-\u{27BF}]|[\u{2600}-\u{26FF}]/gu, '') // Fallback para símbolos/dingbats comuns
      .replace(/```[\s\S]*?```/g, '')
      .replace(/`[^`]+`/g, '')
      .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')
      .replace(/[*_#~\[\]>]/g, '')
      .replace(/\n+/g, '. ')
      .replace(/\s{2,}/g, ' ')
      .trim();

    if (!clean) {
      currentSpeakingBtn = null;
      return;
    }

    // Coloca o botão em estado de "carregando"
    if (btn) {
      btn.classList.add('speaking');
      const span = btn.querySelector('span');
      if (span) span.textContent = 'Carregando...';
    }

    let fallbackTriggered = false;

    // Configura o timeout de 15 segundos para o fallback nativo
    ttsFallbackTimeout = setTimeout(() => {
      if (currentSpeakingBtn === btn) {
        fallbackTriggered = true;
        if (currentAudio) {
          currentAudio.pause();
          currentAudio = null;
        }
        speakTextLocalFallback(clean, btn);
      }
    }, 15000);

    try {
      console.log('[TTS] Solicitando voz neural de alta qualidade ao backend...');
      const response = await fetch('/api/tts', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ text: clean })
      });

      if (!response.ok) {
        throw new Error(`Erro no servidor: ${response.status}`);
      }

      const blob = await response.blob();
      
      // Se o fallback já foi acionado durante a espera, ignora o retorno do áudio do backend
      if (fallbackTriggered) {
        return;
      }

      // Limpar o timeout de fallback já que o áudio respondeu a tempo
      if (ttsFallbackTimeout) {
        clearTimeout(ttsFallbackTimeout);
        ttsFallbackTimeout = null;
      }

      const audioUrl = URL.createObjectURL(blob);
      currentAudio = new Audio(audioUrl);

      currentAudio.onplay = () => {
        if (currentSpeakingBtn === btn) {
          const span = btn.querySelector('span');
          if (span) span.textContent = 'Parar';
        }
      };

      const handleAudioStop = () => {
        if (currentSpeakingBtn === btn) {
          resetSpeakBtnState(btn);
          currentSpeakingBtn = null;
          currentAudio = null;
        }
        URL.revokeObjectURL(audioUrl);
      };

      currentAudio.onended = handleAudioStop;
      currentAudio.onerror = (e) => {
        console.error('[TTS] Erro ao reproduzir áudio do backend:', e);
        if (currentSpeakingBtn === btn && !fallbackTriggered) {
          fallbackTriggered = true;
          speakTextLocalFallback(clean, btn);
        }
      };

      await currentAudio.play();

    } catch (err) {
      console.error('[TTS] Falha ao obter áudio do backend, acionando fallback local imediatamente:', err);
      // Limpa timeout e ativa fallback local imediatamente se der erro de rede
      if (ttsFallbackTimeout) {
        clearTimeout(ttsFallbackTimeout);
        ttsFallbackTimeout = null;
      }
      if (currentSpeakingBtn === btn && !fallbackTriggered) {
        fallbackTriggered = true;
        speakTextLocalFallback(clean, btn);
      }
    }
  };

  // ==========================================================================
  // ANEXOS — Upload de imagens e documentos
  // ==========================================================================

  const fileInput = document.getElementById('fileInput');
  const btnAttach = document.getElementById('btnAttach');
  let attachedFiles = [];

  // Criar preview container se não existir
  let attachPreview = document.querySelector('.attachments-preview');

  const ensureAttachPreview = () => {
    if (!attachPreview) {
      attachPreview = document.createElement('div');
      attachPreview.className = 'attachments-preview';
      document.getElementById('chatForm').appendChild(attachPreview);
    }
  };

  // Botão de anexar → abre seletor de arquivos
  btnAttach.addEventListener('click', () => {
    fileInput.click();
  });

  // Botão alternador de ferramentas (recursos) - FAB Tools
  const fabTools = document.getElementById('fabTools');
  const promptModesBar = document.querySelector('.prompt-modes-bar');

  if (fabTools && promptModesBar) {
    fabTools.addEventListener('click', () => {
      promptModesBar.classList.toggle('show');
      fabTools.classList.toggle('active');
    });
  }

  // Quando arquivos são selecionados
  fileInput.addEventListener('change', () => {
    const files = Array.from(fileInput.files);
    if (files.length === 0) return;

    files.forEach(file => {
      // Limite de 10MB por arquivo
      if (file.size > 10 * 1024 * 1024) {
        alert(`Arquivo "${file.name}" é muito grande. Máximo: 10MB.`);
        return;
      }
      attachedFiles.push(file);
    });

    renderAttachPreview();
    fileInput.value = ''; // reset para permitir selects again
  });

  // Arrastar e soltar na área do chat
  const chatArea = document.querySelector('.chat-area');
  if (chatArea) {
    chatArea.addEventListener('dragover', (e) => {
      e.preventDefault();
      chatArea.classList.add('drag-over');
    });
    chatArea.addEventListener('dragleave', () => {
      chatArea.classList.remove('drag-over');
    });
    chatArea.addEventListener('drop', (e) => {
      e.preventDefault();
      chatArea.classList.remove('drag-over');
      const files = Array.from(e.dataTransfer.files);
      files.forEach(file => {
        if (file.size <= 10 * 1024 * 1024) {
          attachedFiles.push(file);
        }
      });
      renderAttachPreview();
    });
  }

  // Renderizar preview dos anexos
  const renderAttachPreview = () => {
    ensureAttachPreview();
    attachPreview.innerHTML = '';

    if (attachedFiles.length === 0) {
      attachPreview.style.display = 'none';
      btnAttach.classList.remove('has-files');
      return;
    }

    btnAttach.classList.add('has-files');
    attachPreview.style.display = 'flex';

    attachedFiles.forEach((file, index) => {
      const item = document.createElement('div');
      item.className = 'attachment-item';

      const isImage = file.type.startsWith('image/');
      let previewHtml = '';

      if (isImage) {
        const url = URL.createObjectURL(file);
        previewHtml = `<img src="${url}" alt="${file.name}">`;
      } else {
        previewHtml = `<svg xmlns="http://www.w3.org/2000/svg" width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
          <path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" />
        </svg>`;
      }

      item.innerHTML = `
        ${previewHtml}
        <span class="file-name">${file.name}</span>
        <button type="button" class="remove-attachment" data-index="${index}">×</button>
      `;

      attachPreview.appendChild(item);
    });

    // Botões de remover
    attachPreview.querySelectorAll('.remove-attachment').forEach(btn => {
      btn.addEventListener('click', () => {
        const idx = parseInt(btn.dataset.index);
        attachedFiles.splice(idx, 1);
        renderAttachPreview();
      });
    });
  };

  // ==========================================================================
  // ATALHOS DE TECLADO
  // ==========================================================================

  document.addEventListener('keydown', (e) => {
    // Ctrl+N → novo chat
    if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
      e.preventDefault();
      createNewChat();
    }
    // Ctrl+F ou Ctrl+K → focar busca
    if ((e.ctrlKey || e.metaKey) && (e.key === 'f' || e.key === 'k')) {
      e.preventDefault();
      toggleSidebar(true);
      setTimeout(() => searchInput.focus(), 50);
    }
    // Escape → fechar sidebar
    if (e.key === 'Escape') {
      toggleSidebar(false);
    }
  });

  // ==========================================================================
  // HISTÓRICO DE CHATS (LOCALSTORAGE) — VERSÃO COMPLETA COM PINNED, TAGS, BUSCA
  // ==========================================================================

  const saveChats = () => {
    localStorage.setItem('camila_chats', JSON.stringify(chats));
    if (currentChatId) {
      localStorage.setItem('camila_current_chat_id', currentChatId);
    } else {
      localStorage.removeItem('camila_current_chat_id');
    }
  };

  // Agrupamento por data
  const getDateGroup = (timestamp) => {
    const now = new Date();
    const date = new Date(timestamp);
    const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    const weekAgo = new Date(today);
    weekAgo.setDate(weekAgo.getDate() - 7);
    const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);

    const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());

    if (dateOnly.getTime() === today.getTime()) return 'Hoje';
    if (dateOnly.getTime() === yesterday.getTime()) return 'Ontem';
    if (dateOnly >= weekAgo) return 'Esta Semana';
    if (dateOnly >= monthStart) return 'Este Mês';
    return 'Mais Antigas';
  };

  // Filtrar chats por tag
  const filterByTag = (chatList) => {
    if (activeTag === 'all') return chatList;
    return chatList.filter(chat => chat.tags && chat.tags.includes(activeTag));
  };

  // Filtrar chats por busca
  const filterBySearch = (chatList) => {
    if (!searchQuery.trim()) return chatList;
    const q = searchQuery.toLowerCase();
    return chatList.filter(chat => {
      if (chat.title.toLowerCase().includes(q)) return true;
      return chat.messages.some(msg => msg.content.toLowerCase().includes(q));
    });
  };

  // Renderizar um item de chat
  const createHistoryItem = (chat) => {
    const item = document.createElement('div');
    item.className = `history-item ${chat.id === currentChatId ? 'active' : ''} ${chat.pinned ? 'pinned' : ''}`;
    item.dataset.id = chat.id;

    const pinIcon = chat.pinned
      ? `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="pin-icon"><line x1="12" y1="17" x2="12" y2="22" stroke="currentColor" stroke-width="2" stroke-linecap="round"></line><path d="M5 17h14v-1.76a2 2 0 0 0-.44-1.24l-2.78-3.47A2 2 0 0 1 15 9.29V5a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4.29a2 2 0 0 1-.78 1.24L5.44 14a2 2 0 0 0-.44 1.24z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"></path></svg>`
      : '';

    const tagBadges = (chat.tags || []).map(tag =>
      `<span class="history-tag-badge">${getTagEmoji(tag)}</span>`
    ).join('');

    item.innerHTML = `
      <div class="history-item-content">
        ${pinIcon}
        <div class="history-item-title">${escapeHtml(chat.title)}</div>
        ${tagBadges ? `<div class="history-item-tags">${tagBadges}</div>` : ''}
      </div>
      <div class="history-item-actions">
        <button class="btn-history-action btn-pin-chat" title="${chat.pinned ? 'Desafixar' : 'Fixar'}">
          <svg xmlns="http://www.w3.org/2000/svg" fill="${chat.pinned ? 'currentColor' : 'none'}" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <line x1="12" y1="17" x2="12" y2="22"></line>
            <path d="M5 17h14v-1.76a2 2 0 0 0-.44-1.24l-2.78-3.47A2 2 0 0 1 15 9.29V5a2 2 0 0 0-2-2h-2a2 2 0 0 0-2 2v4.29a2 2 0 0 1-.78 1.24L5.44 14a2 2 0 0 0-.44 1.24z"></path>
          </svg>
        </button>
        <button class="btn-history-action btn-tag-chat" title="Tags">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M9.568 3H5.25A2.25 2.25 0 0 0 3 5.25v4.318c0 .597.237 1.17.659 1.591l9.581 9.581a2.25 2.25 0 0 0 3.181 0l4.318-4.318a2.25 2.25 0 0 0 0-3.181l-9.58-9.581A2.25 2.25 0 0 0 9.568 3Z" />
            <path stroke-linecap="round" stroke-linejoin="round" d="M6 6h.008v.008H6V6Z" />
          </svg>
        </button>
        <button class="btn-history-action btn-rename-chat" title="Renomear">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
          </svg>
        </button>
        <button class="btn-history-action btn-delete-chat" title="Excluir">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
          </svg>
        </button>
      </div>
    `;

    return item;
  };

  // Emoji para cada tag
  const getTagEmoji = (tag) => {
    const emojis = { 
      relatorios: '📋', 
      planejamento: '📝', 
      mindlab: '🧠', 
      estudos: '📚',
      htpc: '💻',
      ata: '📝',
      sugestao: '💡',
      duvida: '❓'
    };
    return emojis[tag] || '🏷️';
  };

  // Renderizar histórico completo
  const renderHistory = () => {
    renderSidebarTags(); // Renderizar tags da sidebar de forma dinâmica e atualizada
    historyItems.innerHTML = '';

    if (chats.length === 0) {
      historyItems.innerHTML = '<div style="color: var(--text-muted); font-size: 12px; padding: 10px; text-align: center;">Nenhum chat salvo</div>';
      return;
    }

    // Aplicar filtros
    let filtered = [...chats];
    filtered = filterByTag(filtered);
    filtered = filterBySearch(filtered);

    // Se tem busca, mostrar resultados direto (sem grupo)
    if (searchQuery.trim()) {
      searchResultsHeader.style.display = 'block';
      searchResultsCount.textContent = `${filtered.length} resultado${filtered.length !== 1 ? 's' : ''}`;
      filtered.sort((a, b) => b.updatedAt - a.updatedAt);
      filtered.forEach(chat => {
        const item = createHistoryItem(chat);
        item.addEventListener('click', (e) => {
          if (e.target.closest('.btn-delete-chat')) { e.stopPropagation(); deleteChat(chat.id); return; }
          if (e.target.closest('.btn-pin-chat')) { e.stopPropagation(); togglePin(chat.id); return; }
          if (e.target.closest('.btn-rename-chat')) { e.stopPropagation(); renameChatInline(chat.id, item); return; }
          if (e.target.closest('.btn-tag-chat')) { e.stopPropagation(); editTags(chat.id); return; }
          selectChat(chat.id);
          toggleSidebar(false);
        });
        historyItems.appendChild(item);
      });
      return;
    }

    searchResultsHeader.style.display = 'none';

    // Separar pinned e não-pinned
    const pinned = filtered.filter(c => c.pinned).sort((a, b) => b.updatedAt - a.updatedAt);
    const unpinned = filtered.filter(c => !c.pinned).sort((a, b) => b.updatedAt - a.updatedAt);

    // Renderizar grupo se tiver items
    const renderGroup = (label, items) => {
      if (items.length === 0) return;
      const group = document.createElement('div');
      group.className = 'history-group';
      group.innerHTML = `<h3>${label}</h3>`;
      const container = document.createElement('div');
      container.className = 'history-items';
      items.forEach(chat => {
        const item = createHistoryItem(chat);
        item.addEventListener('click', (e) => {
          if (e.target.closest('.btn-delete-chat')) { e.stopPropagation(); deleteChat(chat.id); return; }
          if (e.target.closest('.btn-pin-chat')) { e.stopPropagation(); togglePin(chat.id); return; }
          if (e.target.closest('.btn-rename-chat')) { e.stopPropagation(); renameChatInline(chat.id, item); return; }
          if (e.target.closest('.btn-tag-chat')) { e.stopPropagation(); editTags(chat.id); return; }
          selectChat(chat.id);
          toggleSidebar(false);
        });
        container.appendChild(item);
      });
      group.appendChild(container);
      historyItems.appendChild(group);
    };

    // Pinned no topo
    if (pinned.length > 0) {
      renderGroup('📌 Fixadas', pinned);
    }

    // Agrupar por data os não-pinned
    const groups = {};
    unpinned.forEach(chat => {
      const group = getDateGroup(chat.updatedAt);
      if (!groups[group]) groups[group] = [];
      groups[group].push(chat);
    });

    ['Hoje', 'Ontem', 'Esta Semana', 'Este Mês', 'Mais Antigas'].forEach(g => {
      if (groups[g]) renderGroup(g, groups[g]);
    });
  };

  // Fixar/desfixar chat
  const togglePin = (id) => {
    const chat = chats.find(c => c.id === id);
    if (!chat) return;
    chat.pinned = !chat.pinned;
    saveChats();
    renderHistory();
  };

  // Renomear chat inline
  const renameChatInline = (id, itemElement) => {
    const chat = chats.find(c => c.id === id);
    if (!chat) return;

    const titleDiv = itemElement.querySelector('.history-item-title');
    if (!titleDiv) return;

    const originalTitle = chat.title;
    const input = document.createElement('input');
    input.type = 'text';
    input.className = 'rename-input';
    input.value = originalTitle;

    // Prevenir clique e propagação para o item
    input.addEventListener('click', (e) => e.stopPropagation());

    const finishRename = () => {
      const newTitle = input.value.trim();
      if (newTitle && newTitle !== originalTitle) {
        chat.title = newTitle;
        chat.updatedAt = Date.now();
        saveChats();
      }
      renderHistory();
    };

    input.addEventListener('keydown', (e) => {
      if (e.key === 'Enter') {
        e.preventDefault();
        finishRename();
      } else if (e.key === 'Escape') {
        e.preventDefault();
        renderHistory();
      }
    });

    input.addEventListener('blur', finishRename);

    titleDiv.replaceWith(input);
    input.focus();
    input.select();
  };

  // Gerenciar tags da conversa
  const editTags = (id) => {
    const chat = chats.find(c => c.id === id);
    if (!chat) return;
    const currentTags = chat.tags || [];
    openTagModal(id, currentTags, (newTags) => {
      chat.tags = newTags;
      chat.updatedAt = Date.now();
      saveChats();
      renderHistory();
    });
  };

  const selectChat = (id) => {
    currentChatId = id;
    const chat = chats.find(c => c.id === id);
    if (!chat) return;

    saveChats();
    renderHistory();
    
    // Ocultar welcome e renderizar as mensagens
    welcomeContainer.style.display = 'none';
    conversationList.innerHTML = '';

    chat.messages.forEach(msg => {
      appendMessageUI(msg.role, msg.content, msg.media);
    });

    scrollToBottom();
  };

  const createNewChat = () => {
    if (isGenerating) return;
    
    currentChatId = null;
    localStorage.removeItem('camila_current_chat_id');
    
    welcomeContainer.style.display = 'flex';
    conversationList.innerHTML = '';
    
    userInput.value = '';
    userInput.style.height = 'auto';
    btnSend.disabled = true;
    
    renderHistory();
  };

  const deleteChat = (id) => {
    chats = chats.filter(c => c.id !== id);
    if (currentChatId === id) {
      currentChatId = null;
      createNewChat();
    } else {
      saveChats();
      renderHistory();
    }
  };

  btnNewChat.addEventListener('click', createNewChat);
  btnNewChatMobile.addEventListener('click', createNewChat);

  // ==========================================================================
  // FLUXO DO CHAT & RENDERIZAÇÃO
  // ==========================================================================

  const appendMessageUI = (role, content, media = null) => {
    const isUser = role === 'user';
    const row = document.createElement('div');
    row.className = `message-row ${role}`;

    const avatarHtml = isUser
      ? `<div class="avatar user-avatar user-avatar-img-wrapper"><img src="${window.agentConfig?.camilaAvatarUrl || 'assets/camila_prof.png'}" alt="Camila" class="user-avatar-img"></div>`
      : `<div class="avatar bot-avatar bot-avatar-img-wrapper"><img src="${window.agentConfig?.kemilyAvatarUrl || 'assets/kemily.png'}" alt="${window.agentConfig?.agentName || 'Kemily'}" class="bot-avatar-img"></div>`;

    let contentHtml = '';
    if (isUser) {
      contentHtml = `<p>${escapeHtml(content).replace(/\n/g, '<br>')}</p>`;
    } else {
      if (media) {
        if (media.type === 'image') {
          contentHtml = `
            <div class="media-message-card">
              <div class="media-img-container">
                <img src="${media.url}" alt="Ilustração gerada" class="generated-image" onload="scrollToBottom()">
              </div>
              <p class="media-caption">✨ "${escapeHtml(media.originalPrompt)}"</p>
              <div class="media-actions-row">
                <a href="${media.url}" download="${getDownloadFileName('imagem', 'png')}" target="_blank" class="media-download-btn">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
                  </svg>
                  <span>Salvar na Galeria</span>
                </a>
              </div>
            </div>
          `;
        } else if (media.type === 'audio') {
          const audioId = 'audio_' + Date.now() + '_' + Math.floor(Math.random() * 10000);
          contentHtml = `
            <div class="media-message-card">
              <div class="custom-audio-player">
                <audio src="${media.url}" id="${audioId}"></audio>
                <button class="audio-play-btn" onclick="toggleCustomAudio(this)" title="Ouvir música">
                  <svg class="play-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                    <path d="M8 5v14l11-7z"/>
                  </svg>
                  <svg class="pause-icon hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                    <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
                  </svg>
                </button>
                <div class="audio-timeline-container">
                  <div class="audio-timeline">
                    <div class="audio-progress"></div>
                  </div>
                </div>
                <span class="audio-time">0:00</span>
              </div>
              <p class="media-caption">🎵 "${escapeHtml(media.originalPrompt)}"</p>
              <div class="media-actions-row">
                <a href="${media.url}" download="${getDownloadFileName('musica', 'mp3')}" target="_blank" class="media-download-btn">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
                  </svg>
                  <span>Baixar Música</span>
                </a>
              </div>
            </div>
          `;
        } else if (media.type === 'video') {
          contentHtml = `
            <div class="media-message-card">
              <div class="media-video-container">
                <video controls src="${media.url}" class="generated-video" preload="metadata"></video>
              </div>
              <p class="media-caption">🎥 "${escapeHtml(media.originalPrompt)}"</p>
              <div class="media-actions-row">
                <a href="${media.url}" download="${getDownloadFileName('video', 'mp4')}" target="_blank" class="media-download-btn">
                  <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
                    <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
                  </svg>
                  <span>Salvar Vídeo</span>
                </a>
              </div>
            </div>
          `;
        }
      } else {
        if (content.trim().startsWith('<div class="media-message-card">')) {
          contentHtml = content;
        } else {
          contentHtml = marked.parse(content);
        }
      }
    }

    const actionsHtml = !isUser ? `
      <div class="message-actions">
        <button class="msg-action-btn btn-copy-msg" title="Copiar resposta" data-content="${media ? escapeHtml(content) : escapeHtml(content).replace(/"/g, '&quot;')}">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
          </svg>
          <span>Copiar</span>
        </button>
        <button class="msg-action-btn btn-regenerate" title="Regenerar resposta">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
          </svg>
          <span>Regenerar</span>
        </button>
        <button class="msg-action-btn btn-speak" title="Ouvir resposta" data-content="${media ? escapeHtml(content) : escapeHtml(content).replace(/"/g, '&quot;')}">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z" />
          </svg>
          <span>Ouvir</span>
        </button>
      </div>
    ` : `
      <div class="message-actions">
        <button class="msg-action-btn btn-edit" title="Editar e reenviar" data-content="${escapeHtml(content).replace(/"/g, '&quot;')}">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
          </svg>
          <span>Editar</span>
        </button>
      </div>
    `;

    row.innerHTML = `
      <div class="message-icon">${avatarHtml}</div>
      <div class="message-content-wrapper">
        <div class="message-content">${contentHtml}</div>
        ${actionsHtml}
      </div>
    `;

    conversationList.appendChild(row);

    // Colorir blocos de código com Highlight.js
    row.querySelectorAll('pre code').forEach((block) => {
      hljs.highlightElement(block);
    });

    // Event listener para copiar mensagem
    const copyBtn = row.querySelector('.btn-copy-msg');
    if (copyBtn) {
      copyBtn.addEventListener('click', () => {
        const text = copyBtn.dataset.content;
        navigator.clipboard.writeText(text).then(() => {
          const span = copyBtn.querySelector('span');
          const original = span.textContent;
          span.textContent = 'Copiado!';
          setTimeout(() => span.textContent = original, 2000);
        });
      });
    }

    // Event listener para editar/reenviar mensagem
    const editBtn = row.querySelector('.btn-edit');
    if (editBtn) {
      editBtn.addEventListener('click', () => {
        const text = editBtn.dataset.content;
        const chat = chats.find(c => c.id === currentChatId);
        if (!chat) return;

        // Encontrar índice desta mensagem no chat
        const rows = conversationList.querySelectorAll('.message-row.user');
        let msgRow = null;
        for (const r of rows) {
          const btn = r.querySelector('.btn-edit');
          if (btn && btn.dataset.content === text) {
            msgRow = r;
            break;
          }
        }

        // Remover esta mensagem e todas as subsequentes (do user e do bot)
        if (msgRow) {
          const allRows = Array.from(conversationList.querySelectorAll('.message-row'));
          const idx = allRows.indexOf(msgRow);
          for (let i = allRows.length - 1; i >= idx; i--) {
            allRows[i].remove();
          }
          // Remover do estado também
          const msgIndex = chat.messages.findIndex(m => m.role === 'user' && m.content === text);
          if (msgIndex >= 0) {
            chat.messages = chat.messages.slice(0, msgIndex);
          }
          saveChats();
        }

        // Colocar texto no input e focar
        userInput.value = text;
        userInput.focus();
        userInput.dispatchEvent(new Event('input'));
        btnSend.disabled = false;
      });
    }

    // Event listener para ouvir resposta (TTS nativo)
    const speakBtn = row.querySelector('.btn-speak');
    if (speakBtn) {
      speakBtn.addEventListener('click', () => {
        const text = speakBtn.dataset.content;
        speakText(text, speakBtn);
      });
    }

    // Event listener para regenerar resposta
    const regenBtn = row.querySelector('.btn-regenerate');
    if (regenBtn) {
      regenBtn.addEventListener('click', () => {
        if (isGenerating) return;
        regenerateLastResponse();
      });
    }

    return row;
  };

  // Regenerar última resposta do bot
  const regenerateLastResponse = () => {
    const chat = chats.find(c => c.id === currentChatId);
    if (!chat || chat.messages.length === 0) return;

    // Encontrar última mensagem do bot
    let lastBotIdx = -1;
    for (let i = chat.messages.length - 1; i >= 0; i--) {
      if (chat.messages[i].role === 'assistant') {
        lastBotIdx = i;
        break;
      }
    }
    if (lastBotIdx === -1) return;

    // Remover última mensagem do bot e todas as mensagens depois da última mensagem do usuário
    let lastUserIdx = -1;
    for (let i = lastBotIdx - 1; i >= 0; i--) {
      if (chat.messages[i].role === 'user') {
        lastUserIdx = i;
        break;
      }
    }

    // Cortar mensagens até a última do usuário
    if (lastUserIdx >= 0) {
      chat.messages = chat.messages.slice(0, lastUserIdx + 1);
    } else {
      chat.messages = [];
    }

    // Remover da UI as mensagens depois do último user
    const rows = conversationList.querySelectorAll('.message-row');
    for (let i = rows.length - 1; i >= 0; i--) {
      const row = rows[i];
      const isBot = row.classList.contains('assistant');
      const isUser = row.classList.contains('user');
      if (isBot) {
        row.remove();
      } else if (isUser) {
        break;
      }
    }

    saveChats();
    scrollToBottom();

    // Reenviar última mensagem do usuário para gerar nova resposta
    const lastUserMsg = chat.messages[chat.messages.length - 1];
    if (lastUserMsg && lastUserMsg.role === 'user') {
      handleSendMessage(lastUserMsg.content, true);
    }
  };

  const scrollToBottom = () => {
    messagesContainer.scrollTop = messagesContainer.scrollHeight;
  };

  const getProgressSteps = (promptText) => {
    const promptLower = (promptText || '').toLowerCase();
    
    if (promptLower.includes('historia') || promptLower.includes('conto') || promptLower.includes('história') || promptLower.includes('escrever')) {
      return [
        { text: "Analisando a solicitação da professora...", progress: 15 },
        { text: "Esboçando o enredo e personagens infantis...", progress: 40 },
        { text: "Elaborando a história pedagógica...", progress: 70 },
        { text: "Fazendo sugestões para uso pedagógico...", progress: 90 }
      ];
    }
    
    if (promptLower.includes('relatorio') || promptLower.includes('relatório') || promptLower.includes('observa') || promptLower.includes('htpc')) {
      return [
        { text: "Analisando as observações pedagógicas...", progress: 15 },
        { text: "Sintetizando os avanços e interações...", progress: 40 },
        { text: "Estruturando os blocos do relatório individual...", progress: 65 },
        { text: "Refinando o texto e alinhando com a BNCC...", progress: 85 },
        { text: "Ajustando o tom formal-pedagógico...", progress: 95 }
      ];
    }
    
    if (promptLower.includes('planejamento') || promptLower.includes('aula') || promptLower.includes('atividade') || promptLower.includes('projeto') || promptLower.includes('brincar')) {
      return [
        { text: "Revisando os campos de experiência da BNCC...", progress: 20 },
        { text: "Estruturando os momentos da vivência lúdica...", progress: 45 },
        { text: "Definindo a intencionalidade educativa e mediação...", progress: 70 },
        { text: "Finalizando as comandas e recursos pedagógicos...", progress: 90 }
      ];
    }
    
    // Caso geral
    return [
      { text: "Analisando a solicitação...", progress: 20 },
      { text: "Processando as diretrizes pedagógicas...", progress: 45 },
      { text: "Elaborando a resposta...", progress: 75 },
      { text: "Refinando a formatação e estilo...", progress: 90 }
    ];
  };

  // Função principal de envio de mensagens
  const handleSendMessage = async (text, skipUserAppend = false, files = null, forcedIntent = null) => {
    if (!text && (!files || files.length === 0)) return;

    // Se não recebe files por parâmetro, usa os anexados globalmente
    const filesToSend = files || attachedFiles;
    let fullText = text || '';

    // Processar anexos: evitar base64 gigantesco em imagens e erro de leitura binária em PDF/DOCX
    if (filesToSend.length > 0) {
      for (const file of filesToSend) {
        if (file.type.startsWith('image/')) {
          // Apenas anexa uma referência textual limpa da imagem para a IA saber que ela existe
          fullText += `\n\n*[Imagem anexada: ${file.name} (${Math.round(file.size/1024)} KB)]*`;
        } else if (file.name.endsWith('.txt') || file.name.endsWith('.md') || file.name.endsWith('.json') || file.name.endsWith('.csv') || file.name.endsWith('.js') || file.name.endsWith('.css') || file.name.endsWith('.html')) {
          const reader = new FileReader();
          const content = await new Promise((resolve) => {
            reader.onload = (e) => resolve(e.target.result);
            reader.readAsText(file);
          });
          const truncated = content.length > 3000 ? content.substring(0, 3000) + '... [conteúdo truncado]' : content;
          fullText += `\n\n*[Conteúdo do arquivo "${file.name}":]*\n\`\`\`\n${truncated}\n\`\`\``;
        } else {
          // Para arquivos binários como PDF/DOCX que não podem ser lidos diretamente como texto cru no frontend
          fullText += `\n\n*[Arquivo anexado: ${file.name} (${Math.round(file.size/1024)} KB) - formato não textual]*`;
        }
      }
      // Limpar anexos após envio
      attachedFiles = [];
      if (attachPreview) {
        attachPreview.innerHTML = '';
        attachPreview.style.display = 'none';
        btnAttach.classList.remove('has-files');
      }
    }

    isGenerating = true;
    btnSend.disabled = true;
    userInput.disabled = true;
    userInput.value = '';
    userInput.style.height = 'auto';

    // Ocultar tela de boas-vindas se for a primeira mensagem
    if (welcomeContainer.style.display !== 'none') {
      welcomeContainer.style.display = 'none';
    }

    // Criar o chat se for novo
    if (!currentChatId) {
      const newId = 'chat_' + Date.now();
      const firstLine = fullText.split('\n')[0];
      const title = firstLine.length > 26 ? firstLine.substring(0, 26) + '...' : firstLine;
      
      chats.push({
        id: newId,
        title: title,
        tags: [],
        pinned: false,
        messages: [],
        createdAt: Date.now(),
        updatedAt: Date.now()
      });
      currentChatId = newId;
    }

    // Achar o chat atual no estado
    const chat = chats.find(c => c.id === currentChatId);
    if (!chat) return;

    // Adicionar mensagem do usuário no estado e na tela (pula se for regeneração)
    if (!skipUserAppend) {
      const userMsg = { role: 'user', content: fullText };
      chat.messages.push(userMsg);
      chat.updatedAt = Date.now();
      appendMessageUI('user', fullText);
      scrollToBottom();
      saveChats();
      renderHistory();
    }

    // Criar container para a resposta do bot (PedaGog) na tela
    const botRow = document.createElement('div');
    botRow.className = 'message-row assistant';
    
    botRow.innerHTML = `
      <div class="message-icon">
        <div class="avatar bot-avatar bot-avatar-img-wrapper"><img src="${window.agentConfig?.kemilyAvatarUrl || 'assets/kemily.png'}" alt="${window.agentConfig?.agentName || 'Kemily'}" class="bot-avatar-img"></div>
      </div>
      <div class="message-content-wrapper">
        <div class="message-content">
          <span class="typing-cursor"></span>
        </div>
      </div>
    `;
    conversationList.appendChild(botRow);
    scrollToBottom();

    const botContentDiv = botRow.querySelector('.message-content');
    let assistantContent = '';

    // Obter etapas de progresso personalizadas
    const progressSteps = getProgressSteps(fullText);
    let currentStepIdx = 0;
    
    // Renderizar barra de progresso inicial
    botContentDiv.innerHTML = `
      <div class="ia-progress-container" id="iaProgressContainer">
        <div class="ia-progress-header">
          <div class="ia-progress-icon"></div>
          <div class="ia-progress-step-text" id="iaProgressStepText">${progressSteps[0].text}</div>
        </div>
        <div class="ia-progress-bar">
          <div class="ia-progress-bar-fill" id="iaProgressBarFill" style="width: ${progressSteps[0].progress}%;"></div>
        </div>
      </div>
    `;
    scrollToBottom();

    // Fechar barra de prompt no mobile se estiver aberta para liberar espaço
    const mobilePromptBar = document.querySelector('.prompt-modes-bar');
    const mobileToggleBtn = document.getElementById('fabTools');
    if (mobilePromptBar && window.innerWidth <= 768) {
      mobilePromptBar.classList.remove('show');
      if (mobileToggleBtn) mobileToggleBtn.classList.remove('active');
    }

    // Iniciar timer para avançar as etapas
    let progressTimer = setInterval(() => {
      if (currentStepIdx < progressSteps.length - 1) {
        currentStepIdx++;
        const step = progressSteps[currentStepIdx];
        const stepTextEl = botContentDiv.querySelector('#iaProgressStepText');
        const barFillEl = botContentDiv.querySelector('#iaProgressBarFill');
        if (stepTextEl && barFillEl) {
          stepTextEl.textContent = step.text;
          barFillEl.style.width = `${step.progress}%`;
        }
      }
    }, 1500);

    try {
      // Filtrar mensagens para enviar apenas o histórico necessário ao OpenRouter, removendo dados base64 pesados de mídias
      const messagesPayload = chat.messages.map(m => {
        let cleanContent = m.content || '';
        if (cleanContent.includes('data:image/') || cleanContent.includes('data:audio/') || cleanContent.includes('data:video/')) {
          const typeLabel = cleanContent.includes('custom-audio-player') ? 'Áudio/Música' : (cleanContent.includes('media-video-container') ? 'Vídeo' : 'Imagem');
          cleanContent = `[Mídia gerada anteriormente: ${typeLabel}]`;
        }
        return { role: m.role, content: cleanContent };
      });

      // Fazer a chamada HTTP usando stream
      const response = await fetch('/api/chat', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ messages: messagesPayload, forcedIntent: forcedIntent })
      });

      if (!response.ok) {
        throw new Error('Falha na resposta do servidor');
      }

      // Processar stream de dados (SSE)
      const reader = response.body.getReader();
      const decoder = new TextDecoder('utf-8');
      let buffer = '';
      let isMediaResponse = false;
      let mediaMsgData = null;

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;

        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split('\n');
        
        // Deixar a última parte inacabada no buffer
        buffer = lines.pop();

        for (const line of lines) {
          const cleanLine = line.trim();
          if (cleanLine.startsWith('data: ')) {
            const dataContent = cleanLine.slice(6);
            if (dataContent === '[DONE]') {
              continue;
            }
            try {
              const parsed = JSON.parse(dataContent);
              
              if (parsed.content) {
                assistantContent += parsed.content;
                // Mantemos o progresso visível sem renderizar o texto parcial
              } else if (parsed.type === 'media_status') {
                isMediaResponse = true;
                if (progressTimer) {
                  clearInterval(progressTimer);
                  progressTimer = null;
                }
                botContentDiv.innerHTML = `
                  <div class="media-loading">
                    <div class="media-spinner"></div>
                    <p class="media-loading-text">${escapeHtml(parsed.message)}</p>
                  </div>
                `;
                scrollToBottom();
              } else if (parsed.type === 'image') {
                isMediaResponse = true;
                if (progressTimer) {
                  clearInterval(progressTimer);
                  progressTimer = null;
                }
                mediaMsgData = { type: 'image', url: parsed.url, originalPrompt: parsed.originalPrompt };
                assistantContent = `
                  <div class="media-message-card">
                    <div class="media-img-container">
                      <img src="${parsed.url}" alt="Ilustração gerada" class="generated-image" onload="scrollToBottom()">
                    </div>
                    <p class="media-caption">✨ "${escapeHtml(parsed.originalPrompt)}"</p>
                    <div class="media-actions-row">
                      <a href="${parsed.url}" download="${getDownloadFileName('imagem', 'png')}" target="_blank" class="media-download-btn">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
                          <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
                        </svg>
                        <span>Salvar na Galeria</span>
                      </a>
                    </div>
                  </div>
                `;
                botContentDiv.innerHTML = assistantContent;
                scrollToBottom();
              } else if (parsed.type === 'error') {
                isMediaResponse = true;
                if (progressTimer) {
                  clearInterval(progressTimer);
                  progressTimer = null;
                }
                botContentDiv.innerHTML = `
                  <div class="message-row bot">
                    <div class="message-content">
                      <p style="color: red; font-weight: bold;">⚠️ Erro na geração: ${escapeHtml(parsed.message)}</p>
                    </div>
                  </div>
                `;
                scrollToBottom();
              } else if (parsed.type === 'audio') {
                isMediaResponse = true;
                if (progressTimer) {
                  clearInterval(progressTimer);
                  progressTimer = null;
                }
                mediaMsgData = { type: 'audio', url: parsed.url, originalPrompt: parsed.originalPrompt };
                const audioId = 'audio_' + Date.now();
                assistantContent = `
                  <div class="media-message-card">
                    <div class="custom-audio-player">
                      <audio src="${parsed.url}" id="${audioId}"></audio>
                      <button class="audio-play-btn" onclick="toggleCustomAudio(this)" title="Ouvir música">
                        <svg class="play-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                          <path d="M8 5v14l11-7z"/>
                        </svg>
                        <svg class="pause-icon hidden" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor">
                          <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/>
                        </svg>
                      </button>
                      <div class="audio-timeline-container">
                        <div class="audio-timeline">
                          <div class="audio-progress"></div>
                        </div>
                      </div>
                      <span class="audio-time">0:00</span>
                    </div>
                    <p class="media-caption">🎵 "${escapeHtml(parsed.originalPrompt)}"</p>
                    <div class="media-actions-row">
                      <a href="${parsed.url}" download="${getDownloadFileName('musica', 'mp3')}" target="_blank" class="media-download-btn">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
                          <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
                        </svg>
                        <span>Baixar Música</span>
                      </a>
                    </div>
                  </div>
                `;
                botContentDiv.innerHTML = assistantContent;
                scrollToBottom();
              } else if (parsed.type === 'video') {
                isMediaResponse = true;
                if (progressTimer) {
                  clearInterval(progressTimer);
                  progressTimer = null;
                }
                mediaMsgData = { type: 'video', url: parsed.url, originalPrompt: parsed.originalPrompt };
                assistantContent = `
                  <div class="media-message-card">
                    <div class="media-video-container">
                      <video controls src="${parsed.url}" class="generated-video" preload="metadata"></video>
                    </div>
                    <p class="media-caption">🎥 "${escapeHtml(parsed.originalPrompt)}"</p>
                    <div class="media-actions-row">
                      <a href="${parsed.url}" download="${getDownloadFileName('video', 'mp4')}" target="_blank" class="media-download-btn">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor">
                          <path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3" />
                        </svg>
                        <span>Salvar Vídeo</span>
                      </a>
                    </div>
                  </div>
                `;
                botContentDiv.innerHTML = assistantContent;
                scrollToBottom();
              }
            } catch (err) {
              // Ignorar erros de JSON incompletos do buffer
            }
          }
        }
      }

      // Remover o cursor de digitação no final se não for mensagem de mídia
      const cursor = botContentDiv.querySelector('.typing-cursor');
      if (cursor) cursor.remove();

      if (progressTimer) {
        clearInterval(progressTimer);
        progressTimer = null;
      }

      // Remover blocos <think> nativos de modelos de reasoning antes de renderizar e extrair conhecimento
      assistantContent = assistantContent.replace(/<think>[\s\S]*?(?:<\/think>|$)/g, '').trim();

      // Parse final limpo do markdown (se for texto normal)
      if (!isMediaResponse) {
        const stepTextEl = botContentDiv.querySelector('#iaProgressStepText');
        const barFillEl = botContentDiv.querySelector('#iaProgressBarFill');
        if (stepTextEl && barFillEl) {
          stepTextEl.textContent = "Concluído com sucesso!";
          barFillEl.style.width = "100%";
        }
        // Aguardar um instante para o feedback visual de conclusão ser percebido
        await new Promise(resolve => setTimeout(resolve, 400));

        botContentDiv.innerHTML = marked.parse(assistantContent);
        botContentDiv.querySelectorAll('pre code').forEach((block) => {
          hljs.highlightElement(block);
        });
      }

      // Extrair e salvar conhecimento aprendido (tags [KNOWLEDGE: ...])
      window.extractAndSaveKnowledge(assistantContent);

      // Adicionar botões de ação (Copiar, Regenerar, Ouvir) após o streaming
      const escapedContent = escapeHtml(assistantContent).replace(/"/g, '&quot;');
      const actionsDiv = document.createElement('div');
      actionsDiv.className = 'message-actions';
      actionsDiv.innerHTML = `
        <button class="msg-action-btn btn-copy-msg" title="Copiar resposta" data-content="${escapedContent}">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
          </svg>
          <span>Copiar</span>
        </button>
        <button class="msg-action-btn btn-regenerate" title="Regenerar resposta">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0 3.181 3.183a8.25 8.25 0 0 0 13.803-3.7M4.031 9.865a8.25 8.25 0 0 1 13.803-3.7l3.181 3.182m0-4.991v4.99" />
          </svg>
          <span>Regenerar</span>
        </button>
        <button class="msg-action-btn btn-speak" title="Ouvir resposta" data-content="${escapedContent}">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" d="M19.114 5.636a9 9 0 0 1 0 12.728M16.463 8.288a5.25 5.25 0 0 1 0 7.424M6.75 8.25l4.72-4.72a.75.75 0 0 1 1.28.53v15.88a.75.75 0 0 1-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.009 9.009 0 0 1 2.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75Z" />
          </svg>
          <span>Ouvir</span>
        </button>
      `;

      const wrapper = botRow.querySelector('.message-content-wrapper');
      wrapper.appendChild(actionsDiv);

      // Vincular listeners dos botões
      const copyBtn = actionsDiv.querySelector('.btn-copy-msg');
      copyBtn.addEventListener('click', () => {
        navigator.clipboard.writeText(assistantContent).then(() => {
          const span = copyBtn.querySelector('span');
          const original = span.textContent;
          span.textContent = 'Copiado!';
          setTimeout(() => span.textContent = original, 2000);
        });
      });

      const regenBtn = actionsDiv.querySelector('.btn-regenerate');
      regenBtn.addEventListener('click', () => {
        if (!isGenerating) regenerateLastResponse();
      });

      const speakBtn = actionsDiv.querySelector('.btn-speak');
      speakBtn.addEventListener('click', () => {
        speakText(assistantContent, speakBtn);
      });

      scrollToBottom();

      // AUTO-TTS: Se a mensagem veio do microfone, ler a resposta em voz alta automaticamente
      if (lastInputWasVoice && assistantContent && !isMediaResponse) {
        console.log('[VOZ] Mensagem veio do microfone — respondendo por voz automaticamente.');
        setTimeout(() => {
          speakText(assistantContent, speakBtn);
        }, 400);
      }
      lastInputWasVoice = false;

      // Salvar resposta no estado e localStorage
      const assistantMsg = { role: 'assistant', content: assistantContent };
      chat.messages.push(assistantMsg);
      chat.updatedAt = Date.now();
      saveChats();
      renderHistory();

    } catch (error) {
      console.error('Erro na resposta do chat:', error);
      if (progressTimer) {
        clearInterval(progressTimer);
        progressTimer = null;
      }
      const cursor = botContentDiv.querySelector('.typing-cursor');
      if (cursor) cursor.remove();
      
      botContentDiv.innerHTML = `
        <p style="color: var(--error); margin-top: 8px; font-size: 13.5px; display: flex; align-items: center; gap: 6px;">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" style="width: 16px; height: 16px;">
            <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v3.75m9-.75a9 9 0 1 1-18 0 9 9 0 0 1 18 0Zm-9 3.75h.008v.008H12v-.008Z" />
          </svg>
          Desculpe, ocorreu um erro ao obter resposta da PedaGog. Por favor, tente novamente.
        </p>
      `;
      scrollToBottom();
    } finally {
      isGenerating = false;
      btnSend.disabled = userInput.value.trim() === '';
      userInput.disabled = false;
      userInput.focus();
    }
  };

  // Envio pelo Formulário
  chatForm.addEventListener('submit', (e) => {
    e.preventDefault();
    const text = userInput.value.trim();
    handleSendMessage(text);
  });

  // Botões de Modos Rápidos de Prompt (Rodapé)
  document.querySelectorAll('.btn-prompt-mode').forEach(btn => {
    btn.addEventListener('click', () => {
      if (window.innerWidth <= 768) {
        if (promptModesBar) promptModesBar.classList.remove('show');
        if (fabTools) fabTools.classList.remove('active');
      }
      if (btn.dataset.prompt) {
        handleSendMessage(btn.dataset.prompt);
        return;
      }
      if (btn.dataset.fill) {
        userInput.value = btn.dataset.fill;
        userInput.focus();
        btnSend.disabled = false;
        return;
      }
      if (btn.id === 'barBtnEstudio') return; // Manipulado separadamente
      if (btn.id === 'barBtnComics') return; // Manipulado separadamente
      if (btn.id === 'barBtnMusica') return;
      if (btn.id === 'barBtnHistoria') return;
      if (btn.id === 'barBtnMindLab') return;
      
      const mode = btn.dataset.mode;
      const text = userInput.value.trim();
      
      let suggestion = "";
      let baseText = text;
      
      // Se o texto atual já for uma das sugestões padrão, limpamos para não duplicar
      const suggestionsList = [
        "Crie uma música pedagógica alegre e animada sobre ",
        "Crie um roteiro detalhado para um vídeo educativo sobre ",
        "Crie uma ilustração pedagógica com cores vibrantes mostrando ",
        "Escreva uma poesia infantil rimada e educativa sobre ",
        "Escreva uma história educativa infantil curta sobre "
      ];
      
      for (const sugg of suggestionsList) {
        if (baseText.startsWith(sugg)) {
          baseText = baseText.replace(sugg, "").trim();
          break;
        }
      }
      
      if (mode === 'AUDIO') {
        suggestion = "Crie uma música pedagógica alegre e animada sobre ";
      } else if (mode === 'VIDEO') {
        suggestion = "Crie um roteiro detalhado para um vídeo educativo sobre ";
      } else if (mode === 'IMAGE') {
        suggestion = "Crie uma ilustração pedagógica com cores vibrantes mostrando ";
      } else if (mode === 'POETRY') {
        suggestion = "Escreva uma poesia infantil rimada e educativa sobre ";
      } else if (mode === 'TEXT') {
        suggestion = "Escreva uma história educativa infantil curta sobre ";
      }
      
      userInput.value = suggestion + baseText;
      userInput.focus();
      
      // Mover cursor para o final do texto
      userInput.selectionStart = userInput.selectionEnd = userInput.value.length;
      
      // Ajustar altura do textarea para acomodar a sugestão
      userInput.style.height = 'auto';
      userInput.style.height = userInput.scrollHeight + 'px';
      if (btnSend) btnSend.disabled = false;
    });
  });

  // Sugestões de Prompt Rápidas
  suggestionCards.forEach(card => {
    card.addEventListener('click', () => {
      const prompt = card.dataset.prompt;
      if (prompt) {
        handleSendMessage(prompt);
      }
    });
  });

  // ==========================================================================
  // LOGOUT & INICIALIZAÇÃO
  // ==========================================================================

  btnLogout.addEventListener('click', async () => {
    try {
      const response = await fetch('/api/logout', {
        method: 'POST'
      });
      if (response.ok) {
        window.location.href = '/login';
      }
    } catch (error) {
      console.error('Erro ao fazer logout:', error);
    }
  });

  // Inicializar interface
  if (currentChatId) {
    // Tenta carregar o chat ativo
    const activeChat = chats.find(c => c.id === currentChatId);
    if (activeChat) {
      selectChat(currentChatId);
    } else {
      createNewChat();
    }
  } else {
    createNewChat();
  }

  // Inicializar reconhecimento de voz
  initVoiceRecognition();

  // ============================================================
  // SISTEMA DE OBSERVAÇÃO POR VOZ
  // ============================================================
  const recordModal = document.getElementById('recordModal');
  const fabRecord = document.getElementById('fabRecord');
  const btnExitRecord = document.getElementById('btnExitRecord');
  const btnStopRecord = document.getElementById('btnStopRecord');
  const recordStateRecording = document.getElementById('recordStateRecording');
  const recordStateProcessing = document.getElementById('recordStateProcessing');
  const recordStatePreview = document.getElementById('recordStatePreview');
  const recordTimer = document.getElementById('recordTimer');
  const reportContent = document.getElementById('reportContent');
  const previewDateTime = document.getElementById('previewDateTime');
  const btnDiscardReport = document.getElementById('btnDiscardReport');
  const btnSaveReport = document.getElementById('btnSaveReport');

  // Novos elementos de transcrição
  const recordStateTranscribed = document.getElementById('recordStateTranscribed');
  const transcriptionTextarea = document.getElementById('transcriptionTextarea');
  const btnDiscardTranscription = document.getElementById('btnDiscardTranscription');
  const btnAnalyzeTranscription = document.getElementById('btnAnalyzeTranscription');
  const recordProcessingText = document.getElementById('recordProcessingText');
  const recordProcessingSubtext = document.getElementById('recordProcessingSubtext');
// Variáveis de gravação
  let mediaRecorder = null;
  let audioChunks = [];
  let recordingStartTime = null;
  let timerInterval = null;
  let audioContext = null;
  let analyser = null;
  let frequencyData = null;
  let silenceFrames = 0;
  let totalFrames = 0;
  let vadCheckInterval = null;
  let generatedReport = null;
  let generatedCriancas = null;
  let generatedTurma = 'não informada';
  let generatedTags = [];

  // Fechar modal - colocada no topo para evitar problemas de inicialização
  function closeRecordModal() {
    if (mediaRecorder && mediaRecorder.state !== 'inactive') {
      try {
        mediaRecorder.stop();
      } catch (e) {}
      if (mediaRecorder.stream) {
        mediaRecorder.stream.getTracks().forEach(t => t.stop());
      }
    }
    clearInterval(timerInterval);
    clearInterval(vadCheckInterval);
    if (audioContext) { audioContext.close(); audioContext = null; }
    if (analyser) { analyser = null; frequencyData = null; }
    audioChunks = [];
    generatedReport = null;
    recordModal.style.display = 'none';
  }

  // Função para controlar a exibição dos estados
  function showRecordState(state) {
    recordStateRecording.style.display = 'none';
    recordStateProcessing.style.display = 'none';
    if (recordStateTranscribed) recordStateTranscribed.style.display = 'none';
    recordStatePreview.style.display = 'none';

    if (state === 'recording') {
      recordStateRecording.style.display = 'flex';
    } else if (state === 'processing') {
      recordStateProcessing.style.display = 'flex';
    } else if (state === 'transcribed') {
      if (recordStateTranscribed) recordStateTranscribed.style.display = 'flex';
    } else if (state === 'preview') {
      recordStatePreview.style.display = 'flex';
    }
  }

  // Abrir modal e iniciar gravação
  if (fabRecord) {
    fabRecord.addEventListener('click', async () => {
      audioChunks = [];
      generatedReport = null;

      // Mostra estado inicial (gravando)
      showRecordState('recording');
      recordModal.style.display = 'flex';

      // Inicia timer
      recordingStartTime = Date.now();
      timerInterval = setInterval(updateTimer, 1000);
      updateTimer();

      // Solicita permissão e inicia gravação
      try {
        const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
        let options = {};
        if (typeof MediaRecorder.isTypeSupported === 'function') {
          if (MediaRecorder.isTypeSupported('audio/webm;codecs=opus')) {
            options = { mimeType: 'audio/webm;codecs=opus' };
          } else if (MediaRecorder.isTypeSupported('audio/webm')) {
            options = { mimeType: 'audio/webm' };
          } else if (MediaRecorder.isTypeSupported('audio/ogg')) {
            options = { mimeType: 'audio/ogg' };
          } else if (MediaRecorder.isTypeSupported('audio/mp4')) {
            options = { mimeType: 'audio/mp4' };
          }
        }
        // Configurar AudioContext para VAD
        audioContext = new AudioContext();
        const source = audioContext.createMediaStreamSource(stream);
        analyser = audioContext.createAnalyser();
        analyser.fftSize = 256;
        source.connect(analyser);
        frequencyData = new Uint8Array(analyser.frequencyBinCount);

        // Iniciar verificação de silêncio (VAD)
        silenceFrames = 0;
        totalFrames = 0;
        vadCheckInterval = setInterval(() => {
          if (!analyser) return;
          analyser.getByteFrequencyData(frequencyData);
          const avg = frequencyData.reduce((a, b) => a + b, 0) / frequencyData.length;
          totalFrames++;
          if (avg < 10) {
            silenceFrames++;
          } else {
            silenceFrames = Math.max(0, silenceFrames - 2); // recupera mais rápido
          }
          // Atualizar indicator visual
          const recordWaveform = document.getElementById('recordWaveform');
          if (recordWaveform && recordWaveform.children[0]) {
            const bars = recordWaveform.children;
            bars.forEach((bar) => {
              const h = Math.max(4, (avg / 255) * 50 + Math.random() * 10);
              bar.style.height = `${h}px`;
            });
          }
          // Se mais de 60% dos últimos 30 frames for silêncio, avisar
          if (totalFrames > 30 && (silenceFrames / 30) > 0.6) {
            const btnStopRecord = document.getElementById('btnStopRecord');
            if (btnStopRecord && !btnStopRecord.disabled) {
              btnStopRecord.style.borderColor = '#ff6b6b';
              btnStopRecord.title = 'Silêncio detectado - Clique se quiser parar';
            }
          } else {
            const btnStopRecord = document.getElementById('btnStopRecord');
            if (btnStopRecord) {
              btnStopRecord.style.borderColor = '';
              btnStopRecord.title = '';
            }
          }
        }, 100);

        mediaRecorder = new MediaRecorder(stream, options);

        mediaRecorder.ondataavailable = (e) => {
          if (e.data.size > 0) audioChunks.push(e.data);
        };

        mediaRecorder.start(100); // chunk a cada 100ms
      } catch (err) {
        console.error('Erro ao acessar microfone:', err);
        alert('Não foi possível acessar o microfone. Verifique as permissões.');
        closeRecordModal();
      }
    });
  }

  // Atualizar timer
  function updateTimer() {
    if (!recordingStartTime) return;
    const elapsed = Math.floor((Date.now() - recordingStartTime) / 1000);
    const mins = Math.floor(elapsed / 60).toString().padStart(2, '0');
    const secs = (elapsed % 60).toString().padStart(2, '0');
    recordTimer.textContent = `${mins}:${secs}`;
  }

  // Parar gravação e transcrever
  if (btnStopRecord) {
    btnStopRecord.addEventListener('click', async () => {
      if (mediaRecorder && mediaRecorder.state !== 'inactive') {
        try {
          mediaRecorder.stop();
        } catch (e) {}
        if (mediaRecorder.stream) {
          mediaRecorder.stream.getTracks().forEach(t => t.stop());
        }
      }
      clearInterval(timerInterval);
      clearInterval(vadCheckInterval);
      if (audioContext) { audioContext.close(); audioContext = null; }
      if (analyser) { analyser = null; frequencyData = null; }

      // Mostra processando com texto de transcrição
      if (recordProcessingText) recordProcessingText.textContent = 'Transcrevendo áudio...';
      if (recordProcessingSubtext) recordProcessingSubtext.textContent = 'Aguarde a transcrição por Whisper';
      showRecordState('processing');

      // Envia áudio para servidor
      const blob = new Blob(audioChunks, { type: 'audio/webm' });
      const formData = new FormData();
      formData.append('audio', blob, 'recording.webm');

      try {
        const res = await fetch('/api/observacao/transcrever', {
          method: 'POST',
          body: formData
        });

        if (!res.ok) {
          const errData = await res.json();
          throw new Error(errData.error || 'Erro na transcrição');
        }

        const data = await res.json();
        
        // Exibe o texto transcrito na área de texto para edição
        if (transcriptionTextarea) {
          transcriptionTextarea.value = data.transcribedText || '';
        }
        
        showRecordState('transcribed');
      } catch (err) {
        console.error('Erro ao processar observação:', err);
        alert('Erro ao transcrever áudio: ' + err.message);
        closeRecordModal();
      }
    });
  }

  // Ação de analisar transcrição
  if (btnAnalyzeTranscription) {
    btnAnalyzeTranscription.addEventListener('click', async () => {
      const text = transcriptionTextarea ? transcriptionTextarea.value.trim() : '';
      if (!text || text.length < 5) {
        alert('Por favor, digite ou revise a transcrição (mínimo de 5 caracteres).');
        return;
      }

      // Mostra processando com texto de análise
      if (recordProcessingText) recordProcessingText.textContent = 'Analisando observação...';
      if (recordProcessingSubtext) recordProcessingSubtext.textContent = 'Gerando relatório pedagógico estruturado';
      showRecordState('processing');

      try {
        const turmaData = localStorage.getItem('camila_turma') || '[]';
        const res = await fetch('/api/observacao/analisar', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ transcribedText: text, turmaContext: JSON.parse(turmaData) })
        });

        if (!res.ok) {
          const errData = await res.json();
          throw new Error(errData.error || 'Erro na análise');
        }

        const data = await res.json();
        generatedReport = data.relatorio || data.report;
        generatedCriancas = data.criancas;
        generatedTurma = data.turma || 'não informada';
        generatedTags = data.tags || [];
        showReportPreview(data);
      } catch (err) {
        console.error('Erro ao analisar observação:', err);
        alert('Erro ao analisar observação: ' + err.message);
        showRecordState('transcribed');
      }
    });
  }

  // Ação de descartar transcrição
  if (btnDiscardTranscription) {
    btnDiscardTranscription.addEventListener('click', () => {
      closeRecordModal();
    });
  }

  // Mostrar prévia do relatório
  function showReportPreview(data) {
    showRecordState('preview');

    const now = new Date();
    previewDateTime.textContent = now.toLocaleString('pt-BR', {
      day: '2-digit', month: '2-digit', year: 'numeric',
      hour: '2-digit', minute: '2-digit'
    });

    // Monta HTML com metadados
    const criancasHtml = data.criancas && data.criancas.length
      ? `<div class="report-meta-item"><span class="meta-label">👧 Crianças:</span> ${data.criancas.join(', ')}</div>`
      : `<div class="report-meta-item"><span class="meta-label">👧 Crianças:</span> <em>não identificadas</em></div>`;
    const tagsHtml = data.tags && data.tags.length
      ? `<div class="report-meta-item"><span class="meta-label">🏷️ Tags:</span> ${data.tags.map(t => `<span class="tag-chip">${t}</span>`).join(' ')}</div>`
      : '';
    const turmaHtml = data.turma && data.turma !== 'não informada'
      ? `<div class="report-meta-item"><span class="meta-label">🏫 Turma:</span> ${data.turma}</div>`
      : '';

    reportContent.innerHTML = `
      <div class="report-meta">${criancasHtml}${turmaHtml}${tagsHtml}</div>
      <hr style="border-color: var(--border-light); margin: 12px 0;">
      ${marked.parse(generatedReport || 'Relatório não disponível.')}
    `;
    reportContent.querySelectorAll('pre code').forEach(b => hljs.highlightElement(b));
  }

  // Descartar relatório
  if (btnDiscardReport) {
    btnDiscardReport.addEventListener('click', () => {
      generatedReport = null;
      closeRecordModal();
    });
  }

  // Salvar relatório
  if (btnSaveReport) {
    btnSaveReport.addEventListener('click', async () => {
      if (!generatedReport) return;
      btnSaveReport.disabled = true;
      btnSaveReport.textContent = 'Salvando...';

      try {
        const res = await fetch('/api/observacao/salvar', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            report: generatedReport,
            criancas: generatedCriancas,
            turma: generatedTurma,
            tags: generatedTags
          })
        });
        const data = await res.json();
        if (data.success) {
          alert('Relatório salvo com sucesso!');
        } else {
          alert('Erro ao salvar: ' + (data.error || 'desconhecido'));
        }
      } catch (err) {
        console.error('Erro ao salvar:', err);
        alert('Erro ao salvar o relatório.');
      } finally {
        btnSaveReport.disabled = false;
        btnSaveReport.textContent = 'Salvar';
        closeRecordModal();
      }
    });
  }

  // Sair / descartar
  if (btnExitRecord) {
    btnExitRecord.addEventListener('click', closeRecordModal);
  }

  // Fechar clicando fora
  if (recordModal) {
    recordModal.addEventListener('click', (e) => {
      if (e.target === recordModal) closeRecordModal();
    });
  }

  // ============================================================
  // MODAL: MINHAS OBSERVAÇÕES
  // ============================================================
  const obsModal = document.getElementById('obsModal');
  const btnObservacoes = document.getElementById('btnObservacoes');
  const btnObsEspeciais = document.getElementById('btnObsEspeciais');
  const btnCloseObsModal = document.getElementById('btnCloseObsModal');
  const obsModalTitle = document.getElementById('obsModalTitle');
  const obsList = document.getElementById('obsList');
  const obsFilterMes = document.getElementById('obsFilterMes');
  const obsFilterTag = document.getElementById('obsFilterTag');
  const obsSearchCrianca = document.getElementById('obsSearchCrianca');

  let allObservations = [];
  let isSpecialObsMode = false;

  // Abrir modal de observações
  if (btnObservacoes) {
    btnObservacoes.addEventListener('click', async () => {
      isSpecialObsMode = false;
      if (obsModalTitle) obsModalTitle.textContent = '📒 Minhas Observações';
      obsModal.style.display = 'flex';
      obsList.innerHTML = '<div class="obs-empty">Carregando...</div>';

      try {
        const res = await fetch('/api/observacoes');
        const data = await res.json();
        allObservations = data.observations || [];
        populateMonthFilter();
        renderObsList();
      } catch (err) {
        console.error('Erro ao carregar observações:', err);
        obsList.innerHTML = '<div class="obs-empty">Erro ao carregar observações.</div>';
      }
    });
  }

  // Abrir modal de observações Especiais
  if (btnObsEspeciais) {
    btnObsEspeciais.addEventListener('click', async () => {
      isSpecialObsMode = true;
      if (obsModalTitle) obsModalTitle.textContent = '📒 Observações Educação Especial';
      obsModal.style.display = 'flex';
      obsList.innerHTML = '<div class="obs-empty">Carregando...</div>';

      try {
        const res = await fetch('/api/observacoes');
        const data = await res.json();
        allObservations = data.observations || [];
        populateMonthFilter();
        renderObsList();
      } catch (err) {
        console.error('Erro ao carregar observações:', err);
        obsList.innerHTML = '<div class="obs-empty">Erro ao carregar observações.</div>';
      }
    });
  }

  // Fechar modal
  if (btnCloseObsModal) {
    btnCloseObsModal.addEventListener('click', () => {
      obsModal.style.display = 'none';
    });
  }
  if (obsModal) {
    obsModal.addEventListener('click', (e) => {
      if (e.target === obsModal) obsModal.style.display = 'none';
    });
  }

  // Filtros
  if (obsFilterMes) obsFilterMes.addEventListener('change', renderObsList);
  if (obsFilterTag) obsFilterTag.addEventListener('change', renderObsList);
  if (obsSearchCrianca) obsSearchCrianca.addEventListener('input', renderObsList);

  // Preenche select de meses
  function populateMonthFilter() {
    if (!obsFilterMes) return;
    const months = [...new Set(allObservations.map(o => o.date?.slice(0, 7)))]
      .filter(Boolean).sort().reverse();
    obsFilterMes.innerHTML = '<option value="">Todos os meses</option>' +
      months.map(m => `<option value="${m}">${m.split('-')[1]}/${m.split('-')[0]}</option>`).join('');
  }

  // Renderiza lista filtrada
  function renderObsList() {
    if (!obsList) return;
    const mes = obsFilterMes?.value || '';
    const tag = obsFilterTag?.value || '';
    const search = obsSearchCrianca?.value.toLowerCase() || '';

    let especialKidsNames = [];
    if (isSpecialObsMode) {
      const turma = JSON.parse(localStorage.getItem('camila_turma') || '[]');
      especialKidsNames = turma.filter(c => c.especial).map(c => (c.nome || '').toLowerCase().trim()).filter(Boolean);
      if (especialKidsNames.length === 0) {
        obsList.innerHTML = '<div class="obs-empty">Nenhuma criança com "Educação Especial" cadastrada na Minha Turma.</div>';
        return;
      }
    }

    const filtered = allObservations.filter(o => {
      if (mes && !o.date?.startsWith(mes)) return false;
      if (tag && !o.tags?.includes(tag)) return false;
      
      const nomes = (o.criancas || []).join(' ').toLowerCase();
      
      if (isSpecialObsMode) {
        // Must contain at least one special kid's name
        const preview = (o.preview || '').toLowerCase();
        const isEspecial = especialKidsNames.some(ekn => nomes.includes(ekn) || preview.includes(ekn));
        if (!isEspecial) return false;
      }

      if (search) {
        if (!nomes.includes(search) && !(o.preview || '').toLowerCase().includes(search)) return false;
      }
      return true;
    });

    if (filtered.length === 0) {
      obsList.innerHTML = '<div class="obs-empty">Nenhuma observação encontrada.</div>';
      return;
    }

    obsList.innerHTML = filtered.map(o => {
      const tagsHtml = (o.tags || []).map(t => `<span class="obs-tag">${t}</span>`).join('');
      const criancasHtml = (o.criancas || []).map(c => `<span class="obs-crianca">${c}</span>`).join('');
      const dateFormatted = o.date ? o.date.split('-').reverse().join('/') : '';
      return `
        <div class="obs-item" data-filename="${o.filename}" data-yearmonth="${o.date?.slice(0, 7)}">
          <div class="obs-item-header">
            <strong>📋 ${dateFormatted}${o.time ? ' às ' + o.time : ''}</strong>
            ${o.turma && o.turma !== 'não informada' ? `<span class="obs-crianca">🏫 ${o.turma}</span>` : ''}
          </div>
          <div class="obs-item-preview">${o.preview || 'Sem prévia disponível.'}</div>
          <div class="obs-item-footer">${tagsHtml}${criancasHtml}</div>
        </div>
      `;
    }).join('');

    // Click para abrir observação
    obsList.querySelectorAll('.obs-item').forEach(item => {
      item.addEventListener('click', async () => {
        const ym = item.dataset.yearmonth;
        const fn = item.dataset.filename;
        if (!ym || !fn) return;
        try {
          const res = await fetch(`/api/observacoes/${ym}/${fn}`);
          const text = await res.text();
          showObsDetail(text);
        } catch (err) {
          console.error('Erro ao carregar observação:', err);
        }
      });
    });
  };

  // ============================================================
  // MODAL: MINHA TURMA
  // ============================================================
  const minhaTurmaModal = document.getElementById('minhaTurmaModal');
  const btnMinhaTurma = document.getElementById('btnMinhaTurma');
  const btnCloseMinhaTurmaModal = document.getElementById('btnCloseMinhaTurmaModal');
  const childrenList = document.getElementById('childrenList');
  const btnCreateChild = document.getElementById('btnCreateChild');
  const btnCancelChild = document.getElementById('btnCancelChild');
  const btnSaveChild = document.getElementById('btnSaveChild');
  const childFormTitle = document.getElementById('childFormTitle');

  // Fields
  const cFormId = document.getElementById('childFormId');
  const cFormTurma = document.getElementById('childFormTurma');
  const cFormSala = document.getElementById('childFormSala');
  const cFormPeriodo = document.getElementById('childFormPeriodo');
  const cFormAuxiliares = document.getElementById('childFormAuxiliares');
  const cFormNome = document.getElementById('childFormNome');
  const cFormApelido = document.getElementById('childFormApelido');
  const cFormDataNasc = document.getElementById('childFormDataNasc');
  const cFormEspecial = document.getElementById('childFormEspecial');
  const divEspecialDetalhes = document.getElementById('divEspecialDetalhes');
  const cFormEspecialDetalhes = document.getElementById('childFormEspecialDetalhes');
  const cFormPais = document.getElementById('childFormPais');
  const cFormAutorizados = document.getElementById('childFormAutorizados');

  // Toggle Especial Fields
  if (cFormEspecial) {
    cFormEspecial.addEventListener('change', () => {
      if (cFormEspecial.checked) {
        divEspecialDetalhes.style.display = 'flex';
      } else {
        divEspecialDetalhes.style.display = 'none';
      }
    });
  }

  const loadTurma = () => {
    return JSON.parse(localStorage.getItem('camila_turma') || '[]');
  };

  const saveTurma = (turma) => {
    localStorage.setItem('camila_turma', JSON.stringify(turma));
  };

  const renderTurmaList = () => {
    if (!childrenList) return;
    const turma = loadTurma();
    if (turma.length === 0) {
      childrenList.innerHTML = '<div style="color: var(--text-secondary); text-align: center; padding: 20px;">Nenhuma criança cadastrada.</div>';
      return;
    }
    
    // Sort by name
    turma.sort((a, b) => (a.nome || '').localeCompare(b.nome || ''));

    childrenList.innerHTML = turma.map(c => `
      <div style="background: var(--bg-secondary); border: 1px solid var(--border-light); padding: 12px; border-radius: 8px; display: flex; justify-content: space-between; align-items: center;">
        <div>
          <div style="font-weight: 600; color: var(--text-primary);">${escapeHtml(c.nome)} ${c.especial ? '⭐' : ''}</div>
          <div style="font-size: 0.8rem; color: var(--text-secondary);">${escapeHtml(c.turma || '')} - ${escapeHtml(c.periodo || '')}</div>
        </div>
        <div style="display: flex; gap: 8px;">
          <button onclick="editChild('${c.id}')" style="background: none; border: none; color: var(--text-secondary); cursor: pointer; padding: 4px;" title="Editar">✏️</button>
          <button onclick="deleteChild('${c.id}')" style="background: none; border: none; color: #ef4444; cursor: pointer; padding: 4px;" title="Excluir">🗑️</button>
        </div>
      </div>
    `).join('');
  };

  const clearChildForm = () => {
    cFormId.value = '';
    cFormTurma.value = '';
    cFormSala.value = '';
    cFormPeriodo.value = 'Integral';
    cFormAuxiliares.value = '';
    cFormNome.value = '';
    cFormApelido.value = '';
    cFormDataNasc.value = '';
    cFormEspecial.checked = false;
    cFormEspecialDetalhes.value = '';
    divEspecialDetalhes.style.display = 'none';
    cFormPais.value = '';
    cFormAutorizados.value = '';
    childFormTitle.textContent = 'Cadastrar Criança';
  };

  window.editChild = (id) => {
    const turma = loadTurma();
    const c = turma.find(x => x.id === id);
    if (!c) return;
    
    cFormId.value = c.id;
    cFormTurma.value = c.turma || '';
    cFormSala.value = c.sala || '';
    cFormPeriodo.value = c.periodo || 'Integral';
    cFormAuxiliares.value = c.auxiliares || '';
    cFormNome.value = c.nome || '';
    cFormApelido.value = c.apelido || '';
    cFormDataNasc.value = c.dataNasc || '';
    cFormEspecial.checked = !!c.especial;
    cFormEspecialDetalhes.value = c.especialDetalhes || '';
    divEspecialDetalhes.style.display = c.especial ? 'flex' : 'none';
    cFormPais.value = c.pais || '';
    cFormAutorizados.value = c.autorizados || '';
    
    childFormTitle.textContent = 'Editar Criança';
  };

  window.deleteChild = async (id) => {
    const isOk = await showCustomConfirm('Excluir', 'Deseja excluir esta criança? Isso não removerá as observações já feitas, apenas removerá da lista da turma.', true);
    if (isOk) {
      let turma = loadTurma();
      turma = turma.filter(x => x.id !== id);
      saveTurma(turma);
      renderTurmaList();
      clearChildForm();
    }
  };

  if (btnMinhaTurma) {
    btnMinhaTurma.addEventListener('click', () => {
      minhaTurmaModal.style.display = 'flex';
      renderTurmaList();
      clearChildForm();
    });
  }

  if (btnCloseMinhaTurmaModal) btnCloseMinhaTurmaModal.addEventListener('click', () => minhaTurmaModal.style.display = 'none');
  if (minhaTurmaModal) {
    minhaTurmaModal.addEventListener('click', (e) => {
      if (e.target === minhaTurmaModal) minhaTurmaModal.style.display = 'none';
    });
  }

  if (btnCreateChild) btnCreateChild.addEventListener('click', clearChildForm);
  if (btnCancelChild) btnCancelChild.addEventListener('click', clearChildForm);

  if (btnSaveChild) {
    btnSaveChild.addEventListener('click', () => {
      if (!cFormNome.value.trim()) {
        showCustomAlert('Aviso', 'O Nome Completo é obrigatório.');
        return;
      }
      
      let turma = loadTurma();
      const id = cFormId.value || 'child_' + Date.now();
      
      const newChild = {
        id,
        turma: cFormTurma.value.trim(),
        sala: cFormSala.value.trim(),
        periodo: cFormPeriodo.value,
        auxiliares: cFormAuxiliares.value.trim(),
        nome: cFormNome.value.trim(),
        apelido: cFormApelido.value.trim(),
        dataNasc: cFormDataNasc.value,
        especial: cFormEspecial.checked,
        especialDetalhes: cFormEspecialDetalhes.value.trim(),
        pais: cFormPais.value.trim(),
        autorizados: cFormAutorizados.value.trim()
      };

      const idx = turma.findIndex(x => x.id === id);
      if (idx > -1) {
        turma[idx] = newChild;
      } else {
        turma.push(newChild);
      }
      
      saveTurma(turma);
      renderTurmaList();
      clearChildForm();
    });
  }

  // Preencher com Voz
  const btnVoiceRecordChild = document.getElementById('btnVoiceRecordChild');
  if (btnVoiceRecordChild && window.SpeechRecognition || window.webkitSpeechRecognition) {
    const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
    const formRecognition = new SpeechRecognition();
    formRecognition.lang = 'pt-BR';
    formRecognition.continuous = false;
    formRecognition.interimResults = false;

    formRecognition.onstart = () => {
      btnVoiceRecordChild.innerHTML = '🛑 Gravando... (Clique para parar)';
      btnVoiceRecordChild.style.background = 'rgba(239, 68, 68, 0.1)';
      btnVoiceRecordChild.style.color = '#ef4444';
      btnVoiceRecordChild.style.borderColor = '#ef4444';
    };

    formRecognition.onresult = async (event) => {
      const transcript = event.results[0][0].transcript;
      btnVoiceRecordChild.innerHTML = '⏳ Processando com IA...';
      
      try {
        const response = await fetch('/api/chat', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            messages: [{
              role: 'user', 
              content: `A professora ditou as seguintes informações para cadastrar uma criança na turma: "${transcript}". 
Por favor, extraia os dados e retorne APENAS um JSON válido com os seguintes campos:
"turma", "sala", "periodo", "auxiliares", "nome", "apelido", "dataNasc" (formato YYYY-MM-DD), "especial" (boolean), "especialDetalhes", "pais", "autorizados". 
Se algum dado não for mencionado, deixe a string vazia ou false para boolean.`
            }],
            temperature: 0.1
          })
        });
        
        if (response.ok) {
          const data = await response.json();
          const assistantReply = data.message;
          // Extract JSON block
          const match = assistantReply.match(/```json\n([\s\S]*?)\n```/) || assistantReply.match(/\{[\s\S]*\}/);
          if (match) {
            const parsed = JSON.parse(match[1] || match[0]);
            if (parsed.turma) cFormTurma.value = parsed.turma;
            if (parsed.sala) cFormSala.value = parsed.sala;
            if (parsed.periodo) cFormPeriodo.value = parsed.periodo;
            if (parsed.auxiliares) cFormAuxiliares.value = parsed.auxiliares;
            if (parsed.nome) cFormNome.value = parsed.nome;
            if (parsed.apelido) cFormApelido.value = parsed.apelido;
            if (parsed.dataNasc) cFormDataNasc.value = parsed.dataNasc;
            if (parsed.especial) cFormEspecial.checked = parsed.especial;
            divEspecialDetalhes.style.display = cFormEspecial.checked ? 'flex' : 'none';
            if (parsed.especialDetalhes) cFormEspecialDetalhes.value = parsed.especialDetalhes;
            if (parsed.pais) cFormPais.value = parsed.pais;
            if (parsed.autorizados) cFormAutorizados.value = parsed.autorizados;
          }
        }
      } catch (err) {
        console.error('Erro ao processar voz:', err);
        showCustomAlert('Erro', 'Não foi possível extrair os dados. Tente novamente ou preencha manualmente.');
      }
    };

    formRecognition.onend = () => {
      btnVoiceRecordChild.innerHTML = '🎤 Preencher com Voz';
      btnVoiceRecordChild.style.background = 'rgba(16, 163, 127, 0.1)';
      btnVoiceRecordChild.style.color = 'var(--brand-green)';
      btnVoiceRecordChild.style.borderColor = 'var(--brand-green)';
    };

    btnVoiceRecordChild.addEventListener('click', () => {
      if (btnVoiceRecordChild.innerHTML.includes('Gravando')) {
        formRecognition.stop();
      } else {
        formRecognition.start();
      }
    });
  }

  // Mostra detalhe da observação em modal
  const showObsDetail = (mdText) => {
    const modal = document.createElement('div');
    modal.className = 'settings-modal';
    modal.style.display = 'flex';
    modal.innerHTML = `
      <div class="settings-modal-content obs-modal-content" style="max-width: 680px;">
        <div class="settings-modal-header">
          <h3>📋 Observação</h3>
          <button class="btn-close-modal" onclick="this.closest('.settings-modal').remove()">
            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
              <path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
            </svg>
          </button>
        </div>
        <div style="padding: 20px; overflow-y: auto; max-height: 70vh;">
          <div class="obs-detail-content" style="color: var(--text-primary); line-height: 1.6;">
            ${marked.parse(mdText.replace(/^---[\s\S]*?---\n/, ''))}
          </div>
          <div style="margin-top: 16px; display: flex; gap: 8px;">
            <button class="btn-save-report" onclick="navigator.clipboard.writeText(this.closest('.settings-modal').querySelector('.obs-detail-content').innerText).then(()=>alert('Copiado!'))">Copiar Texto</button>
            <button class="btn-discard" onclick="this.closest('.settings-modal').remove()">Fechar</button>
          </div>
        </div>
      </div>
    `;
    document.body.appendChild(modal);
    modal.addEventListener('click', (e) => {
      if (e.target === modal) modal.remove();
    });
  };

  // ============================================================
  // CRUD DE MODELOS DE RELATÓRIO
  // ============================================================
  const modelosRelatorioModal = document.getElementById('modelosRelatorioModal');
  const btnModelosRelatorio = document.getElementById('btnModelosRelatorio');
  const btnCloseModelosModal = document.getElementById('btnCloseModelosModal');
  const templatesList = document.getElementById('templatesList');
  const btnCreateTemplate = document.getElementById('btnCreateTemplate');
  const btnCancelTemplate = document.getElementById('btnCancelTemplate');
  const btnSaveTemplate = document.getElementById('btnSaveTemplate');
  
  const templateFormId = document.getElementById('templateFormId');
  const templateFormNome = document.getElementById('templateFormNome');
  const templateFormFinalidade = document.getElementById('templateFormFinalidade');
  const templateFormPeriodicidade = document.getElementById('templateFormPeriodicidade');
  const templateFormEstrutura = document.getElementById('templateFormEstrutura');
  const templateFormTitle = document.getElementById('templateFormTitle');

  let allTemplates = [];

  // Abrir modal de modelos
  if (btnModelosRelatorio) {
    btnModelosRelatorio.addEventListener('click', async () => {
      modelosRelatorioModal.style.display = 'flex';
      clearTemplateForm();
      await fetchTemplates();
    });
  }

  // Fechar modal de modelos
  if (btnCloseModelosModal) {
    btnCloseModelosModal.addEventListener('click', () => {
      modelosRelatorioModal.style.display = 'none';
    });
  }
  if (modelosRelatorioModal) {
    modelosRelatorioModal.addEventListener('click', (e) => {
      if (e.target === modelosRelatorioModal) modelosRelatorioModal.style.display = 'none';
    });
  }

  // Buscar modelos do backend
  async function fetchTemplates() {
    templatesList.innerHTML = '<div style="color: var(--text-secondary); text-align: center; padding: 20px;">Carregando...</div>';
    try {
      const res = await fetch('/api/modelos');
      allTemplates = await res.json();
      renderTemplatesList();
    } catch (err) {
      console.error('Erro ao buscar modelos:', err);
      templatesList.innerHTML = '<div style="color: #ff6b6b; text-align: center; padding: 20px;">Erro ao carregar modelos.</div>';
    }
  }

  // Renderizar a lista de modelos na esquerda
  function renderTemplatesList() {
    if (allTemplates.length === 0) {
      templatesList.innerHTML = '<div style="color: var(--text-secondary); text-align: center; padding: 20px;">Nenhum modelo cadastrado.</div>';
      return;
    }
    templatesList.innerHTML = allTemplates.map(t => `
      <div class="obs-item" style="padding: 10px; margin: 0 0 8px 0; cursor: pointer; border-left: 3px solid var(--brand-green); display: flex; flex-direction: column; gap: 4px; background: var(--bg-secondary); border-radius: 8px;" data-id="${t.id}">
        <div style="font-weight: 600; color: var(--text-primary); font-size: 0.9rem;">${t.nome}</div>
        <div style="font-size: 0.75rem; color: var(--text-secondary);">${t.periodicidade} • ${t.finalidade || 'Sem finalidade'}</div>
        <div style="display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px;">
          <button class="template-duplicate-btn" data-id="${t.id}" style="background: none; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 2px 8px; border-radius: 4px; font-size: 0.72rem; cursor: pointer; transition: opacity 0.2s;">Duplicar</button>
          <button class="template-edit-btn" data-id="${t.id}" style="background: none; border: 1px solid var(--border-light); color: var(--brand-green); padding: 2px 8px; border-radius: 4px; font-size: 0.72rem; cursor: pointer;">Editar</button>
          <button class="template-delete-btn" data-id="${t.id}" style="background: none; border: 1px solid var(--border-light); color: #ff6b6b; padding: 2px 8px; border-radius: 4px; font-size: 0.72rem; cursor: pointer;">Excluir</button>
        </div>
      </div>
    `).join('');

    // Eventos de clique na lista para editar/deletar/duplicar
    templatesList.querySelectorAll('.obs-item').forEach(item => {
      item.addEventListener('click', (e) => {
        if (e.target.tagName === 'BUTTON') return;
        const id = item.dataset.id;
        const template = allTemplates.find(t => t.id == id);
        if (template) fillTemplateForm(template);
      });
    });

    templatesList.querySelectorAll('.template-duplicate-btn').forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.stopPropagation();
        const id = btn.dataset.id;
        const template = allTemplates.find(t => t.id == id);
        if (template) {
          fillTemplateForm(template);
          templateFormId.value = '';
          templateFormNome.value = template.nome + ' (Cópia)';
          templateFormTitle.textContent = 'Duplicar Modelo';
          if (templateFormNome) templateFormNome.focus();
        }
      });
    });

    templatesList.querySelectorAll('.template-edit-btn').forEach(btn => {
      btn.addEventListener('click', (e) => {
        e.stopPropagation();
        const id = btn.dataset.id;
        const template = allTemplates.find(t => t.id == id);
        if (template) fillTemplateForm(template);
      });
    });

    templatesList.querySelectorAll('.template-delete-btn').forEach(btn => {
      btn.addEventListener('click', async (e) => {
        e.stopPropagation();
        const id = btn.dataset.id;
        const template = allTemplates.find(t => t.id == id);
        if (!template) return;
        if (confirm(`Tem certeza que deseja excluir o modelo "${template.nome}"?`)) {
          try {
            const res = await fetch(`/api/modelos/${id}`, { method: 'DELETE' });
            if (res.ok) {
              alert('Modelo excluído com sucesso!');
              clearTemplateForm();
              await fetchTemplates();
            } else {
              const err = await res.json();
              alert('Erro ao excluir: ' + err.error);
            }
          } catch (err) {
            console.error('Erro ao excluir modelo:', err);
          }
        }
      });
    });
  }

  // Preencher formulário de edição
  function fillTemplateForm(template) {
    templateFormId.value = template.id;
    templateFormNome.value = template.nome;
    templateFormFinalidade.value = template.finalidade || '';
    templateFormPeriodicidade.value = template.periodicidade || 'Semanal';
    templateFormEstrutura.value = template.estrutura || '';
    templateFormTitle.textContent = 'Editar Modelo';
  }

  // Limpar formulário
  function clearTemplateForm() {
    templateFormId.value = '';
    templateFormNome.value = '';
    templateFormFinalidade.value = '';
    templateFormPeriodicidade.value = 'Semanal';
    templateFormEstrutura.value = '';
    templateFormTitle.textContent = 'Novo Modelo';
  }

  // Botão "Novo Modelo"
  if (btnCreateTemplate) {
    btnCreateTemplate.addEventListener('click', clearTemplateForm);
  }

  // Botão "Cancelar"
  if (btnCancelTemplate) {
    btnCancelTemplate.addEventListener('click', () => {
      clearTemplateForm();
      if (modelosRelatorioModal) modelosRelatorioModal.style.display = 'none';
    });
  }

  // Botão "Salvar Modelo"
  if (btnSaveTemplate) {
    btnSaveTemplate.addEventListener('click', async () => {
      const id = templateFormId.value;
      const nome = templateFormNome.value.trim();
      const finalidade = templateFormFinalidade.value.trim();
      const periodicidade = templateFormPeriodicidade.value;
      const estrutura = templateFormEstrutura.value.trim();

      if (!nome || !estrutura) {
        alert('Nome e estrutura do modelo são obrigatórios.');
        return;
      }

      const body = { nome, finalidade, periodicidade, estrutura };
      const url = id ? `/api/modelos/${id}` : '/api/modelos';
      const method = id ? 'PUT' : 'POST';

      try {
        const res = await fetch(url, {
          method,
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(body)
        });
        if (res.ok) {
          alert('Modelo salvo com sucesso!');
          clearTemplateForm();
          await fetchTemplates();
        } else {
          const err = await res.json();
          alert('Erro ao salvar modelo: ' + err.error);
        }
      } catch (err) {
        console.error('Erro ao salvar modelo:', err);
      }
    });
  }

  // ============================================================
  // GERAÇÃO / EMISSÃO DE RELATÓRIO PEDAGÓGICO
  // ============================================================
  const emitirRelatorioModal = document.getElementById('emitirRelatorioModal');
  const btnEmitirRelatorio = document.getElementById('btnEmitirRelatorio');
  const btnCloseEmitirModal = document.getElementById('btnCloseEmitirModal');
  
  const emitirFilterAno = document.getElementById('emitirFilterAno');
  const emitirFilterTurma = document.getElementById('emitirFilterTurma');
  const emitirFilterCrianca = document.getElementById('emitirFilterCrianca');
  const emitirFilterDataInicio = document.getElementById('emitirFilterDataInicio');
  const emitirFilterDataFim = document.getElementById('emitirFilterDataFim');
  const emitirTagsContainer = document.getElementById('emitirTagsContainer');
  const emitirFilterTemplate = document.getElementById('emitirFilterTemplate');
  let emitirSelectedTags = [];
  
  const emitirObsCountInfo = document.getElementById('emitirObsCountInfo');
  const btnGenerateCompiledReport = document.getElementById('btnGenerateCompiledReport');
  const emitirReportPreviewArea = document.getElementById('emitirReportPreviewArea');
  
  const btnExportDocx = document.getElementById('btnExportDocx');
  const btnExportPdf = document.getElementById('btnExportPdf');

  let activeCompiledReport = null; // Guarda o texto do relatório compilado ativo

  // Abrir modal de emissão
  if (btnEmitirRelatorio) {
    btnEmitirRelatorio.addEventListener('click', async () => {
      emitirRelatorioModal.style.display = 'flex';
      activeCompiledReport = null;
      emitirReportPreviewArea.innerHTML = `
        <div style="color: var(--text-secondary); text-align: center; margin-top: 50px;">
          Escolha uma criança e um modelo de relatório para começar.
        </div>
      `;
      btnExportDocx.disabled = true;
      btnExportDocx.style.cursor = 'not-allowed';
      btnExportDocx.style.borderColor = 'var(--border-light)';
      btnExportDocx.style.color = 'var(--text-secondary)';
      
      btnExportPdf.disabled = true;
      btnExportPdf.style.cursor = 'not-allowed';
      btnExportPdf.style.borderColor = 'var(--border-light)';
      btnExportPdf.style.color = 'var(--text-secondary)';
      
      emitirFilterDataInicio.value = '';
      emitirFilterDataFim.value = '';
      
      emitirSelectedTags = [];
      if (emitirTagsContainer) {
        emitirTagsContainer.querySelectorAll('.tag-pill').forEach(p => p.classList.remove('active'));
      }
      
      await loadFiltersData();
    });
  }

  // Fechar modal de emissão
  if (btnCloseEmitirModal) {
    btnCloseEmitirModal.addEventListener('click', () => {
      emitirRelatorioModal.style.display = 'none';
    });
  }
  if (emitirRelatorioModal) {
    emitirRelatorioModal.addEventListener('click', (e) => {
      if (e.target === emitirRelatorioModal) emitirRelatorioModal.style.display = 'none';
    });
  }

  // Buscar crianças com base nos filtros de Ano e Turma selecionados
  async function loadChildrenList() {
    try {
      const activeAno = emitirFilterAno ? emitirFilterAno.value : '';
      const activeTurma = emitirFilterTurma ? emitirFilterTurma.value : '';
      const activeCrianca = emitirFilterCrianca ? emitirFilterCrianca.value : '';
      
      let url = '/api/observacoes/criancas';
      const params = [];
      if (activeAno) params.push(`ano=${activeAno}`);
      if (activeTurma) params.push(`turma=${encodeURIComponent(activeTurma)}`);
      if (params.length > 0) url += '?' + params.join('&');
      
      const res = await fetch(url);
      const criancas = await res.json();
      emitirFilterCrianca.innerHTML = '<option value="">Selecione a criança</option>' +
        `<option value="todas" ${activeCrianca === 'todas' ? 'selected' : ''}>Todas as crianças (Relatório Global)</option>` +
        (Array.isArray(criancas) ? criancas : []).map(c => `<option value="${c}" ${c === activeCrianca ? 'selected' : ''}>${c}</option>`).join('');
    } catch (err) {
      console.error('Erro ao carregar lista de crianças:', err);
    }
  }

  // Carregar dados de filtros (anos, turmas, crianças e templates)
  async function loadFiltersData() {
    try {
      const activeAno = emitirFilterAno ? emitirFilterAno.value : '';
      const activeTurma = emitirFilterTurma ? emitirFilterTurma.value : '';
      
      const res = await fetch('/api/observacoes/metadata');
      const meta = await res.json();
      
      if (emitirFilterAno) {
        emitirFilterAno.innerHTML = '<option value="">Todos os anos</option>' +
          (meta.anos || []).map(y => `<option value="${y}" ${y === activeAno ? 'selected' : ''}>${y}</option>`).join('');
      }
      if (emitirFilterTurma) {
        emitirFilterTurma.innerHTML = '<option value="">Todas as turmas</option>' +
          (meta.turmas || []).map(t => `<option value="${t}" ${t === activeTurma ? 'selected' : ''}>${t}</option>`).join('');
      }
    } catch (err) {
      console.error('Erro ao buscar metadados de filtros:', err);
    }

    await loadChildrenList();

    try {
      const activeTemplate = emitirFilterTemplate ? emitirFilterTemplate.value : '';
      const res = await fetch('/api/modelos');
      const modelos = await res.json();
      emitirFilterTemplate.innerHTML = '<option value="">Selecione o modelo</option>' +
        (Array.isArray(modelos) ? modelos : []).map(m => `<option value="${m.id}" ${m.id == activeTemplate ? 'selected' : ''}>${m.nome}</option>`).join('');
    } catch (err) {
      console.error('Erro ao buscar modelos para filtros:', err);
    }

    updateObservationsCount();
  }

  // Ouvintes para atualizar contagem e filtros de criança
  if (emitirFilterAno) {
    emitirFilterAno.addEventListener('change', async () => {
      await loadChildrenList();
      updateObservationsCount();
    });
  }
  if (emitirFilterTurma) {
    emitirFilterTurma.addEventListener('change', async () => {
      await loadChildrenList();
      updateObservationsCount();
    });
  }

  [emitirFilterCrianca, emitirFilterDataInicio, emitirFilterDataFim, emitirFilterTemplate].forEach(el => {
    if (el) el.addEventListener('change', updateObservationsCount);
  });
  if (emitirFilterCrianca) {
    emitirFilterCrianca.addEventListener('input', updateObservationsCount);
  }

  // Adicionar ouvintes para as pills de tags
  if (emitirTagsContainer) {
    emitirTagsContainer.querySelectorAll('.tag-pill').forEach(pill => {
      pill.addEventListener('click', () => {
        const tag = pill.getAttribute('data-tag');
        if (pill.classList.contains('active')) {
          pill.classList.remove('active');
          emitirSelectedTags = emitirSelectedTags.filter(t => t !== tag);
        } else {
          pill.classList.add('active');
          emitirSelectedTags.push(tag);
        }
        updateObservationsCount();
      });
    });
  }

  // Recalcular quantidade de observações elegíveis
  async function updateObservationsCount() {
    const crianca = emitirFilterCrianca ? emitirFilterCrianca.value : '';
    const dataInicio = emitirFilterDataInicio ? emitirFilterDataInicio.value : '';
    const dataFim = emitirFilterDataFim ? emitirFilterDataFim.value : '';
    const tag = emitirSelectedTags.join(',');
    const modeloId = emitirFilterTemplate ? emitirFilterTemplate.value : '';
    const ano = emitirFilterAno ? emitirFilterAno.value : '';
    const turma = emitirFilterTurma ? emitirFilterTurma.value : '';

    if (!crianca || !modeloId) {
      emitirObsCountInfo.textContent = 'Escolha uma criança (ou "Todas") e um modelo para prosseguir.';
      btnGenerateCompiledReport.disabled = true;
      btnGenerateCompiledReport.style.opacity = '0.6';
      btnGenerateCompiledReport.style.cursor = 'not-allowed';
      return;
    }

    try {
      let url = `/api/observacoes/contar?crianca=${encodeURIComponent(crianca)}`;
      if (dataInicio) url += `&dataInicio=${dataInicio}`;
      if (dataFim) url += `&dataFim=${dataFim}`;
      if (tag) url += `&tags=${encodeURIComponent(tag)}`;
      if (ano) url += `&ano=${ano}`;
      if (turma) url += `&turma=${encodeURIComponent(turma)}`;

      const res = await fetch(url);
      const data = await res.json();
      const count = data.count || 0;

      if (count === 0) {
        emitirObsCountInfo.innerHTML = `⚠️ <span style="color: #ff6b6b; font-weight: 600;">Nenhuma observação</span> encontrada para esses filtros.`;
        btnGenerateCompiledReport.disabled = true;
        btnGenerateCompiledReport.style.opacity = '0.6';
        btnGenerateCompiledReport.style.cursor = 'not-allowed';
      } else {
        emitirObsCountInfo.innerHTML = `✨ <strong>${count}</strong> observações selecionadas para compilação.`;
        btnGenerateCompiledReport.disabled = false;
        btnGenerateCompiledReport.style.opacity = '1';
        btnGenerateCompiledReport.style.cursor = 'pointer';
      }
    } catch (err) {
      console.error('Erro ao contar observações:', err);
    }
  }

  // Gerar relatório consolidado com IA
  if (btnGenerateCompiledReport) {
    btnGenerateCompiledReport.addEventListener('click', async () => {
      const crianca = emitirFilterCrianca.value;
      const dataInicio = emitirFilterDataInicio.value;
      const dataFim = emitirFilterDataFim.value;
      const tags = emitirSelectedTags;
      const modeloId = emitirFilterTemplate.value;
      const ano = emitirFilterAno ? emitirFilterAno.value : '';
      const turma = emitirFilterTurma ? emitirFilterTurma.value : '';

      if (!crianca || !modeloId) return;

      emitirReportPreviewArea.innerHTML = `
        <div style="display: flex; flex-direction: column; align-items: center; justify-content: center; height: 100%; gap: 12px; margin-top: 50px;">
          <div style="width: 32px; height: 32px; border: 3px solid var(--border-light); border-top-color: var(--brand-green); border-radius: 50%; animation: spin 1s linear infinite;"></div>
          <div style="color: var(--text-secondary); font-size: 0.9rem; font-weight: 500;">Analisando observações e gerando relatório pedagógico...</div>
        </div>
      `;
      btnGenerateCompiledReport.disabled = true;
      btnGenerateCompiledReport.style.opacity = '0.6';

      try {
        const res = await fetch('/api/modelos/gerar-relatorio', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            crianca,
            dataInicio,
            dataFim,
            tags: tags.length > 0 ? tags : undefined,
            modeloId,
            ano,
            turma
          })
        });

        if (!res.ok) {
          const errData = await res.json();
          throw new Error(errData.error || 'Erro desconhecido');
        }

        const data = await res.json();
        activeCompiledReport = data;

        // Renderizar prévia do relatório em markdown
        emitirReportPreviewArea.innerHTML = `
          <div style="background: var(--bg-primary); padding: 12px; border-radius: 8px; margin-bottom: 16px; border: 1px solid var(--border-light); font-size: 0.85rem;">
            <div><strong>Estudante:</strong> ${data.crianca}</div>
            <div><strong>Período:</strong> ${data.periodo}</div>
            <div><strong>Modelo Aplicado:</strong> ${data.templateNome}</div>
            <div><strong>Quantidade de Observações Consolidadas:</strong> ${data.totalObservacoes}</div>
          </div>
          <div class="report-content-body" style="color: var(--text-primary);">
            ${marked.parse(data.report)}
          </div>
        `;

        // Ativar botões de exportação
        btnExportDocx.disabled = false;
        btnExportDocx.style.cursor = 'pointer';
        btnExportDocx.style.borderColor = 'var(--brand-green)';
        btnExportDocx.style.color = 'var(--brand-green)';
        
        btnExportPdf.disabled = false;
        btnExportPdf.style.cursor = 'pointer';
        btnExportPdf.style.borderColor = 'var(--brand-green)';
        btnExportPdf.style.color = 'var(--brand-green)';

        // Rolar suavemente até o relatório no mobile
        if (window.innerWidth <= 768) {
          const modalBody = emitirRelatorioModal.querySelector('.settings-modal-body');
          if (modalBody) {
            setTimeout(() => {
              modalBody.scrollTo({
                top: modalBody.scrollHeight,
                behavior: 'smooth'
              });
            }, 150);
          }
        }

      } catch (err) {
        console.error('Erro ao gerar relatório compilado:', err);
        emitirReportPreviewArea.innerHTML = `
          <div style="color: #ff6b6b; text-align: center; margin-top: 50px; font-weight: 500;">
            Erro ao gerar relatório: ${err.message}
          </div>
        `;
      } finally {
        btnGenerateCompiledReport.disabled = false;
        btnGenerateCompiledReport.style.opacity = '1';
      }
    });
  }

  // Exportar para DOCX (Formato HTML-DOCX)
  if (btnExportDocx) {
    btnExportDocx.addEventListener('click', () => {
      if (!activeCompiledReport) return;

      const htmlContent = `
        <html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:office:word" xmlns="http://www.w3.org/TR/REC-html40">
        <head>
          <meta charset="utf-8">
          <title>Relatório Pedagógico - ${activeCompiledReport.crianca}</title>
          <style>
            body { font-family: Arial, sans-serif; line-height: 1.5; color: #333; }
            h1, h2, h3 { color: #1f2937; }
            .header-info { background-color: #f3f4f6; padding: 12px; border-radius: 6px; margin-bottom: 20px; border: 1px solid #e5e7eb; }
            .header-info div { margin-bottom: 4px; font-size: 11pt; }
          </style>
        </head>
        <body>
          <div class="header-info">
            <div><b>Estudante:</b> ${activeCompiledReport.crianca}</div>
            <div><b>Período:</b> ${activeCompiledReport.periodo}</div>
            <div><b>Modelo:</b> ${activeCompiledReport.templateNome}</div>
            <div><b>Quantidade de observações consolidadas:</b> ${activeCompiledReport.totalObservacoes}</div>
          </div>
          <hr/>
          ${marked.parse(activeCompiledReport.report)}
        </body>
        </html>
      `;

      const blob = new Blob(['\ufeff' + htmlContent], { type: 'application/msword' });
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      a.download = `relatorio_${activeCompiledReport.crianca.replace(/\s+/g, '_')}_${Date.now()}.doc`;
      document.body.appendChild(a);
      a.click();
      document.body.removeChild(a);
      URL.revokeObjectURL(url);
    });
  }

  // Exportar para PDF (Abre janela de impressão do navegador)
  if (btnExportPdf) {
    btnExportPdf.addEventListener('click', () => {
      if (!activeCompiledReport) return;

      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>Relatório Pedagógico - ${activeCompiledReport.crianca}</title>
          <style>
            body { font-family: 'Outfit', 'Inter', -apple-system, sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #1e293b; margin-top: 24px; margin-bottom: 12px; }
            h1 { border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; font-size: 22px; }
            h2 { font-size: 18px; border-bottom: 1px solid #f1f5f9; padding-bottom: 6px; }
            .meta-box { background: #f8fafc; padding: 16px; border-radius: 8px; margin-bottom: 24px; font-size: 14px; border: 1px solid #e2e8f0; }
            .meta-item { margin-bottom: 6px; display: flex; }
            .meta-label { font-weight: bold; color: #475569; width: 220px; }
            p { margin-bottom: 14px; text-align: justify; }
            ul, ol { margin-bottom: 14px; padding-left: 20px; }
            li { margin-bottom: 6px; }
            @media print {
              body { padding: 0; }
              button { display: none; }
            }
          </style>
        </head>
        <body>
          <h1>Relatório Pedagógico de Desenvolvimento</h1>
          <div class="meta-box">
            <div class="meta-item"><span class="meta-label">Estudante:</span> <span>${activeCompiledReport.crianca}</span></div>
            <div class="meta-item"><span class="meta-label">Período:</span> <span>${activeCompiledReport.periodo}</span></div>
            <div class="meta-item"><span class="meta-label">Modelo Aplicado:</span> <span>${activeCompiledReport.templateNome}</span></div>
            <div class="meta-item"><span class="meta-label">Quantidade de Observações:</span> <span>${activeCompiledReport.totalObservacoes}</span></div>
          </div>
          <div>${marked.parse(activeCompiledReport.report)}</div>
          <script>
            window.onload = function() {
              window.print();
              setTimeout(() => { window.close(); }, 500);
            };
          </script>
        </body>
        </html>
      `);
      printWindow.document.close();
    });
  }

  // ============================================================
  // ESTÚDIO MUSICAL (Criação de música cantada com MiniMax)
  // ============================================================
  const estudioMusicalModal = document.getElementById('estudioMusicalModal');
  const btnCloseEstudioModal = document.getElementById('btnCloseEstudioModal');
  const sidebarBtnEstudio = document.getElementById('sidebarBtnEstudio');
  const barBtnEstudio = document.getElementById('barBtnEstudio');
  const welcomeCardEstudio = document.getElementById('welcomeCardEstudio');

  const btnGenerateStudioMusic = document.getElementById('btnGenerateStudioMusic');
  const musicTemaInput = document.getElementById('musicTemaInput');
  const musicGenerateLoader = document.getElementById('musicGenerateLoader');
  const musicLoaderText = document.getElementById('musicLoaderText');
  const musicResultArea = document.getElementById('musicResultArea');
  const musicStudioAudioPlayer = document.getElementById('musicStudioAudioPlayer');
  const musicStudioDownloadBtn = document.getElementById('musicStudioDownloadBtn');
  const musicStudioLyricsArea = document.getElementById('musicStudioLyricsArea');
  const btnCopyMusicLyrics = document.getElementById('btnCopyMusicLyrics');
  const btnDownloadMusicLyrics = document.getElementById('btnDownloadMusicLyrics');

  let selectedVoice = 'mulher';
  let selectedRhythm = 'roda';
  let selectedDuration = '30s';

  // Toggle classes active para botões de opções de voz do Estúdio Musical
  document.querySelectorAll('#estudioMusicalModal .music-option-grid .btn-music-option').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('#estudioMusicalModal .music-option-grid .btn-music-option').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedVoice = btn.dataset.voice;
    });
  });

  document.querySelectorAll('.btn-music-rhythm').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-music-rhythm').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedRhythm = btn.dataset.rhythm;
    });
  });

  document.querySelectorAll('.btn-music-duration').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-music-duration').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedDuration = btn.dataset.duration;
    });
  });

  // Abrir e fechar modal
  const openEstudioModal = () => {
    estudioMusicalModal.style.display = 'flex';
    musicTemaInput.value = '';
    musicResultArea.style.display = 'none';
    musicStudioAudioPlayer.src = '';
    musicStudioLyricsArea.textContent = '';
    if (musicGenerateLoader) musicGenerateLoader.style.display = 'none';
    btnGenerateStudioMusic.disabled = false;
  };

  if (sidebarBtnEstudio) {
    sidebarBtnEstudio.addEventListener('click', openEstudioModal);
  }

  if (barBtnEstudio) {
    barBtnEstudio.addEventListener('click', openEstudioModal);
  }

  if (welcomeCardEstudio) {
    welcomeCardEstudio.addEventListener('click', openEstudioModal);
  }

  if (btnCloseEstudioModal) {
    btnCloseEstudioModal.addEventListener('click', () => {
      estudioMusicalModal.style.display = 'none';
      musicStudioAudioPlayer.pause();
    });
  }

  // Fechar modal clicando fora
  window.addEventListener('click', (e) => {
    if (e.target === estudioMusicalModal) {
      estudioMusicalModal.style.display = 'none';
      musicStudioAudioPlayer.pause();
    }
  });

  // Ação de gerar música no estúdio
  if (btnGenerateStudioMusic) {
    btnGenerateStudioMusic.addEventListener('click', async () => {
      const tema = musicTemaInput.value.trim();
      if (!tema) {
        alert('Por favor, digite um tema para a música.');
        return;
      }

      btnGenerateStudioMusic.disabled = true;
      musicGenerateLoader.style.display = 'flex';
      musicResultArea.style.display = 'none';
      
      const statusInterval = setInterval(() => {
        const statusMessages = [
          'Compondo a letra pedagógica...',
          'Ajustando a métrica e as rimas...',
          'Gerando o arranjo musical...',
          'Adicionando os vocais cantados...',
          'Quase pronto, finalizando o áudio...'
        ];
        const randomMsg = statusMessages[Math.floor(Math.random() * statusMessages.length)];
        musicLoaderText.textContent = randomMsg;
      }, 5000);

      try {
        const response = await fetch('/api/music/generate', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json'
          },
          body: JSON.stringify({
            tema,
            voz: selectedVoice,
            ritmo: selectedRhythm,
            duracao: selectedDuration
          })
        });

        clearInterval(statusInterval);

        if (!response.ok) {
          const errData = await response.json();
          throw new Error(errData.error || 'Erro na geração de áudio');
        }

        const data = await response.json();
        
        // Exibir resultados
        musicStudioLyricsArea.textContent = data.lyrics;
        musicStudioAudioPlayer.src = data.audioUrl;
        musicStudioDownloadBtn.href = data.audioUrl;
        
        musicGenerateLoader.style.display = 'none';
        musicResultArea.style.display = 'flex';

      } catch (err) {
        clearInterval(statusInterval);
        console.error('Erro ao gerar música no estúdio:', err);
        alert('Erro ao gerar música: ' + err.message);
        musicGenerateLoader.style.display = 'none';
        btnGenerateStudioMusic.disabled = false;
      }
    });
  }

  // Copiar letra
  if (btnCopyMusicLyrics) {
    btnCopyMusicLyrics.addEventListener('click', () => {
      const lyrics = musicStudioLyricsArea.textContent;
      if (lyrics) {
        navigator.clipboard.writeText(lyrics)
          .then(() => {
            btnCopyMusicLyrics.textContent = '✅ Copiado!';
            setTimeout(() => {
              btnCopyMusicLyrics.textContent = '📋 Copiar Letra';
            }, 2000);
          })
          .catch(err => {
            console.error('Falha ao copiar:', err);
          });
      }
    });
  }

  // Baixar letra em arquivo de texto (TXT)
  if (btnDownloadMusicLyrics) {
    btnDownloadMusicLyrics.addEventListener('click', () => {
      const lyrics = musicStudioLyricsArea.textContent;
      const tema = musicTemaInput.value.trim() || 'cantiga';
      if (lyrics) {
        const blob = new Blob([lyrics], { type: 'text/plain;charset=utf-8' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `letra_${tema.replace(/\s+/g, '_').toLowerCase()}.txt`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
      }
    });
  }

  // =====================================
  // HISTÓRICO DO ESTÚDIO MUSICAL
  // =====================================
  const btnOpenEstudioHistory = document.getElementById('btnOpenEstudioHistory');
  const estudioHistoryModal = document.getElementById('estudioHistoryModal');
  const btnCloseEstudioHistory = document.getElementById('btnCloseEstudioHistory');
  const estudioHistoryList = document.getElementById('estudioHistoryList');

  if (btnOpenEstudioHistory) {
    btnOpenEstudioHistory.addEventListener('click', async () => {
      estudioHistoryModal.style.display = 'flex';
      estudioHistoryList.innerHTML = '<div style="text-align: center; color: var(--text-secondary); padding: 20px;">Carregando histórico...</div>';
      try {
        const res = await fetch('/api/music/list');
        const data = await res.json();
        estudioHistoryList.innerHTML = '';
        if (data.length === 0) {
          estudioHistoryList.innerHTML = '<div style="text-align: center; color: var(--text-secondary); padding: 20px;">Nenhuma canção salva ainda no estúdio.</div>';
          return;
        }
        data.forEach(item => {
          const div = document.createElement('div');
          div.style.background = 'var(--bg-tertiary)';
          div.style.padding = '12px 15px';
          div.style.borderRadius = '8px';
          div.style.display = 'flex';
          div.style.justifyContent = 'space-between';
          div.style.alignItems = 'center';
          div.innerHTML = `
            <div style="flex: 1; margin-right: 15px;">
              <div style="font-weight: 600; font-size: 0.95rem; color: var(--text-primary);">🎵 ${item.tema || 'Música'}</div>
              <div style="font-size: 0.8rem; color: var(--text-secondary); margin-top: 4px;">Voz: ${item.voz} | Ritmo: ${item.ritmo}</div>
              <div style="font-size: 0.75rem; color: var(--text-secondary); margin-top: 4px;">${new Date(item.created_at).toLocaleString()}</div>
            </div>
            <div style="display: flex; gap: 8px;">
              <button class="btn-ver-estudio btn-secondary" data-id="${item.id}" style="padding: 6px 12px; font-size: 0.85rem; border-radius: 6px;">Ver/Ouvir</button>
              <button class="btn-del-estudio btn-secondary" data-id="${item.id}" style="padding: 6px 12px; font-size: 0.85rem; border-radius: 6px; color: #ef4444; border-color: rgba(239, 68, 68, 0.3);">🗑️</button>
            </div>
          `;
          estudioHistoryList.appendChild(div);
        });

        document.querySelectorAll('.btn-ver-estudio').forEach(btn => {
          btn.addEventListener('click', async (e) => {
            const id = e.target.dataset.id;
            try {
              const res = await fetch(`/api/music/${id}`);
              const itemData = await res.json();
              
              musicStudioLyricsArea.textContent = itemData.letra;
              musicStudioAudioPlayer.src = itemData.audio_url;
              musicStudioDownloadBtn.href = itemData.audio_url;
              musicResultArea.style.display = 'flex';
              
              estudioHistoryModal.style.display = 'none';
            } catch (err) { alert('Erro ao carregar música do estúdio.'); }
          });
        });

        document.querySelectorAll('.btn-del-estudio').forEach(btn => {
          btn.addEventListener('click', async (e) => {
            if(!confirm('Tem certeza que deseja apagar esta canção?')) return;
            const id = e.target.dataset.id;
            try {
              await fetch(`/api/music/${id}`, { method: 'DELETE' });
              e.target.closest('div[style*="var(--bg-tertiary)"]').remove();
            } catch (err) { alert('Erro ao deletar.'); }
          });
        });

      } catch (err) {
        estudioHistoryList.innerHTML = '<div style="color: #ef4444; padding: 20px;">Erro ao carregar histórico.</div>';
      }
    });
  }

  if (btnCloseEstudioHistory) {
    btnCloseEstudioHistory.addEventListener('click', () => {
      estudioHistoryModal.style.display = 'none';
    });
  }


  // ============================================================
  // FÁBRICA DE QUADRINHOS (Criação de histórias visuais pedagógicas)
  // ============================================================
  const fabricaQuadrinhosModal = document.getElementById('fabricaQuadrinhosModal');
  const btnCloseComicsModal = document.getElementById('btnCloseComicsModal');
  const barBtnComics = document.getElementById('barBtnComics');
  
  const btnGenerateComics = document.getElementById('btnGenerateComics');
  const comicsTemaInput = document.getElementById('comicsTemaInput');
  const comicsGenerateLoader = document.getElementById('comicsGenerateLoader');
  const comicsLoaderText = document.getElementById('comicsLoaderText');
  const comicsLoaderProgress = document.getElementById('comicsLoaderProgress');
  
  const comicsResultArea = document.getElementById('comicsResultArea');
  const comicsResultTitle = document.getElementById('comicsResultTitle');
  const comicsGridContainer = document.getElementById('comicsGridContainer');

  const comicsCenarioSelect = document.getElementById('comicsCenarioSelect');
  const comicsCenarioCustomInput = document.getElementById('comicsCenarioCustomInput');

  // Export PDF / Vídeo
  const btnExportComicsPDFPortrait = document.getElementById('btnExportComicsPDFPortrait');
  const btnExportComicsPDFLandscape = document.getElementById('btnExportComicsPDFLandscape');
  const btnCompileComicsVideo = document.getElementById('btnCompileComicsVideo');
  const comicsVideoMusic = document.getElementById('comicsVideoMusic');
  const comicsVideoDuration = document.getElementById('comicsVideoDuration');
  const comicsVideoLoader = document.getElementById('comicsVideoLoader');
  const comicsVideoResult = document.getElementById('comicsVideoResult');
  const comicsVideoPlayer = document.getElementById('comicsVideoPlayer');
  const comicsVideoDownloadBtn = document.getElementById('comicsVideoDownloadBtn');

  const comicsProjectSelect = document.getElementById('comicsProjectSelect');
  const btnNewComicsProject = document.getElementById('btnNewComicsProject');
  const btnDeleteComicsProject = document.getElementById('btnDeleteComicsProject');
  const comicsProjectTitleInput = document.getElementById('comicsProjectTitleInput');
  const btnSaveComicsProject = document.getElementById('btnSaveComicsProject');
  const btnSaveNewComicsProject = document.getElementById('btnSaveNewComicsProject');

  let currentComicsProjectId = null;
  let currentComicsCharDescEnglish = '';
  let selectedComicsQty = 5;
  let selectedComicsBubbles = true;
  let selectedComicsRatio = '16:9';
  let generatedPanelsData = [];

  // Toggle ativo quantidade de quadros
  document.querySelectorAll('.btn-comics-qty').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-comics-qty').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedComicsQty = parseInt(btn.dataset.qty);
    });
  });

  // Toggle ativo falas/diálogos
  document.querySelectorAll('.btn-comics-bubbles').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-comics-bubbles').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedComicsBubbles = btn.dataset.bubbles === 'true';
    });
  });

  // Toggle ativo proporção visual
  document.querySelectorAll('.btn-comics-ratio').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-comics-ratio').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedComicsRatio = btn.dataset.ratio;
    });
  });

  // Gerenciador dinâmico de personagens
  const comicsCharListContainer = document.getElementById('comicsCharListContainer');
  const btnAddHumanChar = document.getElementById('btnAddHumanChar');
  const btnAddAnimalChar = document.getElementById('btnAddAnimalChar');

  const addCharacterRow = (type = '', name = '', isAnimal = false) => {
    const row = document.createElement('div');
    row.className = 'comic-char-row';
    row.style.cssText = 'display: flex; gap: 8px; align-items: center; background: var(--bg-primary); padding: 8px; border-radius: 8px; border: 1px solid var(--border-light);';

    const emoji = document.createElement('span');
    emoji.style.fontSize = '1.1rem';
    emoji.textContent = isAnimal ? '🐾' : '🧒';
    row.appendChild(emoji);

    const typeInput = document.createElement('input');
    typeInput.type = 'text';
    typeInput.className = 'obs-input char-type-input';
    typeInput.placeholder = isAnimal ? 'Tipo (ex: Gatinho, Leão)' : 'Tipo (ex: Menino, Menina)';
    typeInput.value = type;
    typeInput.style.cssText = 'flex: 1; padding: 6px 10px; font-size: 0.85rem; margin: 0;';
    row.appendChild(typeInput);

    const nameInput = document.createElement('input');
    nameInput.type = 'text';
    nameInput.className = 'obs-input char-name-input';
    nameInput.placeholder = 'Nome';
    nameInput.value = name;
    nameInput.style.cssText = 'flex: 1; padding: 6px 10px; font-size: 0.85rem; margin: 0;';
    row.appendChild(nameInput);

    const deleteBtn = document.createElement('button');
    deleteBtn.type = 'button';
    deleteBtn.className = 'btn-delete-char';
    deleteBtn.innerHTML = '&times;';
    deleteBtn.style.cssText = 'background: none; border: none; color: #ef4444; font-size: 1.3rem; cursor: pointer; padding: 0 4px; line-height: 1;';
    deleteBtn.addEventListener('click', () => {
      row.remove();
    });
    row.appendChild(deleteBtn);

    comicsCharListContainer.appendChild(row);
  };

  if (btnAddHumanChar) {
    btnAddHumanChar.addEventListener('click', () => {
      addCharacterRow('', '', false);
    });
  }

  if (btnAddAnimalChar) {
    btnAddAnimalChar.addEventListener('click', () => {
      addCharacterRow('', '', true);
    });
  }

  // Exibir/ocultar cenário personalizado
  if (comicsCenarioSelect) {
    comicsCenarioSelect.addEventListener('change', () => {
      if (comicsCenarioSelect.value === 'custom') {
        comicsCenarioCustomInput.style.display = 'block';
      } else {
        comicsCenarioCustomInput.style.display = 'none';
      }
    });
  }

  // --- GERENCIADOR DE PROJETOS DE HQ ---
  const startNewComicsProject = () => {
    currentComicsProjectId = null;
    currentComicsCharDescEnglish = '';
    
    const modeContainer = document.getElementById('comicsGenerationModeContainer');
    if (modeContainer) modeContainer.style.display = 'none';
    const radioNew = document.querySelector('input[name="comicsGenMode"][value="new_story"]');
    if (radioNew) radioNew.checked = true;
    
    if (comicsProjectSelect) comicsProjectSelect.value = '';
    if (comicsProjectTitleInput) comicsProjectTitleInput.value = '';
    if (btnDeleteComicsProject) btnDeleteComicsProject.style.display = 'none';
    if (btnSaveComicsProject) btnSaveComicsProject.style.display = 'none';
    
    comicsTemaInput.value = '';
    comicsResultArea.style.display = 'none';
    comicsGenerateLoader.style.display = 'none';
    comicsVideoResult.style.display = 'none';
    comicsVideoLoader.style.display = 'none';
    btnGenerateComics.disabled = false;
    if (comicsLoaderProgress) comicsLoaderProgress.style.width = '0%';
    
    // Set active state for default quick options
    selectedComicsQty = 5;
    document.querySelectorAll('.btn-comics-qty').forEach(b => {
      if (b.dataset.qty === '5') b.classList.add('active');
      else b.classList.remove('active');
    });
    
    selectedComicsBubbles = true;
    document.querySelectorAll('.btn-comics-bubbles').forEach(b => {
      if (b.dataset.bubbles === 'true') b.classList.add('active');
      else b.classList.remove('active');
    });
    
    selectedComicsRatio = '16:9';
    document.querySelectorAll('.btn-comics-ratio').forEach(b => {
      if (b.dataset.ratio === '16:9') b.classList.add('active');
      else b.classList.remove('active');
    });

    if (comicsCenarioSelect) {
      comicsCenarioSelect.value = 'no parque de diversões colorido';
      if (comicsCenarioCustomInput) {
        comicsCenarioCustomInput.style.display = 'none';
        comicsCenarioCustomInput.value = '';
      }
    }

    // Inicializar lista de personagens com padrão se estiver vazia
    comicsCharListContainer.innerHTML = '';
    addCharacterRow("Menino", "Lucas", false);
    addCharacterRow("Menina", "Mariana", false);
    
    generatedPanelsData = [];
    comicsGridContainer.innerHTML = '';
  };

  const loadComicsProjectsList = async () => {
    if (!comicsProjectSelect) return;
    try {
      const resp = await fetch('/api/comics/projects');
      if (!resp.ok) throw new Error('Falha ao listar projetos');
      const projects = await resp.json();
      
      comicsProjectSelect.innerHTML = '<option value="">-- Carregar projeto salvo... --</option>';
      projects.forEach(proj => {
        const opt = document.createElement('option');
        opt.value = proj.id;
        opt.textContent = `${proj.titulo} (${new Date(proj.updated_at).toLocaleDateString('pt-BR')})`;
        comicsProjectSelect.appendChild(opt);
      });
      
      if (currentComicsProjectId) {
        comicsProjectSelect.value = currentComicsProjectId;
      }
    } catch (err) {
      console.error('Erro ao listar projetos:', err);
    }
  };

  const loadComicsProject = async (id) => {
    if (!id) {
      startNewComicsProject();
      return;
    }
    try {
      const resp = await fetch(`/api/comics/projects/${id}`);
      if (!resp.ok) throw new Error('Falha ao carregar projeto');
      const { project, panels } = await resp.json();
      
      currentComicsProjectId = project.id;
      currentComicsCharDescEnglish = project.character_description_english || '';
      
      const modeContainer = document.getElementById('comicsGenerationModeContainer');
      if (modeContainer) modeContainer.style.display = 'flex';
      
      if (comicsProjectTitleInput) comicsProjectTitleInput.value = project.titulo || '';
      comicsTemaInput.value = project.tema || '';
      
      if (btnDeleteComicsProject) btnDeleteComicsProject.style.display = 'block';
      if (btnSaveComicsProject) btnSaveComicsProject.style.display = 'block';
      
      // Carregar proporção
      selectedComicsRatio = project.proporcao || '16:9';
      document.querySelectorAll('.btn-comics-ratio').forEach(b => {
        if (b.dataset.ratio === selectedComicsRatio) b.classList.add('active');
        else b.classList.remove('active');
      });
      
      // Carregar cenário
      if (comicsCenarioSelect) {
        const standardOptions = ['no parque de diversões colorido', 'na sala de aula da escola infantil', 'em uma floresta encantada cheia de flores', 'no zoológico interagindo com animais', 'num jardim ensolarado de uma casa'];
        if (standardOptions.includes(project.cenario)) {
          comicsCenarioSelect.value = project.cenario;
          if (comicsCenarioCustomInput) comicsCenarioCustomInput.style.display = 'none';
        } else {
          comicsCenarioSelect.value = 'custom';
          if (comicsCenarioCustomInput) {
            comicsCenarioCustomInput.style.display = 'block';
            comicsCenarioCustomInput.value = project.cenario || '';
          }
        }
      }
      
      // Carregar quantidade e balões baseados nos painéis retornados
      selectedComicsQty = panels.length || 5;
      document.querySelectorAll('.btn-comics-qty').forEach(b => {
        if (parseInt(b.dataset.qty) === selectedComicsQty) b.classList.add('active');
        else b.classList.remove('active');
      });
      
      const hasDialogue = panels.some(p => p.dialogue);
      selectedComicsBubbles = hasDialogue;
      document.querySelectorAll('.btn-comics-bubbles').forEach(b => {
        if ((b.dataset.bubbles === 'true') === selectedComicsBubbles) b.classList.add('active');
        else b.classList.remove('active');
      });
      
      // Carregar personagens
      comicsCharListContainer.innerHTML = '';
      if (project.character_description_global) {
        try {
          const chars = JSON.parse(project.character_description_global);
          if (Array.isArray(chars)) {
            chars.forEach(c => {
              addCharacterRow(c.type || '', c.name || '', c.isAnimal || false);
            });
          }
        } catch (e) {
          addCharacterRow("Menino", "Lucas", false);
          addCharacterRow("Menina", "Mariana", false);
        }
      } else {
        addCharacterRow("Menino", "Lucas", false);
        addCharacterRow("Menina", "Mariana", false);
      }
      
      // Carregar os painéis
      generatedPanelsData = panels.map(p => ({
        panel_number: p.panel_number,
        imageUrl: p.image_url,
        dialogue: p.dialogue || '',
        image_prompt: p.image_prompt || ''
      }));
      
      if (generatedPanelsData.length > 0) {
        comicsResultTitle.textContent = project.titulo || 'História em Quadrinhos';
        comicsGridContainer.innerHTML = '';
        
        generatedPanelsData.forEach((panel, index) => {
          const panelCard = document.createElement('div');
          panelCard.className = 'comic-panel-card';
          
          const imgContainer = document.createElement('div');
          imgContainer.className = `comic-panel-image-container ratio-${selectedComicsRatio.replace(':', '-')}`;
          
          const img = document.createElement('img');
          img.className = 'comic-panel-image';
          img.src = panel.imageUrl;
          img.alt = `Quadro ${panel.panel_number}`;
          imgContainer.appendChild(img);
          
          const badge = document.createElement('div');
          badge.className = 'comic-panel-number-badge';
          badge.textContent = panel.panel_number;
          imgContainer.appendChild(badge);
          
          panelCard.appendChild(imgContainer);
          
          const caption = document.createElement('div');
          caption.className = 'comic-caption-text';
          caption.style.cssText = 'padding: 10px 14px; background: var(--bg-primary); border-top: 1px solid var(--border-light);';
          
          const textarea = document.createElement('textarea');
          textarea.className = 'comic-caption-input';
          textarea.value = panel.dialogue || '';
          textarea.placeholder = 'Digite a fala ou legenda do quadrinho...';
          textarea.style.cssText = 'width: 100%; border: 1px solid var(--border-light); background: var(--bg-secondary); color: var(--text-primary); border-radius: 6px; padding: 8px; font-family: inherit; font-size: 0.85rem; resize: vertical; box-sizing: border-box; min-height: 50px;';
          
          textarea.addEventListener('input', (e) => {
            panel.dialogue = e.target.value;
            if (generatedPanelsData[index]) {
              generatedPanelsData[index].dialogue = e.target.value;
            }
          });
          
          caption.appendChild(textarea);
          panelCard.appendChild(caption);
          
          comicsGridContainer.appendChild(panelCard);
        });
        
        comicsResultArea.style.display = 'flex';
      } else {
        comicsResultArea.style.display = 'none';
      }
      
      comicsVideoResult.style.display = 'none';
      comicsVideoLoader.style.display = 'none';
      btnGenerateComics.disabled = false;
      
    } catch (err) {
      console.error(err);
      await showCustomAlert('Erro', 'Erro ao carregar projeto: ' + err.message);
    }
  };

  const saveComicsProjectFlow = async (forceNew = false) => {
    const titulo = comicsProjectTitleInput ? comicsProjectTitleInput.value.trim() : '';
    if (!titulo) {
      await showCustomAlert('Campo Obrigatório', 'Por favor, digite um título para salvar seu projeto.');
      return;
    }
    
    const characters = [];
    document.querySelectorAll('.comic-char-row').forEach(row => {
      const typeInput = row.querySelector('.char-type-input');
      const nameInput = row.querySelector('.char-name-input');
      if (typeInput && nameInput) {
        const type = typeInput.value.trim();
        const name = nameInput.value.trim();
        const isAnimal = row.querySelector('span').textContent === '🐾';
        if (type || name) {
          characters.push({ type, name, isAnimal });
        }
      }
    });
    
    let cenario = comicsCenarioSelect ? comicsCenarioSelect.value : 'no parque de diversões colorido';
    if (cenario === 'custom' && comicsCenarioCustomInput) {
      cenario = comicsCenarioCustomInput.value.trim();
    }
    
    const targetId = forceNew ? null : currentComicsProjectId;
    
    const body = {
      id: targetId,
      titulo,
      tema: comicsTemaInput.value.trim(),
      cenario,
      proporcao: selectedComicsRatio,
      character_description_global: JSON.stringify(characters),
      character_description_english: currentComicsCharDescEnglish || '',
      panels: generatedPanelsData.map(p => ({
        panel_number: p.panel_number,
        image_url: p.imageUrl || p.image_url || '',
        image_prompt: p.image_prompt || '',
        dialogue: p.dialogue || ''
      }))
    };
    
    try {
      const resp = await fetch('/api/comics/projects', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(body)
      });
      
      if (!resp.ok) {
        const err = await resp.json();
        throw new Error(err.error || 'Erro ao salvar projeto');
      }
      
      const data = await resp.json();
      currentComicsProjectId = data.id;
      await showCustomAlert('Sucesso', 'Projeto salvo com sucesso!');
      
      if (btnDeleteComicsProject) btnDeleteComicsProject.style.display = 'block';
      if (btnSaveComicsProject) btnSaveComicsProject.style.display = 'block';
      await loadComicsProjectsList();
    } catch (err) {
      console.error(err);
      await showCustomAlert('Erro', 'Erro ao salvar projeto: ' + err.message);
    }
  };

  const saveComicsProject = () => saveComicsProjectFlow(false);
  const saveNewComicsProject = () => saveComicsProjectFlow(true);

  const deleteComicsProject = async () => {
    if (!currentComicsProjectId) return;
    const confirmed = await showCustomConfirm(
      'Confirmar Exclusão',
      'Tem certeza de que deseja excluir este projeto permanentemente?',
      true
    );
    if (!confirmed) return;
    
    try {
      const resp = await fetch(`/api/comics/projects/${currentComicsProjectId}`, {
        method: 'DELETE'
      });
      
      if (!resp.ok) throw new Error('Falha ao excluir projeto');
      
      await showCustomAlert('Excluído', 'Projeto excluído com sucesso!');
      startNewComicsProject();
      await loadComicsProjectsList();
    } catch (err) {
      console.error(err);
      await showCustomAlert('Erro', 'Erro ao excluir projeto: ' + err.message);
    }
  };

  // Abrir e fechar modal Fábrica de Quadrinhos
  const openComicsModal = () => {
    fabricaQuadrinhosModal.style.display = 'flex';
    startNewComicsProject();
    loadComicsProjectsList();
  };

  // Listeners do Gerenciador de Projetos
  if (comicsProjectSelect) {
    comicsProjectSelect.addEventListener('change', (e) => {
      loadComicsProject(e.target.value);
    });
  }

  if (btnNewComicsProject) {
    btnNewComicsProject.addEventListener('click', async () => {
      const confirmed = await showCustomConfirm(
        'Novo Projeto',
        'Deseja iniciar um novo projeto? Alterações não salvas serão perdidas.'
      );
      if (confirmed) {
        startNewComicsProject();
      }
    });
  }

  if (btnSaveComicsProject) {
    btnSaveComicsProject.addEventListener('click', saveComicsProject);
  }

  if (btnSaveNewComicsProject) {
    btnSaveNewComicsProject.addEventListener('click', saveNewComicsProject);
  }

  if (btnDeleteComicsProject) {
    btnDeleteComicsProject.addEventListener('click', deleteComicsProject);
  }

  if (barBtnComics) {
    barBtnComics.addEventListener('click', openComicsModal);
  }

  if (btnCloseComicsModal) {
    btnCloseComicsModal.addEventListener('click', () => {
      fabricaQuadrinhosModal.style.display = 'none';
      if (comicsVideoPlayer) comicsVideoPlayer.pause();
    });
  }

  // Fechar modal clicando fora
  window.addEventListener('click', (e) => {
    if (e.target === fabricaQuadrinhosModal) {
      fabricaQuadrinhosModal.style.display = 'none';
      if (comicsVideoPlayer) comicsVideoPlayer.pause();
    }
  });

  // Helper para converter URL de imagem local em base64
  const getBase64Image = async (imgUrl) => {
    return new Promise((resolve, reject) => {
      const img = new Image();
      img.crossOrigin = 'Anonymous';
      img.onload = () => {
        const canvas = document.createElement('canvas');
        canvas.width = img.width;
        canvas.height = img.height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0);
        resolve(canvas.toDataURL('image/jpeg'));
      };
      img.onerror = (e) => reject(new Error('Falha ao carregar imagem para o PDF: ' + imgUrl));
      img.src = imgUrl;
    });
  };

  // Ação de geração da história e imagens
  if (btnGenerateComics) {
    btnGenerateComics.addEventListener('click', async () => {
      const tema = comicsTemaInput.value.trim();
      if (!tema) {
        await showCustomAlert('Campo Requerido', 'Por favor, digite um tema para a história.');
        return;
      }

      // Reunir personagens dinamicamente
      const personagens = [];
      document.querySelectorAll('.comic-char-row').forEach(row => {
        const type = row.querySelector('.char-type-input').value.trim();
        const name = row.querySelector('.char-name-input').value.trim();
        if (type && name) {
          personagens.push(`${type} chamado(a) ${name}`);
        }
      });

      if (personagens.length === 0) {
        await showCustomAlert('Personagens Faltando', 'Adicione e preencha pelo menos um personagem principal.');
        return;
      }

      // Definir cenário
      let cenario = comicsCenarioSelect.value;
      if (cenario === 'custom') {
        cenario = comicsCenarioCustomInput.value.trim() || 'em um local bonito';
      }

      btnGenerateComics.disabled = true;
      comicsGenerateLoader.style.display = 'flex';
      comicsResultArea.style.display = 'none';
      comicsVideoResult.style.display = 'none';
      comicsLoaderProgress.style.width = '5%';
      comicsLoaderText.textContent = 'Escrevendo o roteiro e diálogos dos quadrinhos...';

      try {
        // 1. Gerar Roteiro
        const genMode = currentComicsProjectId ? (document.querySelector('input[name="comicsGenMode"]:checked')?.value || 'new_story') : 'new_story';
        
        const requestBody = {
          tema,
          quantidade: selectedComicsQty,
          baloes: selectedComicsBubbles,
          proporcao: selectedComicsRatio,
          personagens,
          cenario
        };

        if (currentComicsProjectId) {
          requestBody.continuationType = genMode;
          requestBody.character_description = currentComicsCharDescEnglish;
          requestBody.existingPanels = generatedPanelsData.map(p => ({
            panel_number: p.panel_number,
            image_url: p.imageUrl || p.image_url || '',
            image_prompt: p.image_prompt || '',
            dialogue: p.dialogue || ''
          }));
        }

        const scriptResp = await fetch('/api/comics/generate-script', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(requestBody)
        });

        if (!scriptResp.ok) {
          const err = await scriptResp.json();
          throw new Error(err.error || 'Erro ao planejar roteiro');
        }

        const scriptData = await scriptResp.json();
        comicsLoaderProgress.style.width = '15%';

        if (scriptData.character_description) {
          currentComicsCharDescEnglish = scriptData.character_description;
        }

        // 2. Gerar cada quadrinho sequencialmente
        if (genMode !== 'extend') {
          generatedPanelsData = [];
        }
        const totalPanels = scriptData.panels.length;

        for (let i = 0; i < totalPanels; i++) {
          const panel = scriptData.panels[i];
          const progressPercent = 15 + Math.floor((i / totalPanels) * 80);
          comicsLoaderProgress.style.width = `${progressPercent}%`;
          comicsLoaderText.textContent = `Ilustrando quadrinho ${i + 1} de ${totalPanels}...`;

          // Injetamos a proporção e estilo de forma reforçada no prompt
          const fullPrompt = `${panel.image_prompt}, high resolution children book illustration, cute Pixar style, ${selectedComicsRatio === '16:9' ? '16:9 aspect ratio' : '4:3 aspect ratio'}`;

          const frameResp = await fetch('/api/comics/generate-frame', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ prompt: fullPrompt })
          });

          if (!frameResp.ok) {
            const err = await frameResp.json();
            throw new Error(`Erro no quadrinho ${i + 1}: ${err.error}`);
          }

          const frameData = await frameResp.json();
          generatedPanelsData.push({
            panel_number: panel.panel_number,
            imageUrl: frameData.imageUrl,
            dialogue: panel.dialogue || '',
            image_prompt: panel.image_prompt || ''
          });
        }

        // Renderizar quadrinhos na tela (todos, incluindo os anteriores caso tenha sido extensão)
        comicsResultTitle.textContent = scriptData.title || comicsResultTitle.textContent || 'Fábrica de Quadrinhos Camila';
        comicsGridContainer.innerHTML = '';

        generatedPanelsData.forEach((panel, index) => {
          const panelCard = document.createElement('div');
          panelCard.className = 'comic-panel-card';

          const imgContainer = document.createElement('div');
          imgContainer.className = `comic-panel-image-container ratio-${selectedComicsRatio.replace(':', '-')}`;

          const img = document.createElement('img');
          img.className = 'comic-panel-image';
          img.src = panel.imageUrl || panel.image_url;
          img.alt = `Quadro ${panel.panel_number}`;
          imgContainer.appendChild(img);

          // Selo do número
          const badge = document.createElement('div');
          badge.className = 'comic-panel-number-badge';
          badge.textContent = panel.panel_number;
          imgContainer.appendChild(badge);

          panelCard.appendChild(imgContainer);

          const caption = document.createElement('div');
          caption.className = 'comic-caption-text';
          caption.style.cssText = 'padding: 10px 14px; background: var(--bg-primary); border-top: 1px solid var(--border-light);';

          const textarea = document.createElement('textarea');
          textarea.className = 'comic-caption-input';
          textarea.value = panel.dialogue || '';
          textarea.placeholder = 'Digite a fala ou legenda do quadrinho...';
          textarea.style.cssText = 'width: 100%; border: 1px solid var(--border-light); background: var(--bg-secondary); color: var(--text-primary); border-radius: 6px; padding: 8px; font-family: inherit; font-size: 0.85rem; resize: vertical; box-sizing: border-box; min-height: 50px;';

          textarea.addEventListener('input', (e) => {
            panel.dialogue = e.target.value;
            if (generatedPanelsData[index]) {
              generatedPanelsData[index].dialogue = e.target.value;
            }
          });

          caption.appendChild(textarea);
          panelCard.appendChild(caption);

          comicsGridContainer.appendChild(panelCard);
        });

        // Se for uma nova história derivada de um projeto antigo, limpamos o ID para virar um novo projeto independente ao salvar
        if (genMode === 'new_story' && currentComicsProjectId) {
          currentComicsProjectId = null;
          if (comicsProjectSelect) comicsProjectSelect.value = '';
          const modeContainer = document.getElementById('comicsGenerationModeContainer');
          if (modeContainer) modeContainer.style.display = 'none';
          if (comicsProjectTitleInput) {
            comicsProjectTitleInput.value = scriptData.title || (comicsProjectTitleInput.value + ' (Derivado)');
          }
          if (btnDeleteComicsProject) btnDeleteComicsProject.style.display = 'none';
        }

        comicsGenerateLoader.style.display = 'none';
        comicsResultArea.style.display = 'flex';
        btnGenerateComics.disabled = false;

      } catch (err) {
        console.error('Erro ao fabricar quadrinhos:', err);
        await showCustomAlert('Erro', 'Erro ao fabricar quadrinhos: ' + err.message);
        comicsGenerateLoader.style.display = 'none';
        btnGenerateComics.disabled = false;
      }
    });
  }

  // Exportar PDF Retrato (1 por página)
  if (btnExportComicsPDFPortrait) {
    btnExportComicsPDFPortrait.addEventListener('click', async () => {
      if (generatedPanelsData.length === 0) return;
      btnExportComicsPDFPortrait.disabled = true;
      btnExportComicsPDFPortrait.textContent = '⏳ Montando PDF...';

      try {
        const { jsPDF } = window.jspdf;
        const doc = new jsPDF('p', 'pt', 'a4');
        const title = comicsResultTitle.textContent || 'História em Quadrinhos';

        for (let i = 0; i < generatedPanelsData.length; i++) {
          const panel = generatedPanelsData[i];
          if (i > 0) doc.addPage();

          // Título centralizado
          doc.setFont('helvetica', 'bold');
          doc.setFontSize(18);
          doc.setTextColor(30, 41, 59);
          doc.text(title, 297, 50, { align: 'center' });

          // Imagem
          const base64Img = await getBase64Image(panel.imageUrl);
          const imgWidth = 515;
          const imgHeight = selectedComicsRatio === '16:9' ? 290 : 386;
          doc.addImage(base64Img, 'JPEG', 40, 80, imgWidth, imgHeight);

          // Altura esticada para a caixa de diálogo (160pt de altura - aprox dobro)
          const textHeight = 160;
          const textY = 80 + imgHeight;

          // Caixa de diálogo com fundo cinza claro e borda integrada
          doc.setFillColor(248, 250, 252);
          doc.rect(40, textY, imgWidth, textHeight, 'F');

          // Moldura unificada ao redor de toda a imagem + texto
          doc.setDrawColor(30, 41, 59);
          doc.setLineWidth(2);
          doc.rect(40, 80, imgWidth, imgHeight + textHeight, 'D');

          // Linha divisória entre a imagem e a caixa de texto
          doc.line(40, textY, 555, textY);

          // Texto maior e mais legível (dobro do tamanho relativo - 15pt)
          if (panel.dialogue) {
            doc.setFont('helvetica', 'normal');
            doc.setFontSize(15);
            doc.setTextColor(15, 23, 42);
            
            const splitText = doc.splitTextToSize(panel.dialogue, imgWidth - 40);
            doc.text(splitText, 60, textY + 35);
          }

          // Círculo discreto com o número do quadrinho no canto superior esquerdo da imagem
          doc.setFillColor(254, 240, 138);
          doc.circle(65, 105, 12, 'F');
          doc.setDrawColor(30, 41, 59);
          doc.setLineWidth(1.5);
          doc.circle(65, 105, 12, 'D');
          
          doc.setFont('helvetica', 'bold');
          doc.setFontSize(10);
          doc.setTextColor(30, 41, 59);
          doc.text(String(panel.panel_number), 65, 109, { align: 'center' });

          // Rodapé
          doc.setFont('helvetica', 'italic');
          doc.setFontSize(9);
          doc.setTextColor(148, 163, 184);
          doc.text(`Criado com PedaGog - Quadro ${panel.panel_number} de ${generatedPanelsData.length}`, 297, 815, { align: 'center' });
        }

        doc.save(`quadrinhos_${title.replace(/\s+/g, '_').toLowerCase()}.pdf`);
      } catch (error) {
        console.error('Erro ao gerar PDF Retrato:', error);
        alert('Erro ao gerar PDF: ' + error.message);
      } finally {
        btnExportComicsPDFPortrait.disabled = false;
        btnExportComicsPDFPortrait.textContent = '📄 PDF (1 por página - Retrato)';
      }
    });
  }

  // Exportar PDF Paisagem (2 por página)
  if (btnExportComicsPDFLandscape) {
    btnExportComicsPDFLandscape.addEventListener('click', async () => {
      if (generatedPanelsData.length === 0) return;
      btnExportComicsPDFLandscape.disabled = true;
      btnExportComicsPDFLandscape.textContent = '⏳ Montando PDF...';

      try {
        const { jsPDF } = window.jspdf;
        const doc = new jsPDF('l', 'pt', 'a4');
        const title = comicsResultTitle.textContent || 'História em Quadrinhos';

        const totalPanels = generatedPanelsData.length;
        const totalPages = Math.ceil(totalPanels / 2);

        for (let page = 0; page < totalPages; page++) {
          if (page > 0) doc.addPage();

          // Título centralizado no topo da página paisagem
          doc.setFont('helvetica', 'bold');
          doc.setFontSize(18);
          doc.setTextColor(30, 41, 59);
          doc.text(`${title} - Página ${page + 1} de ${totalPages}`, 421, 45, { align: 'center' });

          // Renderizar até dois quadrinhos lado a lado
          for (let col = 0; col < 2; col++) {
            const index = page * 2 + col;
            if (index >= totalPanels) break;

            const panel = generatedPanelsData[index];
            const startX = col === 0 ? 40 : 426;
            const cardWidth = 376;
            
            // Proporções exatas mantidas
            const imgHeight = selectedComicsRatio === '16:9' ? 211 : 282;
            const textHeight = 140; // Dobro de tamanho (antes era 65)

            // Imagem do quadrinho
            const base64Img = await getBase64Image(panel.imageUrl);
            doc.addImage(base64Img, 'JPEG', startX, 70, cardWidth, imgHeight);

            // Fundo da caixa de texto
            const textY = 70 + imgHeight;
            doc.setFillColor(248, 250, 252);
            doc.rect(startX, textY, cardWidth, textHeight, 'F');

            // Moldura unificada ao redor do quadro (imagem + texto)
            doc.setDrawColor(30, 41, 59);
            doc.setLineWidth(2);
            doc.rect(startX, 70, cardWidth, imgHeight + textHeight, 'D');

            // Linha separando a imagem da caixa de texto
            doc.line(startX, textY, startX + cardWidth, textY);

            // Legenda formatada em tamanho maior (13pt)
            if (panel.dialogue) {
              doc.setFont('helvetica', 'normal');
              doc.setFontSize(13);
              doc.setTextColor(15, 23, 42);
              
              const splitText = doc.splitTextToSize(panel.dialogue, cardWidth - 30);
              doc.text(splitText, startX + 15, textY + 30);
            }

            // Círculo discreto com o numeral do quadro no canto superior esquerdo da imagem
            doc.setFillColor(254, 240, 138);
            doc.circle(startX + 20, 90, 11, 'F');
            doc.setDrawColor(30, 41, 59);
            doc.setLineWidth(1.5);
            doc.circle(startX + 20, 90, 11, 'D');
            
            doc.setFont('helvetica', 'bold');
            doc.setFontSize(9);
            doc.setTextColor(30, 41, 59);
            doc.text(String(panel.panel_number), startX + 20, 93, { align: 'center' });
          }
        }

        doc.save(`quadrinhos_${title.replace(/\s+/g, '_').toLowerCase()}_paisagem.pdf`);
      } catch (error) {
        console.error('Erro ao gerar PDF Paisagem:', error);
        alert('Erro ao gerar PDF: ' + error.message);
      } finally {
        btnExportComicsPDFLandscape.disabled = false;
        btnExportComicsPDFLandscape.textContent = '📄 PDF (2 por página - Paisagem)';
      }
    });
  }

  // Compilar Vídeo de Apresentação (FFmpeg)
  if (btnCompileComicsVideo) {
    btnCompileComicsVideo.addEventListener('click', async () => {
      if (generatedPanelsData.length === 0) return;

      btnCompileComicsVideo.disabled = true;
      comicsVideoLoader.style.display = 'flex';
      comicsVideoResult.style.display = 'none';

      try {
        const response = await fetch('/api/comics/generate-video', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            frames: generatedPanelsData,
            musicSelection: comicsVideoMusic.value,
            frameDuration: comicsVideoDuration.value
          })
        });

        if (!response.ok) {
          const err = await response.json();
          throw new Error(err.error || 'Erro na compilação do vídeo');
        }

        const data = await response.json();
        
        comicsVideoPlayer.src = data.videoUrl;
        comicsVideoDownloadBtn.href = data.videoUrl;
        
        comicsVideoResult.style.display = 'flex';
        comicsVideoLoader.style.display = 'none';
        btnCompileComicsVideo.disabled = false;

      } catch (err) {
        console.error('Erro ao gerar vídeo dos quadrinhos:', err);
        alert('Erro ao compilar o vídeo: ' + err.message);
        comicsVideoLoader.style.display = 'none';
        btnCompileComicsVideo.disabled = false;
      }
    });
  }

  // ============================================================
  // VIDEOMIND (TRANSCRIÇÃO E ANÁLISE DE VÍDEO PEDAGÓGICO)
  // ============================================================
  const videoMindModal = document.getElementById('videoMindModal');
  const btnCloseVideoMindModal = document.getElementById('btnCloseVideoMindModal');
  const barBtnVideoMind = document.getElementById('barBtnVideoMind');
  
  const btnGenerateVideoMind = document.getElementById('btnGenerateVideoMind');
  const videoMindUrlInput = document.getElementById('videoMindUrlInput');
  const videoMindLoader = document.getElementById('videoMindLoader');
  const videoMindLoaderText = document.getElementById('videoMindLoaderText');
  const videoMindResultArea = document.getElementById('videoMindResultArea');
  
  const videoMindThumbnail = document.getElementById('videoMindThumbnail');
  const videoMindTitle = document.getElementById('videoMindTitle');
  const videoMindAuthor = document.getElementById('videoMindAuthor');
  const videoMindReportArea = document.getElementById('videoMindReportArea');
  
  const btnCopyVideoMindReport = document.getElementById('btnCopyVideoMindReport');
  const btnDownloadVideoMindReport = document.getElementById('btnDownloadVideoMindReport');
  const btnPdfVideoMindReport = document.getElementById('btnPdfVideoMindReport');

  let selectedVideoMindLines = 20;
  let activeVideoMindReport = null;

  // Listener para selecionar o tamanho do resumo
  document.querySelectorAll('#videoMindModal .music-option-grid .btn-videomind-lines').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('#videoMindModal .music-option-grid .btn-videomind-lines').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      selectedVideoMindLines = parseInt(btn.dataset.lines) || 20;
    });
  });

  // Abrir modal do VideoMind
  if (barBtnVideoMind) {
    barBtnVideoMind.addEventListener('click', () => {
      videoMindModal.style.display = 'flex';
      videoMindUrlInput.value = '';
      videoMindResultArea.style.display = 'none';
      videoMindReportArea.innerHTML = '';
      if (videoMindLoader) videoMindLoader.style.display = 'none';
      btnGenerateVideoMind.disabled = false;
      activeVideoMindReport = null;
    });
  }

  // Fechar modal
  if (btnCloseVideoMindModal) {
    btnCloseVideoMindModal.addEventListener('click', () => {
      videoMindModal.style.display = 'none';
    });
  }

  window.addEventListener('click', (e) => {
    if (e.target === videoMindModal) {
      videoMindModal.style.display = 'none';
    }
  });

  // Ação de analisar vídeo
  if (btnGenerateVideoMind) {
    btnGenerateVideoMind.addEventListener('click', async () => {
      const url = videoMindUrlInput.value.trim();
      const pastedTranscriptInput = document.getElementById('videoMindPastedTranscriptInput');
      const pastedTranscript = pastedTranscriptInput ? pastedTranscriptInput.value.trim() : '';

      if (!url) {
        alert('Por favor, insira o link de um vídeo do YouTube.');
        return;
      }

      btnGenerateVideoMind.disabled = true;
      videoMindLoader.style.display = 'flex';
      videoMindResultArea.style.display = 'none';
      videoMindLoaderText.textContent = 'Buscando metadados do vídeo...';

      let statusMsgIdx = 0;
      const statusMessages = [
        'Buscando legenda automática do vídeo...',
        'Carregando a transcrição completa...',
        'Enviando transcrição para a IA...',
        'Pedagoga IA analisando o conteúdo...',
        'Alinhando temas do vídeo com a BNCC...',
        'Gerando resumo de ' + selectedVideoMindLines + ' linhas...',
        'Criando propostas de atividades pedagógicas...',
        'Finalizando o parecer pedagógico...'
      ];

      const statusInterval = setInterval(() => {
        if (statusMsgIdx < statusMessages.length) {
          videoMindLoaderText.textContent = statusMessages[statusMsgIdx];
          statusMsgIdx++;
        } else {
          videoMindLoaderText.textContent = 'Ajustando formatação da análise...';
        }
      }, 4000);

      try {
        const response = await fetch('/api/videomind/analyze', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            url,
            lines: selectedVideoMindLines,
            pastedTranscript
          })
        });

        clearInterval(statusInterval);

        if (!response.ok) {
          const errData = await response.json();
          throw new Error(errData.error || 'Erro desconhecido');
        }

        const data = await response.json();
        activeVideoMindReport = data;

        // Preencher informações do vídeo
        videoMindTitle.textContent = data.metadata.title;
        videoMindAuthor.textContent = 'Canal: ' + data.metadata.author;
        videoMindThumbnail.src = data.metadata.thumbnail;

        // Renderizar Markdown
        if (window.marked) {
          videoMindReportArea.innerHTML = marked.parse(data.report);
        } else {
          videoMindReportArea.textContent = data.report;
        }

        videoMindLoader.style.display = 'none';
        videoMindResultArea.style.display = 'flex';

      } catch (err) {
        clearInterval(statusInterval);
        console.error('Erro no VideoMind:', err);
        alert('Erro ao analisar vídeo: ' + err.message);
        videoMindLoader.style.display = 'none';
        btnGenerateVideoMind.disabled = false;
      }
    });
  }

  // Copiar Parecer
  if (btnCopyVideoMindReport) {
    btnCopyVideoMindReport.addEventListener('click', () => {
      if (activeVideoMindReport && activeVideoMindReport.report) {
        navigator.clipboard.writeText(activeVideoMindReport.report)
          .then(() => {
            btnCopyVideoMindReport.textContent = '✅ Copiado!';
            setTimeout(() => {
              btnCopyVideoMindReport.textContent = '📋 Copiar Parecer';
            }, 2000);
          })
          .catch(err => {
            console.error('Falha ao copiar:', err);
          });
      }
    });
  }

  // Baixar relatório TXT
  if (btnDownloadVideoMindReport) {
    btnDownloadVideoMindReport.addEventListener('click', () => {
      if (activeVideoMindReport && activeVideoMindReport.report) {
        const title = activeVideoMindReport.metadata.title || 'analise_video';
        const blob = new Blob([activeVideoMindReport.report], { type: 'text/plain;charset=utf-8' });
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = `VideoMind_${title.replace(/\s+/g, '_').toLowerCase()}.txt`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
        URL.revokeObjectURL(url);
      }
    });
  }

  // Baixar relatório PDF
  if (btnPdfVideoMindReport) {
    btnPdfVideoMindReport.addEventListener('click', () => {
      if (!activeVideoMindReport) return;

      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>VideoMind - Parecer Pedagógico</title>
          <style>
            body { font-family: 'Outfit', 'Inter', -apple-system, sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #0891b2; margin-top: 24px; margin-bottom: 12px; }
            h1 { border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; font-size: 22px; }
            h2 { font-size: 18px; border-bottom: 1px solid #f1f5f9; padding-bottom: 6px; }
            .meta-box { background: #f8fafc; padding: 16px; border-radius: 8px; margin-bottom: 24px; font-size: 14px; border: 1px solid #e2e8f0; display: flex; gap: 16px; align-items: center; }
            .meta-info { display: flex; flex-direction: column; gap: 4px; }
            .meta-label { font-weight: bold; color: #475569; }
            p { margin-bottom: 14px; text-align: justify; }
            ul, ol { margin-bottom: 14px; padding-left: 20px; }
            li { margin-bottom: 6px; }
            @media print {
              body { padding: 0; }
              button { display: none; }
            }
          </style>
        </head>
        <body>
          <h1>🎬 VideoMind - Análise & Parecer Pedagógico</h1>
          <div class="meta-box">
            <img src="${activeVideoMindReport.metadata.thumbnail}" style="width: 100px; aspect-ratio: 16/9; object-fit: cover; border-radius: 6px;">
            <div class="meta-info">
              <div><span class="meta-label">Vídeo:</span> <span>${activeVideoMindReport.metadata.title}</span></div>
              <div><span class="meta-label">Canal:</span> <span>${activeVideoMindReport.metadata.author}</span></div>
              <div><span class="meta-label">Resumo Escolhido:</span> <span>${selectedVideoMindLines} Linhas</span></div>
            </div>
          </div>
          <div>${window.marked ? marked.parse(activeVideoMindReport.report) : activeVideoMindReport.report}</div>
          <script>
            window.onload = function() {
              window.print();
              setTimeout(() => { window.close(); }, 500);
            };
          </script>
        </body>
        </html>
      `);
    });
  }

  // ============================================================
  // GARATUJAS (ANALISADOR DE TRAÇADO INFANTIL)
  // ============================================================
  const garatujasModal = document.getElementById('garatujasModal');
  const btnCloseGaratujasModal = document.getElementById('btnCloseGaratujasModal');
  const barBtnGaratujas = document.getElementById('barBtnGaratujas');
  
  const tabGaratujasNova = document.getElementById('tabGaratujasNova');
  const tabGaratujasHistorico = document.getElementById('tabGaratujasHistorico');
  const contentGaratujasNova = document.getElementById('contentGaratujasNova');
  const contentGaratujasHistorico = document.getElementById('contentGaratujasHistorico');
  
  const garatujasAlunoInput = document.getElementById('garatujasAlunoInput');
  const garatujasIdadeInput = document.getElementById('garatujasIdadeInput');
  const garatujaFileInput = document.getElementById('garatujaFileInput');
  const btnUploadGaratuja = document.getElementById('btnUploadGaratuja');
  const garatujaFileStatus = document.getElementById('garatujaFileStatus');
  const garatujaPreviewContainer = document.getElementById('garatujaPreviewContainer');
  const garatujaImgPreview = document.getElementById('garatujaImgPreview');
  
  const btnGenerateGaratuja = document.getElementById('btnGenerateGaratuja');
  const garatujaLoader = document.getElementById('garatujaLoader');
  const garatujaLoaderText = document.getElementById('garatujaLoaderText');
  const garatujaResultArea = document.getElementById('garatujaResultArea');
  const garatujaReportArea = document.getElementById('garatujaReportArea');
  
  const btnCopyGaratujaReport = document.getElementById('btnCopyGaratujaReport');
  const btnPdfGaratujaReport = document.getElementById('btnPdfGaratujaReport');
  const garatujasListContainer = document.getElementById('garatujasListContainer');
  const garatujasNoData = document.getElementById('garatujasNoData');
  
  let activeGaratujaReport = null;

  // Abas do Garatujas
  if (tabGaratujasNova) {
    tabGaratujasNova.addEventListener('click', () => {
      tabGaratujasNova.classList.add('active');
      tabGaratujasHistorico.classList.remove('active');
      contentGaratujasNova.style.display = 'block';
      contentGaratujasHistorico.style.display = 'none';
    });
  }

  if (tabGaratujasHistorico) {
    tabGaratujasHistorico.addEventListener('click', () => {
      tabGaratujasHistorico.classList.add('active');
      tabGaratujasNova.classList.remove('active');
      contentGaratujasNova.style.display = 'none';
      contentGaratujasHistorico.style.display = 'block';
      loadGaratujasHistory();
    });
  }

  // Abrir Modal
  if (barBtnGaratujas) {
    barBtnGaratujas.addEventListener('click', () => {
      garatujasModal.style.display = 'flex';
      garatujasAlunoInput.value = '';
      garatujaFileInput.value = '';
      garatujaFileStatus.textContent = 'Nenhum arquivo selecionado';
      garatujaPreviewContainer.style.display = 'none';
      garatujaResultArea.style.display = 'none';
      garatujaLoader.style.display = 'none';
      btnGenerateGaratuja.disabled = false;
      activeGaratujaReport = null;
      if (tabGaratujasNova) tabGaratujasNova.click();
    });
  }

  // Fechar Modal
  if (btnCloseGaratujasModal) {
    btnCloseGaratujasModal.addEventListener('click', () => {
      garatujasModal.style.display = 'none';
    });
  }

  window.addEventListener('click', (e) => {
    if (e.target === garatujasModal) {
      garatujasModal.style.display = 'none';
    }
  });

  // Upload trigger
  if (btnUploadGaratuja) {
    btnUploadGaratuja.addEventListener('click', () => {
      garatujaFileInput.click();
    });
  }

  if (garatujaFileInput) {
    garatujaFileInput.addEventListener('change', () => {
      const file = garatujaFileInput.files[0];
      if (file) {
        garatujaFileStatus.textContent = file.name;
        const reader = new FileReader();
        reader.onload = (e) => {
          garatujaImgPreview.src = e.target.result;
          garatujaPreviewContainer.style.display = 'block';
        };
        reader.readAsDataURL(file);
      } else {
        garatujaFileStatus.textContent = 'Nenhum arquivo selecionado';
        garatujaPreviewContainer.style.display = 'none';
      }
    });
  }

  // Gerar Análise
  if (btnGenerateGaratuja) {
    btnGenerateGaratuja.addEventListener('click', async () => {
      const alunoName = garatujasAlunoInput.value.trim();
      const alunoIdade = garatujasIdadeInput ? garatujasIdadeInput.value.trim() : '';
      const file = garatujaFileInput.files[0];

      if (!alunoName) {
        alert('Por favor, informe o nome do aluno.');
        return;
      }
      if (!file) {
        alert('Por favor, selecione a foto do desenho.');
        return;
      }

      btnGenerateGaratuja.disabled = true;
      garatujaLoader.style.display = 'flex';
      garatujaResultArea.style.display = 'none';
      garatujaLoaderText.textContent = 'Enviando imagem pedagógica...';

      const formData = new FormData();
      formData.append('alunoName', alunoName);
      if (alunoIdade) formData.append('alunoIdade', alunoIdade);
      formData.append('image', file);

      let statusMsgIdx = 0;
      const statusMessages = [
        'Carregando desenho infantil...',
        'IA escaneando os traços e formas...',
        'Analisando simetria e coordenação motora...',
        'Definindo estágio evolutivo do desenho...',
        'Criando sugestões de atividades formativas...',
        'Finalizando laudo psicopedagógico...'
      ];

      const statusInterval = setInterval(() => {
        if (statusMsgIdx < statusMessages.length) {
          garatujaLoaderText.textContent = statusMessages[statusMsgIdx];
          statusMsgIdx++;
        } else {
          garatujaLoaderText.textContent = 'Formatando parecer...';
        }
      }, 4500);

      try {
        const response = await fetch('/api/garatujas/analyze', {
          method: 'POST',
          body: formData
        });

        clearInterval(statusInterval);

        if (!response.ok) {
          const errData = await response.json();
          throw new Error(errData.error || 'Erro desconhecido');
        }

        const data = await response.json();
        activeGaratujaReport = data;

        if (window.marked) {
          garatujaReportArea.innerHTML = marked.parse(data.analise);
        } else {
          garatujaReportArea.textContent = data.analise;
        }

        garatujaLoader.style.display = 'none';
        garatujaResultArea.style.display = 'flex';
        btnGenerateGaratuja.disabled = false;

      } catch (err) {
        clearInterval(statusInterval);
        console.error(err);
        alert('Erro na análise: ' + err.message);
        garatujaLoader.style.display = 'none';
        btnGenerateGaratuja.disabled = false;
      }
    });
  }

  // Copiar Parecer Garatujas
  if (btnCopyGaratujaReport) {
    btnCopyGaratujaReport.addEventListener('click', () => {
      if (activeGaratujaReport && activeGaratujaReport.analise) {
        navigator.clipboard.writeText(activeGaratujaReport.analise)
          .then(() => {
            btnCopyGaratujaReport.textContent = '✅ Copiado!';
            setTimeout(() => { btnCopyGaratujaReport.textContent = '📋 Copiar'; }, 2000);
          });
      }
    });
  }

  // Baixar PDF Garatujas
  if (btnPdfGaratujaReport) {
    btnPdfGaratujaReport.addEventListener('click', () => {
      if (!activeGaratujaReport) return;
      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>Garatujas - Laudo do Desenho</title>
          <style>
            body { font-family: 'Outfit', 'Inter', sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #ea580c; margin-top: 24px; margin-bottom: 12px; }
            h1 { border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; font-size: 22px; }
            .meta-box { background: #f8fafc; padding: 16px; border-radius: 8px; margin-bottom: 24px; border: 1px solid #e2e8f0; display: flex; gap: 16px; align-items: center; }
            .meta-label { font-weight: bold; color: #475569; }
            img { border-radius: 6px; border: 1px solid #ddd; max-height: 120px; }
            @media print {
              body { padding: 0; }
              button { display: none; }
            }
          </style>
        </head>
        <body>
          <h1>🎨 Garatujas - Parecer de Traçado Infantil</h1>
          <div class="meta-box">
            <img src="${activeGaratujaReport.imageUrl}">
            <div>
              <div><span class="meta-label">Aluno(a):</span> <span>${activeGaratujaReport.alunoName}</span></div>
              <div><span class="meta-label">Data de Análise:</span> <span>${new Date(activeGaratujaReport.createdAt).toLocaleDateString('pt-BR')}</span></div>
            </div>
          </div>
          <div>${window.marked ? marked.parse(activeGaratujaReport.analise) : activeGaratujaReport.analise}</div>
          <script>
            window.onload = function() {
              window.print();
              setTimeout(() => { window.close(); }, 500);
            };
          <\/script>
        </body>
        </html>
      `);
      printWindow.document.close();
    });
  }

  // Carregar Histórico Garatujas
  async function loadGaratujasHistory() {
    try {
      const response = await fetch('/api/garatujas/list');
      if (!response.ok) throw new Error('Erro ao carregar histórico');
      const list = await response.json();

      garatujasListContainer.innerHTML = '';
      if (list.length === 0) {
        garatujasNoData.style.display = 'block';
        return;
      }
      garatujasNoData.style.display = 'none';

      list.forEach(item => {
        const div = document.createElement('div');
        div.className = 'quick-note-card';
        div.style.cursor = 'pointer';
        div.style.display = 'flex';
        div.style.flexDirection = 'column';
        div.style.gap = '8px';
        div.style.padding = '12px';
        
        div.innerHTML = `
          <div style="position: relative; width: 100%; aspect-ratio: 4/3; overflow: hidden; border-radius: 6px; background: rgba(0,0,0,0.2);">
            <img src="${item.imageUrl}" style="width: 100%; height: 100%; object-fit: cover;">
            <button class="delete-btn" data-id="${item.id}" style="position: absolute; top: 6px; right: 6px; background: rgba(0,0,0,0.5); border: none; width: 26px; height: 26px; border-radius: 50%; color: #fff; display: flex; align-items: center; justify-content: center; cursor: pointer; font-size: 0.8rem; transition: background 0.2s, transform 0.2s; z-index: 10;" title="Deletar análise" onmouseover="this.style.background='rgba(220,53,69,0.95)'; this.style.transform='scale(1.1)';" onmouseout="this.style.background='rgba(0,0,0,0.5)'; this.style.transform='scale(1)';">
              🗑️
            </button>
          </div>
          <div style="font-weight: 600; color: var(--text-primary); font-size: 0.9rem;">${escapeHtml(item.alunoName)}</div>
          <div style="font-size: 0.75rem; color: var(--text-muted);">${new Date(item.createdAt).toLocaleDateString('pt-BR')}</div>
        `;
        
        const deleteBtn = div.querySelector('.delete-btn');
        deleteBtn.addEventListener('click', async (e) => {
          e.stopPropagation();
          if (confirm(`Deseja realmente excluir a análise de desenho do aluno "${item.alunoName}"?`)) {
            try {
              const delResp = await fetch(`/api/garatujas/${item.id}`, { method: 'DELETE' });
              if (!delResp.ok) throw new Error('Falha ao deletar');
              alert('Análise deletada com sucesso.');
              loadGaratujasHistory();
              if (activeGaratujaReport && activeGaratujaReport.id === item.id) {
                activeGaratujaReport = null;
                garatujasAlunoInput.value = '';
                garatujaImgPreview.src = '';
                garatujaPreviewContainer.style.display = 'none';
                garatujaReportArea.innerHTML = '';
                garatujaResultArea.style.display = 'none';
              }
            } catch (err) {
              alert('Erro ao excluir análise: ' + err.message);
            }
          }
        });
        
        div.addEventListener('click', async () => {
          try {
            const detailResp = await fetch(`/api/garatujas/${item.id}`);
            if (!detailResp.ok) throw new Error('Erro ao obter detalhes');
            const detail = await detailResp.json();
            
            activeGaratujaReport = detail;
            garatujasAlunoInput.value = detail.alunoName;
            garatujaImgPreview.src = detail.imageUrl;
            garatujaPreviewContainer.style.display = 'block';
            garatujaReportArea.innerHTML = window.marked ? marked.parse(detail.analise) : detail.analise;
            
            garatujaResultArea.style.display = 'flex';
            if (tabGaratujasNova) tabGaratujasNova.click();
          } catch (e) {
            alert('Falha ao abrir desenho.');
          }
        });
        
        garatujasListContainer.appendChild(div);
      });
    } catch (err) {
      console.error(err);
    }
  }

  // ============================================================
  // ESTÚDIO DE POESIA
  // ============================================================
  const poesiaModal = document.getElementById('poesiaModal');
  const btnClosePoesiaModal = document.getElementById('btnClosePoesiaModal');
  const barBtnPoesia = document.getElementById('barBtnPoesia');
  const btnOpenPoesiaHistory = document.getElementById('btnOpenPoesiaHistory');
  const poesiaHistoryModal = document.getElementById('poesiaHistoryModal');
  const btnClosePoesiaHistory = document.getElementById('btnClosePoesiaHistory');

  const btnGeneratePoesia = document.getElementById('btnGeneratePoesia');
  const poesiaGenerateLoader = document.getElementById('poesiaGenerateLoader');
  const poesiaResultArea = document.getElementById('poesiaResultArea');
  const poesiaTextOutput = document.getElementById('poesiaTextOutput');
  const btnCopyPoesia = document.getElementById('btnCopyPoesia');
  const btnDownloadPoesiaPdf = document.getElementById('btnDownloadPoesiaPdf');

  const poesiaTemaInput = document.getElementById('poesiaTemaInput');
  const poesiaFaixaEtaria = document.getElementById('poesiaFaixaEtaria');
  
  let currentPoesia = null;
  let selectedEstrofes = 3;

  // Seleção de estrofes
  document.querySelectorAll('.btn-poesia-estrofes').forEach(btn => {
    btn.addEventListener('click', (e) => {
      document.querySelectorAll('.btn-poesia-estrofes').forEach(b => b.classList.remove('active'));
      e.target.classList.add('active');
      selectedEstrofes = parseInt(e.target.dataset.estrofes);
    });
  });

  // Abrir/Fechar Modal Principal
  if (barBtnPoesia) {
    barBtnPoesia.addEventListener('click', () => {
      poesiaModal.style.display = 'flex';
      poesiaTemaInput.value = '';
      poesiaResultArea.style.display = 'none';
      poesiaGenerateLoader.style.display = 'none';
      btnGeneratePoesia.disabled = false;
      currentPoesia = null;
    });
  }

  if (btnClosePoesiaModal) {
    btnClosePoesiaModal.addEventListener('click', () => {
      poesiaModal.style.display = 'none';
    });
  }

  // Abrir/Fechar Modal de Histórico
  if (btnOpenPoesiaHistory) {
    btnOpenPoesiaHistory.addEventListener('click', () => {
      poesiaHistoryModal.style.display = 'flex';
      loadPoesiaHistory();
    });
  }

  if (btnClosePoesiaHistory) {
    btnClosePoesiaHistory.addEventListener('click', () => {
      poesiaHistoryModal.style.display = 'none';
    });
  }

  window.addEventListener('click', (e) => {
    if (e.target === poesiaModal) poesiaModal.style.display = 'none';
    if (e.target === poesiaHistoryModal) poesiaHistoryModal.style.display = 'none';
  });

  // Gerar Poesia
  if (btnGeneratePoesia) {
    btnGeneratePoesia.addEventListener('click', async () => {
      const tema = poesiaTemaInput.value.trim();
      const faixaEtaria = poesiaFaixaEtaria.value;

      if (!tema) {
        showToast('Por favor, digite o tema da poesia.', 'error');
        return;
      }

      btnGeneratePoesia.disabled = true;
      poesiaGenerateLoader.style.display = 'flex';
      poesiaResultArea.style.display = 'none';

      try {
        const response = await fetch('/api/poesias/generate', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ faixaEtaria, estrofes: selectedEstrofes, tema })
        });

        const data = await response.json();
        
        if (response.ok && data.success) {
          currentPoesia = data.poesia;
          poesiaTextOutput.innerHTML = window.marked ? marked.parse(currentPoesia) : currentPoesia;
          poesiaResultArea.style.display = 'flex';
          showToast('Poesia criada com sucesso!', 'success');
        } else {
          showToast(data.error || 'Falha ao gerar poesia.', 'error');
        }
      } catch (err) {
        console.error('Erro na geração da poesia:', err);
        showToast('Erro de conexão ao gerar poesia.', 'error');
      } finally {
        btnGeneratePoesia.disabled = false;
        poesiaGenerateLoader.style.display = 'none';
      }
    });
  }

  // Copiar e Baixar
  if (btnCopyPoesia) {
    btnCopyPoesia.addEventListener('click', () => {
      if (currentPoesia) {
        navigator.clipboard.writeText(currentPoesia);
        showToast('Poesia copiada para a área de transferência!', 'success');
      }
    });
  }

  if (btnDownloadPoesiaPdf) {
    btnDownloadPoesiaPdf.addEventListener('click', () => {
      if (!currentPoesia) return;
      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>Poesia - Assistente PedaGog</title>
          <style>
            body { font-family: 'Outfit', 'Inter', sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #10b981; margin-top: 24px; margin-bottom: 12px; }
            @media print {
              body { padding: 0; }
              button { display: none; }
            }
          </style>
        </head>
        <body>
          <div style="max-width: 800px; margin: 0 auto;">
            <div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; margin-bottom: 20px;">
              <h1 style="margin: 0; border: none; padding: 0;">📜 Poesia Pedagógica</h1>
              <button onclick="window.print()" style="background: #10b981; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: bold;">Imprimir / Salvar PDF</button>
            </div>
            <div>
              ${window.marked ? marked.parse(currentPoesia) : currentPoesia}
            </div>
          </div>
        </body>
        </html>
      `);
      printWindow.document.close();
    });
  }

  // Carregar Histórico
  async function loadPoesiaHistory() {
    const listContainer = document.getElementById('poesiaHistoryList');
    if (!listContainer) return;
    
    listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Carregando...</p>';
    
    try {
      const response = await fetch('/api/poesias/list');
      const data = await response.json();
      
      if (data && data.length > 0) {
        listContainer.innerHTML = '';
        data.forEach(item => {
          const date = new Date(item.created_at).toLocaleString('pt-BR');
          const div = document.createElement('div');
          div.className = 'history-item-card';
          div.style.cssText = 'background: rgba(255,255,255,0.02); padding: 14px; border-radius: 8px; border: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 8px; cursor: pointer; position: relative;';
          div.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: flex-start; padding-right: 30px;">
              <strong style="color: var(--brand-green); font-size: 0.95rem;">${item.faixa_etaria} (${item.estrofes} Estrofes)</strong>
              <span style="font-size: 0.75rem; color: var(--text-secondary);">${date}</span>
            </div>
            <p style="margin: 0; font-size: 0.85rem; color: var(--text-primary); opacity: 0.9;">Tema: ${item.tema}</p>
            <button class="btn-delete-poesia" data-id="${item.id}" style="position: absolute; top: 12px; right: 12px; background: transparent; border: none; color: #ef4444; cursor: pointer; font-size: 1.1rem; padding: 4px; border-radius: 4px;" title="Excluir Poesia">🗑️</button>
          `;
          
          div.addEventListener('click', async (e) => {
            if (e.target.closest('.btn-delete-poesia')) {
              e.stopPropagation();
              if (confirm('Tem certeza que deseja excluir esta poesia?')) {
                try {
                  const delRes = await fetch(`/api/poesias/${item.id}`, { method: 'DELETE' });
                  if (delRes.ok) {
                    showToast('Poesia excluída.', 'success');
                    loadPoesiaHistory();
                  } else {
                    showToast('Erro ao excluir.', 'error');
                  }
                } catch (err) {
                  showToast('Erro de conexão.', 'error');
                }
              }
              return;
            }
            try {
              const res = await fetch(`/api/poesias/${item.id}`);
              const detail = await res.json();
              if (res.ok) {
                currentPoesia = detail.poesia;
                poesiaTextOutput.innerHTML = window.marked ? marked.parse(currentPoesia) : currentPoesia;
                poesiaResultArea.style.display = 'flex';
                poesiaHistoryModal.style.display = 'none';
              }
            } catch (err) {
              showToast('Erro ao carregar poesia.', 'error');
            }
          });
          
          listContainer.appendChild(div);
        });
      } else {
        listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Nenhuma poesia salva ainda.</p>';
      }
    } catch (err) {
      listContainer.innerHTML = '<p style="text-align:center; color:#ef4444;">Erro ao carregar histórico.</p>';
    }
  }

  // ============================================================
  // BRINCARATIVO (CIRCUITOS PSICOMOTORES E BRINCADEIRAS)
  // ============================================================
  const brincarAtivoModal = document.getElementById('brincarAtivoModal');
  const btnCloseBrincarAtivoModal = document.getElementById('btnCloseBrincarAtivoModal');
  const barBtnBrincarAtivo = document.getElementById('barBtnBrincarAtivo');
  
  const tabBrincarAtivoNova = document.getElementById('tabBrincarAtivoNova');
  const tabBrincarAtivoHistorico = document.getElementById('tabBrincarAtivoHistorico');
  const contentBrincarAtivoNova = document.getElementById('contentBrincarAtivoNova');
  const contentBrincarAtivoHistorico = document.getElementById('contentBrincarAtivoHistorico');
  
  const brincarAtivoFaixaSelect = document.getElementById('brincarAtivoFaixaSelect');
  const brincarAtivoRecursosInput = document.getElementById('brincarAtivoRecursosInput');
  const btnGenerateBrincarAtivo = document.getElementById('btnGenerateBrincarAtivo');
  const brincarAtivoLoader = document.getElementById('brincarAtivoLoader');
  const brincarAtivoLoaderText = document.getElementById('brincarAtivoLoaderText');
  const brincarAtivoResultArea = document.getElementById('brincarAtivoResultArea');
  const brincarAtivoReportArea = document.getElementById('brincarAtivoReportArea');
  
  const btnCopyBrincarAtivoReport = document.getElementById('btnCopyBrincarAtivoReport');
  const btnPdfBrincarAtivoReport = document.getElementById('btnPdfBrincarAtivoReport');
  const brincarAtivoListContainer = document.getElementById('brincarAtivoListContainer');
  const brincarAtivoNoData = document.getElementById('brincarAtivoNoData');
  
  let activeBrincarAtivoReport = null;

  // Abas do BrincarAtivo
  if (tabBrincarAtivoNova) {
    tabBrincarAtivoNova.addEventListener('click', () => {
      tabBrincarAtivoNova.classList.add('active');
      tabBrincarAtivoHistorico.classList.remove('active');
      contentBrincarAtivoNova.style.display = 'block';
      contentBrincarAtivoHistorico.style.display = 'none';
    });
  }

  if (tabBrincarAtivoHistorico) {
    tabBrincarAtivoHistorico.addEventListener('click', () => {
      tabBrincarAtivoHistorico.classList.add('active');
      tabBrincarAtivoNova.classList.remove('active');
      contentBrincarAtivoNova.style.display = 'none';
      contentBrincarAtivoHistorico.style.display = 'block';
      loadBrincarAtivoHistory();
    });
  }

  // Abrir Modal
  if (barBtnBrincarAtivo) {
    barBtnBrincarAtivo.addEventListener('click', () => {
      brincarAtivoModal.style.display = 'flex';
      brincarAtivoRecursosInput.value = '';
      brincarAtivoResultArea.style.display = 'none';
      brincarAtivoLoader.style.display = 'none';
      btnGenerateBrincarAtivo.disabled = false;
      activeBrincarAtivoReport = null;
      if (tabBrincarAtivoNova) tabBrincarAtivoNova.click();
    });
  }

  // Fechar Modal
  if (btnCloseBrincarAtivoModal) {
    btnCloseBrincarAtivoModal.addEventListener('click', () => {
      brincarAtivoModal.style.display = 'none';
    });
  }

  window.addEventListener('click', (e) => {
    if (e.target === brincarAtivoModal) {
      brincarAtivoModal.style.display = 'none';
    }
  });

  // Gerar Atividade
  if (btnGenerateBrincarAtivo) {
    btnGenerateBrincarAtivo.addEventListener('click', async () => {
      const faixaEtaria = brincarAtivoFaixaSelect.value;
      const recursos = brincarAtivoRecursosInput.value.trim();

      if (!recursos) {
        alert('Por favor, informe os materiais ou recursos disponíveis.');
        return;
      }

      btnGenerateBrincarAtivo.disabled = true;
      brincarAtivoLoader.style.display = 'flex';
      brincarAtivoResultArea.style.display = 'none';
      brincarAtivoLoaderText.textContent = 'Acessando referências BNCC...';

      let statusMsgIdx = 0;
      const statusMessages = [
        'Analisando faixa etária psicomotora...',
        'Estruturando proposta lúdica de circuito...',
        'Conectando objetivos específicos da BNCC...',
        'Gerando instruções passo a passo para o professor...',
        'Finalizando plano de circuito ativo...'
      ];

      const statusInterval = setInterval(() => {
        if (statusMsgIdx < statusMessages.length) {
          brincarAtivoLoaderText.textContent = statusMessages[statusMsgIdx];
          statusMsgIdx++;
        } else {
          brincarAtivoLoaderText.textContent = 'Formatando atividade...';
        }
      }, 4500);

      try {
        const response = await fetch('/api/brincar-ativo/generate', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ faixaEtaria, recursos })
        });

        clearInterval(statusInterval);

        if (!response.ok) {
          const errData = await response.json();
          throw new Error(errData.error || 'Erro desconhecido');
        }

        const data = await response.json();
        activeBrincarAtivoReport = data;

        if (window.marked) {
          brincarAtivoReportArea.innerHTML = marked.parse(data.atividade);
        } else {
          brincarAtivoReportArea.textContent = data.atividade;
        }

        brincarAtivoLoader.style.display = 'none';
        brincarAtivoResultArea.style.display = 'flex';
        btnGenerateBrincarAtivo.disabled = false;

      } catch (err) {
        clearInterval(statusInterval);
        console.error(err);
        alert('Erro ao gerar atividade: ' + err.message);
        brincarAtivoLoader.style.display = 'none';
        btnGenerateBrincarAtivo.disabled = false;
      }
    });
  }

  // Copiar Parecer BrincarAtivo
  if (btnCopyBrincarAtivoReport) {
    btnCopyBrincarAtivoReport.addEventListener('click', () => {
      if (activeBrincarAtivoReport && activeBrincarAtivoReport.atividade) {
        navigator.clipboard.writeText(activeBrincarAtivoReport.atividade)
          .then(() => {
            btnCopyBrincarAtivoReport.textContent = '✅ Copiado!';
            setTimeout(() => { btnCopyBrincarAtivoReport.textContent = '📋 Copiar'; }, 2000);
          });
      }
    });
  }

  // Baixar PDF BrincarAtivo
  if (btnPdfBrincarAtivoReport) {
    btnPdfBrincarAtivoReport.addEventListener('click', () => {
      if (!activeBrincarAtivoReport) return;
      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>BrincarAtivo - Roteiro de Circuito</title>
          <style>
            body { font-family: 'Outfit', 'Inter', sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #10a37f; margin-top: 24px; margin-bottom: 12px; }
            h1 { border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; font-size: 22px; }
            .meta-box { background: #f8fafc; padding: 16px; border-radius: 8px; margin-bottom: 24px; border: 1px solid #e2e8f0; }
            .meta-label { font-weight: bold; color: #475569; }
            @media print {
              body { padding: 0; }
              button { display: none; }
            }
          </style>
        </head>
        <body>
          <h1>🏃‍♂️ BrincarAtivo - Planejamento Psicomotor</h1>
          <div class="meta-box">
            <div><span class="meta-label">Faixa Etária:</span> <span>${activeBrincarAtivoReport.faixaEtaria}</span></div>
            <div><span class="meta-label">Recursos:</span> <span>${activeBrincarAtivoReport.recursos}</span></div>
            <div><span class="meta-label">Data de Criação:</span> <span>${new Date(activeBrincarAtivoReport.createdAt).toLocaleDateString('pt-BR')}</span></div>
          </div>
          <div>${window.marked ? marked.parse(activeBrincarAtivoReport.atividade) : activeBrincarAtivoReport.atividade}</div>
          <script>
            window.onload = function() {
              window.print();
              setTimeout(() => { window.close(); }, 500);
            };
          <\/script>
        </body>
        </html>
      `);
      printWindow.document.close();
    });
  }

  // Carregar Histórico BrincarAtivo
  async function loadBrincarAtivoHistory() {
    try {
      const response = await fetch('/api/brincar-ativo/list');
      if (!response.ok) throw new Error('Erro ao carregar histórico');
      const list = await response.json();

      brincarAtivoListContainer.innerHTML = '';
      if (list.length === 0) {
        brincarAtivoNoData.style.display = 'block';
        return;
      }
      brincarAtivoNoData.style.display = 'none';

      list.forEach(item => {
        const div = document.createElement('div');
        div.className = 'quick-note-card';
        div.style.cursor = 'pointer';
        div.style.display = 'flex';
        div.style.flexDirection = 'column';
        div.style.gap = '6px';
        div.style.padding = '12px';
        
        const lines = item.recursos || '';
        const previewText = lines.length > 60 ? lines.substring(0, 60) + '...' : lines;
        
        div.innerHTML = `
          <div style="font-weight: 600; color: var(--text-primary); font-size: 0.92rem; display: flex; align-items: center; justify-content: space-between; gap: 6px;">
            <span>🏃‍♂️ ${escapeHtml(item.faixaEtaria.split(' ')[0])} (${item.faixaEtaria.includes('bem pequenas') ? 'Bem Pequenas' : (item.faixaEtaria.includes('pequenas') ? 'Pequenas' : 'Bebês')})</span>
            <button class="delete-btn" data-id="${item.id}" style="background: transparent; border: none; color: var(--text-muted); cursor: pointer; font-size: 0.95rem; padding: 2px 6px; border-radius: 4px; transition: color 0.2s, background 0.2s; display: flex; align-items: center; justify-content: center; z-index: 10;" title="Deletar atividade" onmouseover="this.style.color='#ff4d4f'; this.style.background='rgba(255, 77, 79, 0.1)'" onmouseout="this.style.color='var(--text-muted)'; this.style.background='transparent'">
              🗑️
            </button>
          </div>
          <div style="font-size: 0.8rem; color: var(--text-secondary);">Recursos: ${escapeHtml(previewText)}</div>
          <div style="font-size: 0.75rem; color: var(--text-muted);">${new Date(item.createdAt).toLocaleDateString('pt-BR')}</div>
        `;
        
        const deleteBtn = div.querySelector('.delete-btn');
        deleteBtn.addEventListener('click', async (e) => {
          e.stopPropagation();
          if (confirm(`Deseja realmente excluir esta atividade psicomotora do histórico?`)) {
            try {
              const delResp = await fetch(`/api/brincar-ativo/${item.id}`, { method: 'DELETE' });
              if (!delResp.ok) throw new Error('Falha ao deletar');
              alert('Atividade deletada com sucesso.');
              loadBrincarAtivoHistory();
              if (activeBrincarAtivoReport && activeBrincarAtivoReport.id === item.id) {
                activeBrincarAtivoReport = null;
                brincarAtivoFaixaSelect.value = '';
                brincarAtivoRecursosInput.value = '';
                brincarAtivoReportArea.innerHTML = '';
                brincarAtivoResultArea.style.display = 'none';
              }
            } catch (err) {
              alert('Erro ao excluir atividade: ' + err.message);
            }
          }
        });
        
        div.addEventListener('click', async () => {
          try {
            const detailResp = await fetch(`/api/brincar-ativo/${item.id}`);
            if (!detailResp.ok) throw new Error('Erro ao obter detalhes');
            const detail = await detailResp.json();
            
            activeBrincarAtivoReport = detail;
            brincarAtivoFaixaSelect.value = detail.faixaEtaria;
            brincarAtivoRecursosInput.value = detail.recursos;
            brincarAtivoReportArea.innerHTML = window.marked ? marked.parse(detail.atividade) : detail.atividade;
            
            brincarAtivoResultArea.style.display = 'flex';
            if (tabBrincarAtivoNova) tabBrincarAtivoNova.click();
          } catch (e) {
            alert('Falha ao abrir atividade.');
          }
        });
        
        brincarAtivoListContainer.appendChild(div);
      });
    } catch (err) {
      console.error(err);
    }
  }
};

// Player de áudio personalizado global para as mídias geradas
window.toggleCustomAudio = (btn) => {
  const player = btn.closest('.custom-audio-player');
  const audio = player.querySelector('audio');
  const playIcon = btn.querySelector('.play-icon');
  const pauseIcon = btn.querySelector('.pause-icon');
  const progress = player.querySelector('.audio-progress');
  const timeSpan = player.querySelector('.audio-time');

  if (audio.paused) {
    // Pausar outros players que possam estar ativos
    document.querySelectorAll('.custom-audio-player audio').forEach(a => {
      if (a !== audio && !a.paused) {
        a.pause();
        const otherBtn = a.closest('.custom-audio-player').querySelector('.audio-play-btn');
        otherBtn.querySelector('.play-icon').classList.remove('hidden');
        otherBtn.querySelector('.pause-icon').classList.add('hidden');
      }
    });

    audio.play();
    playIcon.classList.add('hidden');
    pauseIcon.classList.remove('hidden');
  } else {
    audio.pause();
    playIcon.classList.remove('hidden');
    pauseIcon.classList.add('hidden');
  }

  // Atualizar progresso em tempo real
  audio.ontimeupdate = () => {
    if (audio.duration) {
      const percent = (audio.currentTime / audio.duration) * 100;
      progress.style.width = percent + '%';
      
      const mins = Math.floor(audio.currentTime / 60);
      const secs = Math.floor(audio.currentTime % 60).toString().padStart(2, '0');
      timeSpan.textContent = `${mins}:${secs}`;
    }
  };

  audio.onended = () => {
    playIcon.classList.remove('hidden');
    pauseIcon.classList.add('hidden');
    progress.style.width = '0%';
    timeSpan.textContent = '0:00';
  };
};
  // ============================================================
  // MUSICANDO IDEIAS
  // ============================================================
  const barBtnMusica = document.getElementById('barBtnMusica');
  const musicaModal = document.getElementById('musicaModal');
  const btnCloseMusicaModal = document.getElementById('btnCloseMusicaModal');
  const btnOpenMusicaHistory = document.getElementById('btnOpenMusicaHistory');
  const musicaHistoryModal = document.getElementById('musicaHistoryModal');
  const btnCloseMusicaHistory = document.getElementById('btnCloseMusicaHistory');

  const musicaFaixaEtaria = document.getElementById('musicaFaixaEtaria');
  const musicaRitmo = document.getElementById('musicaRitmo');
  const musicaTemaInput = document.getElementById('musicaTemaInput');
  const btnGenerateMusica = document.getElementById('btnGenerateMusica');
  
  const musicaGenerateLoader = document.getElementById('musicaGenerateLoader');
  const musicaResultArea = document.getElementById('musicaResultArea');
  const musicaTextOutput = document.getElementById('musicaTextOutput');
  const btnCopyMusica = document.getElementById('btnCopyMusica');
  const btnDownloadMusicaPdf = document.getElementById('btnDownloadMusicaPdf');

  let currentMusicaEstrofes = 3;
  let currentMusica = '';

  document.querySelectorAll('.btn-musica-estrofes').forEach(btn => {
    btn.addEventListener('click', (e) => {
      document.querySelectorAll('.btn-musica-estrofes').forEach(b => b.classList.remove('active'));
      e.target.classList.add('active');
      currentMusicaEstrofes = parseInt(e.target.dataset.estrofes);
    });
  });

  if (barBtnMusica) {
    barBtnMusica.addEventListener('click', () => {
      musicaModal.style.display = 'flex';
      musicaTemaInput.value = '';
      musicaResultArea.style.display = 'none';
      musicaGenerateLoader.style.display = 'none';
      btnGenerateMusica.disabled = false;
      currentMusica = '';
    });
  }

  if (btnCloseMusicaModal) musicaModal.addEventListener('click', (e) => { if(e.target === musicaModal) musicaModal.style.display = 'none'; });
  if (btnCloseMusicaModal) btnCloseMusicaModal.addEventListener('click', () => musicaModal.style.display = 'none');
  
  if (btnOpenMusicaHistory) {
    btnOpenMusicaHistory.addEventListener('click', () => {
      musicaHistoryModal.style.display = 'flex';
      loadMusicaHistory();
    });
  }
  if (btnCloseMusicaHistory) btnCloseMusicaHistory.addEventListener('click', () => musicaHistoryModal.style.display = 'none');
  musicaHistoryModal.addEventListener('click', (e) => { if(e.target === musicaHistoryModal) musicaHistoryModal.style.display = 'none'; });

  if (btnGenerateMusica) {
    btnGenerateMusica.addEventListener('click', async () => {
      const tema = musicaTemaInput.value.trim();
      if (!tema) {
        showToast('Por favor, informe o tema da música.', 'error');
        return;
      }

      btnGenerateMusica.disabled = true;
      musicaResultArea.style.display = 'none';
      musicaGenerateLoader.style.display = 'flex';

      try {
        const response = await fetch('/api/musicas/generate', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            faixaEtaria: musicaFaixaEtaria.value,
            estrofes: currentMusicaEstrofes,
            ritmo: musicaRitmo.value,
            tema: tema
          })
        });

        const data = await response.json();
        
        if (response.ok) {
          currentMusica = data.musica;
          musicaTextOutput.innerHTML = window.marked ? marked.parse(currentMusica) : currentMusica;
          musicaResultArea.style.display = 'flex';
        } else {
          showToast(data.error || 'Erro ao gerar música.', 'error');
        }
      } catch (err) {
        showToast('Erro de conexão.', 'error');
      } finally {
        musicaGenerateLoader.style.display = 'none';
        btnGenerateMusica.disabled = false;
      }
    });
  }

  if (btnCopyMusica) {
    btnCopyMusica.addEventListener('click', () => {
      if (currentMusica) {
        navigator.clipboard.writeText(currentMusica);
        showToast('Música copiada para a área de transferência!', 'success');
      }
    });
  }

  if (btnDownloadMusicaPdf) {
    btnDownloadMusicaPdf.addEventListener('click', () => {
      if (!currentMusica) return;
      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>Música - Assistente PedaGog</title>
          <style>
            body { font-family: 'Outfit', 'Inter', sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #10b981; margin-top: 24px; margin-bottom: 12px; }
            @media print { body { padding: 0; } button { display: none; } }
          </style>
        </head>
        <body>
          <div style="max-width: 800px; margin: 0 auto;">
            <div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; margin-bottom: 20px;">
              <h1 style="margin: 0;">🎵 Música Pedagógica</h1>
              <button onclick="window.print()" style="background: #10b981; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: bold;">Imprimir / PDF</button>
            </div>
            <div>${window.marked ? marked.parse(currentMusica) : currentMusica}</div>
          </div>
        </body>
        </html>
      `);
      printWindow.document.close();
    });
  }

  async function loadMusicaHistory() {
    const listContainer = document.getElementById('musicaHistoryList');
    if (!listContainer) return;
    listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Carregando...</p>';
    try {
      const response = await fetch('/api/musicas/list');
      const data = await response.json();
      if (data && data.length > 0) {
        listContainer.innerHTML = '';
        data.forEach(item => {
          const date = new Date(item.created_at).toLocaleString('pt-BR');
          const div = document.createElement('div');
          div.className = 'history-item-card';
          div.style.cssText = 'background: rgba(255,255,255,0.02); padding: 14px; border-radius: 8px; border: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 8px; cursor: pointer; position: relative;';
          div.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: flex-start; padding-right: 30px;">
              <strong style="color: var(--brand-green); font-size: 0.95rem;">${item.faixa_etaria} - ${item.ritmo}</strong>
              <span style="font-size: 0.75rem; color: var(--text-secondary);">${date}</span>
            </div>
            <p style="margin: 0; font-size: 0.85rem; color: var(--text-primary); opacity: 0.9;">Tema: ${item.tema}</p>
            <button class="btn-delete-musica" data-id="${item.id}" style="position: absolute; top: 12px; right: 12px; background: transparent; border: none; color: #ef4444; cursor: pointer; font-size: 1.1rem; padding: 4px; border-radius: 4px;" title="Excluir">🗑️</button>
          `;
          div.addEventListener('click', async (e) => {
            if (e.target.closest('.btn-delete-musica')) {
              e.stopPropagation();
              if (confirm('Tem certeza que deseja excluir?')) {
                try {
                  const delRes = await fetch(`/api/musicas/${item.id}`, { method: 'DELETE' });
                  if (delRes.ok) { showToast('Música excluída.', 'success'); loadMusicaHistory(); }
                } catch (err) { showToast('Erro ao excluir.', 'error'); }
              }
              return;
            }
            try {
              const res = await fetch(`/api/musicas/${item.id}`);
              const detail = await res.json();
              if (res.ok) {
                currentMusica = detail.musica;
                musicaTextOutput.innerHTML = window.marked ? marked.parse(currentMusica) : currentMusica;
                musicaResultArea.style.display = 'flex';
                musicaHistoryModal.style.display = 'none';
              }
            } catch (err) { showToast('Erro ao carregar.', 'error'); }
          });
          listContainer.appendChild(div);
        });
      } else {
        listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Nenhum histórico.</p>';
      }
    } catch (err) { listContainer.innerHTML = '<p style="text-align:center; color:#ef4444;">Erro ao carregar.</p>'; }
  }


  // ============================================================
  // INVENTANDO HISTORIAS
  // ============================================================
  const barBtnHistoria = document.getElementById('barBtnHistoria');
  const historiaModal = document.getElementById('historiaModal');
  const btnCloseHistoriaModal = document.getElementById('btnCloseHistoriaModal');
  const btnOpenHistoriaHistory = document.getElementById('btnOpenHistoriaHistory');
  const historiaHistoryModal = document.getElementById('historiaHistoryModal');
  const btnCloseHistoriaHistory = document.getElementById('btnCloseHistoriaHistory');

  const historiaFaixaEtaria = document.getElementById('historiaFaixaEtaria');
  const historiaParagrafos = document.getElementById('historiaParagrafos');
  const historiaPersonagens = document.getElementById('historiaPersonagens');
  const historiaEstilo = document.getElementById('historiaEstilo');
  const historiaTemaInput = document.getElementById('historiaTemaInput');
  const btnGenerateHistoria = document.getElementById('btnGenerateHistoria');
  
  const historiaGenerateLoader = document.getElementById('historiaGenerateLoader');
  const historiaResultArea = document.getElementById('historiaResultArea');
  const historiaTextOutput = document.getElementById('historiaTextOutput');
  const btnCopyHistoria = document.getElementById('btnCopyHistoria');
  const btnDownloadHistoriaPdf = document.getElementById('btnDownloadHistoriaPdf');

  let currentHistoria = '';

  if (barBtnHistoria) {
    barBtnHistoria.addEventListener('click', () => {
      historiaModal.style.display = 'flex';
      historiaTemaInput.value = '';
      historiaResultArea.style.display = 'none';
      historiaGenerateLoader.style.display = 'none';
      btnGenerateHistoria.disabled = false;
      currentHistoria = '';
    });
  }

  if (btnCloseHistoriaModal) historiaModal.addEventListener('click', (e) => { if(e.target === historiaModal) historiaModal.style.display = 'none'; });
  if (btnCloseHistoriaModal) btnCloseHistoriaModal.addEventListener('click', () => historiaModal.style.display = 'none');
  
  if (btnOpenHistoriaHistory) {
    btnOpenHistoriaHistory.addEventListener('click', () => {
      historiaHistoryModal.style.display = 'flex';
      loadHistoriaHistory();
    });
  }
  if (btnCloseHistoriaHistory) btnCloseHistoriaHistory.addEventListener('click', () => historiaHistoryModal.style.display = 'none');
  historiaHistoryModal.addEventListener('click', (e) => { if(e.target === historiaHistoryModal) historiaHistoryModal.style.display = 'none'; });

  if (btnGenerateHistoria) {
    btnGenerateHistoria.addEventListener('click', async () => {
      const tema = historiaTemaInput.value.trim();
      if (!tema) {
        showToast('Por favor, informe o tema da história.', 'error');
        return;
      }

      btnGenerateHistoria.disabled = true;
      historiaResultArea.style.display = 'none';
      historiaGenerateLoader.style.display = 'flex';

      try {
        const response = await fetch('/api/historias/generate', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            faixaEtaria: historiaFaixaEtaria.value,
            paragrafos: historiaParagrafos.value,
            personagens: historiaPersonagens.value,
            estilo: historiaEstilo.value,
            tema: tema
          })
        });

        const data = await response.json();
        
        if (response.ok) {
          currentHistoria = data.historia;
          historiaTextOutput.innerHTML = window.marked ? marked.parse(currentHistoria) : currentHistoria;
          historiaResultArea.style.display = 'flex';
        } else {
          showToast(data.error || 'Erro ao inventar história.', 'error');
        }
      } catch (err) {
        showToast('Erro de conexão.', 'error');
      } finally {
        historiaGenerateLoader.style.display = 'none';
        btnGenerateHistoria.disabled = false;
      }
    });
  }

  if (btnCopyHistoria) {
    btnCopyHistoria.addEventListener('click', () => {
      if (currentHistoria) {
        navigator.clipboard.writeText(currentHistoria);
        showToast('História copiada para a área de transferência!', 'success');
      }
    });
  }

  if (btnDownloadHistoriaPdf) {
    btnDownloadHistoriaPdf.addEventListener('click', () => {
      if (!currentHistoria) return;
      const printWindow = window.open('', '_blank');
      printWindow.document.write(`
        <html>
        <head>
          <title>História - Assistente PedaGog</title>
          <style>
            body { font-family: 'Outfit', 'Inter', sans-serif; padding: 40px; color: #333; line-height: 1.6; }
            h1, h2, h3 { color: #10b981; margin-top: 24px; margin-bottom: 12px; }
            @media print { body { padding: 0; } button { display: none; } }
          </style>
        </head>
        <body>
          <div style="max-width: 800px; margin: 0 auto;">
            <div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 2px solid #e2e8f0; padding-bottom: 10px; margin-bottom: 20px;">
              <h1 style="margin: 0;">✍️ História Pedagógica</h1>
              <button onclick="window.print()" style="background: #10b981; color: white; border: none; padding: 8px 16px; border-radius: 6px; cursor: pointer; font-weight: bold;">Imprimir / PDF</button>
            </div>
            <div>${window.marked ? marked.parse(currentHistoria) : currentHistoria}</div>
          </div>
        </body>
        </html>
      `);
      printWindow.document.close();
    });
  }

  async function loadHistoriaHistory() {
    const listContainer = document.getElementById('historiaHistoryList');
    if (!listContainer) return;
    listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Carregando...</p>';
    try {
      const response = await fetch('/api/historias/list');
      const data = await response.json();
      if (data && data.length > 0) {
        listContainer.innerHTML = '';
        data.forEach(item => {
          const date = new Date(item.created_at).toLocaleString('pt-BR');
          const div = document.createElement('div');
          div.className = 'history-item-card';
          div.style.cssText = 'background: rgba(255,255,255,0.02); padding: 14px; border-radius: 8px; border: 1px solid var(--border-light); display: flex; flex-direction: column; gap: 8px; cursor: pointer; position: relative;';
          div.innerHTML = `
            <div style="display: flex; justify-content: space-between; align-items: flex-start; padding-right: 30px;">
              <strong style="color: var(--brand-green); font-size: 0.95rem;">${item.faixa_etaria} (${item.estilo})</strong>
              <span style="font-size: 0.75rem; color: var(--text-secondary);">${date}</span>
            </div>
            <p style="margin: 0; font-size: 0.85rem; color: var(--text-primary); opacity: 0.9;">Tema: ${item.tema}</p>
            <button class="btn-delete-historia" data-id="${item.id}" style="position: absolute; top: 12px; right: 12px; background: transparent; border: none; color: #ef4444; cursor: pointer; font-size: 1.1rem; padding: 4px; border-radius: 4px;" title="Excluir">🗑️</button>
          `;
          div.addEventListener('click', async (e) => {
            if (e.target.closest('.btn-delete-historia')) {
              e.stopPropagation();
              if (confirm('Tem certeza que deseja excluir?')) {
                try {
                  const delRes = await fetch(`/api/historias/${item.id}`, { method: 'DELETE' });
                  if (delRes.ok) { showToast('História excluída.', 'success'); loadHistoriaHistory(); }
                } catch (err) { showToast('Erro ao excluir.', 'error'); }
              }
              return;
            }
            try {
              const res = await fetch(`/api/historias/${item.id}`);
              const detail = await res.json();
              if (res.ok) {
                currentHistoria = detail.historia;
                historiaTextOutput.innerHTML = window.marked ? marked.parse(currentHistoria) : currentHistoria;
                historiaResultArea.style.display = 'flex';
                historiaHistoryModal.style.display = 'none';
              }
            } catch (err) { showToast('Erro ao carregar.', 'error'); }
          });
          listContainer.appendChild(div);
        });
      } else {
        listContainer.innerHTML = '<p style="text-align:center; color:var(--text-secondary);">Nenhum histórico.</p>';
      }
    } catch (err) { listContainer.innerHTML = '<p style="text-align:center; color:#ef4444;">Erro ao carregar.</p>'; }
  }

if (document.readyState === 'loading') {
  document.addEventListener('DOMContentLoaded', initApp);
} else {
  initApp();
}
// ==========================================================================
// PLANEJAMENTO MIND LAB
// ==========================================================================
document.addEventListener('DOMContentLoaded', () => {
  const barBtnMindLab = document.getElementById('barBtnMindLab');
  const mindLabModal = document.getElementById('mindLabModal');
  const btnCloseMindLabModal = document.getElementById('btnCloseMindLabModal');
  const mindLabGamesGrid = document.getElementById('mindLabGamesGrid');
  const mindLabOutroJogoInput = document.getElementById('mindLabOutroJogoInput');
  const btnGenerateMindLab = document.getElementById('btnGenerateMindLab');
  
  const mindLabJogos = {
    infantil: [
      "Gato e Rato", "Cães e Gatos", "Dominó de Cores", "Quebra-cabeças", "Jogos de Encaixe", "Castelo Lógico", "Safari", "Outro"
    ],
    fund1_inicio: [
      "Mancala", "Quoridor", "Hora do Rush", "Bloqueio", "Lig 4", "Pinguins Numa Fria", "Encruzilhada", "Lince", "Outro"
    ],
    fund1_fim: [
      "Abalone", "Quarto", "Octógono Fantástico", "Sudoku", "Damas", "Resta Um", "Xadrez Chinês", "Cilada", "Outro"
    ],
    fund2: [
      "Xadrez", "Mastermind (Senha)", "Abalone Avançado", "Go", "Hex", "Reversi (Othello)", "Blokus", "Outro"
    ]
  };

  function renderMindLabGames(faixa) {
    mindLabGamesGrid.innerHTML = '';
    const jogos = mindLabJogos[faixa] || [];
    jogos.forEach((jogo, index) => {
      const btn = document.createElement('button');
      btn.type = 'button';
      btn.className = `btn-music-option btn-mindlab-jogo ${index === 0 ? 'active' : ''}`;
      btn.dataset.jogo = jogo;
      btn.textContent = jogo === 'Outro' ? '✏️ Outro...' : `🎲 ${jogo}`;
      
      btn.addEventListener('click', () => {
        document.querySelectorAll('.btn-mindlab-jogo').forEach(b => b.classList.remove('active'));
        btn.classList.add('active');
        if (jogo === 'Outro') {
          mindLabOutroJogoInput.style.display = 'block';
          mindLabOutroJogoInput.focus();
        } else {
          mindLabOutroJogoInput.style.display = 'none';
        }
      });
      mindLabGamesGrid.appendChild(btn);
    });
    mindLabOutroJogoInput.style.display = 'none';
  }

  // Setup Faixa Etária
  document.querySelectorAll('.btn-mindlab-faixa').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-mindlab-faixa').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
      renderMindLabGames(btn.dataset.faixa);
    });
  });

  // Setup Método e Foco
  document.querySelectorAll('.btn-mindlab-metodo').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-mindlab-metodo').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
    });
  });

  document.querySelectorAll('.btn-mindlab-foco').forEach(btn => {
    btn.addEventListener('click', () => {
      document.querySelectorAll('.btn-mindlab-foco').forEach(b => b.classList.remove('active'));
      btn.classList.add('active');
    });
  });

  if (barBtnMindLab) {
    barBtnMindLab.addEventListener('click', () => {
      mindLabModal.style.display = 'flex';
      renderMindLabGames('infantil');
      document.getElementById('mindLabTemaLivreInput').value = '';
    });
  }

  if (btnCloseMindLabModal) {
    btnCloseMindLabModal.addEventListener('click', () => {
      mindLabModal.style.display = 'none';
    });
    mindLabModal.addEventListener('click', (e) => {
      if (e.target === mindLabModal) mindLabModal.style.display = 'none';
    });
  }

  if (btnGenerateMindLab) {
    btnGenerateMindLab.addEventListener('click', async () => {
      const activeFaixa = document.querySelector('.btn-mindlab-faixa.active');
      const activeJogoBtn = document.querySelector('.btn-mindlab-jogo.active');
      const activeMetodo = document.querySelector('.btn-mindlab-metodo.active');
      const activeFoco = document.querySelector('.btn-mindlab-foco.active');
      
      const faixaStr = activeFaixa ? activeFaixa.textContent.replace('🧸 ', '').replace('🎒 ', '').replace('📚 ', '').replace('🎓 ', '') : '';
      let jogoStr = activeJogoBtn ? activeJogoBtn.dataset.jogo : '';
      if (jogoStr === 'Outro') {
        jogoStr = mindLabOutroJogoInput.value.trim() || 'Jogo não especificado';
      }
      
      const metodoStr = activeMetodo ? activeMetodo.dataset.metodo : '';
      const focoStr = activeFoco ? activeFoco.dataset.foco : '';
      const duracaoStr = document.getElementById('mindLabDuracaoSelect').value;
      const temaLivre = document.getElementById('mindLabTemaLivreInput').value.trim();

      const btnG = document.getElementById('btnGenerateMindLab');
      const loader = document.getElementById('mindLabGenerateLoader');
      const resultArea = document.getElementById('mindLabResultArea');
      const output = document.getElementById('mindLabOutput');
      
      btnG.style.display = 'none';
      loader.style.display = 'flex';
      resultArea.style.display = 'none';

      try {
        const res = await fetch('/api/mindlab/generate', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` },
          body: JSON.stringify({ faixa_etaria: faixaStr, jogo: jogoStr, metodo: metodoStr, foco: focoStr, duracao: duracaoStr, tema: temaLivre })
        });
        const data = await res.json();
        if (!res.ok) throw new Error(data.error || 'Erro na requisição');
        
        output.innerHTML = typeof marked !== 'undefined' ? marked.parse(data.planejamento) : data.planejamento;
        output.dataset.raw = data.planejamento;
        resultArea.style.display = 'block';
        btnG.style.display = 'flex';
        btnG.innerHTML = '🧠 Criar Novo Planejamento';
      } catch (err) {
        alert('Erro ao gerar: ' + err.message);
        btnG.style.display = 'flex';
      } finally {
        loader.style.display = 'none';
      }
    });
  }

  const btnCopyMindLab = document.getElementById('btnCopyMindLab');
  if (btnCopyMindLab) {
    btnCopyMindLab.addEventListener('click', () => {
      const output = document.getElementById('mindLabOutput');
      if (output && output.dataset.raw) {
        navigator.clipboard.writeText(output.dataset.raw);
        btnCopyMindLab.innerHTML = '✅ Copiado!';
        setTimeout(() => {
          btnCopyMindLab.innerHTML = '📋 Copiar';
        }, 2000);
      }
    });
  }

  const btnPdfMindLab = document.getElementById('btnPdfMindLab');
  if (btnPdfMindLab) {
    btnPdfMindLab.addEventListener('click', () => {
      const output = document.getElementById('mindLabOutput');
      if (output && output.dataset.raw && window.jspdf) {
        const { jsPDF } = window.jspdf;
        const doc = new jsPDF();
        doc.setFontSize(12);
        doc.setFont("helvetica", "normal");
        const lines = doc.splitTextToSize(output.dataset.raw.replace(/[#*]/g, ''), 180);
        doc.text(lines, 15, 20);
        doc.save('Planejamento_Mind_Lab.pdf');
      } else {
        alert('Carregando biblioteca PDF ou nenhum conteúdo para salvar.');
      }
    });
  }

  const btnOpenMindLabHistory = document.getElementById('btnOpenMindLabHistory');
  const mindLabHistoryModal = document.getElementById('mindLabHistoryModal');
  const btnCloseMindLabHistory = document.getElementById('btnCloseMindLabHistory');
  const mindLabHistoryList = document.getElementById('mindLabHistoryList');

  if (btnOpenMindLabHistory) {
    btnOpenMindLabHistory.addEventListener('click', async () => {
      mindLabHistoryModal.style.display = 'flex';
      mindLabHistoryList.innerHTML = '<div style="text-align: center; color: var(--text-secondary); padding: 20px;">Carregando histórico...</div>';
      try {
        const res = await fetch('/api/mindlab/list', {
          headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
        });
        const data = await res.json();
        mindLabHistoryList.innerHTML = '';
        if (data.length === 0) {
          mindLabHistoryList.innerHTML = '<div style="text-align: center; color: var(--text-secondary); padding: 20px;">Nenhum planejamento salvo ainda.</div>';
          return;
        }
        data.forEach(item => {
          const div = document.createElement('div');
          div.style.background = 'var(--bg-tertiary)';
          div.style.padding = '12px 15px';
          div.style.borderRadius = '8px';
          div.style.display = 'flex';
          div.style.justifyContent = 'space-between';
          div.style.alignItems = 'center';
          div.innerHTML = `
            <div>
              <div style="font-weight: 600; font-size: 0.95rem; color: var(--text-primary);">🎲 ${item.jogo} - ${item.faixa_etaria}</div>
              <div style="font-size: 0.8rem; color: var(--text-secondary); margin-top: 4px;">🎯 ${item.foco}</div>
              <div style="font-size: 0.75rem; color: var(--text-secondary); margin-top: 4px;">${new Date(item.created_at).toLocaleString()}</div>
            </div>
            <div style="display: flex; gap: 8px;">
              <button class="btn-ver-mindlab btn-secondary" data-id="${item.id}" style="padding: 6px 12px; font-size: 0.85rem; border-radius: 6px;">Ver</button>
              <button class="btn-del-mindlab btn-secondary" data-id="${item.id}" style="padding: 6px 12px; font-size: 0.85rem; border-radius: 6px; color: #ef4444; border-color: rgba(239, 68, 68, 0.3);">🗑️</button>
            </div>
          `;
          mindLabHistoryList.appendChild(div);
        });

        document.querySelectorAll('.btn-ver-mindlab').forEach(btn => {
          btn.addEventListener('click', async (e) => {
            const id = e.target.dataset.id;
            try {
              const res = await fetch(`/api/mindlab/${id}`, {
                headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
              });
              const itemData = await res.json();
              
              document.getElementById('mindLabOutput').innerHTML = typeof marked !== 'undefined' ? marked.parse(itemData.planejamento) : itemData.planejamento;
              document.getElementById('mindLabOutput').dataset.raw = itemData.planejamento;
              document.getElementById('mindLabResultArea').style.display = 'block';
              
              mindLabHistoryModal.style.display = 'none';
              document.getElementById('btnGenerateMindLab').style.display = 'flex';
            } catch (err) { alert('Erro ao carregar planejamento.'); }
          });
        });

        document.querySelectorAll('.btn-del-mindlab').forEach(btn => {
          btn.addEventListener('click', async (e) => {
            if(!confirm('Tem certeza que deseja apagar este planejamento?')) return;
            const id = e.target.dataset.id;
            try {
              await fetch(`/api/mindlab/${id}`, {
                method: 'DELETE',
                headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }
              });
              e.target.closest('div[style*="var(--bg-tertiary)"]').remove();
            } catch (err) { alert('Erro ao deletar.'); }
          });
        });

      } catch (err) {
        mindLabHistoryList.innerHTML = '<div style="color: #ef4444; padding: 20px;">Erro ao carregar histórico.</div>';
      }
    });
  }

  if (btnCloseMindLabHistory) {
    btnCloseMindLabHistory.addEventListener('click', () => {
      mindLabHistoryModal.style.display = 'none';
    });
  }
});
