| |
| (function () { |
| var BUBBLE_LIFETIME_MS = 8000; |
| var STAGGER_DELAY_MS = 120; |
|
|
| function animateBubbles() { |
| var bubbles = document.querySelectorAll('.bubble:not([data-animated])'); |
| var i = 0; |
| bubbles.forEach(function (b) { |
| b.dataset.animated = '1'; |
| b.dataset.spawned = Date.now(); |
| b.style.animationDelay = (i * STAGGER_DELAY_MS) + 'ms'; |
| setTimeout(function () { typewriter(b); }, i * STAGGER_DELAY_MS + 120); |
| i++; |
| }); |
| |
| setTimeout(function () { |
| document.querySelectorAll('.pawn.speaking').forEach(function (p) { |
| var moodEl = p.querySelector('.pawn-mood'); |
| if (moodEl) { moodEl.classList.remove('pop'); void moodEl.offsetWidth; moodEl.classList.add('pop'); } |
| }); |
| document.querySelectorAll('.roster-card').forEach(function (c) { |
| c.classList.remove('speaking-flash'); void c.offsetWidth; c.classList.add('speaking-flash'); |
| }); |
| }, 200); |
| } |
|
|
| function typewriter(bubble) { |
| var node = bubble.firstChild; |
| if (!node || node.nodeType !== 3) return; |
| var full = node.textContent; |
| if (full.length < 4) return; |
| node.textContent = ''; |
| var k = 0; |
| var speed = Math.max(9, Math.min(22, 520 / full.length)); |
| (function step() { |
| if (k < full.length) { node.textContent += full[k++]; setTimeout(step, speed); } |
| })(); |
| } |
|
|
| function dismissOld() { |
| document.querySelectorAll('.bubble[data-spawned]').forEach(function (b) { |
| if (Date.now() - parseInt(b.dataset.spawned, 10) > BUBBLE_LIFETIME_MS) { |
| b.style.transition = 'opacity .4s ease, transform .4s ease'; |
| b.style.opacity = '0'; |
| b.style.transform = 'translateX(-50%) translateY(8px) scale(.9)'; |
| setTimeout(function () { if (b.parentNode) b.remove(); }, 400); |
| } |
| }); |
| } |
| setInterval(dismissOld, 1000); |
|
|
| function fireShockwave() { |
| var sw = document.querySelector('.shockwave'); |
| if (!sw) return; |
| sw.classList.remove('fire'); void sw.offsetWidth; sw.classList.add('fire'); |
| setTimeout(function () { sw.classList.remove('fire'); }, 900); |
| } |
|
|
| |
| function fireScreenShake() { |
| var stage = document.querySelector('.stage'); |
| if (!stage) return; |
| stage.classList.remove('shake'); void stage.offsetWidth; stage.classList.add('shake'); |
| setTimeout(function () { stage.classList.remove('shake'); }, 550); |
| } |
|
|
| |
| function fireButtonPulse() { |
| var btn = document.querySelector('#throw-btn') || document.querySelector('button.primary'); |
| if (!btn) return; |
| btn.classList.remove('pulse'); void btn.offsetWidth; btn.classList.add('pulse'); |
| setTimeout(function () { btn.classList.remove('pulse'); }, 2500); |
| } |
|
|
| |
| function watchMeters() { |
| var fills = document.querySelectorAll('.vibe-fill'); |
| fills.forEach(function (f) { |
| if (f.dataset.watched) return; |
| f.dataset.watched = '1'; |
| var lastW = f.style.width; |
| var m = new MutationObserver(function () { |
| if (f.style.width !== lastW) { |
| lastW = f.style.width; |
| f.classList.remove('tick'); void f.offsetWidth; f.classList.add('tick'); |
| } |
| }); |
| m.observe(f, { attributes: true, attributeFilter: ['style'] }); |
| }); |
| } |
| setInterval(watchMeters, 500); |
|
|
| |
| function startTintDrift() { |
| var tint = document.querySelector('.stage-tint'); |
| if (tint && !tint.classList.contains('drift')) tint.classList.add('drift'); |
| } |
|
|
| |
| function wander() { |
| document.querySelectorAll('.pawn').forEach(function (p) { |
| if (p.classList.contains('speaking')) return; |
| var dx = (Math.random() * 2 - 1) * 0.7; |
| var dy = (Math.random() * 2 - 1) * 0.4; |
| var t = p.querySelector('.pawn-token'); |
| if (t) t.style.transform = 'translate(' + dx.toFixed(2) + 'px,' + dy.toFixed(2) + 'px)'; |
| }); |
| } |
| setInterval(wander, 2600); |
|
|
| |
| document.addEventListener('mousemove', function (e) { |
| var btn = e.target.closest('button.primary, .gr-button-primary, #throw-btn'); |
| if (!btn) return; |
| var rect = btn.getBoundingClientRect(); |
| btn.style.setProperty('--mx', ((e.clientX - rect.left) / rect.width * 100) + '%'); |
| btn.style.setProperty('--my', ((e.clientY - rect.top) / rect.height * 100) + '%'); |
| }); |
|
|
| var observer = new MutationObserver(function (muts) { |
| var fresh = false; |
| muts.forEach(function (m) { |
| m.addedNodes && m.addedNodes.forEach(function (n) { |
| if (n.nodeType === 1 && (n.querySelector ? (n.querySelector('.bubble') || n.classList.contains('bubble')) : false)) fresh = true; |
| }); |
| }); |
| if (fresh) { |
| setTimeout(function () { |
| animateBubbles(); |
| fireShockwave(); |
| fireScreenShake(); |
| fireButtonPulse(); |
| startTintDrift(); |
| }, 40); |
| } |
| }); |
|
|
| function watch() { |
| var root = document.querySelector('.gradio-container') || document.body; |
| if (root) { observer.observe(root, { childList: true, subtree: true }); animateBubbles(); startTintDrift(); } |
| else setTimeout(watch, 300); |
| } |
| if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', watch); |
| else watch(); |
| })(); |
|
|