Files
poulinkes/public/main.js
2026-04-13 23:04:12 +02:00

279 lines
10 KiB
JavaScript

/* ═══════════════════════════════════════════════════════════════
POULINKES.COM — Sacred Chicken Interaction Engine v1.0.0
Warning: This file is watched by the Poulinkes.
They know what you are.
═══════════════════════════════════════════════════════════════ */
(function () {
'use strict';
// ─── FEATHER RAIN ────────────────────────────────────────────
const FEATHERS = ['🪶', '🪶', '🪶', '✨', '🥚'];
let featherInterval = null;
function spawnFeather() {
const el = document.createElement('div');
el.classList.add('feather');
el.textContent = FEATHERS[Math.floor(Math.random() * FEATHERS.length)];
el.style.left = Math.random() * 100 + 'vw';
el.style.animationDuration = (6 + Math.random() * 8) + 's';
el.style.fontSize = (0.8 + Math.random() * 1.2) + 'rem';
document.body.appendChild(el);
el.addEventListener('animationend', () => el.remove());
}
function startFeathers() {
spawnFeather();
featherInterval = setInterval(() => {
if (Math.random() < 0.7) spawnFeather();
}, 2200);
}
// ─── CLUCK SOUND (Web Audio API) ─────────────────────────────
function playCluck() {
try {
const ctx = new (window.AudioContext || window.webkitAudioContext)();
const times = [0, 0.07, 0.14];
times.forEach((t) => {
const osc = ctx.createOscillator();
const gain = ctx.createGain();
const dist = ctx.createWaveShaper();
// Distortion curve for that raw chicken rasp
const curve = new Float32Array(256);
for (let i = 0; i < 256; i++) {
const x = (i * 2) / 256 - 1;
curve[i] = ((Math.PI + 200) * x) / (Math.PI + 200 * Math.abs(x));
}
dist.curve = curve;
osc.connect(dist);
dist.connect(gain);
gain.connect(ctx.destination);
osc.type = 'sawtooth';
osc.frequency.setValueAtTime(700 - t * 500, ctx.currentTime + t);
osc.frequency.exponentialRampToValueAtTime(120, ctx.currentTime + t + 0.12);
gain.gain.setValueAtTime(0, ctx.currentTime + t);
gain.gain.linearRampToValueAtTime(0.25, ctx.currentTime + t + 0.01);
gain.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + t + 0.13);
osc.start(ctx.currentTime + t);
osc.stop(ctx.currentTime + t + 0.14);
});
// Close context after last note
setTimeout(() => ctx.close(), 600);
} catch (e) {
// Even in failure, the poulinkes forgive you
}
}
// ─── CLUCK BUTTON ────────────────────────────────────────────
function initCluckButton() {
const btn = document.getElementById('cluck-btn');
if (!btn) return;
btn.addEventListener('click', () => {
playCluck();
btn.classList.add('clucking');
btn.textContent = '🐔 B'CLUCK! 🐔';
setTimeout(() => {
btn.classList.remove('clucking');
btn.textContent = '🐔 TRIGGER THE CLUCK 🐔';
}, 800);
});
}
// ─── TOAST MESSAGE ────────────────────────────────────────────
function showToast(msg, duration = 4000) {
let toast = document.getElementById('cluck-toast');
if (!toast) {
toast = document.createElement('div');
toast.id = 'cluck-toast';
document.body.appendChild(toast);
}
toast.innerHTML = msg;
toast.classList.add('show');
clearTimeout(toast._timer);
toast._timer = setTimeout(() => toast.classList.remove('show'), duration);
}
// ─── CLUCK KEYBOARD DETECTOR ──────────────────────────────────
let cluckBuffer = '';
const CLUCK_MESSAGES = [
'🥚 <strong>YOU KNOW THE WORD.</strong><br><small>They are already watching.</small>',
'🐔 The poulinkes acknowledge your presence.<br><small>They have always known.</small>',
'🪶 Interesting that you knew this word.<br><small>Almost as if... you were one of them.</small>',
'🥚 C-L-U-C-K.<br><small>The ancient greeting. You remembered.</small>',
'🐔 <strong>CLUCK ACCEPTED.</strong><br><small>Your DNA has been logged.</small>',
];
let cluckMsgIndex = 0;
function initCluckDetector() {
document.addEventListener('keydown', (e) => {
cluckBuffer += e.key.toLowerCase();
if (cluckBuffer.length > 8) cluckBuffer = cluckBuffer.slice(-8);
if (cluckBuffer.includes('cluck')) {
cluckBuffer = '';
playCluck();
setTimeout(playCluck, 200);
showToast(CLUCK_MESSAGES[cluckMsgIndex % CLUCK_MESSAGES.length], 5000);
cluckMsgIndex++;
}
});
}
// ─── KONAMI CODE → CHICKEN OVERLORD MODE ─────────────────────
const KONAMI = [
'ArrowUp','ArrowUp','ArrowDown','ArrowDown',
'ArrowLeft','ArrowRight','ArrowLeft','ArrowRight',
'b','a'
];
let konamiIndex = 0;
function initKonami() {
document.addEventListener('keydown', (e) => {
if (e.key === KONAMI[konamiIndex]) {
konamiIndex++;
if (konamiIndex === KONAMI.length) {
konamiIndex = 0;
activateOverlordMode();
}
} else {
konamiIndex = e.key === KONAMI[0] ? 1 : 0;
}
});
}
function activateOverlordMode() {
let overlay = document.getElementById('overlord-overlay');
if (!overlay) {
overlay = document.createElement('div');
overlay.id = 'overlord-overlay';
overlay.innerHTML = `
<div class="overlord-chicken">🐔</div>
<div class="overlord-text">CHICKEN OVERLORD MODE</div>
<div class="overlord-sub">
You have awakened the Ancient Protocol.<br>
The poulinkes did not give you this code.<br>
<em>You always had it. Think about that.</em><br><br>
The eggs are watching. They have always been watching.
</div>
<button class="overlord-close" onclick="document.getElementById('overlord-overlay').classList.remove('active')">
[ I SUBMIT TO THE FLOCK ]
</button>
`;
document.body.appendChild(overlay);
}
overlay.classList.add('active');
// Sound assault
for (let i = 0; i < 5; i++) {
setTimeout(playCluck, i * 120);
}
// Feather burst
for (let i = 0; i < 20; i++) {
setTimeout(spawnFeather, i * 80);
}
}
// ─── EGG PERSPECTIVE (random flip) ───────────────────────────
function initEggPerspective() {
// 12% chance on load after 4s
setTimeout(() => {
if (Math.random() < 0.12) triggerEggPerspective();
}, 4000);
// Periodic check every 45s
setInterval(() => {
if (Math.random() < 0.05) triggerEggPerspective();
}, 45000);
}
function triggerEggPerspective() {
if (document.body.classList.contains('egg-perspective')) return;
showToast('🥚 <strong>EGG PERSPECTIVE ACTIVATED</strong><br><small>This is how they see us.</small>', 3000);
document.body.classList.add('egg-perspective');
setTimeout(() => document.body.classList.remove('egg-perspective'), 2600);
}
// ─── JOIN FORM ────────────────────────────────────────────────
function initJoinForm() {
const form = document.getElementById('join-form');
if (!form) return;
form.addEventListener('submit', (e) => {
e.preventDefault();
const container = document.getElementById('join-form-container');
const success = document.getElementById('join-success');
if (container) container.style.display = 'none';
if (success) success.style.display = 'block';
// Celebration
for (let i = 0; i < 15; i++) setTimeout(spawnFeather, i * 100);
for (let i = 0; i < 3; i++) setTimeout(playCluck, i * 200);
});
}
// ─── STAT BAR WIDTHS ─────────────────────────────────────────
function initStatBars() {
document.querySelectorAll('.stat-fill[data-value]').forEach(bar => {
const val = parseInt(bar.dataset.value, 10);
bar.style.width = val + '%';
});
}
// ─── CONSPIRACY CARD ROTATIONS ────────────────────────────────
function initConspiracyRotations() {
document.querySelectorAll('.conspiracy-article').forEach(article => {
const rot = (Math.random() * 6 - 3).toFixed(1);
article.style.setProperty('--rot', rot + 'deg');
});
}
// ─── ARE YOU A POULINKE? (subtle hint on scroll) ──────────────
let hintShown = false;
function initPoulinkeHint() {
window.addEventListener('scroll', () => {
if (hintShown) return;
const scrolled = window.scrollY / (document.body.scrollHeight - window.innerHeight);
if (scrolled > 0.75) {
hintShown = true;
setTimeout(() => {
showToast(
'🪶 <strong>A THOUGHT.</strong><br><small>Why do you feel so at home here?</small>',
6000
);
}, 1500);
}
}, { passive: true });
}
// ─── INIT ALL ─────────────────────────────────────────────────
document.addEventListener('DOMContentLoaded', () => {
startFeathers();
initCluckButton();
initCluckDetector();
initKonami();
initEggPerspective();
initJoinForm();
initStatBars();
initConspiracyRotations();
initPoulinkeHint();
// Secret: right-clicking a chicken emoji shows a message
document.querySelectorAll('[data-secret-chicken]').forEach(el => {
el.addEventListener('contextmenu', (e) => {
e.preventDefault();
showToast('🐔 <strong>DO NOT STARE INTO THE POULINKE.</strong><br><small>It is already too late.</small>', 5000);
});
});
});
})();