'use strict'; (function mountPremiumProjectIllustrations() { const targets = Object.freeze({ 'games-empty': 'library', 'backups-empty': 'protection', 'transfers-empty': 'transfer', 'media-empty': 'media', }); const illustrations = Object.freeze({ 'library': `
`, 'protection': ``, 'transfer': ``, 'media': ``, 'trophies': ``, }); const reducedMotion = typeof window.matchMedia === 'function' ? window.matchMedia('(prefers-reduced-motion: reduce)') : { matches: false, addListener() {}, removeListener() {} }; const mounted = new Set(); const visibilityObserver = 'IntersectionObserver' in window ? new IntersectionObserver(entries => { for (const entry of entries) { entry.target.classList.toggle('is-active', entry.isIntersecting); syncMotion(entry.target); } }, { threshold: .16 }) : null; function motionPaused() { return reducedMotion.matches || document.visibilityState !== 'visible'; } function syncMotion(element) { if (!element) return; element.classList.toggle('is-paused', motionPaused()); } function syncAllMotion() { for (const element of mounted) { if (!element.isConnected) { visibilityObserver?.unobserve(element); mounted.delete(element); continue; } syncMotion(element); } } function bind(illustration) { if (!illustration || mounted.has(illustration)) return; syncAllMotion(); mounted.add(illustration); visibilityObserver?.observe(illustration); if (!visibilityObserver) illustration.classList.add('is-active'); syncMotion(illustration); let pointerFrame = 0; let pointerX = 0; let pointerY = 0; illustration.addEventListener('pointermove', event => { if (motionPaused() || event.pointerType === 'touch') return; pointerX = event.clientX; pointerY = event.clientY; if (pointerFrame) return; pointerFrame = window.requestAnimationFrame(() => { pointerFrame = 0; const rect = illustration.getBoundingClientRect(); illustration.style.setProperty('--illustration-x', `${((pointerX - rect.left) / rect.width - .5) * 7}deg`); illustration.style.setProperty('--illustration-y', `${((pointerY - rect.top) / rect.height - .5) * -5}deg`); }); }, { passive: true }); illustration.addEventListener('pointerleave', () => { if (pointerFrame) window.cancelAnimationFrame(pointerFrame); pointerFrame = 0; illustration.style.removeProperty('--illustration-x'); illustration.style.removeProperty('--illustration-y'); }); } function bindHomeTopology() { const home = document.getElementById('chimera-home-command-center'); if (!home) return; home.classList.add('premium-topology-motion'); bind(home); } function dockImportLauncher() { const launcher = document.getElementById('chimera-import-open'); const sidebarDonate = document.getElementById('sidebar-donate'); if (!launcher || !sidebarDonate) return false; launcher.classList.add('chimera-import-launcher-docked'); sidebarDonate.after(launcher); return true; } function ensureTrophyIllustration() { const target = document.querySelector('.trophy-library-empty'); if (!target) return; let illustration = target.querySelector('.premium-project-illustration'); if (!illustration) { target.insertAdjacentHTML('afterbegin', illustrations.trophies); illustration = target.querySelector('.premium-project-illustration'); } bind(illustration); } for (const [id, variant] of Object.entries(targets)) { const target = document.getElementById(id); if (!target) continue; const ensure = () => { let illustration = target.querySelector('.premium-project-illustration'); if (!illustration) { target.insertAdjacentHTML('afterbegin', illustrations[variant]); illustration = target.querySelector('.premium-project-illustration'); } bind(illustration); }; ensure(); new MutationObserver(ensure).observe(target, { childList: true }); } // Trophy content is rendered by a route module and the page node may be // replaced while the feature is loading. Observe the stable content root so // both a late render and a replacement page receive the illustration. const trophyHost = document.getElementById('content') || document.body; const touchesTrophyLibrary = mutation => { const target = mutation.target?.nodeType === Node.ELEMENT_NODE ? mutation.target : mutation.target?.parentElement; if (target?.matches?.('#page-trophies, #page-trophies *')) return true; return [...mutation.addedNodes].some(node => node.nodeType === Node.ELEMENT_NODE && ( node.matches?.('#page-trophies, .trophy-library-empty') || node.querySelector?.('#page-trophies, .trophy-library-empty') )); }; ensureTrophyIllustration(); new MutationObserver(mutations => { if (mutations.some(touchesTrophyLibrary)) ensureTrophyIllustration(); }).observe(trophyHost, { childList: true, subtree: true }); bindHomeTopology(); if (!dockImportLauncher()) { const importLauncherObserver = new MutationObserver(() => { if (!dockImportLauncher()) return; importLauncherObserver.disconnect(); }); importLauncherObserver.observe(document.body, { childList: true }); } document.addEventListener('visibilitychange', syncAllMotion); if (typeof reducedMotion.addEventListener === 'function') reducedMotion.addEventListener('change', syncAllMotion); else reducedMotion.addListener(syncAllMotion); })();