feather.replace(); // Particles const particlesContainer = document.getElementById('particles'); for (let i = 0; i < 30; i++) { const particle = document.createElement('div'); particle.classList.add('particle'); particle.style.left = Math.random() * 100 + '%'; particle.style.animationDelay = Math.random() * 10 + 's'; particle.style.animationDuration = (Math.random() * 5 + 8) + 's'; particle.style.width = (Math.random() * 4 + 2) + 'px'; particle.style.height = particle.style.width; particlesContainer.appendChild(particle); } // Easter Egg: Konami Code (desktop) ou 10 taps (mobile) const konamiCode = ['ArrowUp', 'ArrowUp', 'ArrowDown', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowLeft', 'ArrowRight', 'b', 'a']; let konamiIndex = 0; let tapCount = 0; let tapTimer = null; const REQUIRED_TAPS = 10; const errorCodeEl = document.querySelector('.error-code'); // Desktop: Konami Code document.addEventListener('keydown', (e) => { if (e.key === konamiCode[konamiIndex]) { konamiIndex++; if (konamiIndex === konamiCode.length) { startPortalTransition(); konamiIndex = 0; } } else { konamiIndex = 0; } }); // Mobile: 10 taps function handleTap(e) { if (e.type === 'touchend') e.preventDefault(); tapCount++; errorCodeEl.style.transform = 'scale(0.95)'; setTimeout(() => errorCodeEl.style.transform = '', 100); if (tapCount >= 3 && tapCount < REQUIRED_TAPS) { showTapCounter(tapCount, REQUIRED_TAPS); } if (tapTimer) clearTimeout(tapTimer); tapTimer = setTimeout(() => { tapCount = 0; hideTapCounter(); }, 500); if (tapCount >= REQUIRED_TAPS) { tapCount = 0; hideTapCounter(); startPortalTransition(); } } function showTapCounter(current, total) { let counter = document.getElementById('tap-counter'); if (!counter) { counter = document.createElement('div'); counter.id = 'tap-counter'; counter.style.cssText = 'position:fixed;top:20px;left:50%;transform:translateX(-50%);background:rgba(139,58,98,0.9);color:white;padding:0.5rem 1rem;border-radius:20px;font-size:0.85rem;font-weight:600;z-index:1000;'; document.body.appendChild(counter); } counter.textContent = current + ' / ' + total + ' 🔓'; } function hideTapCounter() { const counter = document.getElementById('tap-counter'); if (counter) counter.remove(); } errorCodeEl.addEventListener('click', handleTap); errorCodeEl.addEventListener('touchend', handleTap); // Portal Transition function startPortalTransition() { const transition = document.createElement('div'); transition.id = 'portal-transition'; transition.innerHTML = '
ENTRÉE DANS LA MATRICE
'; document.body.appendChild(transition); const style = document.createElement('style'); style.id = 'transition-styles'; style.textContent = '#portal-transition{position:fixed;inset:0;z-index:10000;background:#000;display:flex;align-items:center;justify-content:center;overflow:hidden}.warp-container{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;perspective:500px}.warp-tunnel{position:absolute;width:200vmax;height:200vmax;background:repeating-conic-gradient(from 0deg,transparent 0deg 10deg,rgba(139,58,98,0.1) 10deg 20deg);animation:tunnelSpin 2s linear infinite,tunnelZoom 3s ease-in forwards}@keyframes tunnelSpin{to{transform:rotate(360deg)}}@keyframes tunnelZoom{0%{transform:rotate(0)scale(1);opacity:0}20%{opacity:1}100%{transform:rotate(720deg)scale(20);opacity:0}}.warp-stars{position:absolute;inset:0;background-image:radial-gradient(2px 2px at 20px 30px,#fff,transparent),radial-gradient(2px 2px at 40px 70px,rgba(255,255,255,0.8),transparent),radial-gradient(1px 1px at 90px 40px,#fff,transparent);background-size:350px 200px;animation:starsWarp 3s ease-in forwards}@keyframes starsWarp{0%{transform:scale(1);opacity:0}30%{opacity:1}100%{transform:scale(50);opacity:0}}.warp-center{position:relative;width:150px;height:150px;animation:centerPulse 0.5s ease-in-out infinite,centerGrow 2.5s ease-in forwards}@keyframes centerPulse{0%,100%{filter:brightness(1)}50%{filter:brightness(1.5)}}@keyframes centerGrow{0%{transform:scale(0);opacity:0}20%{transform:scale(1);opacity:1}80%{transform:scale(1);opacity:1}100%{transform:scale(100);opacity:1}}.warp-ring{position:absolute;inset:0;border:4px solid #8b3a62;border-radius:50%;animation:ringPulse 1s ease-in-out infinite;box-shadow:0 0 30px #8b3a62,inset 0 0 30px #8b3a62}.warp-ring:nth-child(2){inset:20px;border-color:#5e2a8b;animation-delay:0.2s;box-shadow:0 0 30px #5e2a8b,inset 0 0 30px #5e2a8b}.warp-ring:nth-child(3){inset:40px;border-color:#d4a5c9;animation-delay:0.4s;box-shadow:0 0 30px #d4a5c9,inset 0 0 30px #d4a5c9}@keyframes ringPulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.1);opacity:0.8}}.warp-flash{position:absolute;inset:0;background:#fff;opacity:0;animation:flashBang 0.5s ease-out 2.5s forwards}@keyframes flashBang{0%{opacity:0}50%{opacity:1}100%{opacity:0}}.warp-text{position:absolute;font-size:1.5rem;font-weight:700;color:#fff;letter-spacing:0.3rem;z-index:10;opacity:0;animation:textAppear 0.5s ease 0.5s forwards,textFade 0.5s ease 2s forwards}@keyframes textAppear{to{opacity:1}}@keyframes textFade{to{opacity:0;transform:scale(2)}}'; document.head.appendChild(style); setTimeout(() => { transition.remove(); style.remove(); launchGameOfLife(); }, 3000); } // Game of Life function launchGameOfLife() { const gameContainer = document.createElement('div'); gameContainer.id = 'game-of-life'; gameContainer.innerHTML = '

🧬 Dimension Secrète

Le Jeu de la Vie de Conway

Règles : Cellule vivante avec 2-3 voisins survit. Cellule morte avec 3 voisins naît.

30px
0
0
0×0
'; document.body.appendChild(gameContainer); const gameStyles = document.createElement('style'); gameStyles.id = 'gol-styles'; gameStyles.textContent = '#game-of-life{position:fixed;inset:0;z-index:10000;background:#050508;animation:golIn 0.5s ease}@keyframes golIn{from{opacity:0}to{opacity:1}}#gol-canvas{position:absolute;inset:0;width:100%;height:100%;cursor:crosshair}.gol-ui{position:absolute;top:20px;left:20px;background:rgba(10,10,15,0.95);backdrop-filter:blur(10px);border:1px solid rgba(139,58,98,0.3);border-radius:16px;padding:1rem;min-width:280px;box-shadow:0 20px 60px rgba(0,0,0,0.5)}.gol-header{display:flex;align-items:center;justify-content:space-between;margin-bottom:0.75rem}.gol-header-text h1{font-size:1.1rem;margin-bottom:0.1rem;background:linear-gradient(135deg,#d4a5c9,#8b3a62);-webkit-background-clip:text;-webkit-text-fill-color:transparent}.gol-header-text p{font-size:0.7rem;color:#6b6b7b}.gol-minimize{width:32px;height:32px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.05);border-radius:8px;color:#b8b8c8;cursor:pointer;display:flex;align-items:center;justify-content:center}.gol-minimize:hover{background:rgba(139,58,98,0.3);border-color:#8b3a62;color:#fff}.gol-minimize svg{width:16px;height:16px}.gol-minimize .icon-max{display:none}.gol-ui.minimized .gol-body,.gol-ui.minimized .gol-exit{display:none}.gol-ui.minimized .gol-minimize .icon-min{display:none}.gol-ui.minimized .gol-minimize .icon-max{display:block}.gol-ui.minimized{min-width:auto}.gol-body{display:flex;flex-direction:column;gap:0.75rem}.gol-description{background:rgba(139,58,98,0.1);border:1px solid rgba(139,58,98,0.2);border-radius:8px;padding:0.5rem}.gol-description p{font-size:0.7rem;color:#b8b8c8;margin:0}.gol-description strong{color:#d4a5c9}.gol-controls{display:flex;gap:0.4rem;flex-wrap:wrap}.gol-btn{width:40px;height:40px;border:1px solid rgba(255,255,255,0.1);background:rgba(255,255,255,0.05);border-radius:8px;color:#b8b8c8;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all 0.2s}.gol-btn:hover{background:rgba(139,58,98,0.3);border-color:#8b3a62;color:#fff;transform:translateY(-2px)}.gol-btn svg{width:18px;height:18px}.gol-btn.active{background:linear-gradient(135deg,#8b3a62,#5e2a8b);border-color:transparent;color:#fff}.gol-btn .icon-play{display:none}.gol-btn .icon-pause{display:block}.gol-btn:not(.active) .icon-play{display:block}.gol-btn:not(.active) .icon-pause{display:none}.gol-btn-sm{width:32px;height:32px;font-size:1.2rem;font-weight:bold}.gol-zoom-row,.gol-speed-row{display:flex;align-items:center;gap:0.5rem}.gol-zoom-row span{color:#d4a5c9;font-family:monospace;font-size:0.85rem;min-width:40px;text-align:center}.gol-speed-row{flex-direction:column;align-items:stretch}.gol-speed-row label{font-size:0.75rem;color:#b8b8c8}.gol-speed-row label span{color:#d4a5c9;font-family:monospace}.gol-speed-row input{width:100%;height:6px;-webkit-appearance:none;background:rgba(255,255,255,0.1);border-radius:3px;cursor:pointer}.gol-speed-row input::-webkit-slider-thumb{-webkit-appearance:none;width:16px;height:16px;background:linear-gradient(135deg,#8b3a62,#5e2a8b);border-radius:50%;cursor:pointer}.gol-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:0.5rem}.gol-stat{text-align:center;padding:0.4rem;background:rgba(255,255,255,0.03);border-radius:6px}.gol-stat span{font-size:1rem;font-weight:700;color:#d4a5c9;font-family:monospace;display:block}.gol-stat label{font-size:0.6rem;color:#6b6b7b;text-transform:uppercase}.gol-exit{width:100%;margin-top:0.5rem;padding:0.6rem;background:transparent;border:1px solid rgba(255,255,255,0.1);border-radius:8px;color:#6b6b7b;font-size:0.8rem;cursor:pointer;transition:all 0.2s}.gol-exit:hover{background:rgba(255,50,50,0.2);border-color:rgba(255,50,50,0.5);color:#ff6b6b}@media(max-width:768px){.gol-ui{top:auto;bottom:0;left:0;right:0;border-radius:16px 16px 0 0;max-height:50vh;overflow-y:auto;min-width:auto}.gol-header-text p,.gol-description{display:none}.gol-ui.minimized{max-height:none}}@media(max-width:480px){.gol-ui{padding:0.75rem}.gol-btn{width:36px;height:36px}.gol-btn-sm{width:28px;height:28px}}'; document.head.appendChild(gameStyles); const canvas = document.getElementById('gol-canvas'); const ctx = canvas.getContext('2d'); const MAX_CELLS = 150, MIN_SIZE = 4, MAX_SIZE = 30; let cellSize = MAX_SIZE, minCellSize = MIN_SIZE, cols, rows, grid, nextGrid; let isRunning = true, generation = 0, speed = 15, lastTime = 0, isDrawing = false, drawValue = 1; function initCanvas() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; minCellSize = Math.max(MIN_SIZE, Math.ceil(canvas.width / MAX_CELLS), Math.ceil(canvas.height / MAX_CELLS)); cellSize = Math.max(minCellSize, Math.min(MAX_SIZE, cellSize)); cols = Math.ceil(canvas.width / cellSize); rows = Math.ceil(canvas.height / cellSize); grid = Array(cols).fill(null).map(() => Array(rows).fill(0)); nextGrid = Array(cols).fill(null).map(() => Array(rows).fill(0)); updateUI(); } function addGlider(sx, sy, dir) { const p = [[[0,1],[1,2],[2,0],[2,1],[2,2]],[[0,1],[1,0],[2,0],[2,1],[2,2]],[[0,0],[0,1],[0,2],[1,2],[2,1]],[[0,0],[0,1],[0,2],[1,0],[2,1]]]; p[dir % 4].forEach(([dx, dy]) => { const x = (sx + dx) % cols, y = (sy + dy) % rows; if (x >= 0 && x < cols && y >= 0 && y < rows) grid[x][y] = 1; }); } function addGliders(n) { grid = Array(cols).fill(null).map(() => Array(rows).fill(0)); for (let i = 0; i < n; i++) addGlider(Math.floor(Math.random() * (cols - 10)) + 5, Math.floor(Math.random() * (rows - 10)) + 5, Math.floor(Math.random() * 4)); generation = 0; updateUI(); } function randomize() { for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) grid[x][y] = Math.random() > 0.7 ? 1 : 0; generation = 0; updateUI(); } function clear() { for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) grid[x][y] = 0; generation = 0; updateUI(); } function step() { for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) { let n = 0; for (let i = -1; i <= 1; i++) for (let j = -1; j <= 1; j++) if (i || j) n += grid[(x + i + cols) % cols][(y + j + rows) % rows]; nextGrid[x][y] = grid[x][y] ? (n === 2 || n === 3 ? 1 : 0) : (n === 3 ? 1 : 0); } [grid, nextGrid] = [nextGrid, grid]; generation++; updateUI(); } function draw() { ctx.fillStyle = '#0a0a0f'; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.strokeStyle = 'rgba(139,58,98,0.1)'; ctx.lineWidth = 0.5; for (let x = 0; x <= cols * cellSize; x += cellSize) { ctx.beginPath(); ctx.moveTo(x, 0); ctx.lineTo(x, rows * cellSize); ctx.stroke(); } for (let y = 0; y <= rows * cellSize; y += cellSize) { ctx.beginPath(); ctx.moveTo(0, y); ctx.lineTo(cols * cellSize, y); ctx.stroke(); } ctx.shadowColor = 'rgba(139,58,98,0.5)'; ctx.shadowBlur = 8; for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) if (grid[x][y]) { const g = ctx.createRadialGradient(x * cellSize + cellSize / 2, y * cellSize + cellSize / 2, 0, x * cellSize + cellSize / 2, y * cellSize + cellSize / 2, cellSize); g.addColorStop(0, '#d4a5c9'); g.addColorStop(0.5, '#8b3a62'); g.addColorStop(1, '#5e2a8b'); ctx.fillStyle = g; ctx.fillRect(x * cellSize + 1, y * cellSize + 1, cellSize - 2, cellSize - 2); } ctx.shadowBlur = 0; } function updateUI() { let pop = 0; for (let x = 0; x < cols; x++) for (let y = 0; y < rows; y++) pop += grid[x][y]; document.getElementById('gol-gen').textContent = generation; document.getElementById('gol-pop').textContent = pop; document.getElementById('gol-dim').textContent = cols + '×' + rows; document.getElementById('gol-zoom-val').textContent = cellSize + 'px'; document.getElementById('gol-speed-val').textContent = speed; } function handleZoom(d) { const old = cellSize; cellSize = Math.max(minCellSize, Math.min(MAX_SIZE, cellSize + d)); if (cellSize !== old) { const og = grid, oc = cols, or = rows; initCanvas(); for (let x = 0; x < Math.min(oc, cols); x++) for (let y = 0; y < Math.min(or, rows); y++) grid[x][y] = og[x][y]; updateUI(); } } function getCell(e) { const r = canvas.getBoundingClientRect(), cx = e.touches ? e.touches[0].clientX : e.clientX, cy = e.touches ? e.touches[0].clientY : e.clientY; return { x: Math.max(0, Math.min(cols - 1, Math.floor((cx - r.left) / cellSize))), y: Math.max(0, Math.min(rows - 1, Math.floor((cy - r.top) / cellSize))) }; } function gameLoop(t) { if (isRunning && t - lastTime > 1000 / speed) { step(); lastTime = t; } draw(); requestAnimationFrame(gameLoop); } canvas.addEventListener('mousedown', e => { isDrawing = true; const c = getCell(e); drawValue = grid[c.x][c.y] ? 0 : 1; grid[c.x][c.y] = drawValue; }); canvas.addEventListener('mousemove', e => { if (isDrawing) { const c = getCell(e); grid[c.x][c.y] = drawValue; } }); canvas.addEventListener('mouseup', () => isDrawing = false); canvas.addEventListener('mouseleave', () => isDrawing = false); canvas.addEventListener('touchstart', e => { e.preventDefault(); isDrawing = true; const c = getCell(e); drawValue = grid[c.x][c.y] ? 0 : 1; grid[c.x][c.y] = drawValue; }, { passive: false }); canvas.addEventListener('touchmove', e => { e.preventDefault(); if (isDrawing) { const c = getCell(e); grid[c.x][c.y] = drawValue; } }, { passive: false }); canvas.addEventListener('touchend', () => isDrawing = false); canvas.addEventListener('wheel', e => { e.preventDefault(); handleZoom(e.deltaY > 0 ? -1 : 1); }); document.getElementById('gol-play').addEventListener('click', function() { isRunning = !isRunning; this.classList.toggle('active', isRunning); }); document.getElementById('gol-step').addEventListener('click', () => { if (!isRunning) step(); }); document.getElementById('gol-random').addEventListener('click', randomize); document.getElementById('gol-clear').addEventListener('click', clear); document.getElementById('gol-gliders').addEventListener('click', () => addGliders(3)); document.getElementById('gol-zoom-in').addEventListener('click', () => handleZoom(2)); document.getElementById('gol-zoom-out').addEventListener('click', () => handleZoom(-2)); document.getElementById('gol-speed').addEventListener('input', function() { speed = parseInt(this.value); updateUI(); }); document.getElementById('gol-minimize').addEventListener('click', () => document.querySelector('.gol-ui').classList.toggle('minimized')); document.getElementById('gol-exit').addEventListener('click', () => { document.getElementById('game-of-life').remove(); document.getElementById('gol-styles').remove(); }); window.addEventListener('resize', () => { const og = grid, oc = cols, or = rows; initCanvas(); for (let x = 0; x < Math.min(oc, cols); x++) for (let y = 0; y < Math.min(or, rows); y++) grid[x][y] = og[x][y]; updateUI(); }); initCanvas(); addGliders(3); requestAnimationFrame(gameLoop); }