chris c503d6dd75 Easter egg: trigger on copyright symbol click only
Previously fired on 5 rapid taps anywhere on the page.
Now triggers with a single click on the © in the footer.
Added id="bpb-copyright" to the symbol span in nav.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-12 06:03:15 -04:00

111 lines
4.0 KiB
JavaScript

(function () {
var COLORS = ['#11b3be','#ff6b9d','#ffd93d','#6bcb77','#4d96ff','#ff6b35','#c77dff','#ff9f43','#54a0ff','#ff6348'];
var SVG_NS = 'http://www.w3.org/2000/svg';
function makeBalloon(color, size) {
var svg = document.createElementNS(SVG_NS, 'svg');
svg.setAttribute('viewBox', '0 0 50 82');
svg.setAttribute('width', size);
svg.setAttribute('height', Math.round(size * 1.64));
var body = document.createElementNS(SVG_NS, 'ellipse');
body.setAttribute('cx', '25'); body.setAttribute('cy', '26');
body.setAttribute('rx', '21'); body.setAttribute('ry', '25');
body.setAttribute('fill', color); body.setAttribute('opacity', '0.88');
var shine = document.createElementNS(SVG_NS, 'ellipse');
shine.setAttribute('cx', '18'); shine.setAttribute('cy', '16');
shine.setAttribute('rx', '7'); shine.setAttribute('ry', '5');
shine.setAttribute('fill', 'white'); shine.setAttribute('opacity', '0.25');
shine.setAttribute('transform', 'rotate(-20 18 16)');
var knot = document.createElementNS(SVG_NS, 'path');
knot.setAttribute('d', 'M25 51 Q27.5 55.5 25 58.5 Q22.5 55.5 25 51Z');
knot.setAttribute('fill', color); knot.setAttribute('opacity', '0.88');
var str = document.createElementNS(SVG_NS, 'path');
str.setAttribute('d', 'M25 58.5 Q20 68 25 80');
str.setAttribute('stroke', '#999'); str.setAttribute('stroke-width', '1.2');
str.setAttribute('fill', 'none'); str.setAttribute('opacity', '0.7');
svg.appendChild(body);
svg.appendChild(shine);
svg.appendChild(knot);
svg.appendChild(str);
return svg;
}
var active = false;
function attach() {
var el = document.getElementById('bpb-copyright');
if (!el) return;
el.addEventListener('click', function () {
if (active) return;
launch();
});
}
// Footer is injected by nav.js — wait for it
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', attach);
} else {
attach();
}
function launch() {
active = true;
var container = document.createElement('div');
Object.assign(container.style, {
position: 'fixed',
inset: '0',
pointerEvents: 'none',
zIndex: '9',
overflow: 'hidden',
});
document.body.insertBefore(container, document.body.firstChild);
var count = 22;
for (var i = 0; i < count; i++) {
(function (idx) {
var delay = idx * 130 + Math.random() * 150;
setTimeout(function () {
var color = COLORS[Math.floor(Math.random() * COLORS.length)];
var size = 38 + Math.random() * 32;
var leftPct = 3 + Math.random() * 94;
var sway = Math.random() * 40 - 20;
var tilt = Math.random() * 24 - 12;
var dur = 4500 + Math.random() * 3500;
var rise = window.innerHeight + size * 2;
var wrap = document.createElement('div');
Object.assign(wrap.style, {
position: 'absolute',
bottom: (-size * 1.64 - 10) + 'px',
left: leftPct + '%',
});
wrap.appendChild(makeBalloon(color, size));
container.appendChild(wrap);
wrap.animate([
{ transform: 'translateX(0px) translateY(0px) rotate(' + tilt + 'deg)', opacity: 0 },
{ transform: 'translateX(0px) translateY(0px) rotate(' + tilt + 'deg)', opacity: 1, offset: 0.06 },
{ transform: 'translateX(' + sway + 'px) translateY(' + (-rise * 0.5) + 'px) rotate(' + (-tilt * 0.3) + 'deg)', opacity: 1, offset: 0.5 },
{ transform: 'translateX(' + (-sway) + 'px) translateY(' + (-rise) + 'px) rotate(' + (-tilt * 0.6) + 'deg)', opacity: 0 },
], {
duration: dur,
easing: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
fill: 'forwards',
});
}, delay);
})(i);
}
setTimeout(function () {
container.remove();
active = false;
}, 14000);
}
})();