// Configurações globais const CONFIG = { testimonials: { autoPlay: false, interval: 10000, totalItems: 8 }, transformations: { autoPlay: false, interval: 10000, totalItems: 6 }, pixKey:'ajudeumpatinha@gmail.com' }; // Estado da aplicação let currentTestimonial = 0; let currentTransformation = 0; let testimonialInterval = null; let transformationInterval = null; // Inicialização quando o DOM estiver carregado document.addEventListener('DOMContentLoaded', function() { initializeProgressiveImageLoading(); initializeCarousel(); initializeTransformationCarousel(); initializeAnimations(); initializePIXCopy(); console.log('Site Fundação Quatro Patas carregado com sucesso!'); }); // ===== CARREGAMENTO PROGRESSIVO DE IMAGENS ===== function initializeProgressiveImageLoading() { // Lista de imagens em ordem de prioridade (de cima para baixo) const imagePriority = [ // Prioridade 1: Logo e banners principais (carregam imediatamente) 'images/logosemfundo2.png', 'images/banner1novo.png', 'images/banner2novo.png', 'images/logo.png', // Prioridade 2: Imagens do carrossel de transformações (carregam logo após) 'images/guerreiro1.webp', 'images/guerreiro2.webp', 'images/theodoro1.webp', 'images/theodoro2.webp', 'images/antes1.png', 'images/depois1.png', 'images/antes 2.png', 'images/depois 2.png', 'images/antes 3.png', 'images/depois 3.png', 'images/antes 4.png', 'images/depois 4.png', // Prioridade 3: Imagens dos depoimentos (carregam em seguida) 'images/daniela.webp', 'images/1.png', 'images/2.png', 'images/3.png', 'images/4.png', 'images/8.png', 'images/9.png', 'images/10.png', // Prioridade 4: Outras imagens (carregam por último) 'images/pixxx.png' ]; // Função para carregar uma imagem function loadImage(src) { return new Promise((resolve, reject) => { const img = new Image(); img.onload = () => resolve(src); img.onerror = () => reject(src); img.src = src; }); } // Função para carregar imagens em lotes com delay async function loadImagesInBatches() { const batchSize = 3; // Carrega 3 imagens por vez const delayBetweenBatches = 100; // 100ms entre lotes for (let i = 0; i < imagePriority.length; i += batchSize) { const batch = imagePriority.slice(i, i + batchSize); // Carrega o lote atual const promises = batch.map(src => loadImage(src).catch(err => { console.warn(`Falha ao carregar imagem: ${src}`, err); return null; })); await Promise.all(promises); // Aguarda um pouco antes do próximo lote (exceto para o primeiro lote) if (i + batchSize < imagePriority.length) { await new Promise(resolve => setTimeout(resolve, delayBetweenBatches)); } } console.log('✅ Todas as imagens foram carregadas progressivamente!'); } // Carrega as imagens críticas imediatamente const criticalImages = [ 'images/logosemfundo2.png', 'images/banner1novo.png', 'images/banner2novo.png', 'images/logo.png' ]; // Carrega imagens críticas primeiro Promise.all(criticalImages.map(src => loadImage(src).catch(err => { console.warn(`Falha ao carregar imagem crítica: ${src}`, err); return null; }))).then(() => { console.log('✅ Imagens críticas carregadas!'); // Inicia o carregamento progressivo das demais imagens loadImagesInBatches(); }); // Função para pré-carregar imagens dos carrosséis function preloadCarouselImages() { const carouselImages = [ // Imagens de transformação 'images/guerreiro1.webp', 'images/guerreiro2.webp', 'images/theodoro1.webp', 'images/theodoro2.webp', 'images/antes1.png', 'images/depois1.png', 'images/antes 2.png', 'images/depois 2.png', 'images/antes 3.png', 'images/depois 3.png', 'images/antes 4.png', 'images/depois 4.png', // Imagens de depoimentos 'images/daniela.webp', 'images/1.png', 'images/2.png', 'images/3.png', 'images/4.png', 'images/8.png', 'images/9.png', 'images/10.png' ]; carouselImages.forEach(src => { const img = new Image(); img.src = src; }); } // Pré-carrega imagens dos carrosséis em background setTimeout(preloadCarouselImages, 500); } // ===== CAROUSEL DE DEPOIMENTOS ===== function initializeCarousel() { createCarouselIndicators(); // Garante que o primeiro depoimento seja mostrado showTestimonial(0); if (CONFIG.testimonials.autoPlay) { startAutoPlay(); } // Event listeners para controles document.addEventListener('keydown', handleKeyboardNavigation); // Pausa autoplay quando mouse está sobre o carousel const carousel = document.getElementById('testimonialsCarousel'); if (carousel) { if (CONFIG.testimonials.autoPlay) { carousel.addEventListener('mouseenter', stopAutoPlay); carousel.addEventListener('mouseleave', startAutoPlay); } // Adiciona suporte para touch/swipe initializeTestimonialTouch(carousel); } } // ===== CAROUSEL DE TRANSFORMAÇÕES ===== function initializeTransformationCarousel() { createTransformationIndicators(); if (CONFIG.transformations.autoPlay) { startTransformationAutoPlay(); } // Pausa autoplay quando mouse está sobre o carousel const transformationCarousel = document.getElementById('transformationCarousel'); if (transformationCarousel) { transformationCarousel.addEventListener('mouseenter', stopTransformationAutoPlay); transformationCarousel.addEventListener('mouseleave', startTransformationAutoPlay); // Adiciona suporte para touch/swipe initializeTransformationTouch(transformationCarousel); } } function createTransformationIndicators() { const indicatorsContainer = document.getElementById('transformationIndicators'); if (!indicatorsContainer) return; indicatorsContainer.innerHTML = ''; for (let i = 0; i < CONFIG.transformations.totalItems; i++) { const indicator = document.createElement('div'); indicator.className = `transformation-indicator ${i === 0 ? 'active' : ''}`; indicator.addEventListener('click', () => goToTransformation(i)); indicator.setAttribute('aria-label', `Ir para história ${i + 1}`); indicator.setAttribute('role', 'button'); indicator.setAttribute('tabindex', '0'); // Suporte para navegação por teclado nos indicadores indicator.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); goToTransformation(i); } }); indicatorsContainer.appendChild(indicator); } } function showTransformation(index) { const transformations = document.querySelectorAll('.transformation-item'); const indicators = document.querySelectorAll('.transformation-indicator'); // Remove classe active de todos transformations.forEach(item => item.classList.remove('active')); indicators.forEach(indicator => indicator.classList.remove('active')); // Adiciona classe active ao atual if (transformations[index]) { transformations[index].classList.add('active'); } if (indicators[index]) { indicators[index].classList.add('active'); } currentTransformation = index; } function nextTransformation() { const next = (currentTransformation + 1) % CONFIG.transformations.totalItems; goToTransformation(next); } function prevTransformation() { const prev = currentTransformation === 0 ? CONFIG.transformations.totalItems - 1 : currentTransformation - 1; goToTransformation(prev); } function goToTransformation(index) { if (index >= 0 && index < CONFIG.transformations.totalItems) { showTransformation(index); } } function startTransformationAutoPlay() { if (transformationInterval) { clearInterval(transformationInterval); } transformationInterval = setInterval(() => { nextTransformation(); }, CONFIG.transformations.interval); } function stopTransformationAutoPlay() { if (transformationInterval) { clearInterval(transformationInterval); transformationInterval = null; } } // ===== TOUCH SUPPORT PARA DEPOIMENTOS ===== function initializeTestimonialTouch(carousel) { let startX = 0; let endX = 0; let isDragging = false; // Touch events carousel.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; isDragging = true; if (CONFIG.testimonials.autoPlay) { stopAutoPlay(); } }); carousel.addEventListener('touchend', (e) => { if (!isDragging) return; endX = e.changedTouches[0].clientX; const diffX = startX - endX; const threshold = 50; // Sensibilidade do swipe if (Math.abs(diffX) > threshold) { if (diffX > 0) { // Swipe para esquerda - próximo nextTestimonial(); } else { // Swipe para direita - anterior prevTestimonial(); } } isDragging = false; // Só reinicia o autoplay se estiver habilitado if (CONFIG.testimonials.autoPlay) { startAutoPlay(); } }); // Mouse events para desktop carousel.addEventListener('mousedown', (e) => { startX = e.clientX; isDragging = true; if (CONFIG.testimonials.autoPlay) { stopAutoPlay(); } }); carousel.addEventListener('mouseup', (e) => { if (!isDragging) return; endX = e.clientX; const diffX = startX - endX; const threshold = 50; if (Math.abs(diffX) > threshold) { if (diffX > 0) { nextTestimonial(); } else { prevTestimonial(); } } isDragging = false; // Só reinicia o autoplay se estiver habilitado if (CONFIG.testimonials.autoPlay) { startAutoPlay(); } }); // Previne seleção de texto durante o drag carousel.addEventListener('selectstart', (e) => { if (isDragging) { e.preventDefault(); } }); } // ===== TOUCH SUPPORT PARA TRANSFORMAÇÕES ===== function initializeTransformationTouch(carousel) { let startX = 0; let endX = 0; let isDragging = false; let currentTranslateX = 0; let prevTranslateX = 0; let animationID = 0; // Touch events carousel.addEventListener('touchstart', (e) => { startX = e.touches[0].clientX; isDragging = true; stopTransformationAutoPlay(); // Captura a posição atual const activeItem = carousel.querySelector('.transformation-item.active'); if (activeItem) { const transform = window.getComputedStyle(activeItem).transform; const matrix = new DOMMatrix(transform); currentTranslateX = matrix.m41; prevTranslateX = currentTranslateX; } }); carousel.addEventListener('touchmove', (e) => { if (!isDragging) return; e.preventDefault(); const currentX = e.touches[0].clientX; const diffX = currentX - startX; const moveX = prevTranslateX + diffX; // Aplica a animação durante o arraste const activeItem = carousel.querySelector('.transformation-item.active'); const nextItem = carousel.querySelector('.transformation-item.next') || carousel.querySelector('.transformation-item:nth-child(' + ((currentTransformation + 1) % CONFIG.transformations.totalItems + 1) + ')'); const prevItem = carousel.querySelector('.transformation-item.prev') || carousel.querySelector('.transformation-item:nth-child(' + (currentTransformation === 0 ? CONFIG.transformations.totalItems : currentTransformation) + ')'); if (activeItem) { activeItem.style.transform = `translateX(${moveX}px)`; activeItem.style.transition = 'none'; } // Mostra o próximo item durante o arraste if (diffX < 0 && nextItem) { // Arrastando para esquerda nextItem.style.display = 'block'; nextItem.style.transform = `translateX(${moveX + carousel.offsetWidth}px)`; nextItem.style.transition = 'none'; nextItem.style.opacity = '0.7'; } else if (diffX > 0 && prevItem) { // Arrastando para direita prevItem.style.display = 'block'; prevItem.style.transform = `translateX(${moveX - carousel.offsetWidth}px)`; prevItem.style.transition = 'none'; prevItem.style.opacity = '0.7'; } }); carousel.addEventListener('touchend', (e) => { if (!isDragging) return; endX = e.changedTouches[0].clientX; const diffX = startX - endX; const threshold = 50; // Sensibilidade do swipe // Reseta as animações const activeItem = carousel.querySelector('.transformation-item.active'); const nextItem = carousel.querySelector('.transformation-item.next') || carousel.querySelector('.transformation-item:nth-child(' + ((currentTransformation + 1) % CONFIG.transformations.totalItems + 1) + ')'); const prevItem = carousel.querySelector('.transformation-item.prev') || carousel.querySelector('.transformation-item:nth-child(' + (currentTransformation === 0 ? CONFIG.transformations.totalItems : currentTransformation) + ')'); if (activeItem) { activeItem.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; activeItem.style.transform = ''; } if (nextItem) { nextItem.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; nextItem.style.transform = ''; nextItem.style.opacity = ''; } if (prevItem) { prevItem.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; prevItem.style.transform = ''; prevItem.style.opacity = ''; } if (Math.abs(diffX) > threshold) { if (diffX > 0) { // Swipe para esquerda - próximo nextTransformation(); } else { // Swipe para direita - anterior prevTransformation(); } } isDragging = false; startTransformationAutoPlay(); }); // Mouse events para desktop carousel.addEventListener('mousedown', (e) => { startX = e.clientX; isDragging = true; stopTransformationAutoPlay(); // Captura a posição atual const activeItem = carousel.querySelector('.transformation-item.active'); if (activeItem) { const transform = window.getComputedStyle(activeItem).transform; const matrix = new DOMMatrix(transform); currentTranslateX = matrix.m41; prevTranslateX = currentTranslateX; } }); carousel.addEventListener('mousemove', (e) => { if (!isDragging) return; e.preventDefault(); const currentX = e.clientX; const diffX = currentX - startX; const moveX = prevTranslateX + diffX; // Aplica a animação durante o arraste const activeItem = carousel.querySelector('.transformation-item.active'); const nextItem = carousel.querySelector('.transformation-item.next') || carousel.querySelector('.transformation-item:nth-child(' + ((currentTransformation + 1) % CONFIG.transformations.totalItems + 1) + ')'); const prevItem = carousel.querySelector('.transformation-item.prev') || carousel.querySelector('.transformation-item:nth-child(' + (currentTransformation === 0 ? CONFIG.transformations.totalItems : currentTransformation) + ')'); if (activeItem) { activeItem.style.transform = `translateX(${moveX}px)`; activeItem.style.transition = 'none'; } // Mostra o próximo item durante o arraste if (diffX < 0 && nextItem) { // Arrastando para esquerda nextItem.style.display = 'block'; nextItem.style.transform = `translateX(${moveX + carousel.offsetWidth}px)`; nextItem.style.transition = 'none'; nextItem.style.opacity = '0.7'; } else if (diffX > 0 && prevItem) { // Arrastando para direita prevItem.style.display = 'block'; prevItem.style.transform = `translateX(${moveX - carousel.offsetWidth}px)`; prevItem.style.transition = 'none'; prevItem.style.opacity = '0.7'; } }); carousel.addEventListener('mouseup', (e) => { if (!isDragging) return; endX = e.clientX; const diffX = startX - endX; const threshold = 50; // Reseta as animações const activeItem = carousel.querySelector('.transformation-item.active'); const nextItem = carousel.querySelector('.transformation-item.next') || carousel.querySelector('.transformation-item:nth-child(' + ((currentTransformation + 1) % CONFIG.transformations.totalItems + 1) + ')'); const prevItem = carousel.querySelector('.transformation-item.prev') || carousel.querySelector('.transformation-item:nth-child(' + (currentTransformation === 0 ? CONFIG.transformations.totalItems : currentTransformation) + ')'); if (activeItem) { activeItem.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; activeItem.style.transform = ''; } if (nextItem) { nextItem.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; nextItem.style.transform = ''; nextItem.style.opacity = ''; } if (prevItem) { prevItem.style.transition = 'all 0.6s cubic-bezier(0.4, 0, 0.2, 1)'; prevItem.style.transform = ''; prevItem.style.opacity = ''; } if (Math.abs(diffX) > threshold) { if (diffX > 0) { nextTransformation(); } else { prevTransformation(); } } isDragging = false; startTransformationAutoPlay(); }); // Previne seleção de texto durante o drag carousel.addEventListener('selectstart', (e) => { if (isDragging) { e.preventDefault(); } }); } function createCarouselIndicators() { const indicatorsContainer = document.getElementById('testimonialIndicators'); if (!indicatorsContainer) return; indicatorsContainer.innerHTML = ''; for (let i = 0; i < CONFIG.testimonials.totalItems; i++) { const indicator = document.createElement('div'); indicator.className = `testimonial-indicator ${i === 0 ? 'active' : ''}`; indicator.addEventListener('click', () => goToTestimonial(i)); indicator.setAttribute('aria-label', `Ir para depoimento ${i + 1}`); indicator.setAttribute('role', 'button'); indicator.setAttribute('tabindex', '0'); // Suporte para navegação por teclado nos indicadores indicator.addEventListener('keydown', (e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); goToTestimonial(i); } }); indicatorsContainer.appendChild(indicator); } } function showTestimonial(index) { const testimonials = document.querySelectorAll('.testimonial-item'); const indicators = document.querySelectorAll('.testimonial-indicator'); // Remove classe active de todos (mesmo princípio do transformation) testimonials.forEach(item => item.classList.remove('active')); indicators.forEach(indicator => indicator.classList.remove('active')); // Adiciona classe active ao atual if (testimonials[index]) { testimonials[index].classList.add('active'); } if (indicators[index]) { indicators[index].classList.add('active'); } currentTestimonial = index; } function nextTestimonial() { const next = (currentTestimonial + 1) % CONFIG.testimonials.totalItems; goToTestimonial(next); } function prevTestimonial() { const prev = currentTestimonial === 0 ? CONFIG.testimonials.totalItems - 1 : currentTestimonial - 1; goToTestimonial(prev); } function goToTestimonial(index) { if (index >= 0 && index < CONFIG.testimonials.totalItems) { showTestimonial(index); if (CONFIG.testimonials.autoPlay) { restartAutoPlay(); } } } function startAutoPlay() { if (CONFIG.testimonials.autoPlay) { stopAutoPlay(); // Limpa interval anterior testimonialInterval = setInterval(nextTestimonial, CONFIG.testimonials.interval); } } function stopAutoPlay() { if (testimonialInterval) { clearInterval(testimonialInterval); testimonialInterval = null; } } function restartAutoPlay() { stopAutoPlay(); startAutoPlay(); } function handleKeyboardNavigation(e) { const carousel = document.getElementById('testimonialsCarousel'); if (!carousel) return; // Verifica se o foco está no carousel ou seus controles const isCarouselFocused = carousel.contains(document.activeElement) || document.activeElement.classList.contains('testimonial-btn') || document.activeElement.classList.contains('testimonial-indicator'); if (isCarouselFocused) { switch(e.key) { case 'ArrowLeft': e.preventDefault(); prevTestimonial(); break; case 'ArrowRight': e.preventDefault(); nextTestimonial(); break; case 'Home': e.preventDefault(); goToTestimonial(0); break; case 'End': e.preventDefault(); goToTestimonial(CONFIG.testimonials.totalItems - 1); break; } } } // ===== FUNCIONALIDADE PIX ===== function initializePIXCopy() { const copyBtn = document.querySelector('.copy-btn'); if (copyBtn) { copyBtn.addEventListener('click', copyPixKey); } } async function copyPixKey() { const button = document.querySelector('.copy-btn'); const pixKey = CONFIG.pixKey; try { // Tenta usar a API moderna de clipboard if (navigator.clipboard && window.isSecureContext) { await navigator.clipboard.writeText(pixKey); showCopySuccess(button); // Dispara Purchase no Facebook pixel fbq('track', 'Purchase', { value: 10.00, currency: 'BRL', content_name: "Doacao PIX" }); } else { // Fallback para navegadores mais antigos const textArea = document.createElement('textarea'); textArea.value = pixKey; textArea.style.position = 'fixed'; textArea.style.left = '-999999px'; textArea.style.top = '-999999px'; document.body.appendChild(textArea); textArea.focus(); textArea.select(); const successful = document.execCommand('copy'); document.body.removeChild(textArea); if (successful) { showCopySuccess(button); } else { throw new Error('Falha ao copiar'); } } } catch (error) { console.error('Erro ao copiar chave PIX:', error); showCopyError(button); } } function showCopySuccess(button) { const originalText = '📋 Copiar Chave PIX'; const originalClass = 'copy-btn'; button.innerHTML = ' Copiado!'; button.classList.add('copy-success'); // Feedback tátil se disponível if (navigator.vibrate) { navigator.vibrate(100); } // Mostra alert informativo setTimeout(() => { alert('✅ Chave PIX copiada com sucesso!\nObrigada por ajudar nossos animais! ❤️'); }, 500); // Volta ao estado original após 3 segundos setTimeout(() => { button.innerHTML = originalText; button.className = originalClass; // Remove qualquer estilo inline para voltar ao CSS original button.style.background = ''; }, 3000); } function showCopyError(button) { const originalText = button.innerHTML; button.innerHTML = ' Erro ao copiar'; button.style.background = '#f44336'; setTimeout(() => { button.innerHTML = originalText; button.style.background = ''; }, 2000); // Mostra a chave PIX para cópia manual alert(`Não foi possível copiar automaticamente. Chave PIX: ${CONFIG.pixKey}`); } // ===== SCROLL SUAVE ===== // ===== ANIMAÇÕES E EFEITOS VISUAIS ===== function initializeAnimations() { // Intersection Observer para animações on scroll if ('IntersectionObserver' in window) { const observerOptions = { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }; const observer = new IntersectionObserver(handleIntersection, observerOptions); // Observa elementos que devem ser animados const animatedElements = document.querySelectorAll( '.stat-item, .testimonial-item, .value-item, .footer-section' ); animatedElements.forEach(el => { el.style.opacity = '0'; el.style.transform = 'translateY(30px)'; observer.observe(el); }); } // Efeito parallax sutil no banner (se suportado) initializeParallax(); } function handleIntersection(entries) { entries.forEach(entry => { if (entry.isIntersecting) { const element = entry.target; // Anima o elemento element.style.transition = 'opacity 0.6s ease, transform 0.6s ease'; element.style.opacity = '1'; element.style.transform = 'translateY(0)'; // Para de observar o elemento após animação setTimeout(() => { entry.target.style.transition = ''; }, 600); } }); } function initializeParallax() { // Desabilitado para evitar problemas de rolagem return; const banner = document.querySelector('.banner-image'); if (!banner) return; // Verifica se o usuário não prefere movimento reduzido const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (prefersReducedMotion) return; // Aplica efeito parallax sutil window.addEventListener('scroll', () => { const scrolled = window.pageYOffset; const parallax = scrolled * 0.3; banner.style.transform = `translateY(${parallax}px)`; }); } // ===== UTILITÁRIOS ===== // Debounce function para otimizar eventos de scroll/resize function debounce(func, wait) { let timeout; return function executedFunction(...args) { const later = () => { clearTimeout(timeout); func(...args); }; clearTimeout(timeout); timeout = setTimeout(later, wait); }; } // Função para detectar dispositivos móveis function isMobile() { return window.innerWidth <= 768; } // Função para logging de eventos (útil para analytics) function trackEvent(eventName, properties = {}) { console.log(`Event: ${eventName}`, properties); // Aqui você pode integrar com Google Analytics, Facebook Pixel, TikTok Pixel, etc. // Exemplo: gtag('event', eventName, properties); } // ===== EVENT LISTENERS ADICIONAIS ===== // Otimização para redimensionamento de tela window.addEventListener('resize', debounce(() => { // Reajusta elementos se necessário if (CONFIG.testimonials.autoPlay) { if (isMobile()) { stopAutoPlay(); } else { startAutoPlay(); } } }, 250)); // Detecta quando a aba fica inativa/ativa document.addEventListener('visibilitychange', () => { if (CONFIG.testimonials.autoPlay) { if (document.hidden) { stopAutoPlay(); } else { startAutoPlay(); } } }); // ===== ACESSIBILIDADE ===== // Melhora a navegação por teclado document.addEventListener('keydown', (e) => { // Esc fecha modais ou para autoplay if (e.key === 'Escape' && CONFIG.testimonials.autoPlay) { stopAutoPlay(); } // Tab trap para elementos focáveis handleTabTrap(e); }); function handleTabTrap(e) { if (e.key !== 'Tab') return; const focusableElements = document.querySelectorAll( 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])' ); const firstElement = focusableElements[0]; const lastElement = focusableElements[focusableElements.length - 1]; if (e.shiftKey) { if (document.activeElement === firstElement) { lastElement.focus(); e.preventDefault(); } } else { if (document.activeElement === lastElement) { firstElement.focus(); e.preventDefault(); } } } // ===== PERFORMANCE ===== // Função para otimizar carregamento de imagens (sem lazy loading) function optimizeImageLoading() { // Adiciona classe 'loaded' quando a imagem termina de carregar const images = document.querySelectorAll('img'); images.forEach(img => { if (img.complete) { img.classList.add('loaded'); } else { img.addEventListener('load', function() { this.classList.add('loaded'); }); } }); } // Otimiza carregamento de imagens optimizeImageLoading(); // ===== FUNÇÕES EXPOSTAS GLOBALMENTE ===== // Exporta funções que podem ser chamadas pelo HTML window.nextTestimonial = nextTestimonial; window.prevTestimonial = prevTestimonial; window.nextTransformation = nextTransformation; window.prevTransformation = prevTransformation; window.copyPixKey = copyPixKey; // Função simples para scroll para seção de doação window.scrollToDonation = function() { const donationSection = document.getElementById('como-doar-pix'); if (donationSection) { // Scroll simples e direto - centraliza a seção na tela donationSection.scrollIntoView({ behavior: 'smooth', block: 'center' }); } }; // ===== ERROR HANDLING ===== // Captura erros JavaScript window.addEventListener('error', (e) => { console.error('Erro JavaScript:', e.error); // Em produção, você enviaria isso para um serviço de logging }); // Captura erros de Promise rejeitadas window.addEventListener('unhandledrejection', (e) => { console.error('Promise rejeitada:', e.reason); e.preventDefault(); }); // ===== INICIALIZAÇÃO FINAL ===== // Marca que o script foi carregado window.RefugioTiaReLoaded = true; // Log de inicialização console.log('🐕 Refúgio da Tia Rê - Sistema carregado com sucesso! 🐱'); console.log('Versão: 1.0.0'); console.log('Desenvolvido com ❤️ para salvar vidas'); // Service Worker registration (se disponível) if ('serviceWorker' in navigator) { window.addEventListener('load', () => { // Registra service worker para cache offline (implementar se necessário) // navigator.serviceWorker.register('/sw.js'); }); }