Todos os sistemas operando

Bem-vindo à evob.
Como podemos ajudar?

Tudo que você precisa para tirar o máximo da sua plataforma — guias, vídeos, dúvidas frequentes e suporte humano.

Comece por aqui

Trilha sob medida pra você

Roteiros passo a passo conforme seu papel na plataforma.

Explore por área

Tudo que sua plataforma faz, organizado em pastinhas.

Os mais buscados

Atualizados recentemente

Não achou o que procurava?

Nosso time de Customer Success responde em até 30 minutos nos planos Pro e superiores.

Informações básicas do curso

os campos da ficha do curso (descrição, carga horária, nível, idioma, pré-requisitos) determinam tanto o SEO da página de venda quanto a expectativa do aluno — preencher bem aumenta conversão e reduz reembolso.

# Informações básicas do curso

⏱️ 6 min de leitura · 🏷️ Cursos · 👤 Admin de Loja · Admin de Curso · 🆓 Todos os planos
Em 1 frase: os campos da ficha do curso (descrição, carga horária, nível, idioma, pré-requisitos) determinam tanto o SEO da página de venda quanto a expectativa do aluno — preencher bem aumenta conversão e reduz reembolso.

Onde editar

Dashboard do Curso → Configurações > Informações Gerais.

Campos:

  • Nome do curso
  • Descrição curta
  • Descrição longa
  • Carga horária
  • Idioma
  • Nível
  • Pré-requisitos
  • Para quem é
  • Tags

Nome do curso

Aparece em: vitrine, AVA, certificado, emails, busca interna. Boas práticas:
  • Curto e descritivo (3-7 palavras)
  • ✅ Inclui palavra-chave principal (SEO)
  • Promessa clara (o que o aluno consegue depois)
  • ❌ Nome interno técnico ("Curso v2.3 com bônus")
  • ❌ Hype excessivo ("O Melhor Curso de Marketing do Brasil")
Exemplos bons:
  • "Marketing Digital do Zero ao Avançado"
  • "Inglês para Negócios — B2 Profissional"
  • "Edição de Vídeo Cinematográfica com DaVinci Resolve"

Descrição curta

Onde aparece:
  • Preview na vitrine (abaixo do thumbnail)
  • Meta description em SEO
  • Compartilhamento social (`og:description`)
  • Resultado de busca interna
Limite: 200 caracteres. Boas práticas:
  • Resuma o benefício em 1 frase
  • Mencione o público-alvo
  • Use verbos de ação (aprenda, domine, conquiste)
Exemplos:
  • ✅ "Aprenda a criar campanhas que vendem em 8 semanas — para quem nunca trabalhou com marketing digital."
  • ❌ "Curso completo. Aulas em vídeo. Comprovante de conclusão. 30 dias de garantia." (genérico)

Descrição longa

Onde aparece: página de venda do curso. Limite: 5.000 caracteres (~700 palavras). Use rich text:
  • Negrito, itálico
  • Listas com bullet
  • Headings (H2, H3)
  • Links

Estrutura recomendada

A descrição longa funciona como carta de venda. Estrutura provada:

  1. Promessa principal (1 parágrafo)

> "Em 8 semanas, você vai sair desse curso sabendo criar uma campanha completa no Meta Ads — do criativo à análise de ROI."

  1. Para quem é (lista)

> Este curso é para você se: > - Nunca trabalhou com marketing digital > - Trabalha em agência e precisa entregar resultado > - Tem pequeno negócio e quer parar de pagar agência

  1. O que você vai aprender (lista de outcomes)

> Ao final, você vai conseguir: > - Criar campanhas no Meta Ads do zero > - Analisar métricas e otimizar > - Entender funis de vendas > - …

  1. Sobre o professor (1-2 parágrafos)

> João Silva é especialista em…

  1. Estrutura do curso (lista de módulos)
  1. Bônus e materiais (se houver)
  1. Garantia (selo de 7 dias)
  1. CTA final
💡 Não copie texto de venda do Hotmart/Eduzz literal. Reescreva — já vimos casos de Google penalizar duplicate content.

Carga horária

Aparece em:
  • Vitrine (badge "40h" ou "40 horas")
  • Certificado (oficial, validação MEC se for o caso)
  • SEO
Como calcular:
  • Some a duração de todas as aulas em vídeo
  • Adicione tempo estimado de leitura dos textos
  • Adicione tempo estimado de resolução dos quizzes
  • Adicione tempo estimado de prática (se houver materiais para fazer offline)
💡 Não infle. Aluno chega no curso e percebe se tem 40h reais ou só 8h. Reembolso e NPS detrator vêm dessa fricção.
Carga horária padrão por tipo:

| Tipo de curso | Carga típica | |---|---| | Workshop curto | 4-8h | | Curso completo | 20-60h | | Pós-graduação | 360h+ | | Mentoria | varia (geralmente declarado por encontro) |

Idioma

Idiomas suportados: pt-BR, en, es.

Se o curso é em inglês para brasileiros, use pt-BR (cliente é brasileiro). Se o curso é em português para latino-americanos, considere es se traduzir os materiais.

💡 Curso multi-idioma: se você tem aulas dubladas em 2 idiomas, crie 2 cursos separados com mesmo nome e idioma diferente. Aluno escolhe na hora da compra.

Nível

3 níveis padrão:

  • Iniciante — quem não sabe nada do tema
  • Intermediário — quem já tem base e quer aprofundar
  • Avançado — quem já é praticante e quer especialização
💡 Atribuir nível ajuda no SEO (pessoas pesquisam "curso de X iniciante" no Google).

Pré-requisitos

Texto livre. Use para alinhar expectativa.

Exemplos:
  • "Saber inglês básico (B1)"
  • "Conhecimento prévio em HTML e CSS"
  • "Computador com mínimo 8GB de RAM e Photoshop instalado"
  • "Nenhum — começamos do zero"
💡 Aluno que entra sem o pré-requisito vira detrator. Vale fechar a porta do que não pode entrar do que ter cliente errado.

Para quem é

Texto livre. Complementa a descrição longa.

Exemplos:
  • "Designers freelancers que querem aumentar ticket"
  • "Gestores de marketing que cuidam de orçamentos > R$ 10k/mês"
  • "Profissionais de RH responsáveis por treinamento corporativo"
💡 Quanto mais específico, melhor. "Para qualquer um" não vende; "para gerentes de marketing de PMEs" vende.

Tags (SEO interno)

Adicione 3-7 tags relevantes:

  • `marketing-digital`
  • `meta-ads`
  • `google-ads`
  • `funil-de-vendas`
  • `iniciante`
Onde aparecem:
  • Busca interna do AVA ("alunos buscaram por X")
  • Filtros da vitrine
  • SEO da página
💡 Não use tags com poucas buscas. Pense no que o aluno digitaria no Google para encontrar.

Pré-visualização

No topo do Dashboard do Curso, botão Pré-visualizar. Mostra como a página de venda vai aparecer antes de publicar.

Compare em:

  • Desktop
  • Mobile
  • Modo escuro (se ativo)

SEO técnico

A evob otimiza automaticamente:

  • `` da página = nome do curso</li></ul> <ul><li>`<meta description>` = descrição curta</li></ul> <ul><li>`og:image` = thumbnail</li></ul> <ul><li>`og:title` e `og:description` = SEO</li></ul> <ul><li>Schema.org `Course` (Google Rich Results)</li></ul> <blockquote>💡 <strong>Você não precisa configurar nada manualmente.</strong> Só preencha bem os campos.</blockquote> <h2>Boas práticas</h2> <h3>✅ Faça</h3> <ul><li><strong>Pesquise palavras-chave</strong> antes de nomear (Ubersuggest, AnswerThePublic)</li></ul> <ul><li><strong>Reescreva</strong> a descrição longa em vez de copiar de outro lugar</li></ul> <ul><li><strong>Atualize</strong> carga horária se você adicionar aulas depois</li></ul> <ul><li><strong>Teste preview</strong> em mobile antes de publicar</li></ul> <h3>❌ Não faça</h3> <ul><li>Nome com <strong>emoji</strong> ("🚀 CURSO INCRÍVEL 🚀") — afeta SEO e parece spam</li></ul> <ul><li>Descrição cheia de <strong>CAIXA ALTA</strong></li></ul> <ul><li>Promessa <strong>irrealista</strong> ("ganhe R$ 50k/mês após 3 dias")</li></ul> <ul><li>Esquecer de preencher <strong>descrição longa</strong> (página de venda fica vazia)</li></ul> <h2>Erros comuns</h2> <h3>"Descrição truncada na vitrine"</h3> <p>Você passou de 200 chars na curta. Encurte. </p> <h3>"SEO não pega palavra-chave"</h3> <p>Coloque a palavra-chave no <strong>nome</strong> + <strong>primeira frase da descrição longa</strong> + 1 tag. </p> <h3>"Carga horária errada no certificado"</h3> <p>Certificado puxa do campo `carga_horaria`. Atualize em <strong>Informações Gerais</strong> que o certificado regenera. </p> <h3>"Página de venda parece curta"</h3> <p>Descrição longa < 200 palavras. Aprofunde, expanda, adicione bônus, FAQ, depoimentos. </p> <h3>"Aluno reclama que esperava outra coisa"</h3> <p>Provável: descrição genérica/inflada. Reveja <strong>promessa principal</strong> e <strong>para quem é</strong>. </p> <hr> <h3>Próximos passos</h3> <ul><li>📖 <a href="./3-3-imagens-curso.md">Imagens do curso (thumbnail, capa)</a></li></ul> <ul><li>📖 <a href="./3-4-criar-modulos.md">Criar módulos</a></li></ul> <ul><li>📖 <strong>Tags e SEO do curso</strong> <em>(em produção)</em></li></ul> <ul><li>📖 <a href="./3-8-publicar-curso.md">Como publicar um curso</a></li></ul> <hr> <strong>Foi útil este artigo?</strong> 👍 👎 <strong>Falar com CS</strong> <em>(em produção)</em> · <strong>Pergunte ao Vob 🤖</strong> <em>(em produção)</em> <em>Última atualização: 2026-05-01</em> </div> </article> </div> <div class="max-w-[1200px] mx-auto px-5 md:px-6 py-7 md:py-14"> <article class="prose mx-auto"> <button id="article-back-mobile" class="article-back-mobile hover:text-gray-900"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width:16px;height:16px;"><path d="M19 12H5"/><path d="m12 19-7-7 7-7"/></svg> Central de Ajuda </button> <nav id="breadcrumb" class="text-[13.5px] text-gray-500 mb-5 flex items-center gap-1.5 flex-wrap"></nav> <h1 id="article-title"></h1> <p id="article-lede" class="lede"></p> <div class="flex flex-wrap items-center justify-between gap-3 mb-10 -mt-4"> <div id="article-meta-strip" class="flex flex-wrap gap-x-3 gap-y-1 text-[12.5px] text-gray-500 items-center"></div> <button id="copy-link-btn" class="text-[12.5px] text-gray-500 hover:text-gray-900 inline-flex items-center gap-1.5"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.7" style="width:14px;height:14px;"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg> Copiar link </button> </div> <div id="article-content"></div> <hr /> <div class="flex flex-wrap items-center justify-between gap-4 text-[14px] text-gray-600 my-2"> <div class="flex items-center gap-2"> <span>Este artigo foi útil?</span> <button class="ml-2 px-3 py-1.5 rounded-md border border-soft hover:border-gray-400 hover:bg-gray-50 text-[13px] inline-flex items-center gap-1.5"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.7" style="width:14px;height:14px;"><path d="M7 10v12"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H7v-12l4-9a3 3 0 0 1 4 4z"/></svg> Sim </button> <button class="px-3 py-1.5 rounded-md border border-soft hover:border-gray-400 hover:bg-gray-50 text-[13px] inline-flex items-center gap-1.5"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.7" style="width:14px;height:14px;"><path d="M17 14V2"/><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H17v12l-4 9a3 3 0 0 1-4-4z"/></svg> Não </button> </div> <a href="#" class="text-[13.5px] text-gray-500 hover:text-gray-900 underline decoration-gray-300 underline-offset-4">Sugerir uma melhoria</a> </div> <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mt-8" id="article-nav-pn"></div> <div class="rounded-xl bg-gradient-to-br from-[#f5f3ff] to-[#ede9fe] border border-soft p-6 mt-10"> <div class="flex items-start gap-4"> <div class="flex-shrink-0 inline-flex items-center justify-center w-12 h-12 rounded-xl bg-white border border-purple-100 text-brand"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.6" style="width:22px;height:22px;"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg> </div> <div class="flex-1"> <div class="font-semibold text-gray-900 mb-1">Ainda com dúvida?</div> <p class="text-[14px] text-gray-600 leading-relaxed mb-3">Nosso time responde em até 30 minutos nos planos Pro e superiores.</p> <button class="bg-brand hover:bg-[#4a0ea3] text-white text-[13.5px] font-medium px-4 h-9 rounded-md inline-flex items-center gap-2"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" style="width:14px;height:14px;"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg> Falar com a evob </button> </div> </div> </div> </article> </div> </main> <!-- SEARCH MODAL --> <div id="search-modal" class="hidden fixed inset-0 z-50 flex items-start justify-center pt-24 px-4 modal-backdrop"> <div class="bg-white rounded-2xl shadow-2xl w-full max-w-2xl max-h-[60vh] flex flex-col overflow-hidden"> <div class="border-b border-soft p-3.5 flex items-center gap-3"> <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-gray-400 flex-shrink-0"><circle cx="11" cy="11" r="8"></circle><line x1="21" y1="21" x2="16.65" y2="16.65"></line></svg> <input id="search-input" type="text" placeholder="O que você quer aprender hoje?" class="flex-1 outline-none text-[16px] placeholder:text-gray-400" autocomplete="off" /> <kbd>esc</kbd> </div> <div id="search-results" class="overflow-y-auto p-2"></div> <div class="border-t border-soft p-3 text-[12px] text-gray-500 flex items-center gap-4"> <span class="flex items-center gap-1"><kbd>↑</kbd><kbd>↓</kbd> navegar</span> <span class="flex items-center gap-1"><kbd>↵</kbd> abrir</span> <span class="flex items-center gap-1"><kbd>esc</kbd> fechar</span> </div> </div> </div> <!-- FOOTER --> <footer class="border-t border-soft bg-white py-8 px-6 mt-16"> <div class="max-w-[1200px] mx-auto flex flex-wrap items-center justify-between gap-4 text-[13px] text-gray-500"> <div class="flex items-center gap-2"> <img src="../../assets/evob-icon.png" alt="evob" class="w-5 h-5 rounded object-contain" /> <span>© 2026 evob — todos os direitos reservados</span> </div> <div class="flex items-center gap-5"> <a href="../../docs.html" class="hover:text-gray-900">Documentação técnica</a> <a href="#" class="hover:text-gray-900">Status</a> <a href="#" class="hover:text-gray-900">Termos</a> <a href="#" class="hover:text-gray-900">Privacidade</a> </div> </div> </footer> <script> 'use strict' // ─── ICONES (line-art, stroke 1.6, baseado em Iconsax/Lucide) ─────────── const ICONS = { rocket: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4.5 16.5c-1.5 1.26-2 5-2 5s3.74-.5 5-2c.71-.84.7-2.13-.09-2.91a2.18 2.18 0 0 0-2.91-.09z"/><path d="m12 15-3-3a22 22 0 0 1 2-3.95A12.88 12.88 0 0 1 22 2c0 2.72-.78 7.5-6 11a22.35 22.35 0 0 1-4 2z"/><path d="M9 12H4s.55-3.03 2-4c1.62-1.08 5 0 5 0"/><path d="M12 15v5s3.03-.55 4-2c1.08-1.62 0-5 0-5"/></svg>', building: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="2" width="16" height="20" rx="2"/><path d="M9 22v-4h6v4"/><path d="M8 6h.01"/><path d="M16 6h.01"/><path d="M12 6h.01"/><path d="M12 10h.01"/><path d="M12 14h.01"/><path d="M16 10h.01"/><path d="M16 14h.01"/><path d="M8 10h.01"/><path d="M8 14h.01"/></svg>', storefront: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M2 7l1.5-4h17L22 7"/><path d="M2 7v2a3 3 0 0 0 6 0 3 3 0 0 0 6 0 3 3 0 0 0 6 0 3 3 0 0 0 2-2.83V7"/><path d="M4 12v8a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-8"/><path d="M9 21v-6h6v6"/></svg>', book: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M4 19.5A2.5 2.5 0 0 1 6.5 17H20"/><path d="M6.5 2H20v20H6.5A2.5 2.5 0 0 1 4 19.5v-15A2.5 2.5 0 0 1 6.5 2z"/></svg>', ticket: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M2 9V7a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v2a2 2 0 0 0 0 6v2a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-2a2 2 0 0 0 0-6z"/><path d="M13 5v2"/><path d="M13 17v2"/><path d="M13 11v2"/></svg>', users: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></svg>', wallet: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12V7H5a2 2 0 0 1 0-4h14v4"/><path d="M3 5v14a2 2 0 0 0 2 2h16v-5"/><path d="M18 12a2 2 0 0 0 0 4h4v-4z"/></svg>', megaphone: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m3 11 18-5v12L3 14v-3z"/><path d="M11.6 16.8a3 3 0 1 1-5.8-1.6"/></svg>', lifebuoy: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="4"/><path d="m4.93 4.93 4.24 4.24"/><path d="m14.83 9.17 4.24-4.24"/><path d="m14.83 14.83 4.24 4.24"/><path d="m9.17 14.83-4.24 4.24"/></svg>', search: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>', clock: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>', flame: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M8.5 14.5A2.5 2.5 0 0 0 11 12c0-1.38-.5-2-1-3-1.072-2.143-.224-4.054 2-6 .5 2.5 2 4.9 4 6.5 2 1.6 3 3.5 3 5.5a7 7 0 1 1-14 0c0-1.153.433-2.294 1-3a2.5 2.5 0 0 0 2.5 2.5z"/></svg>', sparkles: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/></svg>', chat: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>', bot: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/></svg>', pencil: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z"/><path d="m15 5 4 4"/></svg>', arrowRight: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>', arrowLeft: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M19 12H5"/><path d="m12 19-7-7 7-7"/></svg>', thumbUp: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v12"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H7v-12l4-9a3 3 0 0 1 4 4z"/></svg>', thumbDown: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M17 14V2"/><path d="M9 18.12 10 14H4.17a2 2 0 0 1-1.92-2.56l2.33-8A2 2 0 0 1 6.5 2H17v12l-4 9a3 3 0 0 1-4-4z"/></svg>', chevron: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>', trophy: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9H4.5a2.5 2.5 0 0 1 0-5H6"/><path d="M18 9h1.5a2.5 2.5 0 0 0 0-5H18"/><path d="M4 22h16"/><path d="M10 14.66V17c0 .55-.47.98-.97 1.21C7.85 18.75 7 20.24 7 22"/><path d="M14 14.66V17c0 .55.47.98.97 1.21C16.15 18.75 17 20.24 17 22"/><path d="M18 2H6v7a6 6 0 0 0 12 0V2Z"/></svg>', chart: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M3 3v16a2 2 0 0 0 2 2h16"/><path d="M7 16V8"/><path d="M12 16v-5"/><path d="M17 16v-3"/></svg>', palette: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><circle cx="13.5" cy="6.5" r=".5" fill="currentColor"/><circle cx="17.5" cy="10.5" r=".5" fill="currentColor"/><circle cx="8.5" cy="7.5" r=".5" fill="currentColor"/><circle cx="6.5" cy="12.5" r=".5" fill="currentColor"/><path d="M12 2a10 10 0 0 0 0 20 4 4 0 0 0 4-4 2 2 0 0 1 2-2h3a3 3 0 0 0 3-3 10 10 0 0 0-12-11Z"/></svg>', plug: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"><path d="M12 22v-5"/><path d="M9 8V2"/><path d="M15 8V2"/><path d="M18 8v5a4 4 0 0 1-4 4h-4a4 4 0 0 1-4-4V8Z"/></svg>', } function icon(name) { return ICONS[name] || '' } // ─── CATÁLOGO (subset cliente — sem áreas técnicas) ───────────────────── // 9 áreas amigáveis (sem Integrações, sem API, sem Webhooks) const CATALOG = [ { slug:'onboarding', icon:'rocket', color:'bg-orange-50 text-orange-700 border-orange-200', title:'Primeiros passos', desc:'Comece por aqui — sua plataforma do login à primeira venda.', subs:[ { slug:'welcome', title:'Boas-vindas', items:[ { s:'o-que-e-evob', t:'O que é a evob? Visão geral em 5 minutos', f:'onboarding/0-1-1-o-que-e-evob.md', time:'5 min', desc:'A plataforma whitelabel onde você monta sua própria escola online.' }, { s:'hierarquia', t:'Hierarquia: Plataforma → Loja → Curso → Oferta', f:'onboarding/0-1-2-hierarquia-da-plataforma.md', time:'4 min', desc:'Entenda as 5 camadas da evob.' }, { s:'glossario', t:'Glossário evob', f:'onboarding/0-1-3-glossario.md', time:'6 min', desc:'Todos os termos do admin.' }, { s:'tour-admin', t:'Tour pelo admin — onde tudo está', f:'onboarding/0-1-4-tour-pelo-admin.md', time:'7 min', desc:'Passeio guiado pelas áreas do admin.' }, { s:'pedir-suporte', t:'Como pedir suporte', f:'onboarding/0-1-5-pedir-suporte.md', time:'3 min', desc:'O caminho mais rápido para resolver dúvidas.' }, ]}, { slug:'trails', title:'Trilhas por persona', items:[ { s:'trilha-plataforma', t:'Trilha: Admin de Plataforma', f:'onboarding/0-2-1-trilha-admin-plataforma.md', time:'12 min', desc:'Roteiro completo do dono da plataforma.' }, { s:'trilha-loja', t:'Trilha: Admin de Loja', f:'onboarding/0-2-2-trilha-admin-loja.md', time:'9 min', desc:'Roteiro completo de quem opera uma loja.' }, { s:'trilha-curso', t:'Trilha: Admin de Curso', f:'onboarding/0-2-3-trilha-admin-curso.md', time:'7 min', desc:'Roteiro completo de quem cuida do conteúdo.' }, { s:'checklist-pronta', t:'Checklist: plataforma 100% configurada', f:'onboarding/0-2-4-checklist-plataforma-pronta.md', time:'5 min', desc:'32 itens para o go-live.' }, ]}, { slug:'migration', title:'Vindo de outro lugar', items:[ { s:'mig-hotmart', t:'Vindo do Hotmart — mapa de termos e migração', f:'onboarding/0-3-1-vindo-do-hotmart.md', time:'8 min', desc:'Tradução de termos + roteiro de 5 passos para migrar do Hotmart.' }, { s:'mig-eduzz', t:'Vindo do Eduzz — mapa de termos e migração', f:'onboarding/0-3-2-vindo-do-eduzz.md', time:'7 min', desc:'Tradução de termos + roteiro de 5 passos para migrar do Eduzz.' }, { s:'mig-kiwify', t:'Vindo do Kiwify — mapa de termos e migração', f:'onboarding/0-3-3-vindo-do-kiwify.md', time:'6 min', desc:'Migração mais simples das três; conceitos próximos.' }, { s:'mig-curseduca', t:'Vindo do Curseduca / Ensinio — mapa de termos', f:'onboarding/0-3-4-vindo-do-curseduca-ensinio.md', time:'6 min', desc:'Quando faz sentido migrar de um LMS whitelabel para outro.' }, { s:'mig-import', t:'Importação de cursos e alunos em lote', f:'onboarding/0-3-5-importacao-cursos-alunos.md', time:'10 min', desc:'CSV de alunos e matrículas, LGPD, erros comuns.' }, { s:'evob-vs', t:'O que evob faz diferente', f:'onboarding/0-3-6-evob-vs-concorrentes.md', time:'5 min', desc:'Comparativo direto com Hotmart, Eduzz, Kiwify, Curseduca, Ensinio.' }, ]}, ]}, { slug:'plataforma', icon:'building', color:'bg-violet-50 text-violet-700 border-violet-200', title:'Plataforma', desc:'Marca, domínio, equipe, segurança e add-ons.', subs:[ { slug:'p-conceitos', title:'Conceitos', items:[ { s:'p-conceito', t:'O que é a evob — conceito de plataforma', f:'plataforma/1-8-conceito-plataforma.md', time:'2 min', desc:'O nível raiz da evob — onde você configura identidade, equipe e cria as lojas.' }, { s:'p-vs-loja', t:'Plataforma vs. loja — diferença de escopo', f:'plataforma/1-9-plataforma-vs-loja.md', time:'2 min', desc:'O que é global e o que é independente por loja.' }, { s:'p-quem-admin', t:'Quem deve ser Admin de Plataforma', f:'plataforma/1-10-quem-admin-plataforma.md', time:'2 min', desc:'Acesso total — reserve para sócios e responsável pela operação.' }, { s:'p-tipos-uso', t:'Modelos de uso — escola, B2B, franquia e marketplace', f:'plataforma/1-11-tipos-uso.md', time:'3 min', desc:'Como cada modelo de negócio usa a evob de forma diferente.' }, ]}, { slug:'p-setup', title:'Criação e setup', items:[ { s:'p-criar', t:'Como criar sua primeira evob', f:'plataforma/1-1-criar-plataforma.md', time:'6 min', desc:'Do primeiro login ao estado em que você pode criar lojas e cursos.' }, { s:'p-prereq', t:'Pré-requisitos antes de criar lojas', f:'plataforma/1-12-pre-requisitos.md', time:'2 min', desc:'CNPJ, domínio e identidade visual que precisam estar prontos primeiro.' }, { s:'p-subdominio', t:'Subdomínio padrão e domínio próprio', f:'plataforma/1-13-subdominio.md', time:'3 min', desc:'nome.evob.com.br disponível de imediato — troque pelo domínio da marca.' }, { s:'p-contato', t:'E-mail e endereço da evob', f:'plataforma/1-14-contato-plataforma.md', time:'2 min', desc:'Dados que aparecem em contratos, documentos legais e comunicações.' }, { s:'p-seo', t:'SEO da evob — meta título e descrição', f:'plataforma/1-15-seo-plataforma.md', time:'2 min', desc:'Configure title, description e imagem OG para aparecer bem nos buscadores.' }, { s:'p-dominio', t:'Domínio próprio e DNS', f:'plataforma/1-2-dominio.md', time:'7 min', desc:'Apontar cursos.suamarca.com.br para a evob — passo a passo + troubleshooting.' }, { s:'p-ssl', t:'Certificado SSL automático', f:'plataforma/1-2b-ssl.md', time:'4 min', desc:'O cadeado verde, gerado e renovado pela evob via Let\'s Encrypt.' }, ]}, { slug:'p-identidade', title:'Identidade visual', items:[ { s:'p-logos', t:'Configurar logos (header, login, admin)', f:'plataforma/1-4-logos.md', time:'5 min', desc:'Os 4 logos diferentes da evob e onde cada um aparece.' }, { s:'p-cores', t:'Paleta de cores — guia completo', f:'plataforma/1-5-cores.md', time:'6 min', desc:'2 cores configuram toda a interface. Acessibilidade e contraste.' }, { s:'p-banner', t:'Banner da tela de login', f:'plataforma/1-16-banner-login.md', time:'2 min', desc:'Primeira imagem do admin — configure com a identidade visual da marca.' }, { s:'p-cor-prim', t:'Cor primária — impacto e boas práticas', f:'plataforma/1-17-cor-primaria.md', time:'2 min', desc:'Botões, links e destaques — como escolher com contraste adequado.' }, { s:'p-fonte', t:'Tipografia personalizada', f:'plataforma/1-18-fonte.md', time:'2 min', desc:'Substitua a fonte padrão pela fonte da sua identidade visual.' }, { s:'p-fonte-base', t:'Fonte base — texto corrido', f:'plataforma/1-19-fonte-base.md', time:'2 min', desc:'Define o texto corrido de toda a interface — configure após a fonte principal.' }, { s:'p-acess', t:'Acessibilidade — contraste e legibilidade', f:'plataforma/1-20-acessibilidade.md', time:'2 min', desc:'Contraste adequado garante que todos os alunos leiam o conteúdo.' }, { s:'p-preview', t:'Preview de identidade visual', f:'plataforma/1-21-preview-identidade.md', time:'2 min', desc:'Veja como ficam cor e fonte antes de publicar as mudanças.' }, ]}, { slug:'p-seguranca', title:'Login e segurança', items:[ { s:'p-mfa-admin', t:'MFA — conceito e funcionamento', f:'plataforma/1-24-mfa-conceito.md', time:'2 min', desc:'Dois fatores bloqueiam o acesso mesmo se a senha for comprometida.' }, { s:'p-2fa', t:'MFA obrigatório para alunos', f:'plataforma/1-25-mfa-aluno.md', time:'2 min', desc:'Configure 2FA obrigatório para alunos com dados sensíveis ou conteúdo premium.' }, { s:'p-sessao', t:'Sessão e timeout de login', f:'plataforma/1-22-sessao.md', time:'2 min', desc:'Configure o tempo de inatividade que encerra a sessão e força novo login.' }, { s:'p-multi-disp', t:'Multi-dispositivos e sessões simultâneas', f:'plataforma/1-23-multi-dispositivos.md', time:'2 min', desc:'Quantos dispositivos simultâneos um admin pode usar — encerramento remoto.' }, { s:'p-recaptcha', t:'reCAPTCHA no login e checkout', f:'plataforma/1-26-recaptcha.md', time:'2 min', desc:'Bloqueia bots e cadastros automatizados no checkout e tela de login.' }, { s:'p-bloqueio', t:'Tentativas de login e bloqueio de conta', f:'plataforma/1-27-tentativas-login.md', time:'2 min', desc:'Bloqueio após tentativas protege contas de ataques de força bruta.' }, { s:'p-2fa-orig', t:'Ativar 2FA para admin (guia original)', f:'plataforma/1-3-2fa.md', time:'5 min', desc:'Camada extra de segurança — obrigatório para Admin de Plataforma.' }, ]}, { slug:'p-equipe', title:'Equipe e permissões', items:[ { s:'p-convite', t:'Convidar admin para a evob', f:'plataforma/1-6-convidar-admin.md', time:'5 min', desc:'Caminho oficial para dar acesso, com perfil correto.' }, { s:'p-tipos-admin', t:'Tipos de admin: manage, editor, financial e mais', f:'plataforma/1-7-tipos-admin.md', time:'6 min', desc:'Os 5 perfis pré-definidos + permissões granulares.' }, { s:'p-abilities', t:'Abilities granulares de admin', f:'plataforma/1-28-abilities-admin.md', time:'3 min', desc:'Perfis com acesso específico a cada área do sistema.' }, { s:'p-remover', t:'Remover acesso de admin', f:'plataforma/1-29-remover-admin.md', time:'2 min', desc:'Revogue o acesso imediatamente — a remoção é reversível.' }, { s:'p-auditoria', t:'Auditoria de ações', f:'plataforma/1-30-auditoria.md', time:'3 min', desc:'Log imutável de quem fez o quê e quando — essencial para investigar incidentes.' }, { s:'p-plat-vs-loja', t:'Admin de Plataforma vs. Admin de Loja', f:'plataforma/1-31-admin-plataforma-vs-loja.md', time:'2 min', desc:'Admin de Plataforma vê todas as lojas; Admin de Loja vê apenas a sua.' }, ]}, { slug:'p-addons', title:'Add-ons e planos', items:[ { s:'p-addons-o-que', t:'O que são add-ons', f:'plataforma/1-32-o-que-sao-addons.md', time:'2 min', desc:'Módulos que ampliam a evob — habilitados por plano ou avulso.' }, { s:'p-addons-hab', t:'Como habilitar e desabilitar add-ons', f:'plataforma/1-33-habilitar-addons.md', time:'2 min', desc:'Habilite ou desabilite sem perda de dados — a mudança é imediata.' }, { s:'p-gami', t:'Add-on Gamificação', f:'plataforma/1-34-addon-gamificacao.md', time:'3 min', desc:'Pontos, badges, rankings e recompensas para engajar alunos no AVA.' }, { s:'p-member', t:'Add-on Member Area', f:'plataforma/1-35-addon-member-area.md', time:'3 min', desc:'Comunidade exclusiva com posts, eventos e conteúdo extra.' }, { s:'p-afil', t:'Add-on Afiliados', f:'plataforma/1-36-addon-afiliados.md', time:'3 min', desc:'Programa de indicação com links rastreáveis e comissão automática.' }, { s:'p-assin', t:'Add-on Assinatura', f:'plataforma/1-37-addon-assinatura.md', time:'3 min', desc:'Cobrança recorrente — acesso mensal ou anual a cursos e catálogos.' }, { s:'p-sso', t:'Add-on SSO', f:'plataforma/1-38-addon-sso.md', time:'4 min', desc:'Login com credenciais corporativas — Google, Microsoft, Okta e outros.' }, { s:'p-ia', t:'Add-on IA', f:'plataforma/1-39-addon-ia.md', time:'3 min', desc:'Gera descrições, tags e sugestões de conteúdo para cursos e aulas.' }, { s:'p-anot', t:'Add-on Anotações', f:'plataforma/1-40-addon-anotacoes.md', time:'2 min', desc:'Alunos salvam notas vinculadas ao instante exato do vídeo.' }, { s:'p-plano', t:'Mudar de plano', f:'plataforma/1-41-mudar-plano.md', time:'3 min', desc:'Upgrade ou downgrade — o que muda nos limites e add-ons disponíveis.' }, ]}, { slug:'p-publicacao', title:'Publicação', items:[ { s:'p-pub', t:'Publicar a evob', f:'plataforma/1-42-publicar-plataforma.md', time:'3 min', desc:'Torna o AVA acessível aos alunos — revise identidade, lojas e cursos antes.' }, { s:'p-pre-pub', t:'Pré-requisitos antes de publicar', f:'plataforma/1-43-pre-publicar.md', time:'3 min', desc:'Checklist completo: domínio, gateway, conteúdo e testes antes do go-live.' }, { s:'p-despub', t:'Despublicar a evob', f:'plataforma/1-44-despublicar.md', time:'2 min', desc:'Torna o AVA inacessível para alunos — use para manutenção.' }, { s:'p-rascunho', t:'Modo rascunho', f:'plataforma/1-45-rascunho.md', time:'2 min', desc:'Estado inicial: configurável e invisível para alunos até publicar.' }, ]}, ]}, { slug:'lojas', icon:'storefront', color:'bg-blue-50 text-blue-700 border-blue-200', title:'Lojas', desc:'Espaços comerciais dentro da sua conta evob.', subs:[ { slug:'l-conceitos', title:'Conceitos', items:[ { s:'l-o-que-e', t:'O que é uma loja na evob', f:'lojas/2-6-o-que-e-loja.md', time:'3 min', desc:'Hierarquia evob, o que o admin gerencia e o que o aluno vê.' }, { s:'l-multi', t:'Multi-lojas — quando usar', f:'lojas/2-7-multi-lojas.md', time:'2 min', desc:'Casos de uso, elementos compartilhados e como criar uma nova loja.' }, { s:'l-vs-curso', t:'Loja vs. curso — diferença de escopo', f:'lojas/2-8-loja-vs-curso.md', time:'2 min', desc:'A loja vende, o curso entrega — como as duas camadas se relacionam.' }, ]}, { slug:'l-criacao', title:'Criação', items:[ { s:'l-criar', t:'Como criar uma nova loja', f:'lojas/2-1-criar-loja.md', time:'6 min', desc:'Do nome até o estado em que você pode cadastrar cursos e ofertas.' }, { s:'l-dominio', t:'Domínio próprio da loja', f:'lojas/2-2-dominio-loja.md', time:'5 min', desc:'Cada loja pode ter URL própria — útil para multi-marca.' }, { s:'l-imagens', t:'Logo, banners e thumbnail da loja', f:'lojas/2-3-imagens-loja.md', time:'6 min', desc:'As 5 imagens importantes — desktop, mobile, social, OG.' }, ]}, { slug:'l-equipe', title:'Equipe', items:[ { s:'l-convite', t:'Convidar gerente para a loja', f:'lojas/2-4-convidar-gerente.md', time:'5 min', desc:'Fluxo de convite, escopo e cenários de equipe.' }, { s:'l-papeis', t:'Papéis de acesso na loja', f:'lojas/2-9-papeis-acesso.md', time:'2 min', desc:'Admin de Loja para tudo, Admin de Curso apenas para seus cursos.' }, { s:'l-abilities', t:'Abilities detalhadas por papel', f:'lojas/2-10-abilities-por-papel.md', time:'3 min', desc:'Tabela completa do que cada papel pode e não pode fazer.' }, { s:'l-transferir', t:'Transferir gerência da loja', f:'lojas/2-11-transferir-gerencia.md', time:'2 min', desc:'Passar a responsabilidade principal para outro Admin de Loja.' }, ]}, { slug:'l-config', title:'Configuração', items:[ { s:'l-contato', t:'Informações de contato da loja', f:'lojas/2-12-contato-loja.md', time:'2 min', desc:'E-mail, telefone e link de suporte exibidos no rodapé e checkout.' }, { s:'l-endereco', t:'Endereço da loja', f:'lojas/2-13-endereco-loja.md', time:'2 min', desc:'Usado em documentos fiscais, recibos e rodapé — exigência legal.' }, { s:'l-redes', t:'Redes sociais da loja', f:'lojas/2-14-redes-sociais.md', time:'2 min', desc:'Links de Instagram, Facebook, YouTube e outros no rodapé da vitrine.' }, { s:'l-cert', t:'Certificados no nível da loja', f:'lojas/2-17-cert-loja.md', time:'2 min', desc:'Template padrão para cursos que não têm certificado próprio.' }, ]}, { slug:'l-operacao', title:'Operação', items:[ { s:'l-dashboard', t:'Dashboard da loja — entendendo o painel', f:'lojas/2-5-dashboard-loja.md', time:'8 min', desc:'As 4 abas (Cursos, Financeiro, Alunos, Pesquisas) + filtros e exportação.' }, { s:'l-metricas', t:'Métricas da loja', f:'lojas/2-18-metricas-loja.md', time:'3 min', desc:'Receita, matrículas, funil de conversão e desempenho por curso.' }, { s:'l-tracking', t:'Configurar tracking na loja', f:'lojas/2-15-tracking-loja.md', time:'2 min', desc:'GTM, Meta Pixel e GA4 — eventos de compra e navegação.' }, { s:'l-nps', t:'NPS da loja', f:'lojas/2-16-nps-loja.md', time:'2 min', desc:'Satisfação com a compra — separado do NPS de cada curso.' }, { s:'l-performance', t:'Performance e tempo de carregamento', f:'lojas/2-19-performance.md', time:'3 min', desc:'Boas práticas de imagem e tracking para manter a vitrine rápida.' }, { s:'l-resumo', t:'Resumo da semana na loja', f:'lojas/2-20-resumo-semana.md', time:'2 min', desc:'E-mail automático com matrículas, receita e pendências da semana.' }, ]}, ]}, { slug:'cursos', icon:'book', color:'bg-emerald-50 text-emerald-700 border-emerald-200', title:'Cursos', desc:'Conteúdo, módulos, aulas, turmas e certificados.', subs:[ { slug:'c-criacao', title:'Criação e configuração', items:[ { s:'c-criar', t:'Criar seu primeiro curso', f:'cursos/3-1-criar-curso.md', time:'7 min', desc:'Pré-requisitos + 5 passos do rascunho à estrutura mínima.' }, { s:'c-info', t:'Informações básicas do curso', f:'cursos/3-2-info-basicas.md', time:'6 min', desc:'Nome, descrição, carga horária, nível — campos que afetam SEO e conversão.' }, { s:'c-img', t:'Imagens do curso (thumbnail, capa, certificado)', f:'cursos/3-3-imagens-curso.md', time:'6 min', desc:'As 3 imagens essenciais com specs e boas práticas.' }, { s:'c-categoria', t:'Criar e gerenciar categorias', f:'cursos/3-9-criar-categoria.md', time:'2 min', desc:'Pré-requisito para publicar — como criar e organizar categorias.' }, { s:'c-professor', t:'Cadastrar professores', f:'cursos/3-10-cadastrar-professor.md', time:'2 min', desc:'Pré-requisito para publicar — foto, bio e vinculação ao curso.' }, { s:'c-tipos', t:'Tipos de curso: online, ao vivo e presencial', f:'cursos/3-11-tipos-curso.md', time:'2 min', desc:'Diferenças entre os 3 tipos e quando usar cada um.' }, { s:'c-trailer', t:'Trailer do curso', f:'cursos/3-23-trailer-curso.md', time:'2 min', desc:'Vídeo de apresentação exibido na página de vendas.' }, { s:'c-tags', t:'Tags e nível do curso', f:'cursos/3-24-tags-nivel.md', time:'2 min', desc:'Metadados para busca e filtragem no catálogo.' }, { s:'c-visib', t:'Visibilidade do curso', f:'cursos/3-25-visibilidade-curso.md', time:'2 min', desc:'Público, privado ou oculto — quando usar cada opção.' }, { s:'c-clonar', t:'Clonar curso', f:'cursos/3-26-clonar-curso.md', time:'2 min', desc:'Duplicar estrutura para nova edição ou variação do mesmo curso.' }, { s:'c-pg-vendas', t:'Página de vendas do curso', f:'cursos/3-62-pagina-vendas.md', time:'2 min', desc:'Elementos, pré-visualização e personalização da vitrine pública.' }, { s:'c-status', t:'Status do curso', f:'cursos/3-63-status-curso.md', time:'2 min', desc:'Rascunho, publicado e arquivado — ciclo de vida e transições.' }, { s:'c-member-area', t:'Member area do curso', f:'cursos/3-68-member-area-curso.md', time:'2 min', desc:'Banner, mensagem de boas-vindas e identidade visual do AVA por curso.' }, { s:'c-ia-desc', t:'Gerar descrição com IA', f:'cursos/3-69-ia-descricao.md', time:'2 min', desc:'A IA gera um rascunho de descrição a partir do nome e estrutura do curso.' }, ]}, { slug:'c-conteudo', title:'Módulos e aulas', items:[ { s:'c-modulos', t:'Criar módulos e organizar o curso', f:'cursos/3-4-criar-modulos.md', time:'5 min', desc:'5-8 aulas por módulo, padrões pedagógicos, liberação sequencial.' }, { s:'c-aulas', t:'Criar aulas — tipos e configuração', f:'cursos/3-5-criar-aulas.md', time:'7 min', desc:'Os 6 tipos: vídeo, texto, PDF, quiz, ao vivo, conteúdo externo.' }, { s:'c-upload', t:'Upload de vídeos: YouTube, Vimeo ou próprio', f:'cursos/3-6-upload-videos.md', time:'7 min', desc:'Comparativo das plataformas + boas práticas de gravação.' }, { s:'c-preview', t:'Aula de pré-visualização (preview)', f:'cursos/3-27-aula-preview.md', time:'2 min', desc:'Liberar aula antes da compra — conversão e configuração.' }, { s:'c-reorder', t:'Reordenar módulos e aulas', f:'cursos/3-28-reordenar-conteudo.md', time:'2 min', desc:'Arrastar para reorganizar — impacto no drip e na navegação.' }, { s:'c-materiais', t:'Materiais de apoio da aula', f:'cursos/3-29-materiais-aula.md', time:'2 min', desc:'PDFs, links e arquivos complementares vinculados a cada aula.' }, { s:'c-duracao', t:'Duração e progresso das aulas', f:'cursos/3-30-duracao-progresso.md', time:'2 min', desc:'Como o progresso é calculado e o que conta como concluído.' }, { s:'c-drm', t:'DRM — proteção de vídeos', f:'cursos/3-31-drm-protecao.md', time:'2 min', desc:'Widevine + FairPlay — o que protege e o que não protege.' }, { s:'c-player', t:'Player de vídeo — configurações', f:'cursos/3-32-player-video.md', time:'2 min', desc:'Velocidade, legenda, qualidade e comportamento do player.' }, { s:'c-anotacoes', t:'Anotações do aluno', f:'cursos/3-65-anotacoes-aluno.md', time:'2 min', desc:'Registrar observações durante a aula vinculadas ao instante do vídeo.' }, { s:'c-tempo-min', t:'Tempo mínimo por aula', f:'cursos/3-67-tempo-minimo-aula.md', time:'2 min', desc:'Define o tempo de reprodução que o aluno precisa atingir para concluir a aula.' }, ]}, { slug:'c-tipos-curso', title:'Cursos ao vivo e presenciais', items:[ { s:'c-turmas', t:'O que é uma turma', f:'cursos/3-12-turmas-o-que-e.md', time:'2 min', desc:'Curso vs turma — hierarquia e quando criar mais de uma turma.' }, { s:'c-criar-turma', t:'Criar turma', f:'cursos/3-13-criar-turma.md', time:'2 min', desc:'Configurações de uma nova turma dentro de um curso.' }, { s:'c-ao-vivo', t:'Curso ao vivo — configuração', f:'cursos/3-14-curso-ao-vivo.md', time:'2 min', desc:'Sessões ao vivo com Zoom ou Meet dentro do AVA.' }, { s:'c-datas-av', t:'Datas e sessões ao vivo', f:'cursos/3-15-aulas-ao-vivo-datas.md', time:'2 min', desc:'Agendar sessões, fuso horário e lembrete automático.' }, { s:'c-zoom', t:'Integração com Zoom e Meet', f:'cursos/3-16-zoom-meet.md', time:'2 min', desc:'Conectar conta, gerar link e transmitir a sessão.' }, { s:'c-gravacao', t:'Gravação automática de sessões', f:'cursos/3-17-gravacao-automatica.md', time:'2 min', desc:'Disponibilizar a gravação após a sessão ao vivo.' }, { s:'c-presencial', t:'Curso presencial — configuração', f:'cursos/3-18-curso-presencial.md', time:'2 min', desc:'Gestão de vagas, local e lista de presença.' }, { s:'c-endereco', t:'Endereço e local do evento', f:'cursos/3-19-endereco-evento.md', time:'2 min', desc:'Configurar local físico exibido para alunos matriculados.' }, { s:'c-presenca', t:'Lista de presença', f:'cursos/3-20-lista-presenca.md', time:'2 min', desc:'Controlar presença em sessões presenciais ou ao vivo.' }, ]}, { slug:'c-aval', title:'Avaliações e exercícios', items:[ { s:'c-quiz', t:'O que é o quiz', f:'cursos/3-33-quiz-conceito.md', time:'2 min', desc:'Quiz vs avaliação — diferenças e quando usar cada um.' }, { s:'c-criar-quiz', t:'Criar quiz', f:'cursos/3-34-criar-quiz.md', time:'2 min', desc:'Tipos de questão, feedback e configuração de tentativas.' }, { s:'c-nota', t:'Avaliação com nota e critério de aprovação', f:'cursos/3-35-avaliacao-nota.md', time:'2 min', desc:'Nota mínima, peso e bloqueio de certificado.' }, { s:'c-tarefa', t:'Tarefa com upload de arquivo', f:'cursos/3-36-tarefa-upload.md', time:'2 min', desc:'Envio de arquivo pelo aluno com correção manual.' }, { s:'c-banco', t:'Banco de questões', f:'cursos/3-37-banco-questoes.md', time:'2 min', desc:'Reutilizar questões entre avaliações — como salvar e usar.' }, { s:'c-resultados', t:'Resultados e relatório de avaliações', f:'cursos/3-38-resultados-avaliacao.md', time:'2 min', desc:'Notas, tentativas, aprovação e exportação de relatório.' }, ]}, { slug:'c-cert', title:'Certificados', items:[ { s:'c-cert-conceito', t:'Como funciona certificado de conclusão', f:'cursos/3-7-cert-conceito.md', time:'6 min', desc:'Critérios, variáveis dinâmicas, validação por QR Code.' }, { s:'c-cert-editor', t:'Editor visual de certificado', f:'cursos/3-39-editor-visual-certificado.md', time:'2 min', desc:'Criar e editar o layout sem exportar imagem externa.' }, { s:'c-cert-variaveis', t:'Variáveis do certificado', f:'cursos/3-40-variaveis-certificado.md', time:'2 min', desc:'Catálogo completo de variáveis dinâmicas disponíveis.' }, { s:'c-cert-reemissao', t:'Reemissão e revogação de certificados', f:'cursos/3-41-reemissao-revogacao.md', time:'3 min', desc:'Quando e como reemitir ou revogar um certificado emitido.' }, { s:'c-cert-turma', t:'Certificado por turma', f:'cursos/3-42-certificado-por-turma.md', time:'2 min', desc:'Atribuir template e critérios diferentes por turma.' }, { s:'c-cert-icp', t:'Assinatura digital ICP-Brasil', f:'cursos/3-43-assinatura-digital-icp.md', time:'2 min', desc:'Validade jurídica — quando usar e requisitos do plano.' }, ]}, { slug:'c-nps', title:'Feedback e NPS', items:[ { s:'c-nps-conceito', t:'O que é NPS e como funciona', f:'cursos/3-44-nps-conceito.md', time:'2 min', desc:'Detratores, neutros e promotores — cálculo e interpretação.' }, { s:'c-nps-config', t:'Configurar NPS', f:'cursos/3-45-configurar-nps.md', time:'2 min', desc:'Gatilho, canal, pergunta e anonimato.' }, { s:'c-nps-result', t:'Resultados de NPS', f:'cursos/3-46-resultados-nps.md', time:'2 min', desc:'Visualizar, filtrar e exportar respostas de NPS.' }, { s:'c-estrelas', t:'Avaliação por estrelas', f:'cursos/3-47-avaliacao-estrelas.md', time:'2 min', desc:'Nota pública do curso — exibição e configuração.' }, { s:'c-comentarios', t:'Comentários e depoimentos de alunos', f:'cursos/3-48-comentarios-aluno.md', time:'2 min', desc:'Comentários por aula e depoimentos na página de vendas.' }, { s:'c-moderacao', t:'Moderação de feedback e comentários', f:'cursos/3-49-moderacao-feedback.md', time:'2 min', desc:'Aprovar, rejeitar e responder avaliações publicamente.' }, { s:'c-nps-quando', t:'NPS — quando enviar e configurar perguntas', f:'cursos/3-70-nps-quando-perguntas.md', time:'2 min', desc:'Gatilho de envio e perguntas abertas para coletar contexto além da nota.' }, { s:'c-nps-reaplicar', t:'NPS — reaplicar pesquisa', f:'cursos/3-71-nps-reaplicar.md', time:'2 min', desc:'Enviar o NPS novamente para quem não respondeu ou para uma nova turma.' }, ]}, { slug:'c-qa', title:'Q&A', items:[ { s:'c-qa-conceito', t:'O que é o Q&A do curso', f:'cursos/3-50-qa-conceito.md', time:'2 min', desc:'Fórum de perguntas e respostas dentro do AVA.' }, { s:'c-qa-config', t:'Configurar o Q&A', f:'cursos/3-51-configurar-qa.md', time:'2 min', desc:'Habilitar, categorias, quem pode responder e moderação.' }, { s:'c-qa-resp', t:'Responder perguntas no Q&A', f:'cursos/3-52-responder-qa.md', time:'2 min', desc:'Fluxo de resposta, melhor resposta e acompanhamento.' }, { s:'c-tutor', t:'Designar tutores para o Q&A', f:'cursos/3-53-tutor-designado.md', time:'2 min', desc:'Tutor vs professor — permissões e notificações.' }, ]}, { slug:'c-turma-config', title:'Gestão de turmas e alunos', items:[ { s:'c-drip', t:'Liberação progressiva de conteúdo (drip)', f:'cursos/3-54-liberacao-drip.md', time:'3 min', desc:'Liberar módulos por dias desde a matrícula ou data fixa.' }, { s:'c-acesso', t:'Período de acesso do aluno na turma', f:'cursos/3-55-periodo-acesso.md', time:'2 min', desc:'X meses, data fixa ou vitalício — e como estender individualmente.' }, { s:'c-mat-manual', t:'Matrícula manual de alunos', f:'cursos/3-56-matricula-manual.md', time:'2 min', desc:'Adicionar aluno sem compra — individual ou em lote via CSV.' }, { s:'c-transferir', t:'Transferir aluno entre turmas', f:'cursos/3-57-transferir-aluno.md', time:'2 min', desc:'Mover aluno mantendo ou zerando o progresso.' }, { s:'c-encerrar', t:'Encerrar e arquivar uma turma', f:'cursos/3-58-encerrar-turma.md', time:'2 min', desc:'Bloquear acesso e ocultar turmas encerradas.' }, { s:'c-duplicar', t:'Duplicar uma turma', f:'cursos/3-59-replicar-turma.md', time:'2 min', desc:'Copiar estrutura para nova edição sem copiar alunos.' }, { s:'c-clonar-loja', t:'Clonar curso para outra loja', f:'cursos/3-60-clonar-curso-outra-loja.md', time:'2 min', desc:'Replicar curso entre lojas que você administra.' }, { s:'c-sequencial', t:'Acesso sequencial', f:'cursos/3-64-acesso-sequencial.md', time:'2 min', desc:'Obrigar o aluno a concluir cada aula antes de liberar a próxima.' }, { s:'c-marcar', t:'Marcar aula como concluída', f:'cursos/3-66-marcar-concluida.md', time:'2 min', desc:'Corrigir o progresso de um aluno manualmente pelo admin.' }, ]}, { slug:'c-pub', title:'Publicação e ofertas', items:[ { s:'c-publicar', t:'Publicar o curso', f:'cursos/3-61-publicar-curso.md', time:'2 min', desc:'Pré-requisitos, checklist e despublicar.' }, { s:'c-oferta', t:'Criar oferta', f:'cursos/3-21-criar-oferta.md', time:'2 min', desc:'Oferta é o produto que o aluno compra — preço, acesso, tipo.' }, { s:'c-tipos-oferta', t:'Tipos de oferta — pago, gratuito e cortesia', f:'cursos/3-22-tipos-oferta.md', time:'2 min', desc:'Quando usar cada tipo e impacto no relatório financeiro.' }, ]}, ]}, { slug:'ofertas', icon:'ticket', color:'bg-amber-50 text-amber-700 border-amber-200', title:'Ofertas e Vendas', desc:'Oferta, preço, parcelamento, assinatura, cupons, checkout e métricas — do cadastro à conversão.', subs:[ { slug:'o-conc', title:'Conceitos', items:[ { s:'o-oque', t:'O que é oferta', f:'ofertas/10-1-o-que-e-oferta.md', time:'2 min', desc:'Oferta é o produto que o aluno compra — preço, acesso e condições de pagamento.' }, { s:'o-tipos', t:'Tipos de oferta', f:'ofertas/10-2-tipos-oferta.md', time:'2 min', desc:'Pago, gratuito e cortesia — diferenças e quando usar cada tipo.' }, { s:'o-multi', t:'Multi-oferta', f:'ofertas/10-3-multi-oferta.md', time:'2 min', desc:'Múltiplas ofertas para o mesmo curso com preços e condições distintos.' }, ]}, { slug:'o-config', title:'Configuração da oferta', items:[ { s:'o-info', t:'Informações básicas da oferta', f:'ofertas/10-4-info-basicas-oferta.md', time:'2 min', desc:'Nome, descrição, slug e status da oferta.' }, { s:'o-disp', t:'Disponibilidade', f:'ofertas/10-5-disponibilidade.md', time:'2 min', desc:'Controla visibilidade, abertura para compras e período de venda.' }, { s:'o-datas', t:'Datas de acesso', f:'ofertas/10-6-datas-acesso.md', time:'2 min', desc:'Quando o aluno entra no curso e por quanto tempo acessa o conteúdo.' }, { s:'o-vagas', t:'Vagas limitadas', f:'ofertas/10-7-vagas.md', time:'2 min', desc:'Encerra as vendas automaticamente ao atingir o número máximo.' }, { s:'o-banner', t:'Banner da oferta', f:'ofertas/10-8-banner-oferta.md', time:'2 min', desc:'Imagem exibida no checkout para diferenciar visualmente cada oferta.' }, ]}, { slug:'o-preco', title:'Preço e promoção', items:[ { s:'o-promo', t:'Preço promocional (De/Por)', f:'ofertas/10-9-promocao.md', time:'2 min', desc:'Exibe desconto no checkout sem alterar o preço base da oferta.' }, { s:'o-parc-max', t:'Parcelamento máximo', f:'ofertas/10-10-parcelamento-maximo.md', time:'2 min', desc:'Define o número máximo de parcelas no cartão de crédito.' }, { s:'o-sj', t:'Parcelamento sem juros', f:'ofertas/10-11-sem-juros.md', time:'2 min', desc:'Divide o total em parcelas iguais — o custo financeiro fica com a loja.' }, { s:'o-cj', t:'Parcelamento com juros', f:'ofertas/10-12-com-juros.md', time:'2 min', desc:'Repassa o custo financeiro ao aluno — a loja recebe o valor integral.' }, ]}, { slug:'o-pgto', title:'Métodos de pagamento', items:[ { s:'o-boleto', t:'Boleto bancário', f:'ofertas/10-13-boleto.md', time:'2 min', desc:'Pagamento sem cartão — acesso liberado após compensação.' }, { s:'o-boleto-venc', t:'Prazo de vencimento do boleto', f:'ofertas/10-14-boleto-vencimento.md', time:'2 min', desc:'Define até quando o boleto pode ser pago.' }, { s:'o-paypal', t:'PayPal', f:'ofertas/10-15-paypal.md', time:'2 min', desc:'Pagamento internacional e por saldo — requer conta Business.' }, { s:'o-toggle', t:'Habilitar e desabilitar métodos de pagamento', f:'ofertas/10-16-toggle-pagamento.md', time:'2 min', desc:'Liga ou desliga cada método por oferta sem afetar as demais.' }, ]}, { slug:'o-assin', title:'Assinatura recorrente', items:[ { s:'o-assin-conc', t:'Assinatura recorrente — conceito', f:'ofertas/10-17-assinatura-conceito.md', time:'2 min', desc:'Cobrança automática a cada ciclo sem nova compra pelo aluno.' }, { s:'o-assin-rec', t:'Configurar recorrência', f:'ofertas/10-18-assinatura-recorrencia.md', time:'2 min', desc:'Define o ciclo de cobrança — mensal, trimestral, semestral ou anual.' }, { s:'o-assin-trial', t:'Trial (período gratuito)', f:'ofertas/10-19-assinatura-trial.md', time:'2 min', desc:'Período gratuito antes da primeira cobrança da assinatura.' }, { s:'o-assin-tol', t:'Tolerância após cobrança falhada', f:'ofertas/10-20-assinatura-tolerancia.md', time:'2 min', desc:'Mantém o acesso por X dias enquanto o retry tenta novamente.' }, { s:'o-assin-can', t:'Cancelar assinatura', f:'ofertas/10-21-assinatura-cancelar.md', time:'2 min', desc:'Encerra as cobranças futuras — acesso mantido até fim do período pago.' }, { s:'o-assin-pau', t:'Pausar assinatura', f:'ofertas/10-22-assinatura-pausar.md', time:'2 min', desc:'Suspende cobranças temporariamente sem cancelar.' }, ]}, { slug:'o-cup', title:'Cupons', items:[ { s:'o-cup-val', t:'Validade e limite de uso', f:'ofertas/10-23-cupom-validade.md', time:'2 min', desc:'Controla por quanto tempo e quantas vezes o cupom pode ser aplicado.' }, { s:'o-cup-uni', t:'Cupom de uso único', f:'ofertas/10-24-cupom-unico.md', time:'2 min', desc:'Garante que cada aluno aplique o desconto apenas uma vez.' }, { s:'o-cup-res', t:'Restrição por produto', f:'ofertas/10-25-cupom-restricao.md', time:'2 min', desc:'Limita o cupom a ofertas específicas.' }, { s:'o-cup-link', t:'Link com cupom pré-aplicado', f:'ofertas/10-26-cupom-link.md', time:'2 min', desc:'Abre o checkout com o desconto já inserido.' }, { s:'o-cup-perf', t:'Performance de cupons', f:'ofertas/10-27-cupom-performance.md', time:'2 min', desc:'Usos, receita gerada e desconto concedido por código.' }, ]}, { slug:'o-ob', title:'Order Bump', items:[ { s:'o-ob-conc', t:'Order Bump — conceito', f:'ofertas/10-28-order-bump-conceito.md', time:'2 min', desc:'Oferta adicional dentro do checkout com aceite em um clique.' }, { s:'o-ob-conf', t:'Configurar Order Bump', f:'ofertas/10-29-order-bump-config.md', time:'2 min', desc:'Define produto, preço, copy e posição do box adicional.' }, { s:'o-ob-copy', t:'Copy do Order Bump', f:'ofertas/10-30-order-bump-copy.md', time:'2 min', desc:'Três elementos — benefício, prova de valor e escassez.' }, { s:'o-ob-multi', t:'Multi Order Bump', f:'ofertas/10-31-order-bump-multi.md', time:'2 min', desc:'Dois ou mais produtos adicionais no mesmo checkout.' }, ]}, { slug:'o-up', title:'Upsell', items:[ { s:'o-up-conc', t:'Upsell pós-compra — conceito', f:'ofertas/10-32-upsell-conceito.md', time:'2 min', desc:'Oferta apresentada na página de obrigado após o pagamento aprovado.' }, { s:'o-up-conf', t:'Configurar Upsell', f:'ofertas/10-33-upsell-config.md', time:'2 min', desc:'Produto, preço, vídeo, copy e sequência de redirecionamento.' }, { s:'o-up-vid', t:'Vídeo no upsell', f:'ofertas/10-34-upsell-video.md', time:'2 min', desc:'Apresenta o produto adicional com mais contexto e aumenta o aceite.' }, { s:'o-up-met', t:'Métricas de Upsell', f:'ofertas/10-35-upsell-metricas.md', time:'2 min', desc:'Impressões, aceites, recusas e impacto no ticket médio.' }, ]}, { slug:'o-cf', title:'Campos personalizados', items:[ { s:'o-cf-criar', t:'Criar campos personalizados no checkout', f:'ofertas/10-36-custom-fields-criar.md', time:'2 min', desc:'Coletam informações extras do aluno além dos dados padrão.' }, { s:'o-cf-tipos', t:'Tipos de campos personalizados', f:'ofertas/10-37-custom-fields-tipos.md', time:'2 min', desc:'Texto, seleção, documento, data — e a validação de cada um.' }, { s:'o-cf-obr', t:'Campo obrigatório no checkout', f:'ofertas/10-38-custom-fields-obrigatorio.md', time:'2 min', desc:'Impede a conclusão da compra até o campo ser preenchido.' }, { s:'o-cf-resp', t:'Ver respostas dos campos personalizados', f:'ofertas/10-39-custom-fields-respostas.md', time:'2 min', desc:'Respostas ficam na transação e podem ser exportadas em CSV.' }, ]}, { slug:'o-ck', title:'Checkout', items:[ { s:'o-ck-msg', t:'Mensagem personalizada no checkout', f:'ofertas/10-40-mensagem-checkout.md', time:'2 min', desc:'Exibe aviso ou instrução ao aluno antes de finalizar a compra.' }, { s:'o-ck-redir', t:'Redirecionar aluno após compra', f:'ofertas/10-41-redirecionamento.md', time:'2 min', desc:'Envia o aluno para URL específica ao invés da página de obrigado.' }, { s:'o-ck-dep', t:'Depoimentos no checkout', f:'ofertas/10-42-depoimentos.md', time:'2 min', desc:'Prova social de alunos anteriores para aumentar a confiança na compra.' }, { s:'o-ck-cup', t:'Mostrar ou ocultar campo de cupom', f:'ofertas/10-43-cupom-toggle.md', time:'2 min', desc:'Ocultar evita que alunos sem código busquem desconto antes de comprar.' }, { s:'o-ck-login', t:'Login no checkout', f:'ofertas/10-44-login-checkout.md', time:'2 min', desc:'Exige que o aluno esteja logado antes de ver o checkout.' }, { s:'o-ck-timer', t:'Timer de urgência no checkout', f:'ofertas/10-45-timer.md', time:'2 min', desc:'Contagem regressiva para criar urgência antes do encerramento.' }, ]}, { slug:'o-gami', title:'Gamificação na oferta', items:[ { s:'o-gami-pts', t:'Pontos por compra', f:'ofertas/10-46-pontos-gamificacao.md', time:'2 min', desc:'Credita XP ao aluno automaticamente quando a transação é aprovada.' }, { s:'o-gami-rec', t:'Recompensas por pontos', f:'ofertas/10-47-recompensas-pontos.md', time:'2 min', desc:'Benefícios que o aluno resgata usando os pontos acumulados.' }, { s:'o-gami-lim', t:'Limitar recompensa por oferta', f:'ofertas/10-48-limite-recompensa.md', time:'2 min', desc:'Restringe quantas vezes o mesmo benefício pode ser resgatado.' }, ]}, { slug:'o-perf', title:'Performance e testes', items:[ { s:'o-perf-met', t:'Métricas da oferta', f:'ofertas/10-49-metricas-oferta.md', time:'2 min', desc:'Vendas, receita, ticket médio e taxa de conversão por período.' }, { s:'o-perf-fun', t:'Funil de conversão do checkout', f:'ofertas/10-50-funil-conversao.md', time:'2 min', desc:'Mostra onde os alunos abandonam o checkout — da visita à aprovação.' }, { s:'o-perf-ab', t:'Teste A/B em ofertas', f:'ofertas/10-51-ab-test.md', time:'2 min', desc:'Compara duas versões de oferta para identificar qual converte mais.' }, ]}, ]}, { slug:'alunos', icon:'users', color:'bg-pink-50 text-pink-700 border-pink-200', title:'Alunos', desc:'Matrículas, comunicação, grupos, exportações e autenticação.', subs:[ { slug:'a-matriculas', title:'Matrículas', items:[ { s:'a-mat-auto', t:'Matrícula automática (após compra)', f:'alunos/6-1-matricula-automatica.md', time:'5 min', desc:'Fluxo pagamento → matrícula → e-mail → AVA.' }, { s:'a-mat-manual', t:'Matricular manualmente um aluno', f:'alunos/6-2-matricula-manual.md', time:'5 min', desc:'Cortesia, B2B, beta-tester, correção de problema.' }, { s:'a-cancelar', t:'Cancelar matrícula', f:'alunos/6-3-cancelar-matricula.md', time:'4 min', desc:'Cancelar vs bloquear vs reembolsar, sequência ideal.' }, ]}, { slug:'a-visao', title:'Visão geral', items:[ { s:'a-o-que-e', t:'O que é um aluno na evob', f:'alunos/6-6-o-que-e-aluno.md', time:'2 min', desc:'Conta, acesso ao AVA e diferença entre aluno e admin.' }, { s:'a-lista', t:'Listagem e busca de alunos', f:'alunos/6-7-listagem-alunos.md', time:'2 min', desc:'Filtros disponíveis, colunas e exportação da lista.' }, { s:'a-status', t:'Status do aluno', f:'alunos/6-8-status-aluno.md', time:'2 min', desc:'Ativo, bloqueado e inativo — diferenças e transições.' }, ]}, { slug:'a-cadastro', title:'Cadastro avançado', items:[ { s:'a-pre-mat', t:'Pré-matrícula', f:'alunos/6-9-pre-matricula.md', time:'2 min', desc:'Reservar vaga antes do pagamento — prazo e configuração.' }, { s:'a-bloquear', t:'Bloquear aluno', f:'alunos/6-10-bloquear-aluno.md', time:'2 min', desc:'Suspender acesso sem cancelar matrícula — individual e em lote.' }, { s:'a-reativar', t:'Reativar aluno', f:'alunos/6-11-reativar-aluno.md', time:'2 min', desc:'Restaurar acesso bloqueado — histórico preservado.' }, ]}, { slug:'a-ficha', title:'Ficha do aluno', items:[ { s:'a-ficha-geral', t:'Ficha do aluno', f:'alunos/6-12-ficha-aluno.md', time:'2 min', desc:'Dados de cadastro, matrículas, pagamentos e histórico em uma tela.' }, { s:'a-cursos', t:'Cursos e progresso do aluno', f:'alunos/6-13-cursos-aluno.md', time:'2 min', desc:'Progresso por curso, ações disponíveis e detalhes de matrícula.' }, { s:'a-certs', t:'Certificados do aluno', f:'alunos/6-14-certs-aluno.md', time:'2 min', desc:'Emissão manual, reemissão e código de validação.' }, { s:'a-pgtos', t:'Pagamentos do aluno', f:'alunos/6-15-pagamentos-aluno.md', time:'2 min', desc:'Histórico de compras, status da transação e reembolso.' }, { s:'a-engaj', t:'Engajamento do aluno', f:'alunos/6-16-engajamento-aluno.md', time:'2 min', desc:'Logins, aulas assistidas, NPS e sinais de abandono.' }, ]}, { slug:'a-comunicacao', title:'Comunicação', items:[ { s:'a-email-1', t:'Enviar e-mail para um aluno', f:'alunos/6-4-email-aluno.md', time:'4 min', desc:'Comunicação 1:1 oficial, com auditoria e identidade da loja.' }, { s:'a-massa', t:'Comunicação em massa', f:'alunos/6-5-comunicacao-massa.md', time:'7 min', desc:'E-mail, WhatsApp e push — segmentação, métricas, LGPD.' }, { s:'a-templates', t:'Templates de e-mail', f:'alunos/6-17-templates-email.md', time:'2 min', desc:'Personalizar os 11 templates de e-mails transacionais.' }, { s:'a-whatsapp', t:'WhatsApp para alunos', f:'alunos/6-18-whatsapp-aluno.md', time:'2 min', desc:'Mensagens individuais ou em lote via WhatsApp Business API.' }, { s:'a-push', t:'Push notifications', f:'alunos/6-19-push-aluno.md', time:'2 min', desc:'Alertar alunos sobre novas aulas e lives sem abrir o AVA.' }, ]}, { slug:'a-grupos', title:'Grupos e segmentação', items:[ { s:'a-grupo-o-que-e', t:'Grupos de alunos', f:'alunos/6-20-grupos-o-que-e.md', time:'2 min', desc:'Segmentar a base e aplicar ações em conjunto.' }, { s:'a-grupo-manual', t:'Grupo manual', f:'alunos/6-21-grupo-manual.md', time:'2 min', desc:'Adicionar alunos individualmente ou via CSV — lista fixa.' }, { s:'a-grupo-din', t:'Grupo dinâmico', f:'alunos/6-22-grupo-dinamico.md', time:'2 min', desc:'Critérios automáticos — lista atualiza sem intervenção.' }, { s:'a-acoes-massa', t:'Ações em massa', f:'alunos/6-23-acoes-em-massa.md', time:'2 min', desc:'Matricular, bloquear, enviar e-mail ou exportar um grupo inteiro.' }, ]}, { slug:'a-newsletter', title:'Newsletter', items:[ { s:'a-nl-config', t:'Newsletter — configuração', f:'alunos/6-24-newsletter-config.md', time:'2 min', desc:'Remetente, listas e autenticação SPF/DKIM/DMARC.' }, { s:'a-nl-captacao', t:'Newsletter — captação de assinantes', f:'alunos/6-25-newsletter-captacao.md', time:'2 min', desc:'Formulário na vitrine e opt-in no checkout.' }, { s:'a-nl-disparo', t:'Newsletter — disparar campanha', f:'alunos/6-26-newsletter-disparo.md', time:'2 min', desc:'Criar, enviar e acompanhar métricas de um disparo.' }, ]}, { slug:'a-auth', title:'Autenticação do aluno', items:[ { s:'a-login', t:'Login do aluno no AVA', f:'alunos/6-27-login-aluno.md', time:'2 min', desc:'E-mail e senha, redes sociais, SSO — métodos disponíveis.' }, { s:'a-senha', t:'Recuperação de senha', f:'alunos/6-28-recuperar-senha.md', time:'2 min', desc:'Link temporário por e-mail — self-service e ação de admin.' }, { s:'a-sso', t:'SSO para alunos', f:'alunos/6-29-sso-aluno.md', time:'2 min', desc:'Login corporativo — grupo mapping e desativação automática.' }, { s:'a-mfa', t:'MFA do aluno', f:'alunos/6-30-mfa-aluno-config.md', time:'2 min', desc:'Segundo fator — SMS, app ou e-mail; obrigatório ou opcional.' }, { s:'a-magic', t:'Magic link', f:'alunos/6-31-magic-link.md', time:'2 min', desc:'Acesso sem senha — link de uso único válido por 15 minutos.' }, ]}, { slug:'a-export', title:'Exportações e relatórios', items:[ { s:'a-exp-lista', t:'Exportar lista de alunos', f:'alunos/6-32-exportar-lista.md', time:'2 min', desc:'CSV com dados de cadastro — campos incluídos e LGPD.' }, { s:'a-exp-mat', t:'Exportar matrículas', f:'alunos/6-33-exportar-matriculas.md', time:'2 min', desc:'1 linha por matrícula — curso, turma, progresso e origem.' }, { s:'a-rel-prog', t:'Relatório de progresso', f:'alunos/6-34-relatorio-progresso.md', time:'2 min', desc:'Aulas concluídas, tempo assistido e último acesso por aluno.' }, { s:'a-rel-cert', t:'Relatório de certificados', f:'alunos/6-35-relatorio-certificados.md', time:'2 min', desc:'Todos os certificados emitidos — código de validação e status.' }, ]}, ]}, { slug:'financeiro', icon:'wallet', color:'bg-green-50 text-green-700 border-green-200', title:'Financeiro', desc:'Gateway, taxas, saldo, transações, NF e relatórios — do checkout ao repasse.', subs:[ { slug:'f-conc', title:'Conceitos', items:[ { s:'f-como', t:'Como funciona o financeiro na evob', f:'financeiro/9-1-como-funciona-financeiro.md', time:'3 min', desc:'Saldo da loja vs. plataforma, quem recebe o quê.' }, { s:'f-plat', t:'Plataforma vs. loja — o que cada admin controla', f:'financeiro/9-2-plataforma-vs-loja.md', time:'2 min', desc:'Escopos distintos e cálculo cascata de taxas.' }, { s:'f-fluxo', t:'Fluxo de pagamento — do checkout ao saldo', f:'financeiro/9-3-fluxo-pagamento.md', time:'3 min', desc:'Cartão, Pix e boleto em etapas rastreáveis.' }, { s:'f-glos', t:'Glossário financeiro', f:'financeiro/9-4-glossario.md', time:'4 min', desc:'MDR, chargeback, D+30, split — definições por categoria.' }, ]}, { slug:'f-gwrec', title:'Gateway e recebedor', items:[ { s:'f-cad', t:'Cadastrar recebedor', f:'financeiro/9-5-cadastro-recebedor.md', time:'2 min', desc:'CNPJ ou CPF vinculado ao gateway para receber repasses.' }, { s:'f-doc', t:'Documentos para aprovação', f:'financeiro/9-6-documentos.md', time:'2 min', desc:'O que enviar, prazo de análise e status possíveis.' }, { s:'f-paypal', t:'Receber via PayPal', f:'financeiro/9-7-paypal.md', time:'2 min', desc:'Conta Business, Client ID/Secret e estrutura de taxas.' }, { s:'f-split', t:'Split de pagamento', f:'financeiro/9-8-split-pagamento.md', time:'2 min', desc:'Divisão automática de receita entre co-produtores.' }, ]}, { slug:'f-tax', title:'Taxas', items:[ { s:'f-gw', t:'Taxas do gateway de pagamento', f:'financeiro/9-9-taxas-gateway.md', time:'2 min', desc:'MDR por método, fórmula de margem, regulação de repasse.' }, { s:'f-evob', t:'Taxas da evob por plano', f:'financeiro/9-10-taxas-evob.md', time:'2 min', desc:'Starter a Business — percentual e ponto de break-even.' }, { s:'f-loja', t:'Taxa da loja configurada pela plataforma', f:'financeiro/9-11-taxas-loja.md', time:'2 min', desc:'Como incide, onde ver e como zerar se necessário.' }, { s:'f-ant-custo', t:'Custo da antecipação de recebíveis', f:'financeiro/9-12-antecipacao-custo.md', time:'2 min', desc:'Fórmula, exemplo e quando faz sentido antecipar.' }, ]}, { slug:'f-sal', title:'Saldo e antecipação', items:[ { s:'f-bloq', t:'Saldo bloqueado — o que é e quando libera', f:'financeiro/9-13-saldo-bloqueado.md', time:'2 min', desc:'Prazo regulatório por método e calendário "A liberar".' }, { s:'f-ant', t:'Antecipar saldo', f:'financeiro/9-14-antecipar-saldo.md', time:'2 min', desc:'Passo a passo, limites e custo da antecipação.' }, { s:'f-hist', t:'Histórico de saldo', f:'financeiro/9-15-historico-saldo.md', time:'2 min', desc:'Créditos, débitos e bloqueios com filtros por período.' }, ]}, { slug:'f-trans', title:'Transações', items:[ { s:'f-lista', t:'Lista de transações', f:'financeiro/9-16-lista-transacoes.md', time:'2 min', desc:'Filtros por status, exportação e monitoramento diário.' }, { s:'f-det', t:'Detalhe de transação', f:'financeiro/9-17-detalhe-transacao.md', time:'2 min', desc:'Linha do tempo completa do pedido ao repasse.' }, { s:'f-status', t:'Status de transação — o que cada um significa', f:'financeiro/9-18-status-transacao.md', time:'3 min', desc:'11 status com ação recomendada e matrícula concedida.' }, ]}, { slug:'f-cob', title:'Cobranças e reembolsos', items:[ { s:'f-reproc', t:'Reprocessar cobrança com cartão', f:'financeiro/9-19-reprocessar-cobranca.md', time:'2 min', desc:'Nova tentativa sem o aluno refazer o checkout.' }, { s:'f-remb-parc', t:'Reembolso parcial', f:'financeiro/9-20-reembolso-parcial.md', time:'2 min', desc:'Devolve valor menor sem cancelar a matrícula.' }, { s:'f-chgbk', t:'Chargeback — contestação bancária', f:'financeiro/9-21-chargeback.md', time:'3 min', desc:'Processo, prazo, evidências e limites de risco.' }, { s:'f-aberta', t:'Cobrança em aberto (boleto não pago)', f:'financeiro/9-22-cobranca-aberta.md', time:'2 min', desc:'Identificar e agir antes de perder a venda.' }, { s:'f-reenv', t:'Reenviar cobrança ao aluno', f:'financeiro/9-23-reenviar-cobranca.md', time:'2 min', desc:'Novo boleto ou link de pagamento com prazo atualizado.' }, ]}, { slug:'f-inad', title:'Inadimplência e retry', items:[ { s:'f-inadimp', t:'Inadimplência em assinaturas', f:'financeiro/9-24-inadimplencia.md', time:'3 min', desc:'Ciclo de inadimplência, painel e ação por aluno.' }, { s:'f-retry', t:'Retry automático de cobranças', f:'financeiro/9-25-retry-automatico.md', time:'2 min', desc:'Configurar intervalos e notificações para cobrança recorrente.' }, ]}, { slug:'f-aff', title:'Afiliados — visão financeira', items:[ { s:'f-aff-prog', t:'Programa de afiliados — visão financeira', f:'financeiro/9-26-afiliados-programa.md', time:'2 min', desc:'Comissões geradas, aprovadas e pagas por período.' }, { s:'f-aff-tab', t:'Tabela de comissões de afiliados', f:'financeiro/9-27-afiliados-tabela.md', time:'2 min', desc:'Quanto cada afiliado gerou e o saldo a pagar.' }, { s:'f-aff-apr', t:'Aprovar comissões de afiliados', f:'financeiro/9-28-afiliados-aprovacao.md', time:'2 min', desc:'Aprovação manual ou automática por gatilho.' }, { s:'f-aff-pag', t:'Pagar comissões de afiliados', f:'financeiro/9-29-afiliados-pagar.md', time:'2 min', desc:'Pix ou TED diretamente do painel, com pagamento automático.' }, { s:'f-aff-rel', t:'Relatório de afiliados', f:'financeiro/9-30-afiliados-relatorio.md', time:'2 min', desc:'Vendas, comissões e repasses consolidados por período.' }, ]}, { slug:'f-nf', title:'Notas fiscais', items:[ { s:'f-nf-int', t:'Integração de nota fiscal', f:'financeiro/9-31-nf-integracao.md', time:'3 min', desc:'eNotas, NFe.io e webhooks — emissão automática por venda.' }, { s:'f-nf-emit', t:'Emitir nota fiscal', f:'financeiro/9-32-nf-emissao.md', time:'2 min', desc:'Emissão manual para transação específica fora do fluxo.' }, { s:'f-nf-reem', t:'Reemitir nota fiscal', f:'financeiro/9-33-nf-reemitir.md', time:'2 min', desc:'Cancelar NF com erro e gerar nova com dados corrigidos.' }, { s:'f-nf-trib', t:'Tributação e alíquotas', f:'financeiro/9-34-nf-tributacao.md', time:'3 min', desc:'ISS, código de serviço e regimes tributários.' }, ]}, { slug:'f-rel', title:'Relatórios', items:[ { s:'f-dre', t:'DRE da loja', f:'financeiro/9-35-dre.md', time:'3 min', desc:'Receita, taxas e resultado líquido em formato gerencial.' }, { s:'f-rec-curso', t:'Receita por curso', f:'financeiro/9-36-receita-por-curso.md', time:'2 min', desc:'Vendas e valor gerado por produto no período.' }, { s:'f-rec-aff', t:'Receita de afiliados', f:'financeiro/9-37-receita-afiliados.md', time:'2 min', desc:'Quanto cada parceiro gerou e o custo em comissões.' }, { s:'f-exp', t:'Exportar dados financeiros', f:'financeiro/9-38-exportar-dados.md', time:'2 min', desc:'CSVs de transações, saldo e NFs para conciliação.' }, { s:'f-concil', t:'Conciliação bancária', f:'financeiro/9-39-conciliacao-bancaria.md', time:'3 min', desc:'Cruzar repasses da evob com o extrato bancário.' }, ]}, ]}, { slug:'mkt', icon:'megaphone', color:'bg-rose-50 text-rose-700 border-rose-200', title:'Marketing', desc:'Cupons, captação de leads, automações, afiliados, order bump e comunidade.', subs:[ { slug:'mkt-cup', title:'Cupons e promoções', items:[ { s:'mkt-cup-est', t:'Estratégias de cupom que funcionam', f:'marketing/7-1-estrategias-cupom.md', time:'6 min', desc:'6 estratégias com motivo claro + o que NÃO usar.' }, { s:'mkt-cup-bf', t:'Cupom Black Friday — campanha completa', f:'marketing/7-2-cupom-bf.md', time:'7 min', desc:'Cronograma de 3 fases, cupom escalonado, anúncios pagos.' }, { s:'mkt-cup-combo', t:'Cupom combo e bundle', f:'marketing/7-9-cupom-combo.md', time:'2 min', desc:'Desconto que só vale quando dois cursos específicos estão no carrinho.' }, ]}, { slug:'mkt-cap', title:'Captação e páginas', items:[ { s:'mkt-cap-sq', t:'Squeeze page — página de captura', f:'marketing/7-5-squeeze-page.md', time:'2 min', desc:'Formulário de captura de lead + oferta isca + redirecionamento.' }, { s:'mkt-cap-leads', t:'Gestão de leads', f:'marketing/7-6-gestao-leads.md', time:'2 min', desc:'Lista de leads, exportação CSV e diferença entre lead e aluno.' }, { s:'mkt-cap-pv', t:'Páginas de venda da loja', f:'marketing/7-7-paginas-de-venda.md', time:'2 min', desc:'Seções configuráveis, depoimentos e landing page de lançamento.' }, { s:'mkt-cap-seo', t:'SEO da loja', f:'marketing/7-8-seo-loja.md', time:'2 min', desc:'Título, meta description, slug e sitemap por curso e por loja.' }, ]}, { slug:'mkt-email', title:'E-mail marketing', items:[ { s:'mkt-int', t:'Integrar ferramenta de e-mail marketing', f:'marketing/7-10-integracao-email-mkt.md', time:'3 min', desc:'ActiveCampaign, RD Station, Mailchimp — API key e mapeamento de listas.' }, { s:'mkt-map', t:'Mapeamento de eventos de e-mail', f:'marketing/7-11-mapeamento-eventos.md', time:'2 min', desc:'O que acontece na ferramenta de e-mail quando um evento ocorre na loja.' }, { s:'mkt-trig', t:'Gatilhos de automação', f:'marketing/7-12-gatilhos-automacao.md', time:'3 min', desc:'Matrícula, progresso, inatividade — todos os gatilhos disponíveis.' }, ]}, { slug:'mkt-aut', title:'Automações', items:[ { s:'mkt-aut-conc', t:'O que são automações', f:'marketing/7-3-automacoes-conceito.md', time:'5 min', desc:'Gatilho + condição + ação. 7 casos de uso comuns.' }, { s:'mkt-aut-criar', t:'Criar primeira automação', f:'marketing/7-4-criar-automacao.md', time:'6 min', desc:'Boas-vindas, carrinho abandonado, cross-sell — exemplos completos.' }, { s:'mkt-aut-trig', t:'Condições avançadas em automações', f:'marketing/7-13-automacao-gatilhos-avancados.md', time:'3 min', desc:'Filtros AND/OR por produto, tag, progresso e data de matrícula.' }, { s:'mkt-aut-acao', t:'Ações de automação', f:'marketing/7-14-automacao-acoes.md', time:'3 min', desc:'Enviar e-mail, aplicar tag, conceder matrícula — catálogo completo.' }, { s:'mkt-aut-metr', t:'Métricas de automação', f:'marketing/7-15-automacao-metricas.md', time:'2 min', desc:'Entradas, concluídos, taxa de abertura e conversão por fluxo.' }, ]}, { slug:'mkt-aff', title:'Afiliados', items:[ { s:'mkt-aff-evob', t:'Afiliados — o que é e como funciona', f:'marketing/7-16-afiliados-o-que-e.md', time:'3 min', desc:'Link rastreado, painel do afiliado e modelos de comissão.' }, { s:'mkt-aff-conv', t:'Configurar comissão de afiliado', f:'marketing/7-17-afiliados-comissao.md', time:'2 min', desc:'Percentual, valor fixo, escalonado e gatilho de cálculo.' }, { s:'mkt-aff-mat', t:'Materiais para afiliados', f:'marketing/7-18-afiliados-materiais.md', time:'2 min', desc:'Banners, textos prontos e links por curso — centralizado no painel.' }, { s:'mkt-aff-cookie', t:'Cookie de rastreamento de afiliado', f:'marketing/7-19-afiliados-cookie.md', time:'2 min', desc:'Duração, modelos de atribuição e quando o cookie não atribui.' }, ]}, { slug:'mkt-ob', title:'Order Bump e Upsell', items:[ { s:'mkt-ob-vs-up', t:'Order Bump vs Upsell', f:'marketing/7-20-ob-vs-upsell.md', time:'2 min', desc:'Dentro do checkout vs pós-compra — quando e como usar cada um.' }, { s:'mkt-copy-ob', t:'Copy do Order Bump — como escrever', f:'marketing/7-21-copy-order-bump.md', time:'3 min', desc:'Headline, benefício, preço e CTA em no máximo 3 linhas.' }, { s:'mkt-cascata', t:'Funil cascata — Order Bump + Upsell', f:'marketing/7-22-funil-cascata.md', time:'3 min', desc:'Sequência de ofertas que maximiza o valor médio por transação.' }, ]}, { slug:'mkt-com', title:'Comunidade', items:[ { s:'mkt-mural', t:'Mural da comunidade', f:'marketing/7-23-mural-comunidade.md', time:'2 min', desc:'Feed social interno — posts, comentários e moderação de conteúdo.' }, { s:'mkt-discord', t:'Integrar Discord', f:'marketing/7-24-discord.md', time:'2 min', desc:'Enviar alunos automaticamente para um servidor Discord após a matrícula.' }, { s:'mkt-forum', t:'Fórum de dúvidas', f:'marketing/7-25-forum.md', time:'2 min', desc:'Threads por curso, resposta marcada como correta e indexação Google.' }, ]}, ]}, { slug:'integ', icon:'plug', color:'bg-teal-50 text-teal-700 border-teal-200', title:'Integrações', desc:'Pixel, GA4, vídeo, e-mail, webhooks e CRMs — conecte sua stack.', subs:[ { slug:'integ-nativas', title:'Pixels e analytics nativos', items:[ { s:'i-gtm', t:'Google Tag Manager (GTM)', f:'integracoes/14-1-gtm.md', time:'5 min', desc:'Container central de tags — instale 1x e gerencie qualquer pixel.' }, { s:'i-pixel', t:'Meta Pixel (Facebook)', f:'integracoes/14-2-meta-pixel.md', time:'5 min', desc:'Retarget e otimização de Meta Ads — integração nativa.' }, { s:'i-ga4', t:'Google Analytics 4', f:'integracoes/14-3-ga4.md', time:'5 min', desc:'Comportamento dos visitantes, conversões, e-commerce e UTM.' }, ]}, { slug:'integ-via-gtm', title:'Outros pixels (via GTM)', items:[ { s:'i-tt', t:'TikTok Pixel (via GTM)', f:'integracoes/14-4-tiktok.md', time:'4 min', desc:'Não é nativo — instale via GTM em 5 passos.' }, { s:'i-li', t:'LinkedIn Insight Tag (via GTM)', f:'integracoes/14-5-linkedin.md', time:'4 min', desc:'B2B premium — instalação via GTM com Custom HTML.' }, { s:'i-hot', t:'Hotjar (via GTM)', f:'integracoes/14-6-hotjar.md', time:'4 min', desc:'Gravações + heatmaps via GTM — atenção ao opt-in LGPD.' }, ]}, { slug:'integ-video', title:'Vídeo nas aulas', items:[ { s:'i-yt', t:'YouTube nas aulas', f:'integracoes/14-8-youtube.md', time:'2 min', desc:'Link do vídeo incorporado diretamente no AVA — sem sair da plataforma.' }, { s:'i-vimeo', t:'Vimeo nas aulas', f:'integracoes/14-9-vimeo.md', time:'2 min', desc:'Mais privacidade e player sem anúncios — restrição por domínio no Pro+.' }, { s:'i-upload', t:'Upload e player próprio', f:'integracoes/14-10-upload-video.md', time:'3 min', desc:'Vídeo hospedado na evob — download bloqueado e sem dependência externa.' }, ]}, { slug:'integ-email', title:'E-mail', items:[ { s:'i-email-tipos', t:'Tipos de e-mails automáticos da plataforma', f:'integracoes/14-11-emails-nativos-tipos.md', time:'3 min', desc:'Matrícula, cobrança, certificado, NPS — lista completa de envios nativos.' }, { s:'i-email-tpl', t:'Personalizar templates de e-mail', f:'integracoes/14-12-email-personalizar.md', time:'2 min', desc:'Assunto, corpo, variáveis e identidade visual dos e-mails automáticos.' }, { s:'i-email-rem', t:'Configurar remetente e domínio de envio', f:'integracoes/14-13-email-remetente.md', time:'2 min', desc:'Domínio próprio, registros SPF, DKIM e DMARC para boa entregabilidade.' }, ]}, { slug:'integ-wh', title:'Webhooks', items:[ { s:'i-wh-conc', t:'Webhooks — conceito e funcionamento', f:'integracoes/14-14-webhook-conceito.md', time:'2 min', desc:'Notificação em tempo real para sistemas externos a cada evento na evob.' }, { s:'i-wh-ev', t:'Eventos disponíveis para webhooks', f:'integracoes/14-15-webhook-eventos.md', time:'2 min', desc:'Lista completa: aluno, matrícula, compra, assinatura, conteúdo.' }, { s:'i-wh-conf', t:'Configurar e testar um webhook', f:'integracoes/14-16-webhook-configurar.md', time:'3 min', desc:'URL receptora, seleção de eventos, teste e ferramentas de apoio.' }, { s:'i-wh-retry', t:'Retry e depuração de webhooks', f:'integracoes/14-17-webhook-retry.md', time:'2 min', desc:'Intervalo de retentativas, log de envios e reenvio manual de falhas.' }, { s:'i-wh-hmac', t:'Segurança e autenticação (HMAC)', f:'integracoes/14-18-webhook-hmac.md', time:'2 min', desc:'Valida que o webhook veio da evob — impede dados forjados no receptor.' }, ]}, { slug:'integ-crm', title:'CRMs e ferramentas externas', items:[ { s:'i-webhook', t:'Conectar CRM ou ferramenta via Webhook', f:'integracoes/14-7-conectar-via-webhook.md', time:'5 min', desc:'RD, HubSpot, Salesforce, Mailchimp, AC — todos via Webhook ou Zapier.' }, { s:'i-ll', t:'Conectar LeadLovers via webhook', f:'integracoes/14-19-leadlovers.md', time:'3 min', desc:'Adiciona leads e move funis no LeadLovers após cada compra aprovada.' }, { s:'i-crm', t:'Conectar outras ferramentas via webhook', f:'integracoes/14-20-outras-ferramentas-webhook.md', time:'3 min', desc:'ActiveCampaign, Brevo, ConvertKit, RD Station e Slack via Zapier ou Make.' }, ]}, ]}, { slug:'marca', icon:'palette', color:'bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200', title:'Marca e Customização', desc:'Logo, paleta, fontes, banners, certificados — cara da sua plataforma.', subs:[ { slug:'marca-id', title:'Identidade visual', items:[ { s:'m-logo-guide', t:'Guia de uso do logo', f:'marca/13-1-logo-guide.md', time:'5 min', desc:'4 logos diferentes por contexto, variações e especificações técnicas.' }, { s:'m-paleta', t:'Paleta de cores expandida', f:'marca/13-2-paleta.md', time:'5 min', desc:'2 cores controlam toda a UI — variações automáticas, contraste WCAG.' }, { s:'m-fontes', t:'Famílias de fontes', f:'marca/13-3-fontes.md', time:'4 min', desc:'15 fontes prontas, custom em Pro+, LGPD-friendly (hospedagem local).' }, ]}, { slug:'marca-banner', title:'Banners', items:[ { s:'m-banner-conc', t:'O que é banner da loja', f:'marca/13-4-banner-conceito.md', time:'3 min', desc:'5 posições onde banner aparece + frequência ideal de troca.' }, { s:'m-banner-criar', t:'Criar banner', f:'marca/13-5-banner-criar.md', time:'4 min', desc:'Tamanhos por contexto, headlines e CTAs que convertem.' }, { s:'m-banner-video', t:'Banner em vídeo', f:'marca/13-6-banner-video.md', time:'4 min', desc:'+30-50% engajamento; specs, performance mobile e fallback.' }, { s:'m-banner-val', t:'Validade e agendamento', f:'marca/13-7-banner-validade.md', time:'3 min', desc:'Programar campanhas (BF, lançamento) com início e fim.' }, { s:'m-banner-cta', t:'CTA do banner', f:'marca/13-8-banner-cta.md', time:'3 min', desc:'Verbo + benefício; cor; tamanho mobile-first; CTRs benchmarks.' }, { s:'m-banner-ab', t:'Teste A/B de banner', f:'marca/13-9-banner-ab.md', time:'4 min', desc:'1 variável por teste, significância 95%, mínimo 7 dias.' }, ]}, { slug:'marca-pages', title:'Páginas customizadas', items:[ { s:'m-pages-edit', t:'Editar páginas customizadas', f:'marca/13-10-pages-edit.md', time:'4 min', desc:'4 páginas pré-criadas (Sobre, Contato, Termos, Privacidade) + custom.' }, { s:'m-sobre', t:'Página "Sobre"', f:'marca/13-11-sobre.md', time:'4 min', desc:'Lugar de credibilidade — estrutura ideal e tom humano.' }, { s:'m-termos', t:'Termos de uso', f:'marca/13-12-termos.md', time:'5 min', desc:'Obrigatório por CDC + LGPD — modelo padrão evob e adaptações.' }, { s:'m-contato', t:'Página de contato', f:'marca/13-13-contato.md', time:'3 min', desc:'Email, formulário, WhatsApp, anti-spam, SLA realista.' }, ]}, { slug:'marca-faq', title:'FAQ', items:[ { s:'m-faq-config', t:'Configurar FAQ', f:'marca/13-14-faq-config.md', time:'4 min', desc:'FAQ bem feito reduz SAC em 30-50% — 2 tipos (loja e curso).' }, { s:'m-faq-bp', t:'Boas práticas de FAQ', f:'marca/13-15-faq-bp.md', time:'4 min', desc:'Pergunta na voz do aluno, resposta em 2-3 frases, atualização trimestral.' }, { s:'m-faq-reord', t:'Reordenar FAQ', f:'marca/13-16-faq-reord.md', time:'3 min', desc:'Ordem decide o que aluno vê primeiro — top 3 captura 60% das leituras.' }, ]}, { slug:'marca-cat', title:'Categorias', items:[ { s:'m-cat-criar', t:'Criar categoria', f:'marca/13-17-cat-criar.md', time:'4 min', desc:'Quando criar (5+ cursos), naming, slug, banner, ícone.' }, { s:'m-cat-banner', t:'Banner da categoria', f:'marca/13-18-cat-banner.md', time:'3 min', desc:'Identidade visual por grupo — 1920×400, sem texto na imagem.' }, { s:'m-cat-reord', t:'Reordenar categorias', f:'marca/13-19-cat-reord.md', time:'3 min', desc:'Por popularidade, por momento, por sazonalidade — não alfabética.' }, { s:'m-cat-ocult', t:'Ocultar categoria', f:'marca/13-20-cat-ocult.md', time:'3 min', desc:'Pausada, privada, whitelist — alternativas a deletar.' }, ]}, { slug:'marca-cert', title:'Certificate Themes', items:[ { s:'m-cert-tem', t:'Temas de certificado', f:'marca/13-21-cert-temas.md', time:'4 min', desc:'3 temas prontos (Clássico, Moderno, Premium) + custom em Pro+.' }, { s:'m-cert-criar', t:'Criar tema de certificado', f:'marca/13-22-cert-criar.md', time:'5 min', desc:'Layout, variáveis, QR de validação, idiomas — passo a passo.' }, { s:'m-cert-vars', t:'Variáveis do certificado', f:'marca/13-23-cert-vars.md', time:'4 min', desc:'Catálogo completo: aluno, curso, data, validação e formatação.' }, { s:'m-cert-padrao', t:'Tema padrão da plataforma', f:'marca/13-24-cert-padrao.md', time:'3 min', desc:'Fallback para curso sem tema explícito — multi-loja, por nível.' }, ]}, { slug:'marca-dom', title:'Domínio', items:[ { s:'m-dom-evob', t:'Subdomínio evob.com.br', f:'marca/13-25-dom-evob.md', time:'3 min', desc:'Padrão grátis (suamarca.evob.com.br) — quando migrar para próprio.' }, { s:'m-dom-dns', t:'DNS — passo a passo', f:'marca/13-26-dom-dns.md', time:'5 min', desc:'CNAME, A, TXT, propagação 2-24h, troubleshooting.' }, { s:'m-dom-ssl', t:'SSL no domínio próprio', f:'marca/13-27-dom-ssl.md', time:'4 min', desc:'Cadeado verde via Let\'s Encrypt — automático, renovação a cada 60 dias.' }, { s:'m-dom-redir', t:'Redirecionamento de domínio', f:'marca/13-28-dom-redir.md', time:'3 min', desc:'HTTP→HTTPS, www, custom 301, regex (Pro+).' }, ]}, { slug:'marca-email', title:'Email visual', items:[ { s:'m-email-tpl', t:'Templates de email', f:'marca/13-29-email-templates.md', time:'4 min', desc:'Emails transacionais (compra, senha, certificado) — variáveis e tom.' }, { s:'m-email-head', t:'Cabeçalho do email', f:'marca/13-30-email-head.md', time:'3 min', desc:'Logo, nome da loja, cor — primeira impressão do email.' }, { s:'m-email-foot', t:'Rodapé do email', f:'marca/13-31-email-foot.md', time:'4 min', desc:'Obrigatório por LGPD/CDC — CNPJ, descadastro, Política e Termos.' }, ]}, ]}, { slug:'dash', icon:'chart', color:'bg-indigo-50 text-indigo-700 border-indigo-200', title:'Dashboard e Métricas', desc:'Vendas, alunos, NPS, funil — entenda o que importa em sua plataforma.', subs:[ { slug:'dash-plat', title:'Dashboard da plataforma', items:[ { s:'d-plat-vg', t:'Dashboard da plataforma — visão geral', f:'dashboard/12-1-dashboard-plataforma.md', time:'5 min', desc:'Primeira tela ao logar — receita, alunos, lojas e saúde técnica.' }, { s:'d-plat-met', t:'Métricas-chave da plataforma', f:'dashboard/12-2-metricas-chave.md', time:'6 min', desc:'As 8 métricas que respondem 90% das perguntas operacionais.' }, { s:'d-plat-filt', t:'Filtros da dashboard', f:'dashboard/12-3-filtros-dashboard.md', time:'4 min', desc:'Período, loja, status e UTM — combine para a resposta certa.' }, ]}, { slug:'dash-loja', title:'Dashboard da loja', items:[ { s:'d-loja-met', t:'Métricas da loja', f:'dashboard/12-4-metricas-loja.md', time:'5 min', desc:'4 abas (Cursos, Financeiro, Alunos, Pesquisas) e cards do topo.' }, { s:'d-loja-cur', t:'Aba Cursos', f:'dashboard/12-5-aba-cursos.md', time:'4 min', desc:'Top 5, drop, NPS e tabela completa de cursos.' }, { s:'d-loja-fin', t:'Aba Financeiro', f:'dashboard/12-6-aba-financeiro.md', time:'5 min', desc:'Receita bruta, líquida, mix de pagamento e saldo.' }, { s:'d-loja-al', t:'Aba Alunos', f:'dashboard/12-7-aba-alunos.md', time:'4 min', desc:'Quem entra, fica e sai — base para retenção e SAC.' }, { s:'d-loja-pesq', t:'Aba Pesquisas', f:'dashboard/12-8-aba-pesquisas.md', time:'4 min', desc:'NPS, CSAT e feedback aberto — pulso emocional da loja.' }, { s:'d-loja-res', t:'Resumo da semana', f:'dashboard/12-9-resumo-semana.md', time:'4 min', desc:'Email + modal automático toda segunda — 5 KPIs em narrativa.' }, ]}, { slug:'dash-curso', title:'Dashboard do curso', items:[ { s:'d-curso-mat', t:'Métricas de matrícula', f:'dashboard/12-10-metricas-matricula.md', time:'4 min', desc:'Quem entrou, como entrou, quando — origem e demografia.' }, { s:'d-curso-eng', t:'Engajamento do curso', f:'dashboard/12-11-engajamento-curso.md', time:'4 min', desc:'Conclusão, drop por aula e heatmap de engajamento.' }, { s:'d-curso-nps', t:'NPS do curso', f:'dashboard/12-12-nps-curso.md', time:'4 min', desc:'Score por curso, distribuição, tendência e como atender detratores.' }, { s:'d-curso-turm', t:'Métricas por turma', f:'dashboard/12-13-metricas-turma.md', time:'4 min', desc:'Compare cohorts e identifique o que funcionou em cada turma.' }, ]}, { slug:'dash-rel', title:'Relatórios exportáveis', items:[ { s:'d-rel-cur', t:'Relatório por curso', f:'dashboard/12-14-relatorio-por-curso.md', time:'4 min', desc:'Exportação completa de tudo de um curso (CSV, PDF, PNG).' }, { s:'d-rel-tur', t:'Relatório por turma', f:'dashboard/12-15-relatorio-turma.md', time:'3 min', desc:'Fechamento de cohort com lições aprendidas.' }, { s:'d-rel-tic', t:'Relatório de tickets (matrículas)', f:'dashboard/12-16-relatorio-tickets.md', time:'3 min', desc:'Auditoria de quem matriculou em quê e por qual valor.' }, { s:'d-rel-tx', t:'Relatório de transações', f:'dashboard/12-17-relatorio-transacoes.md', time:'4 min', desc:'Extrato detalhado para conciliação bancária e fechamento contábil.' }, { s:'d-rel-nps', t:'Relatório de NPS', f:'dashboard/12-18-relatorio-nps.md', time:'3 min', desc:'CSV consolidado de respostas para análise estatística.' }, { s:'d-rel-csat', t:'Relatório de CSAT', f:'dashboard/12-19-relatorio-csat.md', time:'3 min', desc:'Satisfação imediata por aula — complementa NPS.' }, ]}, { slug:'dash-adv', title:'Análise avançada', items:[ { s:'d-funil', t:'Funil de conversão', f:'dashboard/12-20-funil-conversao.md', time:'5 min', desc:'Onde o aluno em potencial perde no caminho — visita até matrícula.' }, { s:'d-ltv', t:'LTV — Lifetime Value', f:'dashboard/12-21-ltv.md', time:'5 min', desc:'Receita média por aluno na vida + razão LTV/CAC.' }, { s:'d-churn', t:'Churn — taxa de saída', f:'dashboard/12-22-churn.md', time:'5 min', desc:'% de alunos que saem — voluntário, involuntário e como reduzir.' }, { s:'d-coh', t:'Análise de coorte', f:'dashboard/12-23-analise-coorte.md', time:'5 min', desc:'Agrupe por mês de entrada e veja se está melhorando ou piorando.' }, ]}, ]}, { slug:'gam', icon:'trophy', color:'bg-yellow-50 text-yellow-700 border-yellow-200', title:'Gamificação', desc:'Pontos, recompensas, ranking — engaje alunos como Duolingo.', subs:[ { slug:'gam-conceito', title:'Conceitos', items:[ { s:'gam-o-que-e', t:'O que é gamificação na evob', f:'gamificacao/9-1-o-que-e-gamificacao.md', time:'5 min', desc:'Pontos, recompensas, ranking, loja — as 4 mecânicas e quando ativar.' }, { s:'gam-pre-req', t:'Pré-requisitos para ativar', f:'gamificacao/9-2-pre-requisitos.md', time:'4 min', desc:'Plano, orçamento, pessoa responsável e decisões antes de ativar.' }, ]}, { slug:'gam-pontos', title:'Pontos (coins)', items:[ { s:'gam-coins', t:'Como funcionam os pontos', f:'gamificacao/9-3-como-funcionam-pontos.md', time:'5 min', desc:'Ciclo do ponto, ganhos, gastos, anti-inflação e auditoria.' }, { s:'gam-regras', t:'Configurar regras de pontos', f:'gamificacao/9-4-configurar-regras.md', time:'6 min', desc:'Triggers, pontos, limites e simulação antes de ativar.' }, { s:'gam-pts-aulas', t:'Pontos por aula, NPS e comentário', f:'gamificacao/9-5-pontos-por-aula-nps-comentario.md', time:'4 min', desc:'Os 3 triggers essenciais — núcleo da gamificação saudável.' }, { s:'gam-whitelist', t:'Whitelist de cursos', f:'gamificacao/9-6-whitelist-cursos.md', time:'3 min', desc:'Pontos diferentes por curso (premium, lançamento, compliance).' }, ]}, { slug:'gam-rec', title:'Recompensas', items:[ { s:'gam-criar-rec', t:'Criar uma recompensa', f:'gamificacao/9-7-criar-recompensa.md', time:'5 min', desc:'Anatomia, custo em pontos, imagem e fluxo de aprovação.' }, { s:'gam-tipos-rec', t:'Tipos: virtual, física e status', f:'gamificacao/9-8-tipos-recompensa.md', time:'4 min', desc:'Comparativo de custo, logística e engajamento por tipo.' }, { s:'gam-lim', t:'Limite de resgate', f:'gamificacao/9-9-limite-resgate.md', time:'4 min', desc:'Caps por aluno e estoque global para evitar drenagem.' }, { s:'gam-aprov', t:'Aprovar resgates', f:'gamificacao/9-10-aprovar-resgate.md', time:'4 min', desc:'Fluxo de aprovação, SLA, comunicação e bulk approval.' }, ]}, { slug:'gam-loja', title:'Loja de itens', items:[ { s:'gam-store', t:'Loja de itens (Items Store)', f:'gamificacao/9-11-loja-itens.md', time:'4 min', desc:'Vitrine onde o aluno gasta os pontos — categorias e ordenação.' }, { s:'gam-prod', t:'Adicionar produtos resgatáveis', f:'gamificacao/9-12-adicionar-produtos-resgataveis.md', time:'4 min', desc:'Curso, mentoria ou aula da plataforma como recompensa.' }, { s:'gam-wl-store', t:'Whitelist de Items Store', f:'gamificacao/9-13-whitelist-items-store.md', time:'3 min', desc:'Recompensas exclusivas por nível, curso, ranking ou tag.' }, ]}, { slug:'gam-rank', title:'Ranking', items:[ { s:'gam-ativar-rank', t:'Ativar ranking', f:'gamificacao/9-14-ativar-ranking.md', time:'5 min', desc:'Público vs privado, escopo, visibilidade e LGPD.' }, { s:'gam-periodo', t:'Período do ranking', f:'gamificacao/9-15-periodo-ranking.md', time:'4 min', desc:'Diário, semanal, mensal — comportamento e trade-offs de cada um.' }, { s:'gam-prem', t:'Premiação do top', f:'gamificacao/9-16-premiacao-top.md', time:'4 min', desc:'Prêmios automáticos para top alunos — pontos, recompensas e hall da fama.' }, ]}, { slug:'gam-trig', title:'Triggers e ajustes', items:[ { s:'gam-trig-auto', t:'Triggers automáticos', f:'gamificacao/9-17-triggers-automaticos.md', time:'5 min', desc:'Catálogo completo de eventos do sistema que disparam pontos.' }, { s:'gam-add-pts', t:'Adicionar pontos manualmente', f:'gamificacao/9-18-adicionar-pontos-manual.md', time:'4 min', desc:'Crédito/débito ad-hoc com auditoria — eventos offline e correções.' }, ]}, ]}, { slug:'sup', icon:'lifebuoy', color:'bg-cyan-50 text-cyan-700 border-cyan-200', title:'Conta e Suporte', desc:'Sua conta, recuperação de acesso, problemas comuns e falar com CS.', subs:[ { slug:'s-conta', title:'Conta do admin', items:[ { s:'s-perfil', t:'Editar perfil do admin', f:'suporte/8-1-editar-perfil.md', time:'3 min', desc:'Foto, nome, email, telefone, cargo — privacidade.' }, { s:'s-senha', t:'Trocar senha (e boas práticas)', f:'suporte/8-2-trocar-senha.md', time:'4 min', desc:'Requisitos, gerenciadores, sessões ativas.' }, { s:'s-email', t:'Alterar e-mail da conta', f:'suporte/8-7-alterar-email.md', time:'2 min', desc:'Confirmação dupla — e-mail atual e novo precisam confirmar.' }, { s:'s-sess', t:'Sessões ativas e desconectar dispositivos', f:'suporte/8-8-sessoes-ativas.md', time:'2 min', desc:'Ver dispositivos logados e encerrar sessões remotamente.' }, { s:'s-excluir', t:'Excluir conta do admin', f:'suporte/8-9-excluir-conta.md', time:'2 min', desc:'Dados removidos, dados preservados e checklist antes de excluir.' }, ]}, { slug:'s-recuperacao', title:'Recuperação de acesso', items:[ { s:'s-esq-senha', t:'Esqueci minha senha', f:'suporte/8-10-esqueci-senha.md', time:'2 min', desc:'Link por e-mail — válido por 30 minutos.' }, { s:'s-no-email', t:'E-mail de recuperação não chega', f:'suporte/8-11-email-nao-chega.md', time:'2 min', desc:'Checklist de diagnóstico — spam, typo, filtro corporativo.' }, { s:'s-mfa-perda', t:'Perdi acesso ao MFA', f:'suporte/8-12-mfa-perda.md', time:'2 min', desc:'Código de backup, novo dispositivo ou recuperação via CS.' }, ]}, { slug:'s-convites', title:'Convites e acesso', items:[ { s:'s-conv-aceitar', t:'Aceitar convite para ser admin', f:'suporte/8-13-aceitar-convite.md', time:'2 min', desc:'Link por e-mail — válido por 7 dias.' }, { s:'s-conv-exp', t:'Convite expirado', f:'suporte/8-14-convite-expirado.md', time:'2 min', desc:'Como pedir reenvio e o que verificar.' }, { s:'s-multi-plat', t:'Gerenciar múltiplas contas evob', f:'suporte/8-15-multiplas-plataformas.md', time:'2 min', desc:'Um e-mail para várias lojas e contas — como alternar.' }, ]}, { slug:'s-bug', title:'Problemas comuns', items:[ { s:'s-loop', t:'Página em branco / loop', f:'suporte/8-3-pagina-loop.md', time:'5 min', desc:'5 níveis de troubleshoot — do refresh forçado ao navegador alternativo.' }, { s:'s-pgto', t:'Pagamento recusado — causas e diagnóstico', f:'suporte/8-4-pagamento-recusado.md', time:'6 min', desc:'10 causas mais comuns + script padrão para atendimento.' }, { s:'s-503', t:'Erro 503 — AVA fora do ar', f:'suporte/8-16-erro-503.md', time:'2 min', desc:'Diagnóstico passo a passo e quando reportar.' }, { s:'s-401', t:'Erro 401 — sem permissão', f:'suporte/8-17-erro-401.md', time:'2 min', desc:'Sessão expirada, acesso revogado ou token inválido.' }, { s:'s-img', t:'Imagens quebradas no AVA', f:'suporte/8-18-imagens-quebradas.md', time:'2 min', desc:'URL inválida ou arquivo removido — como corrigir por tipo.' }, { s:'s-video', t:'Vídeo não carrega no AVA', f:'suporte/8-19-video-nao-carrega.md', time:'2 min', desc:'Processamento, formato, conexão e firewall corporativo.' }, { s:'s-email-mat', t:'E-mail de matrícula não chegou', f:'suporte/8-20-email-matricula-nao-chegou.md', time:'2 min', desc:'Checklist de diagnóstico e como reenviar.' }, { s:'s-wh-fail', t:'Webhook falhou — reenvio e diagnóstico', f:'suporte/8-21-webhook-falhou.md', time:'2 min', desc:'Status HTTP, retry automático e reenvio manual.' }, { s:'s-sem-curso', t:'Aluno não vê o curso após a compra', f:'suporte/8-22-aluno-sem-curso.md', time:'2 min', desc:'Checklist: pagamento, matrícula, e-mail, publicação da turma.' }, ]}, { slug:'s-status', title:'Status do sistema', items:[ { s:'s-stat-page', t:'Página de status do sistema', f:'suporte/8-23-status-page.md', time:'2 min', desc:'Componentes monitorados e o que cada status significa.' }, { s:'s-stat-hist', t:'Histórico de incidentes', f:'suporte/8-24-historico-incidentes.md', time:'2 min', desc:'90 dias de ocorrências com duração e causa identificada.' }, { s:'s-stat-sub', t:'Assinar alertas de status', f:'suporte/8-25-assinar-status.md', time:'2 min', desc:'Receber notificações de incidentes por e-mail automaticamente.' }, ]}, { slug:'s-lixeira', title:'Lixeira', items:[ { s:'s-lix-o-que', t:'O que é a lixeira', f:'suporte/8-26-lixeira-o-que-e.md', time:'2 min', desc:'30 dias de buffer antes da exclusão definitiva — o que vai para lá.' }, { s:'s-rest', t:'Restaurar item da lixeira', f:'suporte/8-27-restaurar-item.md', time:'2 min', desc:'O que volta junto com o item e o status após restaurar.' }, { s:'s-esv', t:'Esvaziar a lixeira', f:'suporte/8-28-esvaziar-lixeira.md', time:'2 min', desc:'Exclusão permanente — irreversível e sem backup.' }, ]}, { slug:'s-cs', title:'Falar com a evob', items:[ { s:'s-quando', t:'Quando abrir um chamado', f:'suporte/8-5-quando-abrir-chamado.md', time:'5 min', desc:'A regra dos 3 passos, estrutura ideal, prioridades P0-P3.' }, { s:'s-sla', t:'SLA de suporte por plano', f:'suporte/8-6-sla-por-plano.md', time:'4 min', desc:'Tempos de resposta por plano e prioridade.' }, { s:'s-como', t:'Como abrir chamado com o CS', f:'suporte/8-29-como-abrir-chamado.md', time:'2 min', desc:'Canais disponíveis, o que incluir e como priorizar.' }, { s:'s-enviar', t:'Enviar evidências para o CS', f:'suporte/8-30-enviar-evidencias.md', time:'2 min', desc:'Prints, gravações, IDs e logs — o que capturar por tipo de problema.' }, ]}, ]}, ] window.CATALOG = CATALOG const POPULAR_SLUGS = ['o-que-e-evob', 'tour-admin', 'trilha-plataforma', 'glossario', 'pedir-suporte'] const RECENT_SLUGS = ['trilha-plataforma', 'checklist-pronta', 'trilha-loja', 'trilha-curso', 'pedir-suporte'] // ─── Util ─────────────────────────────────────────────────────────────── function el(tag, opts) { opts = opts || {} const node = document.createElement(tag) if (opts.class) node.className = opts.class if (opts.text) node.textContent = opts.text if (opts.attrs) for (const k in opts.attrs) node.setAttribute(k, opts.attrs[k]) if (opts.on) for (const evt in opts.on) node.addEventListener(evt, opts.on[evt]) return node } const ALL_ARTICLES = [] CATALOG.forEach(cat => cat.subs.forEach(sub => sub.items.forEach(it => { ALL_ARTICLES.push({ ...it, catSlug: cat.slug, catTitle: cat.title, catIcon: cat.icon, catColor: cat.color, subTitle: sub.title }) }))) function findArticle(s) { return ALL_ARTICLES.find(a => a.s === s) } function findCategory(slug) { return CATALOG.find(c => c.slug === slug) } // ─── Home ─────────────────────────────────────────────────────────────── function renderHome() { // TRILHAS const trails = document.getElementById('trails-list') trails.replaceChildren() const TRAILS = [ { name:'Admin de Plataforma', icon:'building', sub:'Dono ou sócio do negócio', desc:'15 passos do login à primeira venda.', time:'~30 min', slug:'trilha-plataforma', color:'from-violet-500 to-purple-600' }, { name:'Admin de Loja', icon:'storefront', sub:'Quem opera uma loja', desc:'12 passos focados em catálogo e marketing.', time:'~25 min', slug:'trilha-loja', color:'from-blue-500 to-cyan-600' }, { name:'Admin de Curso', icon:'book', sub:'Professor ou coordenador', desc:'10 passos para entregar boa experiência.', time:'~20 min', slug:'trilha-curso', color:'from-emerald-500 to-teal-600' }, ] TRAILS.forEach(t => { const card = el('button', { class: 'trail-card text-left bg-white rounded-2xl border border-soft p-6 hover:border-purple-300 group w-full', on: { click: () => openArticle(t.slug) }, }) const head = el('div', { class:`icon-tile icon-trail w-12 h-12 rounded-xl bg-gradient-to-br ${t.color} mb-4` }) head.innerHTML = icon(t.icon) card.appendChild(head) card.appendChild(el('div', { class:'text-[12.5px] text-gray-500 font-medium mb-1', text: t.sub })) card.appendChild(el('div', { class:'text-[18px] font-bold text-gray-900 mb-2', text: t.name })) card.appendChild(el('p', { class:'text-[14px] text-gray-600 leading-snug mb-4', text: t.desc })) const footer = el('div', { class:'flex items-center justify-between text-[13px] pt-3 border-t border-gray-100' }) footer.appendChild(el('span', { class:'text-gray-500', text: t.time })) const cta = el('span', { class:'text-brand font-medium flex items-center gap-1 group-hover:gap-1.5 transition-all' }) cta.appendChild(el('span', { text: 'Começar' })) const arrow = el('span', { class:'icon-tile' }) arrow.style.width = '14px' arrow.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width:14px;height:14px;"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>' cta.appendChild(arrow) footer.appendChild(cta) card.appendChild(footer) trails.appendChild(card) }) // CATEGORIAS const cats = document.getElementById('cat-list') cats.replaceChildren() CATALOG.forEach(cat => { const total = cat.subs.reduce((a, s) => a + s.items.length, 0) const card = el('button', { class: 'cat-card text-left bg-white rounded-xl border border-soft p-5 group w-full', on: { click: () => openCategoryListing(cat.slug) }, }) const head = el('div', { class:`icon-tile w-11 h-11 rounded-xl ${cat.color} border mb-3` }) head.innerHTML = icon(cat.icon) card.appendChild(head) card.appendChild(el('div', { class:'text-[16px] font-bold text-gray-900 mb-1', text: cat.title })) card.appendChild(el('p', { class:'text-[13.5px] text-gray-600 leading-snug mb-3', text: cat.desc })) const meta = el('div', { class:'flex items-center justify-between text-[12.5px]' }) meta.appendChild(el('span', { class:'text-gray-400', text: total + (total === 1 ? ' artigo' : ' artigos') })) const cArrow = el('span', { class:'text-brand group-hover:translate-x-0.5 transition flex items-center' }) cArrow.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width:14px;height:14px;"><path d="m9 18 6-6-6-6"/></svg>' meta.appendChild(cArrow) card.appendChild(meta) cats.appendChild(card) }) // POPULARES const popular = document.getElementById('popular-list') popular.replaceChildren() POPULAR_SLUGS.forEach((slug, i) => { const a = findArticle(slug); if (!a) return popular.appendChild(buildArticleRow(a, i + 1)) }) // RECENTES const recent = document.getElementById('recent-list') recent.replaceChildren() RECENT_SLUGS.forEach((slug, i) => { const a = findArticle(slug); if (!a) return recent.appendChild(buildArticleRow(a, i + 1)) }) } function buildArticleRow(a, n) { const item = el('button', { class: 'block w-full text-left p-3 rounded-lg hover:bg-gray-50 transition group flex items-start gap-3', on: { click: () => openArticle(a.s) }, }) const num = el('div', { class:'flex-shrink-0 w-7 h-7 rounded-md bg-gray-50 group-hover:bg-brand-soft text-gray-400 group-hover:text-brand text-[12.5px] font-semibold flex items-center justify-center mt-0.5', text: String(n).padStart(2,'0') }) item.appendChild(num) const txt = el('div', { class:'min-w-0 flex-1' }) txt.appendChild(el('div', { class:'text-[14.5px] text-gray-900 font-medium group-hover:text-brand truncate', text: a.t })) if (a.desc) txt.appendChild(el('div', { class:'text-[13px] text-gray-500 leading-snug truncate mt-0.5', text: a.desc })) const meta = el('div', { class:'text-[12px] text-gray-400 mt-1.5 flex items-center gap-2' }) meta.appendChild(el('span', { text: a.catTitle })) if (a.time) { meta.appendChild(el('span', { text:'·' })); meta.appendChild(el('span', { text: a.time })) } txt.appendChild(meta) item.appendChild(txt) return item } // ─── Listagem de categoria ───────────────────────────────────────────── function openCategoryListing(slug) { const cat = findCategory(slug); if (!cat) return document.getElementById('home-view').classList.add('hidden') document.getElementById('article-view').classList.remove('hidden') window.scrollTo(0, 0) const bc = document.getElementById('breadcrumb') bc.replaceChildren() bc.appendChild(el('a', { class:'hover:text-gray-900 cursor-pointer', text:'Central de Ajuda', on:{ click: goHome } })) bc.appendChild(el('span', { class:'text-gray-300', text:'/' })) bc.appendChild(el('span', { class:'text-gray-900', text: cat.title })) const titleEl = document.getElementById('article-title') titleEl.replaceChildren() const tIcon = el('span', { class:`icon-tile w-9 h-9 rounded-lg ${cat.color} border align-middle mr-3` }) tIcon.innerHTML = icon(cat.icon) titleEl.appendChild(tIcon) titleEl.appendChild(el('span', { text: cat.title })) const totalArt = cat.subs.reduce((a, s) => a + s.items.length, 0) document.getElementById('article-lede').textContent = cat.desc + ' ' + totalArt + ' artigos disponíveis.' document.getElementById('article-meta-strip').replaceChildren() const content = document.getElementById('article-content') content.replaceChildren() cat.subs.forEach(sub => { content.appendChild(el('h2', { text: sub.title })) const list = el('ul', {}) sub.items.forEach(it => { const li = el('li') if (it.f) { const a = el('a', { attrs: { href: '#/article/' + it.s }, text: it.t }) a.addEventListener('click', e => { e.preventDefault(); openArticle(it.s) }) li.appendChild(a) if (it.time) li.appendChild(el('span', { class:'text-gray-400 text-[13px] ml-2', text: '· ' + it.time })) } else { li.appendChild(el('span', { class:'text-gray-400 italic', text: it.t + ' (em produção)' })) } list.appendChild(li) }) content.appendChild(list) }) document.getElementById('article-nav-pn').replaceChildren() } // ─── Abrir artigo real ───────────────────────────────────────────────── async function openArticle(slug) { const article = findArticle(slug); if (!article) return if (!article.f) { document.getElementById('home-view').classList.add('hidden') document.getElementById('article-view').classList.remove('hidden') window.scrollTo(0, 0) document.getElementById('breadcrumb').replaceChildren( el('a', { class:'hover:text-gray-900 cursor-pointer', text:'Central de Ajuda', on:{ click: goHome } }), el('span', { class:'text-gray-300', text:'/' }), el('span', { class:'text-gray-900', text: article.t }), ) document.getElementById('article-title').textContent = article.t document.getElementById('article-lede').textContent = '' document.getElementById('article-meta-strip').replaceChildren() const content = document.getElementById('article-content') content.replaceChildren() const box = el('div', { class:'border-2 border-dashed border-gray-200 rounded-xl p-10 text-center bg-gray-50' }) const pIcon = el('div', { class:'inline-flex items-center justify-center w-14 h-14 rounded-full bg-white border border-gray-200 text-brand mb-4' }) pIcon.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.6" style="width:26px;height:26px;">' + icon('pencil').match(/<svg[^>]*>([\s\S]*)<\/svg>/)[1] + '</svg>' box.appendChild(pIcon) box.appendChild(el('p', { class:'text-gray-800 font-semibold mb-1', text:'Estamos escrevendo este artigo' })) box.appendChild(el('p', { class:'text-sm text-gray-500', text:'Enquanto isso, fale com nosso time — ele te ajuda em até 30 min.' })) content.appendChild(box) document.getElementById('article-nav-pn').replaceChildren() return } document.getElementById('home-view').classList.add('hidden') document.getElementById('article-view').classList.remove('hidden') window.scrollTo(0, 0) const bc = document.getElementById('breadcrumb') bc.replaceChildren() bc.appendChild(el('a', { class:'hover:text-gray-900 cursor-pointer', text:'Central de Ajuda', on:{ click: goHome } })) bc.appendChild(el('span', { class:'text-gray-300', text:'/' })) const catLink = el('a', { class:'hover:text-gray-900 cursor-pointer inline-flex items-center gap-1.5', on:{ click: () => openCategoryListing(article.catSlug) } }) const catIco = el('span', { class:'icon-bc inline-flex items-center text-gray-400' }) catIco.innerHTML = icon(article.catIcon) catLink.appendChild(catIco) catLink.appendChild(el('span', { text: article.catTitle })) bc.appendChild(catLink) bc.appendChild(el('span', { class:'text-gray-300', text:'/' })) bc.appendChild(el('span', { class:'text-gray-900', text: article.subTitle })) const meta = document.getElementById('article-meta-strip') meta.replaceChildren() if (article.time) { const t = el('span', { class:'icon-meta inline-flex items-center gap-1.5 text-gray-500' }) t.innerHTML = icon('clock') t.appendChild(el('span', { text: article.time + ' de leitura' })) meta.appendChild(t) } meta.appendChild(el('span', { class:'text-gray-300', text: '·' })) meta.appendChild(el('span', { text: 'Atualizado em 30 abr 2026' })) document.getElementById('article-title').textContent = article.t document.getElementById('article-lede').textContent = article.desc || '' const content = document.getElementById('article-content') content.replaceChildren() try { // Configura renderer de links na primeira abertura de artigo. // marked.min.js é carregado com defer, então não pode ser chamado no top-level. if (!openArticle._markedReady) { openArticle._markedReady = true marked.use({ renderer: { link({ href, title, text }) { if (href && href.endsWith('.md')) { const filename = href.split('/').pop() const art = ALL_ARTICLES.find(a => a.f && (a.f === filename || a.f.endsWith('/' + filename))) if (art) return '<a href="#/a/' + art.s + '">' + text + '</a>' return '<span class="text-gray-400">' + text + '</span>' } if (href && (href.startsWith('http://') || href.startsWith('https://'))) { return '<a href="' + href + '"' + (title ? ' title="' + title + '"' : '') + ' target="_blank" rel="noopener noreferrer">' + text + '</a>' } return '<a href="' + (href || '#') + '"' + (title ? ' title="' + title + '"' : '') + '>' + text + '</a>' } } }) } // Resolve path relativo correto (pré-render fica em /ajuda/<slug>/, então sobe 2 níveis) const isPrerendered = !!document.body.dataset.prerenderSlug const fetchPath = isPrerendered ? '../../' + article.f : article.f const response = await fetch(fetchPath) if (!response.ok) throw new Error('fetch failed') const md = await response.text() const stripped = stripHeader(md) const html = DOMPurify.sanitize(marked.parse(stripped), { ALLOWED_TAGS: ['h2','h3','h4','p','a','strong','em','ul','ol','li','code','pre','blockquote','table','thead','tbody','tr','th','td','hr','br','span'], ALLOWED_ATTR: ['href','title','class','target','rel'], }) content.innerHTML = html } catch (e) { content.appendChild(el('div', { class:'border border-yellow-200 bg-yellow-50 rounded-lg p-4 text-sm text-yellow-800', text: 'Erro ao carregar conteúdo. Sirva via HTTP local.' })) } buildPrevNext(slug) history.replaceState(null, '', '#/article/' + slug) } function stripHeader(md) { return md.replace(/^# [^\n]+\n+>[^\n]+\n+>[^\n]+\n+---\n+/, '') } // ─── Prev/Next ───────────────────────────────────────────────────────── function buildPrevNext(slug) { const idx = ALL_ARTICLES.findIndex(a => a.s === slug) const prev = ALL_ARTICLES.slice(0, idx).reverse().find(a => a.f) const next = ALL_ARTICLES.slice(idx + 1).find(a => a.f) const wrap = document.getElementById('article-nav-pn') wrap.replaceChildren() function card(a, label, dir) { if (!a) return el('div') const c = el('button', { class: 'border border-soft rounded-xl p-4 text-left hover:border-purple-300 hover:shadow-sm transition w-full', on: { click: () => openArticle(a.s) }, }) const head = el('div', { class:'text-[11.5px] uppercase tracking-wider text-gray-400 mb-1.5 font-medium flex items-center gap-1.5' }) if (dir === 'prev') { const ico = el('span', { class:'inline-flex items-center' }) ico.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width:12px;height:12px;"><path d="M19 12H5"/><path d="m12 19-7-7 7-7"/></svg>' head.appendChild(ico) head.appendChild(el('span', { text: label })) } else { head.classList.add('justify-end') head.appendChild(el('span', { text: label })) const ico = el('span', { class:'inline-flex items-center' }) ico.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" style="width:12px;height:12px;"><path d="M5 12h14"/><path d="m12 5 7 7-7 7"/></svg>' head.appendChild(ico) } c.appendChild(head) const titleClass = dir === 'next' ? 'text-[14.5px] font-semibold text-gray-900 text-right' : 'text-[14.5px] font-semibold text-gray-900' c.appendChild(el('div', { class: titleClass, text: a.t })) return c } wrap.appendChild(card(prev, 'Anterior', 'prev')) wrap.appendChild(card(next, 'Próximo', 'next')) } // ─── Search modal ────────────────────────────────────────────────────── let searchActiveIdx = 0 let searchMatches = [] function openSearchModal(query) { document.getElementById('search-modal').classList.remove('hidden') const input = document.getElementById('search-input') input.value = query || '' input.focus() renderSearch(input.value) } function closeSearchModal() { document.getElementById('search-modal').classList.add('hidden') } function renderSearch(query) { const list = document.getElementById('search-results') list.replaceChildren() const q = query.toLowerCase().trim() searchMatches = q ? ALL_ARTICLES.filter(a => a.t.toLowerCase().includes(q) || (a.desc || '').toLowerCase().includes(q) || a.catTitle.toLowerCase().includes(q)) : ALL_ARTICLES.filter(a => a.f).slice(0, 10) if (searchMatches.length === 0) { const empty = el('div', { class:'p-10 text-center' }) const emIcon = el('div', { class:'inline-flex items-center justify-center w-12 h-12 rounded-full bg-gray-100 text-gray-400 mb-3' }) emIcon.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.6" style="width:24px;height:24px;"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/></svg>' empty.appendChild(emIcon) empty.appendChild(el('div', { class:'text-gray-700 font-medium mb-1', text:'Não achamos nada para "' + query + '"' })) empty.appendChild(el('div', { class:'text-sm text-gray-500', text:'Tente termos mais simples ou fale com nosso time.' })) list.appendChild(empty) return } searchMatches.forEach((a, i) => { const result = el('div', { class: 'search-result' + (i === searchActiveIdx ? ' active' : ''), on: { click: () => { closeSearchModal(); openArticle(a.s) } }, }) const top = el('div', { class:'flex items-center gap-2 mb-0.5' }) const ti = el('span', { class:'inline-flex items-center text-gray-500' }) ti.style.width = '14px' ti.style.height = '14px' ti.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.8" style="width:14px;height:14px;">' + icon(a.catIcon).match(/<svg[^>]*>([\s\S]*)<\/svg>/)[1] + '</svg>' top.appendChild(ti) top.appendChild(el('span', { class:'text-[11.5px] uppercase tracking-wider text-gray-500 font-medium', text: a.catTitle })) if (!a.f) top.appendChild(el('span', { class:'text-[10.5px] uppercase tracking-wider text-amber-600 font-medium', text:'· em produção' })) result.appendChild(top) result.appendChild(el('div', { class:'text-[14.5px] font-medium text-gray-900', text: a.t })) if (a.desc) result.appendChild(el('div', { class:'text-[13px] text-gray-500 mt-0.5', text: a.desc })) list.appendChild(result) }) } // ─── SEO/Meta dinâmica ───────────────────────────────────────────────── const BASE_TITLE = 'Central de Ajuda — evob' const BASE_DESC = 'Tudo que você precisa para tirar o máximo da sua plataforma evob — guias, vídeos, dúvidas frequentes e suporte humano.' function setMeta(title, desc) { const t = title ? title + ' — Central de Ajuda evob' : BASE_TITLE const d = desc || BASE_DESC document.title = t document.getElementById('page-title').textContent = t document.getElementById('og-title').setAttribute('content', t) document.getElementById('tw-title').setAttribute('content', t) document.getElementById('og-desc').setAttribute('content', d) document.getElementById('tw-desc').setAttribute('content', d) document.getElementById('meta-desc').setAttribute('content', d) } // ─── Toast ───────────────────────────────────────────────────────────── let _toastTimer function showToast(msg) { const t = document.getElementById('toast') t.textContent = msg t.classList.add('show') clearTimeout(_toastTimer) _toastTimer = setTimeout(() => t.classList.remove('show'), 2200) } // ─── Copy link ───────────────────────────────────────────────────────── async function copyCurrentLink() { const url = window.location.href try { if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(url) } else { const ta = document.createElement('textarea') ta.value = url; document.body.appendChild(ta); ta.select() document.execCommand('copy'); document.body.removeChild(ta) } showToast('Link copiado') } catch { showToast('Não foi possível copiar') } } // ─── Drawer mobile ───────────────────────────────────────────────────── function populateDrawer() { const wrap = document.getElementById('drawer-cats') wrap.replaceChildren() CATALOG.forEach(cat => { const btn = el('button', { class: 'w-full text-left px-3 py-2.5 rounded-lg hover:bg-gray-50 flex items-center gap-3 text-gray-700', on: { click: () => { closeDrawer(); openCategoryListing(cat.slug) } }, }) const ti = el('span', { class:`inline-flex items-center justify-center w-7 h-7 rounded-md ${cat.color} border` }) ti.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.7" style="width:14px;height:14px;">' + icon(cat.icon).match(/<svg[^>]*>([\s\S]*)<\/svg>/)[1] + '</svg>' btn.appendChild(ti) btn.appendChild(el('span', { text: cat.title })) wrap.appendChild(btn) }) } function openDrawer() { document.getElementById('drawer').classList.add('open') document.getElementById('drawer-backdrop').classList.add('open') document.body.style.overflow = 'hidden' } function closeDrawer() { document.getElementById('drawer').classList.remove('open') document.getElementById('drawer-backdrop').classList.remove('open') document.body.style.overflow = '' } // ─── Navegação + Deep Linking ────────────────────────────────────────── function goHome(opts) { document.getElementById('article-view').classList.add('hidden') document.getElementById('home-view').classList.remove('hidden') window.scrollTo(0, 0) setMeta(null, null) if (!opts || opts.updateHash !== false) history.replaceState(null, '', window.location.pathname) } // Estende openCategoryListing/openArticle para escrever hash + meta const _origOpenCategoryListing = openCategoryListing openCategoryListing = function(slug) { _origOpenCategoryListing(slug) const cat = findCategory(slug); if (!cat) return setMeta(cat.title, cat.desc) history.replaceState(null, '', '#/c/' + slug) } const _origOpenArticle = openArticle openArticle = async function(slug) { await _origOpenArticle(slug) const a = findArticle(slug); if (!a) return setMeta(a.t, a.desc) history.replaceState(null, '', '#/a/' + slug) } function handleHash() { const h = window.location.hash let m if ((m = h.match(/[#\/]a(?:rticle)?\/([\w-]+)/))) openArticle(m[1]) else if ((m = h.match(/[#\/]c(?:ategoria)?\/([\w-]+)/))) openCategoryListing(m[1]) else if ((m = h.match(/[#\/]b(?:uscar)?\/([^&]+)/))) { goHome({ updateHash:false }); openSearchModal(decodeURIComponent(m[1])) } else goHome({ updateHash:false }) } // Atualiza openSearchModal para escrever hash quando há query const _origOpenSearchModal = openSearchModal openSearchModal = function(query) { _origOpenSearchModal(query) if (query) history.replaceState(null, '', '#/b/' + encodeURIComponent(query)) } // ─── Bootstrap ───────────────────────────────────────────────────────── renderHome() populateDrawer() document.getElementById('logo-btn').addEventListener('click', () => goHome()) document.getElementById('nav-help').addEventListener('click', e => { e.preventDefault(); goHome() }) document.getElementById('hero-search-trigger').addEventListener('click', () => openSearchModal()) document.getElementById('search-icon-mobile').addEventListener('click', () => openSearchModal()) document.getElementById('contact-btn').addEventListener('click', () => showToast('Em breve: chat com Customer Success')) document.getElementById('fab-contact').addEventListener('click', () => showToast('Em breve: chat com Customer Success')) document.getElementById('drawer-contact').addEventListener('click', () => { closeDrawer(); showToast('Em breve: chat com Customer Success') }) document.getElementById('menu-btn').addEventListener('click', openDrawer) document.getElementById('drawer-close').addEventListener('click', closeDrawer) document.getElementById('drawer-backdrop').addEventListener('click', closeDrawer) document.querySelectorAll('.drawer-link').forEach(b => { b.addEventListener('click', () => { const action = b.dataset.action if (action === 'home') { closeDrawer(); goHome() } else if (action === 'search') { closeDrawer(); openSearchModal() } }) }) document.getElementById('article-back-mobile').addEventListener('click', () => goHome()) document.getElementById('copy-link-btn').addEventListener('click', copyCurrentLink) document.querySelectorAll('.suggestion').forEach(b => { b.addEventListener('click', e => openSearchModal(e.target.dataset.q)) }) document.getElementById('search-modal').addEventListener('click', e => { if (e.target.id === 'search-modal') closeSearchModal() }) document.getElementById('search-input').addEventListener('input', e => { searchActiveIdx = 0 renderSearch(e.target.value) if (e.target.value) history.replaceState(null, '', '#/b/' + encodeURIComponent(e.target.value)) }) document.addEventListener('keydown', e => { if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); openSearchModal() } if (e.key === 'Escape') { closeSearchModal(); closeDrawer() } if (!document.getElementById('search-modal').classList.contains('hidden')) { if (e.key === 'ArrowDown') { e.preventDefault(); searchActiveIdx = Math.min(searchMatches.length - 1, searchActiveIdx + 1); renderSearch(document.getElementById('search-input').value) } if (e.key === 'ArrowUp') { e.preventDefault(); searchActiveIdx = Math.max(0, searchActiveIdx - 1); renderSearch(document.getElementById('search-input').value) } if (e.key === 'Enter' && searchMatches[searchActiveIdx]) { closeSearchModal(); openArticle(searchMatches[searchActiveIdx].s) } } }) window.addEventListener('hashchange', handleHash) // Detecta pré-render: se body tem data-prerender-slug, abre o artigo direto // (evita flash da home antes de navegar para o artigo) const prerenderSlug = document.body.dataset.prerenderSlug if (prerenderSlug) { // Remove o conteúdo pré-renderizado (o JS vai re-renderizar do markdown) const prerendered = document.getElementById('prerender-content') if (prerendered) prerendered.remove() openArticle(prerenderSlug) } else { handleHash() } </script> <!-- ═══════════════════════════════════════════════════════════════════════ Review Mode UI — ativado com ?review=1 na URL (uso interno evob) ═══════════════════════════════════════════════════════════════════════ --> <style> #rv-bar{display:none;position:fixed;top:0;left:0;right:0;z-index:9000;background:#fbbf24;color:#1c1917; padding:7px 14px;align-items:center;gap:9px;font-size:12.5px;font-family:system-ui,sans-serif; box-shadow:0 2px 8px rgba(0,0,0,.15);} #rv-bar button{border:none;cursor:pointer;font-size:12px;font-weight:600;padding:4px 10px;border-radius:6px;} #rv-ed{position:fixed;top:38px;right:0;bottom:0;width:46%;background:#1e1e2e; z-index:8000;display:none;flex-direction:column;box-shadow:-4px 0 20px rgba(0,0,0,.3);} #rv-chat{position:fixed;bottom:18px;right:18px;width:355px;background:#fff;border-radius:16px; z-index:9100;display:none;flex-direction:column;box-shadow:0 8px 32px rgba(0,0,0,.2); max-height:530px;font-family:system-ui,sans-serif;} #rv-ov{position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9200; display:none;align-items:center;justify-content:center;} #rv-ov-box{background:#fff;border-radius:16px;padding:24px;width:400px;max-width:90vw;font-family:system-ui,sans-serif;} .rv-lbl{font-size:12px;font-weight:600;color:#374151;margin-bottom:4px;} .rv-hint{font-size:11px;color:#9ca3af;margin-top:3px;} .rv-input{width:100%;padding:8px;border:1px solid #d1d5db;border-radius:8px;font-size:13px;box-sizing:border-box;} </style> <!-- Top bar --> <div id="rv-bar"> <span style="font-weight:700;white-space:nowrap;">✎ Revisão</span> <span id="rv-info" style="flex:1;opacity:.7;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">Navegue para um artigo</span> <button id="rv-eb" style="background:#fff;color:#1c1917;">Abrir Editor</button> <button id="rv-cb" style="background:#1c1917;color:#fff;">💬 IA</button> <button id="rv-sb" style="background:transparent;border:1px solid rgba(0,0,0,.2);">⚙</button> <button id="rv-xb" style="background:transparent;border:1px solid rgba(0,0,0,.2);">✕ Sair</button> </div> <!-- Editor panel --> <div id="rv-ed"> <div style="padding:9px 14px;background:#2a2a3e;display:flex;align-items:center;gap:8px;flex-shrink:0;"> <span id="rv-ef" style="color:#a5b4fc;font-size:11px;flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"></span> <button id="rv-cpb" style="background:transparent;border:1px solid #444;color:#888;font-size:11px;padding:3px 8px;border-radius:5px;cursor:pointer;">Copiar</button> <button id="rv-svb" style="background:#7c3aed;color:#fff;border:none;font-size:12px;font-weight:600;padding:4px 12px;border-radius:6px;cursor:pointer;">💾 Salvar</button> <button id="rv-cled" style="background:transparent;border:none;color:#888;font-size:17px;cursor:pointer;line-height:1;">✕</button> </div> <textarea id="rv-ta" style="flex:1;background:#1e1e2e;color:#e2e8f0;border:none;padding:16px; font-family:'JetBrains Mono',Consolas,monospace;font-size:13px;line-height:1.6; resize:none;outline:none;" spellcheck="false" placeholder="Abra um artigo para editar..."></textarea> <div id="rv-st" style="padding:5px 14px;background:#2a2a3e;color:#777;font-size:11px;flex-shrink:0;"></div> </div> <!-- AI Chat panel --> <div id="rv-chat"> <div style="padding:11px 15px;background:#7c3aed;border-radius:16px 16px 0 0;color:#fff;display:flex;align-items:center;gap:8px;"> <span style="font-weight:700;flex:1;">✨ Gemini — Editor de Ajuda</span> <button id="rv-chcl" style="background:transparent;border:none;color:#fff;font-size:17px;cursor:pointer;line-height:1;">✕</button> </div> <div id="rv-msgs" style="flex:1;overflow-y:auto;padding:12px;min-height:140px;max-height:280px;display:flex;flex-direction:column;gap:8px;"></div> <div id="rv-imgpv" style="padding:0 12px 8px;display:none;"> <div style="position:relative;display:inline-block;"> <img id="rv-imgt" alt="" style="max-height:48px;border-radius:8px;display:block;" /> <button id="rv-imgr" style="position:absolute;top:-5px;right:-5px;background:#ef4444;color:#fff;border:none;border-radius:50%;width:16px;height:16px;font-size:9px;cursor:pointer;line-height:16px;text-align:center;">✕</button> </div> </div> <div style="padding:9px 11px;border-top:1px solid #f0f0f0;display:flex;gap:7px;align-items:flex-end;"> <label title="Anexar imagem" style="cursor:pointer;padding:6px 8px;color:#7c3aed;border:1px solid #e5e7eb;border-radius:8px;font-size:14px;flex-shrink:0;line-height:1;"> 📎<input type="file" id="rv-imgi" accept="image/*" style="display:none;"> </label> <textarea id="rv-chin" placeholder="Pergunte ou peça sugestões..." rows="1" style="flex:1;border:1px solid #e5e7eb;border-radius:8px;padding:7px 9px;font-size:13px;resize:none;outline:none;line-height:1.4;max-height:90px;min-height:34px;"></textarea> <button id="rv-sndb" style="background:#7c3aed;color:#fff;border:none;padding:7px 13px;border-radius:8px;cursor:pointer;font-weight:600;font-size:13px;flex-shrink:0;">Enviar</button> </div> <div style="padding:0 12px 10px;text-align:center;"> <button id="rv-apb" style="display:none;background:#f3f0ff;color:#7c3aed;border:1px solid #c4b5fd;padding:5px 13px;border-radius:6px;cursor:pointer;font-size:12px;font-weight:600;">↙ Aplicar ao Editor</button> </div> </div> <!-- Settings overlay --> <div id="rv-ov"> <div id="rv-ov-box"> <h3 style="margin:0 0 16px;font-size:15px;font-weight:700;">⚙ Configurações — Modo Revisão</h3> <div style="margin-bottom:12px;"> <div class="rv-lbl">Bunny Storage API Key (evob-docs)</div> <input type="password" id="rv-sk1" class="rv-input" placeholder="Chave do storage zone evob-docs"> <div class="rv-hint">Para salvar artigos diretamente no CDN</div> </div> <div style="margin-bottom:20px;"> <div class="rv-lbl">Gemini API Key</div> <input type="password" id="rv-sk2" class="rv-input" placeholder="AIzaSy..."> <div class="rv-hint">Chaves salvas no localStorage deste browser</div> </div> <div style="display:flex;gap:8px;justify-content:flex-end;"> <button id="rv-skcl" style="padding:8px 15px;border:1px solid #d1d5db;border-radius:8px;background:#fff;cursor:pointer;font-size:13px;">Cancelar</button> <button id="rv-sksv" style="padding:8px 15px;background:#7c3aed;color:#fff;border:none;border-radius:8px;cursor:pointer;font-weight:600;font-size:13px;">Salvar</button> </div> </div> </div> <script> /* ── Review Mode logic ──────────────────────────────────────────────────── */ ;(function(){ if(!new URLSearchParams(location.search).has('review'))return function gk(){return{bunny:localStorage.getItem('rv_bunny')||'',gemini:localStorage.getItem('rv_gemini')||'',zone:'evob-docs'}} function slugNow(){const h=location.hash;return h.startsWith('#/a/')?h.slice(4):null} function findA(s){if(!window.CATALOG||!s)return null;for(const c of window.CATALOG)for(const b of c.subs)for(const i of b.items)if(i.s===s)return i;return null} const $ = id => document.getElementById(id) /* show the bar */ $('rv-bar').style.display='flex' document.body.style.paddingTop='38px' /* state */ let edO=false, chO=false, art=null, lastAI='', pImg=null const hist=[] function sts(m){$('rv-st').textContent=m} function setEd(){ if(edO){$('rv-ed').style.display='flex';document.body.style.marginRight='46%';$('rv-eb').textContent='Fechar Editor'} else{$('rv-ed').style.display='none';document.body.style.marginRight='';$('rv-eb').textContent='Abrir Editor'} } async function loadA(a){ art=a $('rv-info').textContent=a?a.t+' · '+a.f:'Navegue para um artigo' if(!a||!edO)return $('rv-ef').textContent=a.f;$('rv-ta').value='';sts('Carregando...') try{ const r=await fetch(a.f+'?nc='+Date.now()) if(!r.ok)throw new Error('HTTP '+r.status) $('rv-ta').value=await r.text();sts('Carregado — sem alterações') }catch(e){sts('Erro: '+e.message)} } async function save(){ if(!art)return const{bunny,zone}=gk();if(!bunny){openOv();return} const body=$('rv-ta').value;sts('Salvando...') try{ const r=await fetch('https://br.storage.bunnycdn.com/'+zone+'/'+art.f,{ method:'PUT',headers:{'AccessKey':bunny,'Content-Type':'text/markdown; charset=utf-8'},body }) if(!r.ok)throw new Error('HTTP '+r.status) sts('✅ Salvo — '+new Date().toLocaleTimeString('pt-BR')) }catch(e){ sts('⚠ CORS — comando curl copiado para clipboard') navigator.clipboard.writeText('curl -s -X PUT "https://br.storage.bunnycdn.com/'+zone+'/'+art.f+'" -H "AccessKey: '+bunny+'" -H "Content-Type: text/markdown; charset=utf-8" --data-binary @"'+art.f+'"').catch(function(){}) } } function addMsg(role,txt){ const d=document.createElement('div') d.style.cssText=role==='user' ?'background:#f3f0ff;padding:8px 11px;border-radius:12px 12px 4px 12px;font-size:12.5px;align-self:flex-end;max-width:87%;white-space:pre-wrap;word-break:break-word;' :'background:#f9fafb;padding:8px 11px;border-radius:12px 12px 12px 4px;font-size:12.5px;align-self:flex-start;max-width:92%;line-height:1.55;white-space:pre-wrap;word-break:break-word;' d.textContent=txt const m=$('rv-msgs');m.appendChild(d);m.scrollTop=m.scrollHeight;return d } async function send(){ const inp=$('rv-chin'),txt=inp.value.trim() if(!txt&&!pImg)return const{gemini}=gk();if(!gemini){openOv();return} inp.value='';const parts=[] if(pImg)parts.push({inlineData:{mimeType:pImg.mime,data:pImg.base64}}) if(txt)parts.push({text:txt}) addMsg('user',txt||'(imagem)');clearImg() const ta=$('rv-ta') const ctx=art?'Arquivo: '+art.f+'\nArtigo: "'+art.t+'"\nConteúdo:\n---\n'+(ta?ta.value:'(editor fechado)')+'\n---':'Nenhum artigo.' const tk=addMsg('ai','...');$('rv-apb').style.display='none' try{ const res=await fetch('https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key='+gemini,{ method:'POST',headers:{'Content-Type':'application/json'}, body:JSON.stringify({ systemInstruction:{parts:[{text:'Você é editor da Central de Ajuda evob (plataforma educacional de beleza). Revise artigos em pt-BR. Seja direto. Para sugestões use blocos ```markdown ... ```.'}]}, contents:[ {role:'user',parts:[{text:'Contexto:\n'+ctx}]}, {role:'model',parts:[{text:'Entendido. Pronto.'}]}, ...hist, {role:'user',parts} ], generationConfig:{temperature:0.65,maxOutputTokens:1500} }) }) const data=await res.json() if(!res.ok)throw new Error(data.error?data.error.message:'HTTP '+res.status) lastAI=data.candidates&&data.candidates[0]&&data.candidates[0].content&&data.candidates[0].content.parts&&data.candidates[0].content.parts[0]?data.candidates[0].content.parts[0].text:'(sem resposta)' tk.textContent=lastAI hist.push({role:'user',parts},{role:'model',parts:[{text:lastAI}]}) if(lastAI.indexOf('```')!==-1)$('rv-apb').style.display='inline-block' }catch(e){tk.textContent='❌ '+e.message} } function applyEd(){ const m=lastAI.match(/```(?:markdown)?\n?([\s\S]+?)```/) if(!m)return const ta=$('rv-ta');if(!ta){edO=true;setEd();return} const s=ta.selectionStart,e=ta.selectionEnd if(s!==e)ta.setRangeText(m[1].trim());else ta.value=m[1].trim() sts('Texto da IA aplicado — revise antes de salvar');$('rv-apb').style.display='none' } function clearImg(){pImg=null;$('rv-imgpv').style.display='none';$('rv-imgt').src=''} function openOv(){const k=gk();$('rv-sk1').value=k.bunny;$('rv-sk2').value=k.gemini;$('rv-ov').style.display='flex'} /* wire events */ $('rv-eb').onclick=function(){edO=!edO;setEd();if(edO&&art)loadA(art)} $('rv-svb').onclick=save $('rv-cpb').onclick=function(){navigator.clipboard.writeText($('rv-ta').value).then(function(){sts('Copiado!')})} $('rv-cled').onclick=function(){edO=false;setEd()} $('rv-cb').onclick=function(){chO=!chO;$('rv-chat').style.display=chO?'flex':'none'} $('rv-chcl').onclick=function(){chO=false;$('rv-chat').style.display='none'} $('rv-sndb').onclick=send $('rv-chin').addEventListener('keydown',function(e){if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();send()}}) $('rv-apb').onclick=applyEd $('rv-imgi').addEventListener('change',function(e){ var f=e.target.files[0];if(!f)return var r=new FileReader() r.onload=function(ev){ var parts=ev.target.result.split(','),b64=parts[1] pImg={base64:b64,mime:f.type} $('rv-imgt').src=ev.target.result $('rv-imgpv').style.display='block' } r.readAsDataURL(f);e.target.value='' }) $('rv-imgr').onclick=clearImg $('rv-sb').onclick=openOv $('rv-sksv').onclick=function(){ localStorage.setItem('rv_bunny',$('rv-sk1').value.trim()) localStorage.setItem('rv_gemini',$('rv-sk2').value.trim()) $('rv-ov').style.display='none' } $('rv-skcl').onclick=function(){$('rv-ov').style.display='none'} $('rv-ov').addEventListener('click',function(e){if(e.target===$('rv-ov'))$('rv-ov').style.display='none'}) $('rv-xb').onclick=function(){var u=new URL(location.href);u.searchParams.delete('review');location.href=u} /* track hash */ function onH(){var a=findA(slugNow());if(a)loadA(a);else{art=null;$('rv-info').textContent='Navegue para um artigo'}} window.addEventListener('hashchange',onH) setTimeout(onH,300) if(!gk().gemini||!gk().bunny)setTimeout(openOv,700) })(); </script> </body> </html>