/* Neon Survivors — service worker (cache-first, versioned) */ 'use strict'; const CACHE = 'neon-survivors-v1'; const ASSETS = [ './', './index.html', './manifest.webmanifest', './css/style.css', './icons/icon-192.png', './icons/icon-512.png', './js/util.js', './js/i18n.js', './js/save.js', './js/audio.js', './js/data.js', './js/entities.js', './js/systems.js', './js/render.js', './js/ui.js', './js/game.js', './js/main.js' ]; self.addEventListener('install', (e) => { e.waitUntil( caches.open(CACHE).then(c => c.addAll(ASSETS)).then(() => self.skipWaiting()) ); }); self.addEventListener('activate', (e) => { e.waitUntil( caches.keys() .then(keys => Promise.all(keys.filter(k => k !== CACHE).map(k => caches.delete(k)))) .then(() => self.clients.claim()) ); }); self.addEventListener('fetch', (e) => { if (e.request.method !== 'GET') return; const url = new URL(e.request.url); if (url.origin !== location.origin) return; e.respondWith( caches.match(e.request, { ignoreSearch: true }).then(hit => hit || fetch(e.request).then(res => { const copy = res.clone(); caches.open(CACHE).then(c => c.put(e.request, copy)); return res; }).catch(() => hit) ) ); });