@joaobarrosfranca · 8/12/2026, 7:12:08 AM
Versão inicial — todas as linhas são novas.
+<!DOCTYPE html>+<html lang="en">+<head>+ <meta charset="UTF-8">+ <meta name="viewport" content="width=device-width, initial-scale=1.0">+ <title>Signal Hunt</title>+ <style>+ * { box-sizing: border-box; }+ html, body {+ width: 100%;+ height: 100%;+ margin: 0;+ padding: 0;+ overflow: hidden;+ background: linear-gradient(135deg, #FFF8F0 0%, #FFEBD8 100%);+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;+ }++ .container {+ display: flex;+ flex-direction: column;+ width: 100%;+ height: 100%;+ padding: 16px;+ gap: 12px;+ }++ .header {+ display: flex;+ justify-content: space-between;+ align-items: center;+ padding: 0 8px;+ font-size: 14px;+ font-weight: 600;+ color: #5a3a5a;+ }++ .stat {+ display: flex;+ flex-direction: column;+ align-items: center;+ gap: 2px;+ }++ .stat-label {+ font-size: 12px;+ opacity: 0.7;+ text-transform: uppercase;+ letter-spacing: 0.5px;+ }++ .stat-value {+ font-size: 20px;+ font-weight: 700;+ color: #d97b3a;+ }++ .timer-ring {+ position: relative;+ width: 60px;+ height: 60px;+ display: flex;+ align-items: center;+ justify-content: center;+ }++ .timer-svg {+ position: absolute;+ width: 100%;+ height: 100%;+ transform: rotate(-90deg);+ }++ .timer-circle-bg {+ fill: none;+ stroke: #f0d9cc;+ stroke-width: 4;+ }++ .timer-circle-fg {+ fill: none;+ stroke: #d97b3a;+ stroke-width: 4;+ stroke-linecap: round;+ transition: stroke-dashoffset 0.05s linear;+ }++ .timer-text {+ position: relative;+ font-size: 18px;+ font-weight: 700;+ color: #5a3a5a;+ }++ .game-area {+ flex: 1;+ display: flex;+ align-items: center;+ justify-content: center;+ min-height: 0;+ }++ .grid {+ display: grid;+ grid-template-columns: repeat(4, 1fr);+ gap: 8px;+ aspect-ratio: 1;+ width: 100%;+ max-width: 320px;+ }++ .cell {+ aspect-ratio: 1;+ border: none;+ border-radius: 16px;+ font-size: 48px;+ display: flex;+ align-items: center;+ justify-content: center;+ cursor: pointer;+ background: white;+ box-shadow: 0 4px 12px rgba(90, 58, 90, 0.12);+ transition: all 0.15s cubic-bezier(0.34, 1.56, 0.64, 1);+ user-select: none;+ -webkit-user-select: none;+ -webkit-tap-highlight-color: transparent;+ }++ .cell:active {+ transform: scale(0.92);+ }++ .cell.correct {+ animation: correctPulse 0.4s ease-out;+ }++ .cell.wrong {+ animation: wrongShake 0.4s ease-out;+ }++ @keyframes correctPulse {+ 0% { transform: scale(1); background: white; }+ 50% { transform: scale(1.08); background: #d4f4dd; box-shadow: 0 8px 24px rgba(76, 175, 80, 0.4); }+ 100% { transform: scale(1); background: white; }+ }++ @keyframes wrongShake {+ 0%, 100% { transform: translateX(0); }+ 25% { transform: translateX(-8px); }+ 75% { transform: translateX(8px); }+ }++ .footer {+ display: flex;+ gap: 8px;+ justify-content: center;+ padding: 8px 0;+ }++ .btn {+ padding: 12px 24px;+ border: none;+ border-radius: 12px;+ font-size: 16px;+ font-weight: 600;+ cursor: pointer;+ transition: all 0.2s ease;+ user-select: none;+ -webkit-user-select: none;+ -webkit-tap-highlight-color: transparent;+ }++ .btn-replay {+ background: linear-gradient(135deg, #d97b3a 0%, #e8965a 100%);+ color: white;+ padding: 14px 32px;+ font-size: 17px;+ box-shadow: 0 4px 12px rgba(217, 123, 58, 0.3);+ }++ .btn-replay:active {+ transform: scale(0.96);+ box-shadow: 0 2px 6px rgba(217, 123, 58, 0.3);+ }++ .modal {+ display: none;+ position: fixed;+ top: 0;+ left: 0;+ right: 0;+ bottom: 0;+ background: rgba(0, 0, 0, 0.5);+ z-index: 1000;+ align-items: center;+ justify-content: center;+ padding: 16px;+ }++ .modal.active {+ display: flex;+ }++ .modal-content {+ background: linear-gradient(135deg, #FFF8F0 0%, #FFEBD8 100%);+ border-radius: 24px;+ padding: 40px 32px;+ text-align: center;+ box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);+ max-width: 320px;+ }++ .modal-title {+ font-size: 28px;+ font-weight: 700;+ color: #5a3a5a;+ margin: 0 0 8px 0;+ }++ .modal-subtitle {+ font-size: 14px;+ color: #8b5a8b;+ margin: 0 0 24px 0;+ opacity: 0.8;+ }++ .modal-stats {+ display: flex;+ flex-direction: column;+ gap: 16px;+ margin-bottom: 32px;+ }++ .modal-stat-item {+ display: flex;+ flex-direction: column;+ gap: 4px;+ }++ .modal-stat-label {+ font-size: 12px;+ text-transform: uppercase;+ letter-spacing: 0.5px;+ color: #8b5a8b;+ font-weight: 600;+ }++ .modal-stat-value {+ font-size: 36px;+ font-weight: 700;+ color: #d97b3a;+ }++ .share-prompt {+ font-size: 13px;+ color: #5a3a5a;+ margin-bottom: 24px;+ line-height: 1.4;+ }+ </style>+</head>+<body>+ <div class="container">+ <div class="header">+ <div class="stat">+ <div class="stat-label">Score</div>+ <div class="stat-value" id="scoreDisplay">0</div>+ </div>+ <div class="timer-ring">+ <svg class="timer-svg" viewBox="0 0 60 60">+ <circle class="timer-circle-bg" cx="30" cy="30" r="26"></circle>+ <circle class="timer-circle-fg" id="timerCircle" cx="30" cy="30" r="26"+ style="stroke-dasharray: 163.36; stroke-dashoffset: 0;"></circle>+ </svg>+ <div class="timer-text" id="timerText">10</div>+ </div>+ <div class="stat">+ <div class="stat-label">Streak</div>+ <div class="stat-value" id="streakDisplay">0</div>+ </div>+ </div>++ <div class="game-area">+ <div class="grid" id="grid"></div>+ </div>++ <div class="footer">+ <button class="btn btn-replay" id="replayBtn">Play Again</button>+ </div>+ </div>++ <div class="modal" id="gameOverModal">+ <div class="modal-content">+ <div class="modal-title" id="modalTitle">Game Over!</div>+ <div class="modal-subtitle">Final Results</div>+ <div class="modal-stats">+ <div class="modal-stat-item">+ <div class="modal-stat-label">Final Score</div>+ <div class="modal-stat-value" id="modalScore">0</div>+ </div>+ <div class="modal-stat-item">+ <div class="modal-stat-label">Best Streak</div>+ <div class="modal-stat-value" id="modalStreak">0</div>+ </div>+ </div>+ <div class="share-prompt">Tap "Play Again" for another round! 🎯</div>+ <button class="btn btn-replay" id="modalReplayBtn">Play Again</button>+ </div>+ </div>++ <script>+ // Symbols for the grid+ const SYMBOLS = ['🎯', '⭐', '🔥', '💎', '🎪', '🌙', '⚡', '🎨'];++ // Game state+ let gameState = {+ score: 0,+ streak: 0,+ maxStreak: 0,+ timeLeft: 10,+ gameActive: true,+ board: null,+ targetIndex: null,+ answered: false,+ };++ let timerInterval = null;+ let audioCtx = null;++ // Initialize grid+ const gridEl = document.getElementById('grid');+ const replayBtn = document.getElementById('replayBtn');+ const modalReplayBtn = document.getElementById('modalReplayBtn');+ const gameOverModal = document.getElementById('gameOverModal');++ function generateBoard() {+ const mainSymbol = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)];+ let oddSymbol = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)];+ while (oddSymbol === mainSymbol) {+ oddSymbol = SYMBOLS[Math.floor(Math.random() * SYMBOLS.length)];+ }++ const targetIndex = Math.floor(Math.random() * 16);+ const board = Array(16).fill(mainSymbol);+ board[targetIndex] = oddSymbol;++ return { board, targetIndex, mainSymbol, oddSymbol };+ }++ function renderBoard() {+ gridEl.innerHTML = '';+ gameState.board.board.forEach((symbol, index) => {+ const cell = document.createElement('button');+ cell.className = 'cell';+ cell.textContent = symbol;+ cell.addEventListener('click', () => handleCellClick(index));+ gridEl.appendChild(cell);+ });+ }++ function handleCellClick(index) {+ if (!gameState.gameActive || gameState.answered) return;++ gameState.answered = true;+ const cell = document.querySelector('.grid').children[index];++ if (index === gameState.board.targetIndex) {+ // Correct!+ playSound(800, 200, 0.3);+ cell.classList.add('correct');+ gameState.score += 10;+ gameState.streak += 1;+ gameState.maxStreak = Math.max(gameState.maxStreak, gameState.streak);+ } else {+ // Wrong!+ playSound(300, 300, 0.2);+ cell.classList.add('wrong');+ gameState.streak = 0;+ }++ updateDisplay();+ setTimeout(nextRound, 500);+ }++ function nextRound() {+ if (!gameState.gameActive) return;+ gameState.board = generateBoard();+ gameState.answered = false;+ renderBoard();+ }++ function updateDisplay() {+ document.getElementById('scoreDisplay').textContent = gameState.score;+ document.getElementById('streakDisplay').textContent = gameState.streak;+ }++ function startTimer() {+ gameState.timeLeft = 10;+ if (timerInterval) clearInterval(timerInterval);++ updateTimerDisplay();+ timerInterval = setInterval(() => {+ gameState.timeLeft -= 0.1;+ updateTimerDisplay();++ if (gameState.timeLeft <= 0) {+ endGame();+ }+ }, 100);+ }++ function updateTimerDisplay() {+ const displayTime = Math.max(0, Math.ceil(gameState.timeLeft));+ document.getElementById('timerText').textContent = displayTime;++ const circumference = 2 * Math.PI * 26;+ const offset = circumference * (1 - gameState.timeLeft / 10);+ document.getElementById('timerCircle').style.strokeDashoffset = offset;+ }++ function endGame() {+ gameState.gameActive = false;+ if (timerInterval) clearInterval(timerInterval);++ // Show modal after a brief delay+ setTimeout(() => {+ document.getElementById('modalScore').textContent = gameState.score;+ document.getElementById('modalStreak').textContent = gameState.maxStreak;+ gameOverModal.classList.add('active');+ }, 200);+ }++ function resetGame() {+ gameState.score = 0;+ gameState.streak = 0;+ gameState.maxStreak = 0;+ gameState.timeLeft = 10;+ gameState.gameActive = true;+ gameState.answered = false;+ gameOverModal.classList.remove('active');+ updateDisplay();+ gameState.board = generateBoard();+ renderBoard();+ startTimer();+ }++ function playSound(freq, duration, volume) {+ try {+ if (!audioCtx) {+ audioCtx = new (window.AudioContext || window.webkitAudioContext)();+ }+ if (audioCtx.state === 'suspended') audioCtx.resume();++ const now = audioCtx.currentTime;+ const osc = audioCtx.createOscillator();+ const gain = audioCtx.createGain();++ osc.connect(gain);+ gain.connect(audioCtx.destination);++ osc.frequency.value = freq;+ osc.type = 'sine';++ gain.gain.setValueAtTime(volume, now);+ gain.gain.exponentialRampToValueAtTime(0.01, now + duration / 1000);++ osc.start(now);+ osc.stop(now + duration / 1000);+ } catch (e) {+ // Audio unavailable+ }+ }++ // Event listeners+ replayBtn.addEventListener('click', resetGame);+ modalReplayBtn.addEventListener('click', resetGame);++ // Visibility handling+ if (window.liveloop && window.liveloop.onVisibility) {+ window.liveloop.onVisibility(function(visible) {+ if (!visible && timerInterval) {+ clearInterval(timerInterval);+ } else if (visible && gameState.gameActive) {+ startTimer();+ }+ });+ }++ // Start the game+ resetGame();+ </script>+</body>+</html>