(() => { const textSelectors = 'p, h1, h2, h3, h4, h5, h6, span, li, label, td, th, pre, .code'; const linkSelectors = 'a, button, [role="button"], input[type="submit"], input[type="button"]'; const padding = 6; let ac = null; let sig = null; let mouseX = 0, mouseY = 0; let currentLinkEl = null; let rafId = null; let cursor = null; let cursorVisible = false; let lastTouchTime = 0; let isMouseDown = false; const TOUCH_MOUSE_GUARD_MS = 800; window.__scriptCleanup = () => { if (ac) ac.abort(); if (rafId) { cancelAnimationFrame(rafId); rafId = null; } document.documentElement.style.cursor = ''; if (cursor) cursor.classList.remove('visible', 'on-link', 'on-text'); cursorVisible = false; currentLinkEl = null; }; function showCursor() { if (!cursorVisible && cursor) { cursorVisible = true; cursor.classList.add('visible'); } } function hideCursor() { if (cursor) { cursorVisible = false; cursor.classList.remove('visible'); currentLinkEl = null; if (rafId) { cancelAnimationFrame(rafId); rafId = null; } cursor.classList.remove('on-link', 'on-text'); } } function isSyntheticMouse() { return Date.now() - lastTouchTime < TOUCH_MOUSE_GUARD_MS; } function updateCursorForLink(el) { const rect = el.getBoundingClientRect(); cursor.classList.remove('on-text'); cursor.classList.add('on-link'); cursor.style.transform = 'none'; cursor.style.left = (rect.left - padding) + 'px'; cursor.style.top = (rect.top - padding) + 'px'; cursor.style.width = (rect.width + padding * 2) + 'px'; cursor.style.height = (rect.height + padding * 2) + 'px'; } function trackLink() { if (currentLinkEl) { updateCursorForLink(currentLinkEl); rafId = requestAnimationFrame(trackLink); } } document.documentElement.style.cursor = 'none'; function init() { ac = new AbortController(); sig = ac.signal; cursor = document.getElementById('cursor'); if (!cursor) return; document.addEventListener('touchstart', () => { lastTouchTime = Date.now(); hideCursor(); }, { passive: true, signal: sig }); document.addEventListener('touchmove', () => { lastTouchTime = Date.now(); hideCursor(); }, { passive: true, signal: sig }); document.addEventListener('touchend', () => { lastTouchTime = Date.now(); }, { passive: true, signal: sig }); document.addEventListener('mousemove', (e) => { if (isSyntheticMouse()) return; if (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents) return; mouseX = e.clientX; mouseY = e.clientY; showCursor(); const el = document.elementFromPoint(mouseX, mouseY); const linkEl = el ? el.closest(linkSelectors) : null; if (linkEl) { if (currentLinkEl !== linkEl) { currentLinkEl = linkEl; if (rafId) cancelAnimationFrame(rafId); rafId = requestAnimationFrame(trackLink); } } else { if (currentLinkEl) { currentLinkEl = null; if (rafId) { cancelAnimationFrame(rafId); rafId = null; } } cursor.classList.remove('on-link'); cursor.style.transform = isMouseDown ? 'translate(-50%, -50%) scale(0.9)' : 'translate(-50%, -50%)'; cursor.style.left = mouseX + 'px'; cursor.style.top = mouseY + 'px'; cursor.style.width = ''; cursor.style.height = ''; if (el && el.closest(textSelectors)) { cursor.classList.add('on-text'); } else { cursor.classList.remove('on-text'); } } }, { signal: sig }); document.addEventListener('mousedown', () => { isMouseDown = true; cursor.style.transform = currentLinkEl ? 'none' : 'translate(-50%, -50%) scale(0.9)'; }, { signal: sig }); document.addEventListener('mouseup', () => { isMouseDown = false; cursor.style.transform = currentLinkEl ? 'none' : 'translate(-50%, -50%) scale(1)'; }, { signal: sig }); window.addEventListener('scroll', () => { if (currentLinkEl) updateCursorForLink(currentLinkEl); }, { passive: true, signal: sig }); } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init, { signal: sig }); } else { init(); } function preloadAssets(newDoc) { const curStyleHrefs = new Set( [...document.head.querySelectorAll('link[rel="stylesheet"]')].map(l => l.href) ); const curScriptSrcs = new Set( [...document.head.querySelectorAll('script[src]')].map(s => s.src) ); const tasks = []; [...newDoc.head.querySelectorAll('link[rel="stylesheet"]')] .filter(l => !curStyleHrefs.has(new URL(l.href, location.href).href)) .forEach(link => tasks.push(new Promise(resolve => { const l = link.cloneNode(true); l.addEventListener('load', resolve, { once: true }); l.addEventListener('error', resolve, { once: true }); document.head.appendChild(l); }))); [...newDoc.head.querySelectorAll('script[src]')] .filter(s => !curScriptSrcs.has(new URL(s.src, location.href).href)) .forEach(script => tasks.push(new Promise(resolve => { const s = document.createElement('script'); [...script.attributes].forEach(a => s.setAttribute(a.name, a.value)); s.addEventListener('load', resolve, { once: true }); s.addEventListener('error', resolve, { once: true }); document.head.appendChild(s); }))); return Promise.all(tasks); } function updateHead(newDoc) { const head = document.head; const newHead = newDoc.head; const t = newHead.querySelector('title'); if (t) document.title = t.textContent; const META_KEEP = new Set(['charset', 'viewport', 'color-scheme', 'theme-color']); head.querySelectorAll('meta').forEach(m => { const key = m.getAttribute('name') || m.getAttribute('property'); if (!key || META_KEEP.has(key)) return; m.remove(); }); const insertRef = head.querySelector( 'link[rel="preconnect"], link[rel="stylesheet"], link[rel="manifest"], link[rel="icon"], script' ); newHead.querySelectorAll('meta[name], meta[property]').forEach(m => { const key = m.getAttribute('name') || m.getAttribute('property'); if (!META_KEEP.has(key)) head.insertBefore(m.cloneNode(true), insertRef); }); const nc = newHead.querySelector('link[rel="canonical"]'); const cc = head.querySelector('link[rel="canonical"]'); if (nc && cc) cc.href = nc.href; const newStyleHrefs = new Set( [...newHead.querySelectorAll('link[rel="stylesheet"]')] .map(l => new URL(l.href, location.href).href) ); head.querySelectorAll('link[rel="stylesheet"]').forEach(l => { if (!newStyleHrefs.has(l.href)) l.remove(); }); const newScriptSrcs = new Set( [...newHead.querySelectorAll('script[src]')] .map(s => new URL(s.src, location.href).href) ); head.querySelectorAll('script[src]').forEach(s => { if (!newScriptSrcs.has(s.src)) s.remove(); }); head.querySelectorAll('style').forEach(s => s.remove()); newHead.querySelectorAll('style').forEach(s => head.appendChild(s.cloneNode(true))); } if (document.startViewTransition) { document.addEventListener('click', (event) => { const link = event.target.closest('a'); if (!link || link.hasAttribute('download')) return; const url = new URL(link.href, location.href); if (url.origin !== location.origin) return; if (link.target || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return; if (url.hash && url.pathname === location.pathname) { event.preventDefault(); const target = document.querySelector(url.hash); if (target) { target.scrollIntoView({ behavior: 'smooth', block: 'start' }); history.pushState(null, '', url.hash); } return; } event.preventDefault(); document.startViewTransition(async () => { const response = await fetch(url.href, { headers: { 'X-Requested-With': 'view-transition' } }); const html = await response.text(); const doc = new DOMParser().parseFromString(html, 'text/html'); if (typeof window.__scriptCleanup === 'function') { window.__scriptCleanup(); window.__scriptCleanup = null; } await preloadAssets(doc); updateHead(doc); for (const tag of ['header', 'main', 'footer']) { const newEl = doc.querySelector(tag); const curEl = document.querySelector(tag); if (!newEl || !curEl) { location.href = url.href; return; } curEl.innerHTML = newEl.innerHTML; curEl.querySelectorAll('script').forEach(old => { const s = document.createElement('script'); [...old.attributes].forEach(a => s.setAttribute(a.name, a.value)); s.textContent = old.textContent; old.replaceWith(s); }); } history.pushState(null, '', url.href); if (cursor) { currentLinkEl = null; if (rafId) { cancelAnimationFrame(rafId); rafId = null; } cursor.classList.remove('on-link', 'on-text'); cursor.style.transform = 'translate(-50%, -50%)'; cursor.style.left = mouseX + 'px'; cursor.style.top = mouseY + 'px'; cursor.style.width = ''; cursor.style.height = ''; const el = document.elementFromPoint(mouseX, mouseY); const newLinkEl = el ? el.closest(linkSelectors) : null; if (newLinkEl) { currentLinkEl = newLinkEl; rafId = requestAnimationFrame(trackLink); } else if (el && el.closest(textSelectors)) { cursor.classList.add('on-text'); } } init(); }); }, { signal: sig }); window.addEventListener('popstate', () => location.reload(), { signal: sig }); } })();