/** * CONSELHO ESCOLAR DEMOCRÁTICO - DIRETRIZES MEC & LEI 14.644/2023 * Script Interativo: Efeito Cascata Scrollytelling, Linha do Tempo e Simulador */ document.addEventListener('DOMContentLoaded', () => { // 1. Inicializar Ícones Lucide if (typeof lucide !== 'undefined') { lucide.createIcons(); } // Elementos do DOM const progressBar = document.getElementById('reading-progress-bar'); const scrollTrack = document.getElementById('cascade-scroll-track'); const stickyStage = document.getElementById('cascade-sticky-stage'); const cards = document.querySelectorAll('.cascade-card'); const navSteps = document.querySelectorAll('.cascade-nav-step'); const prevBtn = document.getElementById('cascade-prev-btn'); const nextBtn = document.getElementById('cascade-next-btn'); const miniProgress = document.getElementById('cascade-mini-progress'); const counterElement = document.getElementById('cascade-counter'); // Elementos da Gravura Dinâmica da Cascata const dynamicImg = document.getElementById('dynamic-dimension-img'); const badgeCategory = document.getElementById('dimension-badge-category'); const captionDesc = document.getElementById('dimension-caption'); // Metadados Visuais das 5 Dimensões MEC const dimensionMetadata = [ { category: "Poder Decisório Soberano", caption: "O Conselho Escolar vota e aprova com força normativa o Projeto Político-Pedagógico (PPP), Regimento e destinação de recursos.", image: "https://images.unsplash.com/photo-1544717305-2782549b5136?auto=format&fit=crop&w=1000&q=80", colorClass: "bg-blue-600" }, { category: "Aconselhamento e Mediação", caption: "Câmara de diálogo para resolução de conflitos, pareceres sobre inovações pedagógicas e fomento à cultura da paz.", image: "https://images.unsplash.com/photo-1573496359142-b8d87734a5a2?auto=format&fit=crop&w=1000&q=80", colorClass: "bg-sky-600" }, { category: "Controle Social e Probidade", caption: "Auditoria cidadã dos recursos do PDDE, conferência de notas fiscais, prestação de contas da UEx e vistoria predial.", image: "https://images.unsplash.com/photo-1454165804606-c3d57bc86b40?auto=format&fit=crop&w=1000&q=80", colorClass: "bg-amber-600" }, { category: "Engajamento Sociocomunitário", caption: "Busca ativa escolar, engajamento familiar, articulação com a rede de proteção social (CRAS/UBS) e protagonismo estudantil.", image: "https://images.unsplash.com/photo-1529156069898-49953e39b3ac?auto=format&fit=crop&w=1000&q=80", colorClass: "bg-emerald-600" }, { category: "Aprendizagem e Qualidade Social", caption: "Acompanhamento do IDEB, SAEB, taxas de aprovação, inclusão e validação de planos de reforço pedagógico.", image: "https://images.unsplash.com/photo-1509062522246-3755977927d7?auto=format&fit=crop&w=1000&q=80", colorClass: "bg-purple-600" } ]; let currentCascadeIndex = 0; // ========================================================================= // MOTOR DE ROLAGEM CASCATA (SCROLLYTELLING ENGINE) // ========================================================================= function updateCascadeState(targetIndex) { if (targetIndex < 0) targetIndex = 0; if (targetIndex > cards.length - 1) targetIndex = cards.length - 1; currentCascadeIndex = targetIndex; // Atualiza os cards cards.forEach((card, idx) => { card.classList.remove('is-active', 'is-passed', 'is-upcoming'); if (idx === targetIndex) { card.classList.add('is-active'); } else if (idx < targetIndex) { card.classList.add('is-passed'); } else { card.classList.add('is-upcoming'); } }); // Atualiza os botões da linha do tempo da cascata navSteps.forEach((step, idx) => { if (idx === targetIndex) { step.classList.add('active-step', 'bg-blue-600', 'text-white'); step.classList.remove('text-slate-400'); } else { step.classList.remove('active-step', 'bg-blue-600', 'text-white'); step.classList.add('text-slate-400'); } }); // Atualiza o painel visual esquerdo const meta = dimensionMetadata[targetIndex]; if (meta && dynamicImg) { if (dynamicImg.src !== meta.image) { dynamicImg.style.opacity = '0.4'; setTimeout(() => { dynamicImg.src = meta.image; dynamicImg.style.opacity = '1'; }, 200); } if (badgeCategory) { badgeCategory.textContent = meta.category; } if (captionDesc) { captionDesc.textContent = meta.caption; } } // Atualiza o contador e mini progresso if (counterElement) { counterElement.innerHTML = `Dimensão ${targetIndex + 1} de ${cards.length}`; } if (miniProgress) { const pct = ((targetIndex + 1) / cards.length) * 100; miniProgress.style.width = `${pct}%`; } // Atualiza os botões Prev/Next if (prevBtn) prevBtn.disabled = targetIndex === 0; if (nextBtn) nextBtn.disabled = targetIndex === cards.length - 1; } // Função para rolar a janela diretamente até um step específico da cascata function scrollToCascadeStep(index) { if (!scrollTrack) return; const trackRect = scrollTrack.getBoundingClientRect(); const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const trackTop = trackRect.top + scrollTop; const trackHeight = scrollTrack.offsetHeight - window.innerHeight; // Calcula o ponto exato dentro da pista de rolagem const targetScrollY = trackTop + (trackHeight * (index / (cards.length - 1))); window.scrollTo({ top: targetScrollY, behavior: 'smooth' }); } // Exportar para escopo global para links e cards externos window.scrollToCascadeIndex = function(index) { scrollToCascadeStep(index); }; // Clique nos botões de Step da Linha do Tempo da Cascata navSteps.forEach((step) => { step.addEventListener('click', (e) => { e.preventDefault(); const stepIdx = parseInt(step.getAttribute('data-step'), 10); scrollToCascadeStep(stepIdx); }); }); // Botões Próximo / Anterior if (prevBtn) { prevBtn.addEventListener('click', () => { if (currentCascadeIndex > 0) { scrollToCascadeStep(currentCascadeIndex - 1); } }); } if (nextBtn) { nextBtn.addEventListener('click', () => { if (currentCascadeIndex < cards.length - 1) { scrollToCascadeStep(currentCascadeIndex + 1); } }); } // Teclado: Navegação pelas teclas de seta quando na zona da cascata window.addEventListener('keydown', (e) => { if (!scrollTrack) return; const trackRect = scrollTrack.getBoundingClientRect(); // Se o sticky stage estiver visível na viewport if (trackRect.top <= 50 && trackRect.bottom >= window.innerHeight - 50) { if (e.key === 'ArrowRight' || e.key === 'ArrowDown') { if (currentCascadeIndex < cards.length - 1) { e.preventDefault(); scrollToCascadeStep(currentCascadeIndex + 1); } } else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') { if (currentCascadeIndex > 0) { e.preventDefault(); scrollToCascadeStep(currentCascadeIndex - 1); } } } }); // Monitoramento do Scroll Geral function onScroll() { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; const docHeight = document.documentElement.scrollHeight - window.innerHeight; // 1. Barra de Leitura Global Superior if (progressBar && docHeight > 0) { const scrollPct = (scrollTop / docHeight) * 100; progressBar.style.width = `${scrollPct}%`; } // 2. Controle do Efeito Cascata baseado na Pista de Rolagem if (scrollTrack) { const trackRect = scrollTrack.getBoundingClientRect(); const trackTop = trackRect.top; const trackHeight = scrollTrack.offsetHeight - window.innerHeight; if (trackTop <= 0 && Math.abs(trackTop) <= trackHeight) { // Estamos dentro da zona de cascata! const progress = Math.abs(trackTop) / trackHeight; // Mapeia para índice de 0 a 4 const calculatedIndex = Math.min( cards.length - 1, Math.floor(progress * cards.length) ); if (calculatedIndex !== currentCascadeIndex) { updateCascadeState(calculatedIndex); } } else if (trackTop > 0 && currentCascadeIndex !== 0) { updateCascadeState(0); } else if (Math.abs(trackTop) > trackHeight && currentCascadeIndex !== cards.length - 1) { updateCascadeState(cards.length - 1); } } // 3. Atualizar Linha do Tempo Lateral Flutuante (Desktop) updateFloatingTimeline(); } window.addEventListener('scroll', onScroll, { passive: true }); // Inicialização do primeiro card updateCascadeState(0); // ========================================================================= // LINHA DO TEMPO LATERAL FLUTUANTE // ========================================================================= const timelineButtons = document.querySelectorAll('.timeline-dot-btn'); const sectionsToTrack = [ '#hero', '#marco-legal', '#dimensoes-cascata', '#composicao', '#boas-praticas', '#simulador', '#faq' ]; timelineButtons.forEach(btn => { btn.addEventListener('click', () => { const targetSelector = btn.getAttribute('data-target'); const targetElement = document.querySelector(targetSelector); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth' }); } }); }); function updateFloatingTimeline() { const scrollPosition = window.pageYOffset + 250; sectionsToTrack.forEach(selector => { const el = document.querySelector(selector); const btn = document.querySelector(`.timeline-dot-btn[data-target="${selector}"]`); if (el && btn) { const top = el.offsetTop; const height = el.offsetHeight; if (scrollPosition >= top && scrollPosition < top + height) { btn.classList.add('active'); } else { btn.classList.remove('active'); } } }); } // ========================================================================= // SIMULADOR DE DECISÕES DO CONSELHO ESCOLAR (QUIZ INTERATIVO) // ========================================================================= const quizScenarios = [ { title: "Cenário 1: Recursos do PDDE para Recomposição da Aprendizagem", desc: "A escola recebeu um recurso suplementar do PDDE no valor de R$ 25.000,00. A gestão escolar propôs a compra de kits pedagógicos de robótica e matemática. Antes de efetivar a compra, a reunião oficial do conselho foi convocada para deliberar e votar se esses são de fato os itens prioritários para a escola.", correct: "deliberativa", feedback: "Excelente! Trata-se da **Função Deliberativa**. A destinação dos recursos financeiros e o plano de aplicação da Unidade Executora (UEx) exigem aprovação e voto soberano do Conselho Escolar em ata." }, { title: "Cenário 2: Mediação de Clima Escolar e Convivência", desc: "Houve um aumento nos desentendimentos no recreio entre turmas do 8º e 9º anos. A equipe pedagógica chamou o conselho para ouvir os representantes de pais e alunos, acolher sugestões e emitir um parecer orientativo antes de alterar o horário do intervalo.", correct: "consultiva", feedback: "Muito bem! Trata-se da **Função Consultiva**. O conselho atua emitindo pareceres e conselhos fundamentados, servindo de espaço de escuta e mediação para que a gestão tome a melhor decisão coletiva." }, { title: "Cenário 3: Prestação de Contas e Conferência de Notas Fiscais", desc: "Ao final do semestre, os conselheiros se reuniram para conferir o livro caixa, extratos bancários, os 3 orçamentos realizados para a reforma do telhado e assinar o parecer do relatório anual de prestação de contas do FNDE.", correct: "fiscalizadora", feedback: "Correto! É a **Função Fiscalizadora**. O conselho exerce o controle social e zela pela legalidade e transparência da coisa pública, conferindo comprovantes antes do envio aos órgãos de controle." }, { title: "Cenário 4: Busca Ativa Escolar de Alunos com Alta Infrequência", desc: "O conselho organizou uma campanha no bairro junto ao posto de saúde da família e lideranças locais para visitar famílias cujos filhos faltaram mais de 20% das aulas no bimestre, sensibilizando-os para o retorno escolar.", correct: "mobilizadora", feedback: "Exato! É a **Função Mobilizadora**. O conselho atua articulando a comunidade escolar e o território, combatendo a evasão e criando pontes entre as famílias e a escola pública." }, { title: "Cenário 5: Análise dos Resultados do SAEB e Diagnóstico Pedagógico", desc: "Após a divulgação dos resultados do SAEB e do IDEB, o Conselho Escolar reuniu-se para debater os níveis de alfabetização dos estudantes e aprovou uma reformulação no plano de reforço escolar do contraturno.", correct: "pedagogica", feedback: "Perfeito! É a **Função Pedagógica (ou Avaliativa)**. O conselho acompanha os indicadores educacionais e garante que todas as decisões da escola estejam orientadas para o sucesso e equidade na aprendizagem dos alunos." } ]; let currentQuizStep = 0; let quizScore = 0; const quizQuestionNum = document.getElementById('quiz-question-number'); const quizScoreBadge = document.getElementById('quiz-score-badge'); const quizTitle = document.getElementById('quiz-scenario-title'); const quizDesc = document.getElementById('quiz-scenario-desc'); const quizOptionsContainer = document.getElementById('quiz-options-container'); const quizFeedbackBox = document.getElementById('quiz-feedback-box'); const quizFeedbackStatus = document.getElementById('quiz-feedback-status'); const quizFeedbackText = document.getElementById('quiz-feedback-text'); const quizNextBtn = document.getElementById('quiz-next-btn'); function loadQuizScenario(index) { if (!quizTitle) return; const scenario = quizScenarios[index]; quizQuestionNum.textContent = `Cenário ${index + 1} de ${quizScenarios.length}`; quizTitle.textContent = scenario.title; quizDesc.textContent = scenario.desc; // Resetar feedback quizFeedbackBox.classList.add('hidden'); quizNextBtn.classList.add('hidden'); // Habilitar opções const optionBtns = quizOptionsContainer.querySelectorAll('.quiz-opt-btn'); optionBtns.forEach(btn => { btn.disabled = false; btn.classList.remove('correct-choice', 'wrong-choice', 'opacity-50'); }); } if (quizOptionsContainer) { quizOptionsContainer.addEventListener('click', (e) => { const btn = e.target.closest('.quiz-opt-btn'); if (!btn || btn.disabled) return; const chosenFunc = btn.getAttribute('data-function'); const scenario = quizScenarios[currentQuizStep]; const isCorrect = (chosenFunc === scenario.correct); // Desabilitar todas as opções const allBtns = quizOptionsContainer.querySelectorAll('.quiz-opt-btn'); allBtns.forEach(b => { b.disabled = true; if (b.getAttribute('data-function') === scenario.correct) { b.classList.add('correct-choice'); } else if (b === btn && !isCorrect) { b.classList.add('wrong-choice'); } else { b.classList.add('opacity-50'); } }); // Exibir Feedback Pedagógico quizFeedbackBox.classList.remove('hidden', 'bg-emerald-950/40', 'border-emerald-800', 'bg-rose-950/40', 'border-rose-800'); if (isCorrect) { quizScore++; quizScoreBadge.textContent = `Pontuação: ${quizScore} acerto(s)`; quizFeedbackBox.classList.add('bg-emerald-950/40', 'border-emerald-800'); quizFeedbackStatus.innerHTML = ` Resposta Correta!`; } else { quizFeedbackBox.classList.add('bg-rose-950/40', 'border-rose-800'); quizFeedbackStatus.innerHTML = ` Atenção à Diretriz!`; } quizFeedbackText.innerHTML = scenario.feedback; if (typeof lucide !== 'undefined') lucide.createIcons(); // Mostrar botão próximo if (currentQuizStep < quizScenarios.length - 1) { quizNextBtn.innerHTML = `Avançar para o Próximo Cenário`; } else { quizNextBtn.innerHTML = `Finalizar Simulador (${quizScore}/${quizScenarios.length})`; } quizNextBtn.classList.remove('hidden'); if (typeof lucide !== 'undefined') lucide.createIcons(); }); } if (quizNextBtn) { quizNextBtn.addEventListener('click', () => { if (currentQuizStep < quizScenarios.length - 1) { currentQuizStep++; loadQuizScenario(currentQuizStep); } else { // Finalização do Quiz quizQuestionNum.textContent = "Simulação Concluída!"; quizTitle.textContent = `Parabéns! Você concluiu os 5 cenários com ${quizScore} de 5 acertos!`; quizDesc.textContent = "Você compreendeu as nuances entre deliberar, consultar, fiscalizar, mobilizar e avaliar pedagogicamente conforme as diretrizes do MEC. Esse conhecimento é essencial para transformar o conselho da sua escola."; quizOptionsContainer.innerHTML = ` `; quizFeedbackBox.classList.add('hidden'); quizNextBtn.classList.add('hidden'); document.getElementById('restart-quiz-btn')?.addEventListener('click', () => { location.reload(); }); } }); } // ========================================================================= // ACCORDION FAQ // ========================================================================= const faqItems = document.querySelectorAll('.faq-item'); faqItems.forEach(item => { const trigger = item.querySelector('.faq-trigger'); const content = item.querySelector('.faq-content'); if (trigger && content) { trigger.addEventListener('click', () => { const isActive = item.classList.contains('active'); // Fecha todos os outros itens faqItems.forEach(otherItem => { otherItem.classList.remove('active'); const otherContent = otherItem.querySelector('.faq-content'); if (otherContent) otherContent.classList.add('hidden'); }); // Alterna o atual if (!isActive) { item.classList.add('active'); content.classList.remove('hidden'); } }); } }); // ========================================================================= // MENU MOBILE // ========================================================================= const mobileMenuBtn = document.getElementById('mobile-menu-btn'); const mobileMenu = document.getElementById('mobile-menu'); const mobileNavLinks = document.querySelectorAll('.mobile-nav-link'); if (mobileMenuBtn && mobileMenu) { mobileMenuBtn.addEventListener('click', () => { mobileMenu.classList.toggle('hidden'); }); mobileNavLinks.forEach(link => { link.addEventListener('click', () => { mobileMenu.classList.add('hidden'); }); }); } });