Skip to content

Commit e1d709f

Browse files
committed
Lady bug is getting curious
1 parent e80c877 commit e1d709f

3 files changed

Lines changed: 123 additions & 3 deletions

File tree

layouts/partials/ladybug.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
{{- /* Ladybug easter egg — home page only; hidden until “Alpha” is used (see ladybug.js) */ -}}
1+
{{- /* Ladybug easter egg — home page only; hidden until “Beta” is clicked (see ladybug.js) */ -}}
22
<div id="ladybug-container" class="ladybug-gate-hidden" aria-hidden="true" role="presentation">
33
<svg viewBox="0 0 100 100" width="100%" height="100%">
44
<!-- Legs: 3 pill segments / side (inspired by horizontal “elbow” stack); CSS animates .ladybug-leg-swing -->

static/css/ladybug.css

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
Ladybug Feature — Home Page Only
33
============================================================ */
44

5-
/* Gated: hidden until user clicks “Alpha” (home) */
5+
/* Gated: hidden until user clicks “Beta” (home) */
66
#ladybug-container.ladybug-gate-hidden,
77
#ladybug-particles-host.ladybug-gate-hidden,
88
#ladybug-message.ladybug-gate-hidden {
@@ -11,6 +11,41 @@
1111
pointer-events: none;
1212
}
1313

14+
/* Brief peek near the Beta tag before the user reveals the easter egg */
15+
#ladybug-container.ladybug-gate-hidden.ladybug-gate-teaser {
16+
visibility: visible;
17+
opacity: 1;
18+
pointer-events: none;
19+
}
20+
21+
#ladybug-container.ladybug-gate-teaser {
22+
transition: filter 0.25s ease, opacity 0.22s ease, visibility 0.22s ease;
23+
}
24+
25+
@keyframes ladybug-beta-teaser-bob {
26+
0%,
27+
100% { transform: translate3d(var(--ladybug-teaser-x, 0), var(--ladybug-teaser-y, 0), 0) rotate(178deg) scale(0.9); }
28+
50% { transform: translate3d(var(--ladybug-teaser-x, 0), calc(var(--ladybug-teaser-y, 0px) - 5px), 0) rotate(182deg) scale(0.96); }
29+
}
30+
31+
#ladybug-container.ladybug-gate-teaser.ladybug-beta-teaser-animate {
32+
animation: ladybug-beta-teaser-bob 0.55s ease-in-out 2;
33+
}
34+
35+
.site-beta-tag.site-beta-tag--teaser-hint {
36+
animation: ladybug-beta-tag-pulse 0.65s ease-in-out 2;
37+
}
38+
39+
@keyframes ladybug-beta-tag-pulse {
40+
0%,
41+
100% {
42+
box-shadow: 0 0 0 0 rgba(14, 165, 233, 0);
43+
}
44+
50% {
45+
box-shadow: 0 0 0 3px rgba(14, 165, 233, 0.35);
46+
}
47+
}
48+
1449
/* Bug container: fixed overlay, full-page movement space */
1550
#ladybug-container {
1651
position: fixed;

static/js/ladybug.js

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1300,9 +1300,93 @@
13001300
requestAnimationFrame(animateLoop);
13011301
}
13021302

1303-
// ---------- Reveal gate (home: hidden until “Alpha” is clicked) ----------
1303+
// ---------- Reveal gate (home: hidden until “Beta” is clicked) ----------
1304+
1305+
var BETA_TEASER_INTERVAL_MS = 120000; /* 2 minutes between peeks */
1306+
var BETA_TEASER_VISIBLE_MS = 1100;
1307+
var betaTeaserIntervalTimer = null;
1308+
var betaTeaserHideTimer = null;
1309+
1310+
function getBetaRevealButton() {
1311+
return document.getElementById('ladybug-reveal-beta');
1312+
}
1313+
1314+
function positionBugForBetaTeaser(betaEl) {
1315+
var r = betaEl.getBoundingClientRect();
1316+
if (r.width < 2 || r.height < 2) return false;
1317+
var tx = r.right - bugSize * 0.42;
1318+
var ty = r.top - bugSize * 0.12;
1319+
tx = clamp(tx, 4, window.innerWidth - bugSize - 4);
1320+
ty = clamp(ty, 4, window.innerHeight - bugSize - 4);
1321+
bug.style.setProperty('--ladybug-teaser-x', tx + 'px');
1322+
bug.style.setProperty('--ladybug-teaser-y', ty + 'px');
1323+
bug.style.transform = 'translate3d(' + tx + 'px, ' + ty + 'px, 0) rotate(180deg) scale(0.9)';
1324+
x = tx;
1325+
y = ty;
1326+
return true;
1327+
}
1328+
1329+
function stopBetaTeaserLoop() {
1330+
if (betaTeaserIntervalTimer) {
1331+
clearInterval(betaTeaserIntervalTimer);
1332+
betaTeaserIntervalTimer = null;
1333+
}
1334+
}
1335+
1336+
function cancelBetaTeaser() {
1337+
stopBetaTeaserLoop();
1338+
if (betaTeaserHideTimer) {
1339+
clearTimeout(betaTeaserHideTimer);
1340+
betaTeaserHideTimer = null;
1341+
}
1342+
bug.classList.remove('ladybug-gate-teaser', 'ladybug-beta-teaser-animate', 'ladybug-flying');
1343+
bug.style.removeProperty('--ladybug-teaser-x');
1344+
bug.style.removeProperty('--ladybug-teaser-y');
1345+
var betaBtn = getBetaRevealButton();
1346+
if (betaBtn) {
1347+
betaBtn.classList.remove('site-beta-tag--teaser-hint');
1348+
}
1349+
}
1350+
1351+
function endBetaTeaser() {
1352+
betaTeaserHideTimer = null;
1353+
if (!isLadybugGateHidden()) return;
1354+
bug.classList.remove('ladybug-gate-teaser', 'ladybug-beta-teaser-animate', 'ladybug-flying');
1355+
var betaBtn = getBetaRevealButton();
1356+
if (betaBtn) {
1357+
betaBtn.classList.remove('site-beta-tag--teaser-hint');
1358+
}
1359+
}
1360+
1361+
function runBetaTeaser() {
1362+
if (!isLadybugGateHidden()) return;
1363+
if (bug.classList.contains('ladybug-gate-teaser')) return;
1364+
var betaBtn = getBetaRevealButton();
1365+
if (!betaBtn) return;
1366+
if (!positionBugForBetaTeaser(betaBtn)) return;
1367+
1368+
bug.classList.add('ladybug-gate-teaser', 'ladybug-beta-teaser-animate', 'ladybug-flying');
1369+
betaBtn.classList.add('site-beta-tag--teaser-hint');
1370+
1371+
betaTeaserHideTimer = setTimeout(endBetaTeaser, BETA_TEASER_VISIBLE_MS);
1372+
}
1373+
1374+
function startBetaTeaserLoop() {
1375+
if (!getBetaRevealButton()) return;
1376+
if (window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
1377+
stopBetaTeaserLoop();
1378+
1379+
betaTeaserIntervalTimer = setInterval(function () {
1380+
if (!isLadybugGateHidden()) {
1381+
stopBetaTeaserLoop();
1382+
return;
1383+
}
1384+
runBetaTeaser();
1385+
}, BETA_TEASER_INTERVAL_MS);
1386+
}
13041387

13051388
function revealLadybugEasterEgg() {
1389+
cancelBetaTeaser();
13061390
if (!bug.classList.contains('ladybug-gate-hidden')) return;
13071391
if (particlesHost) particlesHost.classList.remove('ladybug-gate-hidden');
13081392
if (pill) pill.classList.remove('ladybug-gate-hidden');
@@ -1337,6 +1421,7 @@
13371421
lastScrollY = window.scrollY || window.pageYOffset || 0;
13381422
initH1BiteTarget();
13391423
bindLadybugRevealControl();
1424+
startBetaTeaserLoop();
13401425
requestAnimationFrame(animateLoop);
13411426
setTimeout(function () {
13421427
if (!isLadybugGateHidden() && isDarkTheme()) {

0 commit comments

Comments
 (0)