PageSourceSearch

https://www.juegomania.org/wp-content/cache/flying-press/50faaca16fb5.jm-frontend.js

js juegomania.org collected 2026-10-02 12:24:10 UTC 28,445 bytes, 110 lines download raw bytes

1document.addEventListener('DOMContentLoaded',()=>{initMobileNavigation();initMobileSearchModal();initBottomBarSmoothScroll();initGameSubNav();initSingleGameGallery();initInteractiveStarRater();initCheatRatingAndCopy();initViewSwitcher();initGuideQuickPreview();initLiveSearch();initContactForm();initPlatformChipsFilter();initAdSenseSafePush();initAdSenseFallbacks();initTurboVignettes()});function escapeHtml(str){if(!str)return'';return String(str).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;').replace(/'/g,'&#039;')}
2function initMobileNavigation(){const drawer=document.getElementById('jm-mobile-drawer');const overlay=document.getElementById('jm-mobile-drawer-overlay');const closeBtn=document.getElementById('jm-drawer-close-btn');const menuTriggers=document.querySelectorAll('#jm-bottom-menu-trigger, .jm-mobile-menu-btn, .menu-toggle');if(!drawer||!overlay)return;function openDrawer(){drawer.classList.add('is-open');overlay.classList.add('is-visible');document.body.classList.add('jm-drawer-locked');drawer.setAttribute('aria-hidden','false');overlay.setAttribute('aria-hidden','false')}
3function closeDrawer(){drawer.classList.remove('is-open');overlay.classList.remove('is-visible');document.body.classList.remove('jm-drawer-locked');drawer.setAttribute('aria-hidden','true');overlay.setAttribute('aria-hidden','true')}
4menuTriggers.forEach(btn=>{btn.addEventListener('click',(e)=>{e.preventDefault();openDrawer()})});if(closeBtn){closeBtn.addEventListener('click',closeDrawer)}
5overlay.addEventListener('click',closeDrawer);document.addEventListener('keydown',(e)=>{if(e.key==='Escape'&&drawer.classList.contains('is-open')){closeDrawer()}})}
6function initMobileSearchModal(){const modal=document.getElementById('jm-mobile-search-modal');const searchTrigger=document.getElementById('jm-bottom-search-trigger');const closeBtn=document.getElementById('jm-search-modal-close');const input=document.getElementById('jm-modal-search-field');const backdrop=modal?modal.querySelector('.jm-search-modal-backdrop'):null;if(!modal)return;function openSearch(){modal.classList.add('is-open');document.body.classList.add('jm-search-locked');modal.setAttribute('aria-hidden','false');setTimeout(()=>{if(input)input.focus();},100)}
7function closeSearch(){modal.classList.remove('is-open');document.body.classList.remove('jm-search-locked');modal.setAttribute('aria-hidden','true')}
8if(searchTrigger){searchTrigger.addEventListener('click',(e)=>{e.preventDefault();openSearch()})}
9if(closeBtn)closeBtn.addEventListener('click',closeSearch);if(backdrop)backdrop.addEventListener('click',closeSearch);document.addEventListener('keydown',(e)=>{if(e.key==='Escape'&&modal.classList.contains('is-open')){closeSearch()}})}
10function initBottomBarSmoothScroll(){const tabs=document.querySelectorAll('.jm-bottom-tab[data-target]');tabs.forEach(tab=>{tab.addEventListener('click',(e)=>{const targetId=tab.getAttribute('data-target');if(!targetId||targetId.startsWith('http')||targetId.startsWith('/'))return;const targetEl=document.querySelector(targetId);if(targetEl){e.preventDefault();const headerOffset=60;const elementPosition=targetEl.getBoundingClientRect().top;const offsetPosition=elementPosition+window.pageYOffset-headerOffset;window.scrollTo({top:offsetPosition,behavior:'smooth'});tabs.forEach(t=>t.classList.remove('active'));tab.classList.add('active')}})})}
11function initGameSubNav(){const subnav=document.getElementById('jm-game-subnav');if(!subnav)return;const navLinks=subnav.querySelectorAll('.jm-subnav-item');if(!navLinks.length)return;navLinks.forEach(link=>{link.addEventListener('click',(e)=>{const href=link.getAttribute('href');if(!href||!href.startsWith('#'))return;const target=document.querySelector(href);if(target){e.preventDefault();const headerOffset=70;const elPos=target.getBoundingClientRect().top+window.pageYOffset;window.scrollTo({top:elPos-headerOffset,behavior:'smooth'});navLinks.forEach(l=>l.classList.remove('active'));link.classList.add('active');link.scrollIntoView({behavior:'smooth',block:'nearest',inline:'center'})}})});if(window.location.hash){const hashTarget=document.querySelector(window.location.hash);if(hashTarget){setTimeout(()=>{const headerOffset=70;const elPos=hashTarget.getBoundingClientRect().top+window.pageYOffset;window.scrollTo({top:elPos-headerOffset,behavior:'smooth'});navLinks.forEach(l=>{if(l.getAttribute('href')===window.location.hash){l.classList.add('active');l.scrollIntoView({behavior:'smooth',block:'nearest',inline:'center'})}else{l.classList.remove('active')}})},300)}}
12const observedSections=[];navLinks.forEach(link=>{const href=link.getAttribute('href');if(href&&href.startsWith('#')){const sec=document.querySelector(href);if(sec)observedSections.push({el:sec,link:link})}});if('IntersectionObserver' in window&&observedSections.length>0){const observer=new IntersectionObserver((entries)=>
12{entries.forEach(entry=>{if(entry.isIntersecting){const match=observedSections.find(s=>s.el===entry.target);if(match){navLinks.forEach(l=>l.classList.remove('active'));match.link.classList.add('active')}}})},{rootMargin:'-70px 0px -60% 0px',threshold:0});observedSections.forEach(s=>observer.observe(s.el))}}
13function initSingleGameGallery(){const mainImg=document.getElementById('jm-main-cover');const zoomContainer=document.getElementById('jm-zoom-container');const thumbs=document.querySelectorAll('.jm-thumb-item');const fullscreenBtn=document.getElementById('jm-btn-fullscreen');const modal=document.getElementById('jm-lightbox-modal');const modalImg=document.getElementById('jm-lightbox-img');const modalCaption=document.getElementById('jm-lightbox-caption');const modalCounter=document.getElementById('jm-lightbox-counter');const closeBtn=document.getElementById('jm-lightbox-close');const prevBtn=document.getElementById('jm-lightbox-prev');const nextBtn=document.getElementById('jm-lightbox-next');const galleryItems=Array.from(document.querySelectorAll('.jm-gallery-item-data')).map(el=>({full:el.getAttribute('data-full'),title:el.getAttribute('data-title')||''}));if(!galleryItems.length&&thumbs.length){thumbs.forEach(t=>{galleryItems.push({full:t.getAttribute('data-full')||(t.querySelector('img')?t.querySelector('img').src:''),title:t.getAttribute('data-alt')||''})})}
14let currentIndex=0;thumbs.forEach(thumb=>{thumb.addEventListener('click',()=>{const fullSrc=thumb.getAttribute('data-full');const idx=parseInt(thumb.getAttribute('data-index')||'0',10);if(fullSrc&&mainImg){mainImg.src=fullSrc;mainImg.setAttribute('data-index',idx);currentIndex=idx;thumbs.forEach(t=>t.classList.remove('active'));thumb.classList.add('active');thumb.scrollIntoView({behavior:'smooth',inline:'center',block:'nearest'})}})});if(zoomContainer&&mainImg){zoomContainer.addEventListener('mousemove',(e)=>{const rect=zoomContainer.getBoundingClientRect();const x=((e.clientX-rect.left)/rect.width)*100;const y=((e.clientY-rect.top)/rect.height)*100;mainImg.style.transformOrigin=`${x}% ${y}%`;mainImg.style.transform='scale(1.4)'});zoomContainer.addEventListener('mouseleave',()=>{mainImg.style.transformOrigin='center center';mainImg.style.transform='scale(1)'})}
15function openLightbox(index=0){if(!modal||!galleryItems.length)return;currentIndex=(index>=0&&index<galleryItems.length)?index:0;updateLightbox();modal.classList.add('is-open');modal.setAttribute('aria-hidden','false');document.body.style.overflow='hidden'}
16function closeLightbox(){if(!modal)return;modal.classList.remove('is-open');modal.setAttribute('aria-hidden','true');document.body.style.overflow=''}
17function updateLightbox(){const item=galleryItems[currentIndex];if(!item||!modalImg)return;modalImg.src=item.full;if(modalCaption)modalCaption.textContent=item.title;if(modalCounter)modalCounter.textContent=`${currentIndex + 1} / ${galleryItems.length}`}
18function showPrev(){currentIndex=(currentIndex>0)?currentIndex-1:galleryItems.length-1;updateLightbox()}
19function showNext(){currentIndex=(currentIndex<galleryItems.length-1)?currentIndex+1:0;updateLightbox()}
20if(fullscreenBtn){fullscreenBtn.addEventListener('click',(e)=>{e.preventDefault();const currentMainIdx=parseInt(mainImg?mainImg.getAttribute('data-index')||'0':'0',10);openLightbox(currentMainIdx)})}
21if(mainImg){mainImg.style.cursor='zoom-in';mainImg.addEventListener('click',()=>{const currentMainIdx=parseInt(mainImg.getAttribute('data-index')||'0',10);openLightbox(currentMainIdx)})}
22if(closeBtn)closeBtn.addEventListener('click',closeLightbox);if(prevBtn)prevBtn.addEventListener('click',showPrev);if(nextBtn)nextBtn.addEventListener('click',showNext);if(modal){modal.addEventListener('click',(e)=>{if(e.target===modal)closeLightbox();})}
23document.addEventListener('keydown',(e)=>{if(!modal||!modal.classList.contains('is-open'))return;if(e.key==='Escape')closeLightbox();if(e.key==='ArrowLeft')showPrev();if(e.key==='ArrowRight')showNext();})}
24function initInteractiveStarRater(){const raters=document.querySelectorAll('.jm-interactive-rater');if(!raters.length)return;function updatePageRatings(ratingMedia,ratingVotos){if(ratingMedia!==undefined&&ratingMedia!==null){document.querySelectorAll('.jm-rating-val').forEach(el=>{el.textContent=ratingMedia})}
25if(ratingVotos!==undefined&&ratingVotos!==null){const formatted=typeof ratingVotos==='number'?ratingVotos.toLocaleStr
25ing('es-ES'):ratingVotos;document.querySelectorAll('.jm-rating-cnt').forEach(el=>{el.textContent=formatted})}}
26raters.forEach(rater=>{const postId=rater.getAttribute('data-post-id');const stars=Array.from(rater.querySelectorAll('.jm-star-btn'));const scoreHoverLabel=rater.querySelector('.jm-rater-score-hover');const stateLabel=rater.querySelector('.jm-rater-state');if(!postId||!stars.length)return;const storageKey='jm_rated_game_'+postId;let storedData=null;const rawStored=localStorage.getItem(storageKey);if(rawStored){try{storedData=JSON.parse(rawStored)}catch(e){const num=parseFloat(rawStored);if(!isNaN(num)&&num>0){storedData={rating:num}}}}
27let currentActiveRating=(storedData&&storedData.rating>0)?parseFloat(storedData.rating):0;function highlightStars(val){stars.forEach(s=>{const starVal=parseFloat(s.getAttribute('data-val')||'0');if(starVal<=val){s.classList.add('active')}else{s.classList.remove('active')}});if(scoreHoverLabel){scoreHoverLabel.textContent=val>0?val.toFixed(1):'--'}}
28if(currentActiveRating>0){highlightStars(currentActiveRating);if(stateLabel)stateLabel.textContent='Tu voto: '+currentActiveRating.toFixed(1);if(storedData&&storedData.media&&storedData.votos){const firstVoteEl=document.querySelector('.jm-rating-cnt');const htmlVotes=firstVoteEl?parseInt(firstVoteEl.textContent.replace(/\D/g,''),10):0;if(htmlVotes<=storedData.votos){updatePageRatings(storedData.media,storedData.votos)}}}
29stars.forEach(star=>{const val=parseFloat(star.getAttribute('data-val')||'0');star.addEventListener('mouseenter',()=>{highlightStars(val)});star.addEventListener('click',async(e)=>{e.preventDefault();const oldRating=currentActiveRating>0?currentActiveRating:null;currentActiveRating=val;highlightStars(val);if(stateLabel)stateLabel.textContent='Guardando voto...';try{const headers={'Content-Type':'application/json'};if(window.wpApiSettings&&window.wpApiSettings.nonce){headers['X-WP-Nonce']=window.wpApiSettings.nonce}
30const response=await fetch('/wp-json/jm/v1/rate-game',{method:'POST',headers:headers,body:JSON.stringify({post_id:parseInt(postId,10),rating:val,old_rating:oldRating})});const data=await response.json();if(data&&data.success){localStorage.setItem(storageKey,JSON.stringify({rating:val,media:data.rating_media,votos:data.rating_votos,ts:Date.now()}));if(stateLabel)stateLabel.innerHTML='✅ ¡Gracias por votar!';updatePageRatings(data.rating_media,data.rating_votos)}else{if(stateLabel)stateLabel.textContent='Tu voto: '+val.toFixed(1);}}catch(err){console.error('Error al registrar valoración:',err);if(stateLabel)stateLabel.textContent='Tu voto: '+val.toFixed(1);}})});const starsContainer=rater.querySelector('.jm-rater-stars');if(starsContainer){starsContainer.addEventListener('mouseleave',()=>{highlightStars(currentActiveRating)})}})}
31function initCheatRatingAndCopy(){const copyBtns=document.querySelectorAll('.jm-btn-copy-cheat');copyBtns.forEach(btn=>{btn.addEventListener('click',()=>{const card=btn.closest('.jm-cheat-card');const codeEl=card?card.querySelector('.jm-cheat-body'):null;if(codeEl){const text=codeEl.innerText.trim();navigator.clipboard.writeText(text).then(()=>{const originalText=btn.innerHTML;btn.innerHTML='✓ ¡Copiado!';btn.classList.add('copied');setTimeout(()=>{btn.innerHTML=originalText;btn.classList.remove('copied')},2000)}).catch(()=>{const ta=document.createElement('textarea');ta.value=text;document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);btn.innerHTML='✓ ¡Copiado!';setTimeout(()=>{btn.innerHTML='📋 Copiar'},2000)})}})});const rateBtns=document.querySelectorAll('.jm-btn-rate-cheat');rateBtns.forEach(btn=>{const cheatId=btn.getAttribute('data-cheat-id');if(!cheatId)return;const storageKey=`jm_voted_cheat_${cheatId}`;const hasVoted=localStorage.getItem(storageKey);if(hasVoted){btn.classList.add('voted');btn.title='Ya has valorado este truco como útil';const icon=btn.querySelector('.jm-cheat-thumb-icon');if(icon)icon.textContent='✅'}
32btn.addEventListener('click',async(e)=>{e.preventDefault();if(localStorage.getItem(storageKey)){btn.classList.add('voted');return}
33try{const res=await fetch('/wp-json/jm/v1/rate-cheat',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({cheat_id:parseInt(cheatId,10)})});const data=await res.json();if(data&&data.success){localStorage.setItem(storageKey,'1');btn.classList.add('voted');btn.classList.add('jm-pulse-anim');const countEl=btn.querySelector('.jm-cheat-votes-count');if(countEl&&typeof data.votos_total!=='undefined'){countEl.textContent=data.votos_total}
34const icon=btn.querySelector('.jm-cheat-thumb-icon');if(icon)icon.textContent='✅';
34btn.title='¡Gracias por tu valoración!'}}catch(e){console.warn('Error al registrar utilidad del truco:',e)}})})}
35function initViewSwitcher(){const switchers=document.querySelectorAll('.jm-view-switcher');if(!switchers.length)return;const savedView=localStorage.getItem('jm_view_pref');function applyView(viewType){const tableContainer=document.getElementById('jm-view-table-container');const gridContainer=document.getElementById('jm-view-grid-container');const viewBtns=document.querySelectorAll('.jm-view-btn');viewBtns.forEach(btn=>{if(btn.getAttribute('data-view')===viewType){btn.classList.add('active')}else{btn.classList.remove('active')}});if(tableContainer&&gridContainer){if(viewType==='grid'){tableContainer.style.display='none';gridContainer.style.display='block'}else{tableContainer.style.display='block';gridContainer.style.display='none'}}}
36if(savedView==='grid'||savedView==='table'){applyView(savedView)}
37switchers.forEach(switcher=>{const btns=switcher.querySelectorAll('.jm-view-btn');btns.forEach(btn=>{btn.addEventListener('click',(e)=>{e.preventDefault();const view=btn.getAttribute('data-view');if(view){applyView(view);localStorage.setItem('jm_view_pref',view)}})})})}
38function initGuideQuickPreview(){const previewBtns=document.querySelectorAll('.jm-btn-preview-modal');if(!previewBtns.length)return;let modal=document.getElementById('jm-guide-modal');if(!modal){modal=document.createElement('div');modal.id='jm-guide-modal';modal.className='jm-modal-overlay';modal.setAttribute('aria-hidden','true');modal.setAttribute('role','dialog');modal.setAttribute('aria-modal','true');modal.innerHTML=`
39            <div class="jm-modal-dialog">
40                <header class="jm-modal-header">
41                    <div class="jm-modal-header-text">
42                        <span class="jm-modal-tag">📘 Vista Rápida de Guía</span>
43                        <h3 id="jm-modal-guide-title" class="jm-modal-title">Cargando guía...</h3>
44                    </div>
45                    <button type="button" class="jm-modal-close" aria-label="Cerrar ventana modal">&times;</button>
46                </header>
47                <div class="jm-modal-body" id="jm-modal-guide-body">
48                    <div class="jm-modal-loading">
49                        <div class="jm-spinner"></div>
50                        <p>Cargando contenido de la guía...</p>
51                    </div>
52                </div>
53                <footer class="jm-modal-footer" id="jm-modal-guide-footer">
54                    <button type="button" class="jm-modal-btn-close">Cerrar</button>
55                    <a href="#" target="_blank" rel="noopener" class="jm-modal-btn-syt" id="jm-modal-syt-link" style="display:none;">
56                        <span>📖 Abrir Guía Completa en Soluciones y Trucos</span> ↗
57                    </a>
58                </footer>
59            </div>
60        `;document.body.appendChild(modal)}
61const modalTitle=modal.querySelector('#jm-modal-guide-title');const modalBody=modal.querySelector('#jm-modal-guide-body');const modalSytLink=modal.querySelector('#jm-modal-syt-link');const closeBtns=modal.querySelectorAll('.jm-modal-close, .jm-modal-btn-close');function closeModal(){modal.classList.remove('active','is-open');modal.setAttribute('aria-hidden','true');document.body.style.overflow=''}
62function openModal(){modal.classList.add('active','is-open');modal.setAttribute('aria-hidden','false');document.body.style.overflow='hidden'}
63closeBtns.forEach(btn=>btn.addEventListener('click',closeModal));modal.addEventListener('click',(e)=>{if(e.target===modal)closeModal();});document.addEventListener('keydown',(e)=>{if(e.key==='Escape'&&(modal.classList.contains('active')||modal.classList.contains('is-open'))){closeModal()}});const guideCache={};previewBtns.forEach(btn=>{btn.addEventListener('click',async(e)=>{const guiaId=btn.getAttribute('data-guia-id');if(!guiaId)return;e.preventDefault();openModal();if(modalTitle)modalTitle.textContent='Cargando guía...';if(modalBody){modalBody.innerHTML=`
64                    <div class="jm-modal-loading">
65                        <div class="jm-spinner"></div>
66                        <p>Cargando contenido de la guía...</p>
67                    </div>
68                `}
69if(modalSytLink)modalSytLink.style.display='none';if(guideCache[guiaId]){renderGuideData(guideCache[guiaId]);return}
70try{const response=await fetch(`/wp-json/jm/v1/guia-preview?id=${encodeURIComponent(guiaId)}`);const data=await response.json();if(data&&data.success){guideCache[guiaId]=data;renderGuideData(data)}else{if(modalBody){modalBody.innerHTML=`<div class="jm-guide-empty-notice"><p>⚠️ No se pudo cargar el contenido de esta guía.</p></div>`}}}catch(err){console.error('Error al cargar guía:',err);
70if(modalBody){modalBody.innerHTML=`<div class="jm-guide-empty-notice"><p>⚠️ Error de conexión al cargar la guía.</p></div>`}}})});function renderGuideData(data){if(modalTitle){modalTitle.textContent=data.titulo||(data.game_title?`Guía de ${data.game_title}`:'Guía Paso a Paso')}
71if(modalBody){let html='';if(data.autor){html+=`<div style="font-size:12px; color:var(--jm-text-muted); margin-bottom:16px;">✍️ Por <strong>${escapeHtml(data.autor)}</strong></div>`}
72html+=data.content_html||'';modalBody.innerHTML=html}
73if(modalSytLink){if(data.tipo_fuente==='syt'&&data.syt_url){modalSytLink.href=data.syt_url;modalSytLink.style.display='inline-flex'}else{modalSytLink.style.display='none'}}}}
74function initLiveSearch(){const searchInputs=document.querySelectorAll('.jm-header-search-input, .jm-home-search-input, .jm-drawer-search-input, #jm-modal-search-field');if(!searchInputs.length)return;searchInputs.forEach(input=>{const form=input.closest('form')||input.parentElement;if(!form)return;const computedPos=window.getComputedStyle(form).position;if(computedPos==='static'){form.style.position='relative'}
75let dropdown=form.querySelector('.jm-live-search-dropdown');if(!dropdown){dropdown=document.createElement('div');dropdown.className='jm-live-search-dropdown';dropdown.setAttribute('role','listbox');dropdown.setAttribute('aria-label','Sugerencias de búsqueda');form.appendChild(dropdown)}
76let debounceTimer=null;let selectedIndex=-1;let currentResults=[];function hideDropdown(){dropdown.classList.remove('is-active');dropdown.innerHTML='';selectedIndex=-1;currentResults=[]}
77function highlightMatch(text,query){if(!query)return escapeHtml(text);const escapedQuery=query.replace(/[.*+?^${}()|[\]\\]/g,'\\$&');const regex=new RegExp(`(${escapedQuery})`,'gi');return escapeHtml(text).replace(regex,'<mark>$1</mark>')}
78async function performSearch(query){const trimmed=query.trim();if(trimmed.length<2){hideDropdown();return}
79try{const response=await fetch(`/wp-json/jm/v1/search?q=${encodeURIComponent(trimmed)}`);const results=await response.json();if(!Array.isArray(results)||!results.length){dropdown.innerHTML=`
80                        <div class="jm-live-no-results">
81                            <span>🔍 Sin resultados para "<strong>${escapeHtml(trimmed)}</strong>"</span>
82                        </div>
83                    `;dropdown.classList.add('is-active');currentResults=[];selectedIndex=-1;return}
84currentResults=results;selectedIndex=-1;let html='<div class="jm-live-results-list">';results.forEach((item,idx)=>{const thumbHtml=item.cover?`<img src="${escapeHtml(item.cover)}" alt="${escapeHtml(item.title)}" loading="lazy" />`:`<span class="jm-live-no-thumb">🎮</span>`;const ratingHtml=item.rating?`<span class="jm-live-rating">★ ${escapeHtml(item.rating)}</span>`:'';const yearHtml=item.ano?`<span class="jm-live-year">${escapeHtml(item.ano.toString())}</span>`:'';const sysHtml=item.system_name?`<span class="jm-live-sys">${escapeHtml(item.system_name)}</span>`:'';html+=`
85                        <a href="${escapeHtml(item.url)}" class="jm-live-result-item" data-index="${idx}">
86                            <div class="jm-live-thumb">${thumbHtml}</div>
87                            <div class="jm-live-info">
88                                <span class="jm-live-title">${highlightMatch(item.title, trimmed)}</span>
89                                <div class="jm-live-meta">
90                                    ${sysHtml}
91                                    ${yearHtml}
92                                    ${ratingHtml}
93                                </div>
94                            </div>
95                        </a>
96                    `});const searchUrl=`/?s=${encodeURIComponent(trimmed)}`;html+=`
97                    </div>
98                    <a href="${escapeHtml(searchUrl)}" class="jm-live-result-item" style="justify-content:center; background:rgba(0,0,0,0.25); font-size:12px; font-weight:700; color:var(--jm-gold); border-top:1px solid #516986; text-align:center;">
99                        Ver todos los resultados para "${escapeHtml(trimmed)}" ➔
100                    </a>
101                `;dropdown.innerHTML=html;dropdown.classList.add('is-active')}catch(err){console.warn('Error en Live Search:',err);hideDropdown()}}
102input.addEventListener('input',()=>{clearTimeout(debounceTimer);debounceTimer=setTimeout(()=>{performSearch(input.value)},200)});input.addEventListener('focus',()=>{if(input.value.trim().length>=2&&!dropdown.classList.contains('is-active')){performSearch(input.value)}});input.addEventListener('keydown',(e)=>{if(!dropdown.classList.contains('is-active')||!currentResults.length)return;const items=dropdown.querySelectorAll('.jm-live-result-item[data-index]');if(e.key==='ArrowDown'){e.preventDefault();selectedIndex=(selectedIndex+1)<items.length?selectedIndex+1:0;updateSelection(items)}else if(e.key==='ArrowUp'){e.preventDefault();selectedIndex=(selectedIndex-1)>=0?selectedIndex-1:items.length-1;updateSelection(items)}else if(e.key==='Enter'&&selectedIndex>=0&&items[selectedIndex]){e.preventDefault();items[selectedIndex].click()}else if(e.key==='Escape'){hideDropdown()}});
102function updateSelection(items){items.forEach((it,idx)=>{if(idx===selectedIndex){it.classList.add('is-selected');it.scrollIntoView({block:'nearest'})}else{it.classList.remove('is-selected')}})}
103document.addEventListener('click',(e)=>{if(!form.contains(e.target)){hideDropdown()}})})}
104function initContactForm(){const form=document.getElementById('jm-contact-form');if(!form)return;const statusBox=document.getElementById('jm-contact-status');const submitBtn=form.querySelector('button[type="submit"]');form.addEventListener('submit',async(e)=>{e.preventDefault();if(submitBtn){submitBtn.disabled=!0;submitBtn.textContent='⏳ Enviando mensaje...'}
105if(statusBox){statusBox.style.display='none';statusBox.className='';statusBox.innerHTML=''}
106const formData=new FormData(form);const payload={};formData.forEach((value,key)=>{payload[key]=value});try{const response=await fetch('/wp-json/jm/v1/contact',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)});const result=await response.json();if(statusBox){statusBox.style.display='block';if(result&&result.success){statusBox.style.cssText='display:block; padding:14px 18px; border-radius:8px; background:rgba(34,197,94,0.15); border:1px solid #22c55e; color:#86efac; font-size:14px; margin-bottom:16px; font-weight:600;';statusBox.innerHTML=`✅ ${escapeHtml(result.message || '¡Tu mensaje ha sido enviado correctamente!')}`;form.reset()}else{statusBox.style.cssText='display:block; padding:14px 18px; border-radius:8px; background:rgba(239,68,68,0.15); border:1px solid #ef4444; color:#fca5a5; font-size:14px; margin-bottom:16px; font-weight:600;';statusBox.innerHTML=`⚠️ ${escapeHtml(result.message || 'Hubo un error al enviar el mensaje. Por favor revisa los campos.')}`}}}catch(err){console.error('Error al enviar formulario de contacto:',err);if(statusBox){statusBox.style.cssText='display:block; padding:14px 18px; border-radius:8px; background:rgba(239,68,68,0.15); border:1px solid #ef4444; color:#fca5a5; font-size:14px; margin-bottom:16px; font-weight:600;';statusBox.innerHTML='⚠️ Error de conexión con el servidor. Inténtalo de nuevo en unos minutos.'}}finally{if(submitBtn){submitBtn.disabled=!1;submitBtn.textContent='🚀 Enviar Mensaje'}}})}
107function initPlatformChipsFilter(){const chips=document.querySelectorAll('.jm-family-chip');const groups=document.querySelectorAll('.jm-family-group');if(!chips.length||!groups.length)return;chips.forEach(chip=>{chip.addEventListener('click',()=>{const familyTarget=chip.getAttribute('data-family');chips.forEach(c=>c.classList.remove('active'));chip.classList.add('active');groups.forEach(group=>{const groupFamily=group.getAttribute('data-family-name');if(familyTarget==='all'||groupFamily===familyTarget){group.style.display='block'}else{group.style.display='none'}})})})}
108function initAdSenseSafePush(){const insElements=document.querySelectorAll('ins.adsbygoogle');if(!insElements.length)return;insElements.forEach(ins=>{if(!ins.getAttribute('data-adsbygoogle-status')&&ins.clientWidth>0&&ins.clientHeight>0){try{(window.adsbygoogle=window.adsbygoogle||[]).push({})}catch(e){}}})}
109function initAdSenseFallbacks(){const reserveBoxes=document.querySelectorAll('.jm-ad-reserve-box');if(!reserveBoxes.length)return;reserveBoxes.forEach(box=>{const ins=box.querySelector('ins.adsbygoogle');const fallback=box.querySelector('.jm-ad-house-fallback');if(!ins||!fallback)return;const observer=new MutationObserver(mutations=>{mutations.forEach(mutation=>{if(mutation.type==='attributes'&&mutation.attributeName==='data-ad-status'){if(ins.getAttribute('data-ad-status')==='unfilled'){ins.style.display='none';fallback.style.display='block';fallback.setAttribute('aria-hidden','false')}}})});observer.observe(ins,{attributes:!0,attributeFilter:['data-ad-status']});setTimeout(()=>{const hasRendered=ins.getAttribute('data-adsbygoogle-status')==='done'&&ins.clientHeight>0;const isUnfilled=ins.getAttribute('data-ad-status')==='unfilled';if(isUnfilled||(!hasRendered&&ins.clientHeight===0)){ins.style.display='none';fallback.style.display='block';fallback.setAttribute('aria-hidden','false')}},3500)})}
110function initTurboVignettes(){const internalLinks=document.querySelectorAll('a[href^="/"], a[href*="juegomania.org"], a[href*="onlinemania.es"], a[href*="juegoviejo.com"]');internalLinks.forEach(link=>{const href=link.getAttribute('href')||'';const isFile=/\.(zip|rar|7z|iso|exe|apk)(\?.*)?$/i.test(href);if(!isFile&&link.getAttribute('target')==='_blank'){link.setAttribute('target','_self')}})}

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.