Add balloon easter egg — long press logo to trigger

Hold the logo for 0.6s (works on mobile touch and desktop mouse) to launch
22 balloon silhouettes floating up from the bottom. Balloons drift with a
slight sway, have a shine highlight, and naturally disappear under the navbar.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chris 2026-06-06 21:07:06 -04:00
parent 5900ce817e
commit 2002d7f35a
7 changed files with 134 additions and 0 deletions

View File

@ -111,6 +111,7 @@ Our expertise lies in crafting memorable experiences through a diverse array of
<div id="site-footer"></div> <div id="site-footer"></div>
<script defer src="../script.js"></script> <script defer src="../script.js"></script>
<script src="../easter-egg.js"></script>
<!-- <script defer data-domain="beachpartyballoons.com" src="https://metrics.beachpartyballoons.com/js/script.js"></script> --> <!-- <script defer data-domain="beachpartyballoons.com" src="https://metrics.beachpartyballoons.com/js/script.js"></script> -->
<script async data-nf='{"formurl":"https://forms.beachpartyballoons.com/forms/contact-us-vjz40v","emoji":"💬","position":"left","bgcolor":"#0dc9ba","width":"500"}' src='https://forms.beachpartyballoons.com/widgets/embed-min.js'></script> <script async data-nf='{"formurl":"https://forms.beachpartyballoons.com/forms/contact-us-vjz40v","emoji":"💬","position":"left","bgcolor":"#0dc9ba","width":"500"}' src='https://forms.beachpartyballoons.com/widgets/embed-min.js'></script>

View File

@ -104,6 +104,7 @@
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script> <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="script.js"></script> <script src="script.js"></script>
<script src="easter-egg.js"></script>
</body> </body>
</html> </html>

View File

@ -132,6 +132,7 @@
<div id="site-footer"></div> <div id="site-footer"></div>
<script src="../script.js"></script> <script src="../script.js"></script>
<script src="../easter-egg.js"></script>
<script src="../contact-form.js"></script> <script src="../contact-form.js"></script>
</body> </body>
</html> </html>

128
main-site/easter-egg.js Normal file
View File

@ -0,0 +1,128 @@
(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');
// shine
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;
var pressTimer = null;
function startPress() {
pressTimer = setTimeout(function () {
if (!active) launch();
}, 600);
}
function cancelPress() {
clearTimeout(pressTimer);
}
// Long-press on the navbar brand (logo area)
document.addEventListener('mousedown', function (e) {
if (e.target.closest('.navbar-brand')) startPress();
});
document.addEventListener('mouseup', cancelPress);
document.addEventListener('mouseleave', cancelPress);
document.addEventListener('touchstart', function (e) {
if (e.target.closest('.navbar-brand')) startPress();
}, { passive: true });
document.addEventListener('touchend', cancelPress);
document.addEventListener('touchmove', cancelPress);
function launch() {
active = true;
// Inject keyframes once
if (!document.getElementById('bpb-balloon-style')) {
var style = document.createElement('style');
style.id = 'bpb-balloon-style';
style.textContent = [
'@keyframes bpb-float {',
' 0% { transform: translateX(var(--bx)) translateY(0) rotate(var(--br)); opacity: 0; }',
' 8% { opacity: 1; }',
' 85% { opacity: 1; }',
' 100% { transform: translateX(calc(var(--bx) * -1)) translateY(var(--by)) rotate(calc(var(--br) * -0.5)); opacity: 0; }',
'}',
].join('\n');
document.head.appendChild(style);
}
var container = document.createElement('div');
Object.assign(container.style, {
position: 'fixed',
inset: '0',
pointerEvents: 'none',
zIndex: '9', // below Bulma navbar (z-index 30)
overflow: 'hidden',
});
document.body.insertBefore(container, document.body.firstChild);
var count = 22;
for (var i = 0; i < count; i++) {
(function (idx) {
setTimeout(function () {
var color = COLORS[Math.floor(Math.random() * COLORS.length)];
var size = 38 + Math.random() * 32; // 3870 px
var leftPct = 3 + Math.random() * 94; // 397 %
var sway = (Math.random() * 40 - 20) + 'px'; // ±20 px horizontal drift
var tilt = (Math.random() * 24 - 12) + 'deg';
var dur = 4500 + Math.random() * 3500; // 4.58 s
var riseAmt = -(window.innerHeight + size * 2); // rise full viewport height
var wrap = document.createElement('div');
Object.assign(wrap.style, {
position: 'absolute',
bottom: (-size * 1.64 - 10) + 'px',
left: leftPct + '%',
'--bx': sway,
'--by': riseAmt + 'px',
'--br': tilt,
animation: 'bpb-float ' + dur + 'ms cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards',
animationDelay: (idx * 120 + Math.random() * 200) + 'ms',
});
wrap.appendChild(makeBalloon(color, size));
container.appendChild(wrap);
}, 0);
})(i);
}
setTimeout(function () {
container.remove();
active = false;
}, 12000);
}
})();

View File

@ -232,6 +232,7 @@
</div> </div>
<div id="site-footer"></div> <div id="site-footer"></div>
<script src="../script.js"></script> <script src="../script.js"></script>
<script src="../easter-egg.js"></script>
<script> <script>
document.addEventListener('DOMContentLoaded', () => { document.addEventListener('DOMContentLoaded', () => {
const tabs = document.querySelectorAll('.faq-tabs li'); const tabs = document.querySelectorAll('.faq-tabs li');

View File

@ -107,6 +107,7 @@
window.GALLERY_API_URL = 'https://photobackend.beachpartyballoons.com'; window.GALLERY_API_URL = 'https://photobackend.beachpartyballoons.com';
</script> </script>
<script src="../script.js" defer></script> <script src="../script.js" defer></script>
<script src="../easter-egg.js"></script>
<script src="../update.js" defer></script> <script src="../update.js" defer></script>
<script src="gallery.js" defer></script> <script src="gallery.js" defer></script>
</body> </body>

View File

@ -244,6 +244,7 @@
<div id="site-footer"></div> <div id="site-footer"></div>
<script src="script.js"></script> <script src="script.js"></script>
<script src="easter-egg.js"></script>
<script src="update.js"></script> <script src="update.js"></script>
<script src="reviews-data.js"></script> <script src="reviews-data.js"></script>
<script src="reviews.js?v=6"></script> <script src="reviews.js?v=6"></script>