2026-01-07 00:43:05 -05:00
|
|
|
<div class="background-container" id="bg-container">
|
2026-01-06 23:33:22 -05:00
|
|
|
<img id="background-thumb" alt="Background" class="background-image">
|
|
|
|
|
<img id="background-full" alt="Background" class="background-image background-full" loading="lazy">
|
2026-01-07 00:43:05 -05:00
|
|
|
<div id="cursor-circle"></div>
|
2026-01-06 23:33:22 -05:00
|
|
|
<script>
|
|
|
|
|
const thumbImg = document.getElementById('background-thumb');
|
|
|
|
|
const fullImg = document.getElementById('background-full');
|
|
|
|
|
const imageName = 'Apophysis_071008-64.webp';
|
|
|
|
|
const thumbPath = `/backgrounds/thumbs/${imageName}`;
|
|
|
|
|
const fullPath = `/backgrounds/${imageName}`;
|
|
|
|
|
|
|
|
|
|
thumbImg.src = thumbPath;
|
|
|
|
|
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
const preloadImg = new Image();
|
|
|
|
|
preloadImg.onload = () => {
|
|
|
|
|
fullImg.src = fullPath;
|
|
|
|
|
fullImg.classList.add('loaded');
|
|
|
|
|
setTimeout(() => thumbImg.remove(), 2000);
|
|
|
|
|
};
|
|
|
|
|
preloadImg.onerror = () => {
|
|
|
|
|
fullImg.src = fullPath;
|
|
|
|
|
fullImg.classList.add('loaded');
|
|
|
|
|
};
|
|
|
|
|
preloadImg.src = fullPath;
|
|
|
|
|
}, 800);
|
2026-01-07 00:43:05 -05:00
|
|
|
|
|
|
|
|
const container = document.getElementById('bg-container');
|
|
|
|
|
const circle = document.getElementById('cursor-circle');
|
|
|
|
|
let hoverTimer = null;
|
|
|
|
|
let revealTimer = null;
|
|
|
|
|
let isRevealed = false;
|
|
|
|
|
|
2026-01-07 01:17:13 -05:00
|
|
|
const isOverContent = (e) => {
|
|
|
|
|
const target = e.target;
|
|
|
|
|
return target.closest('article, header, nav, footer, section') !== null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
window.addEventListener('mousemove', (e) => {
|
2026-01-07 00:43:05 -05:00
|
|
|
if (isRevealed) return;
|
|
|
|
|
|
|
|
|
|
circle.style.left = e.clientX + 'px';
|
|
|
|
|
circle.style.top = e.clientY + 'px';
|
|
|
|
|
|
2026-01-07 01:17:13 -05:00
|
|
|
if (isOverContent(e)) {
|
|
|
|
|
if (hoverTimer) {
|
|
|
|
|
resetTimer();
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-07 00:43:05 -05:00
|
|
|
if (!hoverTimer) {
|
|
|
|
|
hoverTimer = setTimeout(() => {
|
|
|
|
|
circle.classList.add('active');
|
|
|
|
|
revealTimer = setTimeout(() => {
|
|
|
|
|
circle.classList.remove('active');
|
|
|
|
|
circle.classList.add('fade-out');
|
|
|
|
|
fullImg.classList.add('unblurred');
|
|
|
|
|
isRevealed = true;
|
|
|
|
|
}, 4000);
|
|
|
|
|
}, 1000);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
2026-01-07 01:17:13 -05:00
|
|
|
const resetTimer = () => {
|
2026-01-07 00:43:05 -05:00
|
|
|
clearTimeout(hoverTimer);
|
|
|
|
|
clearTimeout(revealTimer);
|
|
|
|
|
hoverTimer = null;
|
|
|
|
|
revealTimer = null;
|
2026-01-07 01:17:13 -05:00
|
|
|
circle.classList.remove('active');
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const resetEffect = () => {
|
|
|
|
|
resetTimer();
|
|
|
|
|
circle.classList.remove('fade-out');
|
2026-01-07 00:43:05 -05:00
|
|
|
fullImg.classList.remove('unblurred');
|
|
|
|
|
isRevealed = false;
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-07 01:17:13 -05:00
|
|
|
document.addEventListener('mouseout', (e) => {
|
|
|
|
|
if (!e.relatedTarget && !e.toElement) {
|
|
|
|
|
resetTimer();
|
2026-01-07 00:43:05 -05:00
|
|
|
}
|
|
|
|
|
});
|
2026-01-07 01:17:13 -05:00
|
|
|
window.addEventListener('blur', resetTimer);
|
2026-01-06 23:33:22 -05:00
|
|
|
</script>
|
2025-04-03 01:42:15 -04:00
|
|
|
</div>
|
|
|
|
|
<article class="prose max-w-full dark:prose-invert glass">
|
|
|
|
|
{{ with .Title }}
|
|
|
|
|
<header>
|
|
|
|
|
<h1>{{ . | emojify }}</h1>
|
|
|
|
|
</header>
|
|
|
|
|
{{ end }}
|
|
|
|
|
<section>{{ .Content | emojify }}</section>
|
|
|
|
|
</article>
|
|
|
|
|
<section>
|
|
|
|
|
{{ partial "recent-articles.html" . }}
|
|
|
|
|
</section>
|