summaryrefslogtreecommitdiff
path: root/internal/generator/templates/shared
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-18 23:40:23 +0300
committerPaul Buetow <paul@buetow.org>2026-04-18 23:40:23 +0300
commitb5fcb74d0967b23e5fa5c92bca6d45ba4e8755cf (patch)
tree39349dd3e5d2c241b791425a7edf2206173a0e94 /internal/generator/templates/shared
parent795cdaa73b48f7d63c85693f1b5e5e8f8f55e2d6 (diff)
feat(themes): add PgUp/PgDn scroll effects, wild mode lightning & badge fix
- PgUp/PgDn now calls snonuxScrollEffect(dir) in all 14 themes - Each theme gets a unique directional colour strip (theme-matched gradient) sliding across the screen in the scroll direction; thicker when wild - Wild mode activation fires dramatic multi-flash lightning overlay plus a persistent storm overlay that flickers intermittently while active - Wild mode deactivation shows a brief dark veil then removes the storm - Fixed WILD MODE badge: animation now only runs under .sno-wild-on so the badge stays fully hidden (opacity:0, no pulsing) when wild is off Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/generator/templates/shared')
-rw-r--r--internal/generator/templates/shared/nav.tmpl53
1 files changed, 50 insertions, 3 deletions
diff --git a/internal/generator/templates/shared/nav.tmpl b/internal/generator/templates/shared/nav.tmpl
index a13b660..e5c3bab 100644
--- a/internal/generator/templates/shared/nav.tmpl
+++ b/internal/generator/templates/shared/nav.tmpl
@@ -75,20 +75,32 @@
/* ~Half-height footer bar vs default .page-nav padding */
.page-nav-footer .page-nav a { padding-top:4px; padding-bottom:4px; }
/* Shared nav FX keyframes — themes apply these classes for brief effects */
+/* Modal open: post zooms/flies into the modal overlay */
+@keyframes sno-modal-zoom { 0%{transform:scale(0.82) translateY(18px);opacity:0} 60%{transform:scale(1.02) translateY(-3px);opacity:1} 100%{transform:scale(1) translateY(0);opacity:1} }
+@keyframes sno-modal-fly-up { 0%{transform:translateY(60px) scale(0.92);opacity:0} 70%{transform:translateY(-4px) scale(1.01);opacity:1} 100%{transform:translateY(0) scale(1);opacity:1} }
+@keyframes sno-modal-slide-in { 0%{transform:translateX(-40px) scale(0.96);opacity:0} 65%{transform:translateX(4px) scale(1.005);opacity:1} 100%{transform:translateX(0) scale(1);opacity:1} }
+@keyframes sno-modal-expand { 0%{transform:scale(0.05) rotate(-4deg);opacity:0} 55%{transform:scale(1.04) rotate(0.5deg);opacity:1} 100%{transform:scale(1) rotate(0);opacity:1} }
+.sno-modal-zoom .modal-inner { animation:sno-modal-zoom 0.36s cubic-bezier(0.22,1,0.36,1) both !important; }
+.sno-modal-fly .modal-inner { animation:sno-modal-fly-up 0.34s cubic-bezier(0.22,1,0.36,1) both !important; }
+.sno-modal-slide .modal-inner { animation:sno-modal-slide-in 0.32s cubic-bezier(0.22,1,0.36,1) both !important; }
+.sno-modal-expand .modal-inner { animation:sno-modal-expand 0.4s cubic-bezier(0.22,1,0.36,1) both !important; }
@keyframes sno-shake { 0%,100%{transform:translate(0)} 14%{transform:translate(-7px,4px)} 28%{transform:translate(7px,-5px)} 42%{transform:translate(-5px,6px)} 56%{transform:translate(6px,-4px)} 70%{transform:translate(-4px,3px)} 86%{transform:translate(4px,-2px)} }
@keyframes sno-zoom-fwd { 0%{transform:scale(1)} 40%{transform:scale(1.05)} 100%{transform:scale(1)} }
@keyframes sno-glitch { 0%,100%{transform:translate(0) skewX(0)} 20%{transform:translate(-5px,0) skewX(-4deg)} 40%{transform:translate(5px,0) skewX(4deg)} 60%{transform:translate(-3px,0)} 80%{transform:translate(3px,0)} }
@keyframes sno-wild-pulse { 0%,100%{opacity:1} 50%{opacity:0.6} }
+/* Storm overlay that flickers like distant lightning while wild mode is on */
+@keyframes sno-wild-flicker { 0%,84%,87%,91%,94%,100%{opacity:0} 85%,90%{opacity:0.75} 86%,92%{opacity:0.35} }
.sno-fx-shake { animation:sno-shake 0.38s cubic-bezier(.36,.07,.19,.97) both !important; transform-origin:center; }
.sno-fx-zoom { animation:sno-zoom-fwd 0.32s ease both !important; }
.sno-fx-glitch { animation:sno-glitch 0.3s ease both !important; }
-/* Wild mode badge — visible when active */
+/* Wild mode badge — only visible (opacity:1) when .sno-wild-on is present */
#sno-wild-badge { position:fixed; top:10px; right:12px; z-index:5000; padding:3px 12px;
font-size:0.64rem; letter-spacing:0.2em; text-transform:uppercase; border-radius:2px;
pointer-events:none; opacity:0; transition:opacity 0.4s;
background:rgba(220,0,0,0.92); color:#fff; border:1px solid rgba(255,100,100,0.8);
- font-family:monospace; animation:sno-wild-pulse 0.9s ease-in-out infinite; }
-#sno-wild-badge.sno-wild-on { opacity:1; }
+ font-family:monospace; }
+/* Animation only runs when wild is actually on, preventing invisible badge pulse */
+#sno-wild-badge.sno-wild-on { opacity:1; animation:sno-wild-pulse 0.9s ease-in-out infinite; }
/* Host note under the site subtitle (all themes) */
.logo-host { font-size:0.65rem; opacity:0.55; margin-top:4px; letter-spacing:0.3px; line-height:1.3; }
/* Atom feed link in header (paired with transmit in .nav) */
@@ -147,6 +159,36 @@ html.sno-splash-skip #splash-overlay { display:none !important; visibility:hidde
const SNONUX_SOUNDS = {{.ThemeSoundsJSON}};
// Inject wild-mode badge used by all themes
(function() { var b=document.createElement('div'); b.id='sno-wild-badge'; b.textContent='WILD MODE'; document.body.appendChild(b); })();
+ // Dramatic lightning flash on wild mode activation/deactivation
+ function snonuxWildFlash(on) {
+ var ov = document.createElement('div');
+ ov.style.cssText = 'position:fixed;inset:0;z-index:9998;pointer-events:none;';
+ document.body.appendChild(ov);
+ if (on) {
+ // Three rapid lightning flashes on activation
+ [0, 80, 180, 300, 440].forEach(function(d, i) {
+ setTimeout(function() {
+ ov.style.background = (i % 2 === 0) ? 'rgba(255,255,200,0.72)' : 'transparent';
+ }, d);
+ });
+ setTimeout(function() { ov.remove(); }, 550);
+ // Persistent storm overlay with intermittent flicker
+ var storm = document.createElement('div');
+ storm.id = 'sno-wild-storm';
+ storm.style.cssText = 'position:fixed;inset:0;z-index:4998;pointer-events:none;' +
+ 'background:radial-gradient(ellipse at 50% 0%,rgba(255,255,200,0.88) 0%,transparent 55%);' +
+ 'animation:sno-wild-flicker 3.7s ease-in-out infinite;';
+ document.body.appendChild(storm);
+ } else {
+ // Brief dark veil on deactivation
+ ov.style.background = 'rgba(0,0,0,0.45)';
+ ov.style.transition = 'opacity 0.45s';
+ setTimeout(function() { ov.style.opacity = '0'; }, 60);
+ setTimeout(function() { ov.remove(); }, 550);
+ var storm = document.getElementById('sno-wild-storm');
+ if (storm) { storm.style.transition = 'opacity 0.5s'; storm.style.opacity = '0'; setTimeout(function() { storm.remove(); }, 600); }
+ }
+ }
function snonuxWaveType(w) {
if (w === 'square') return 'square';
if (w === 'triangle') return 'triangle';
@@ -342,6 +384,7 @@ html.sno-splash-skip #splash-overlay { display:none !important; visibility:hidde
var modalInner = modal ? modal.querySelector('.modal-inner') : null;
document.getElementById('modal-content').innerHTML = postText.innerHTML;
modal.classList.add('active');
+ if (window.snonuxOpenEffect) window.snonuxOpenEffect(post);
modal.scrollTop = 0;
if (modalInner) {
modalInner.scrollTop = 0;
@@ -355,6 +398,7 @@ html.sno-splash-skip #splash-overlay { display:none !important; visibility:hidde
function closeModal() {
document.getElementById('post-modal').classList.remove('active');
playCloseSound();
+ if (window.snonuxCloseEffect) window.snonuxCloseEffect();
}
(function postClickOpen() {
@@ -404,6 +448,7 @@ html.sno-splash-skip #splash-overlay { display:none !important; visibility:hidde
}
var idx = activeIndexForVisibleRegion(sc);
if (idx >= 0) setActiveHighlight(idx, true, false);
+ if (window.snonuxScrollEffect) window.snonuxScrollEffect(e.key === 'PageUp' ? 'up' : 'down');
e.preventDefault();
break;
}
@@ -417,7 +462,9 @@ html.sno-splash-skip #splash-overlay { display:none !important; visibility:hidde
e.preventDefault(); break;
case 'Enter': openPostAt(currentIndex, true); e.preventDefault(); break;
case 'w':
+ window._snoWildActive = !window._snoWildActive;
if (window.snonuxWildToggle) window.snonuxWildToggle();
+ snonuxWildFlash(window._snoWildActive);
e.preventDefault(); break;
}
});