1( function () { 2 'use strict'; 3 4 const prefersReducedMotion = window.matchMedia( '(prefers-reduced-motion: reduce)' ).matches; 5 6 // âââ Intersection Observer helper ââââââââââââââââââââââââââââ 7 function observe( selector, options ) { 8 const el = document.querySelector( selector ); 9 if ( ! el ) return; 10 11 const observer = new IntersectionObserver( function ( entries ) { 12 entries.forEach( function ( entry ) { 13 if ( entry.isIntersecting ) { 14 entry.target.classList.add( 'is-visible' ); 15 observer.unobserve( entry.target ); 16 } 17 } ); 18 }, options ); 19 20 observer.observe( el ); 21 } 22 23 // âââ Footer sections reveal âââââââââââââââââââââââââââââââââââ 24 observe( '.footer-social', { threshold: 0.5 } ); 25 observe( '.footer-newsletter', { threshold: 0.3 } ); 26 observe( '.footer', { threshold: 0.15, rootMargin: '0px 0px -50px 0px' } ); 27 28 // âââ Back-to-top button âââââââââââââââââââââââââââââââââââââââ 29 const backToTop = document.querySelector( '.back-to-top' ); 30 if ( backToTop ) { 31 window.addEventListener( 'scroll', function () { 32 if ( window.scrollY > 400 ) { 33 backToTop.classList.add( 'is-visible' ); 34 } else { 35 backToTop.classList.remove( 'is-visible' ); 36 } 37 }, { passive: true } ); 38 39 backToTop.addEventListener( 'click', function () { 40 window.scrollTo( { top: 0, behavior: prefersReducedMotion ? 'instant' : 'smooth' } ); 41 } ); 42 } 43 44 // âââ Newsletter form ââââââââââââââââââââââââââââââââââââââââââ 45 const form = document.querySelector( '.footer-newsletter__form' ); 46 const feedback = document.querySelector( '.footer-newsletter__feedback' ); 47 48 if ( ! form ) return; 49 50 form.addEventListener( 'submit', async function ( e ) { 51 e.preventDefault(); 52 53 const input = form.querySelector( '[name="email"]' ); 54 const btn = form.querySelector( '[type="submit"]' ); 55 const email = input ? input.value.trim() : ''; 56 const re = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 57 58 // Limpar estado anterior 59 input && input.classList.remove( 'is-error' ); 60 if ( feedback ) { 61 feedback.hidden = true; 62 feedback.removeAttribute( 'data-state' ); 63 feedback.textContent = ''; 64 } 65 66 // Validar 67 if ( ! re.test( email ) ) { 68 input && input.classList.add( 'is-error' ); 69 if ( feedback ) { 70 feedback.hidden = false; 71 feedback.dataset.state = 'error'; 72 feedback.textContent = 'Insira um e-mail válido.'; 73 } 74 input && input.focus(); 75 return; 76 } 77 78 // Estado enviando 79 if ( btn ) { 80 btn.disabled = true; 81 btn.textContent = 'Enviandoâ¦'; 82 } 83 84 // Simular envio (sem integração real â fase posterior) 85 await new Promise( function ( resolve ) { setTimeout( resolve, 800 ); } ); 86 87 // Sucesso 88 form.hidden = true; 89 if ( feedback ) { 90 feedback.hidden = false; 91 feedback.dataset.state = 'success'; 92 feedback.textContent = 'â Pronto! Você receberá nossas novidades em breve.'; 93 } 94 } ); 95 96} )();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.