1(function(){� 2 var reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;� 3 // listado de clientes: los destacados quedan fijos, el resto se mezcla en cada carga� 4 [].slice.call(document.querySelectorAll('[data-shuffle-from]')).forEach(function(box){� 5 var pin=parseInt(box.getAttribute('data-shuffle-from'),10)||0;� 6 var kids=[].slice.call(box.children),rest=kids.slice(pin);� 7 for(var i=rest.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1));var t=rest[i];rest[i]=rest[j];rest[j]=t;}� 8 var frag=document.createDocumentFragment();� 9 rest.forEach(function(el){frag.appendChild(el);});� 10 box.appendChild(frag);� 11 });� 12 requestAnimationFrame(function(){document.body.classList.add('ready');});� 13 // reveals (self-completing, one-shot)� 14 var revEls=document.querySelectorAll('.reveal,.rv');� 15 if(reduce){revEls.forEach(function(e){e.classList.add('in');});}� 16 else{var io=new IntersectionObserver(function(es){es.forEach(function(x){if(x.isIntersecting){x.target.classList.add('in');io.unobserve(x.target);}});},{threshold:0.16,rootMargin:'0px 0px -8% 0px'});� 17 revEls.forEach(function(e){io.observe(e);});}� 18 // header state + FAB + dark-aware, computed on scroll (no permanent loop)� 19 var hdr=document.getElementById('hdr');� 20 var themed=[].slice.call(document.querySelectorAll('[data-theme]'));� 21 var fab=document.getElementById('fabtop');� 22 function darkAtLine(line){for(var i=0;i<themed.length;i++){var t=themed[i].getAttribute('data-theme');if(t==='dark'||t==='orange'){var r=themed[i].getBoundingClientRect();if(r.top<=line&&r.bottom>line)return true;}}return false;}� 23 function state(){� 24 if(hdr){hdr.classList.toggle('solid',scrollY>40);hdr.classList.toggle('invert',darkAtLine(44));}� 25 if(fab){fab.classList.toggle('show',scrollY>innerHeight*0.6);fab.classList.toggle('on-dark',darkAtLine(innerHeight-innerHeight*0.06));}� 26 }� 27 // parallax on-demand� 28 var pxEls=reduce?[]:[].slice.call(document.querySelectorAll('[data-parallax]'));� 29 var tg=pxEls.map(function(){return 0;}),cur=pxEls.map(function(){return 0;}),running=false;� 30 function targets(){var vh=innerHeight;pxEls.forEach(function(el,i){var r=el.getBoundingClientRect();var p=(r.top+r.height/2-vh/2)/vh;var amp=parseFloat(el.getAttribute('data-parallax'))*vh*0.5;tg[i]=Math.max(-amp,Math.min(amp,-p*amp));});}� 31 function applyAll(){for(var i=0;i<pxEls.length;i++){pxEls[i].style.transform='translate3d(0,'+cur[i].toFixed(2)+'px,0)';}}� 32 function tick(){var moving=false;for(var i=0;i<pxEls.length;i++){cur[i]+=(tg[i]-cur[i])*0.1;if(Math.abs(tg[i]-cur[i])>0.2)moving=true;else cur[i]=tg[i];}applyAll();if(moving)requestAnimationFrame(tick);else running=false;}� 33 function ensureRun(){if(!running&&pxEls.length){running=true;requestAnimationFrame(tick);}}� 34 // init positions once (no loop)� 35 targets();for(var i=0;i<pxEls.length;i++){cur[i]=tg[i];}applyAll();state();� 36 var ticking=false;� 37 function onScroll(){if(!ticking){ticking=true;requestAnimationFrame(function(){state();targets();ensureRun();ticking=false;});}}� 38 addEventListener('scroll',onScroll,{passive:true});� 39 addEventListener('resize',function(){targets();ensureRun();state();},{passive:true});� 40 if(fab)fab.addEventListener('click',function(){scrollTo({top:0,behavior:reduce?'auto':'smooth'});});� 41 // menu� 42 var burger=document.getElementById('burger'),menu=document.getElementById('menu'),mclose=document.getElementById('mclose');� 43 if(menu){var mis=menu.querySelectorAll('.mi .mroll');� 44 function open(){mis.forEach(function(el,i){el.style.transitionDelay=(0.06+i*0.055).toFixed(2)+'s';});menu.classList.add('open');document.documentElement.classList.add('lock');}� 45 function close(){menu.classList.remove('open');document.documentElement.classList.remove('lock');mis.forEach(function(el){el.style.transitionDelay='';});}� 46 burger.addEventListener('click',function(){menu.classList.contains('open')?close():open();});� 47 if(mclose)mclose.addEventListener('click',close);� 48 menu.querySelectorAll('a').forEach(function(a){a.addEventListener('click',close);});� 49 addEventListener('keydown',function(e){if(e.key==='Escape'&&menu.classList.contains('open'))close();});� 50 }� 51})();
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.