// bonzi homepage — minimal, no framework (() => { 'use strict'; // 1. type-typing effect on commands const cmds = document.querySelectorAll('[data-typing]'); const speeds = [55, 38, 75, 30, 38, 30]; // per command ms/char let i = 0; const typeNext = () => { if (i >= cmds.length) return; const el = cmds[i]; const text = el.textContent; el.textContent = ''; let j = 0; const speed = speeds[i] || 45; const tick = () => { if (j <= text.length) { el.textContent = text.slice(0, j); j++; setTimeout(tick, speed + (Math.random() * 30 - 15)); } else { i++; setTimeout(typeNext, 220); } }; tick(); }; // start after a short delay setTimeout(typeNext, 350); // 2. reveal output blocks as they scroll into view const blocks = document.querySelectorAll('[data-reveal]'); if ('IntersectionObserver' in window) { const io = new IntersectionObserver((entries) => { entries.forEach((e) => { if (e.isIntersecting) { e.target.classList.add('in'); io.unobserve(e.target); } }); }, { threshold: 0.12 }); blocks.forEach((b) => io.observe(b)); } else { blocks.forEach((b) => b.classList.add('in')); } // 3. live timestamp const nowEl = document.getElementById('now'); if (nowEl) { const fmt = () => { const d = new Date(); const pad = (n) => String(n).padStart(2, '0'); return `${d.getUTCFullYear()}-${pad(d.getUTCMonth()+1)}-${pad(d.getUTCDate())} ${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())} UTC`; }; nowEl.textContent = fmt(); setInterval(() => { nowEl.textContent = fmt(); }, 60_000); } })();