joshua / index.html
Joshua353's picture
Add 3 files
8fad19f verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Tic-Tac-Toe Ultimate Edition</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes fadeIn {
from { opacity: 0; transform: scale(0.8); }
to { opacity: 1; transform: scale(1); }
}
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.1); }
100% { transform: scale(1); }
}
@keyframes flash {
0% { opacity: 0.3; }
50% { opacity: 1; }
100% { opacity: 0.3; }
}
@keyframes highlight {
0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); }
100% { box-shadow: 0 0 15px 5px rgba(255, 255, 255, 0); }
}
.cell-animate {
animation: fadeIn 0.3s ease-out;
}
.winner-flash {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
animation: flash 0.5s ease-in-out 3;
}
.x-color {
color: #ef4444;
}
.o-color {
color: #3b82f6;
}
.highlight {
animation: highlight 1.5s ease-out;
}
.btn-pulse {
animation: pulse 0.5s infinite;
}
.modal {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-content {
background-color: #1f2937;
padding: 2rem;
border-radius: 1rem;
max-width: 500px;
width: 90%;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
}
.tab-active {
background-color: #374151;
border-bottom: 3px solid #3b82f6;
}
.sound-toggle {
position: fixed;
bottom: 20px;
right: 20px;
background: #374151;
width: 50px;
height: 50px;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 100;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
</style>
</head>
<body class="bg-gray-900 text-white min-h-screen flex flex-col items-center justify-center p-4 transition-colors duration-500">
<!-- Sound Toggle -->
<div id="soundToggle" class="sound-toggle">
<i id="soundIcon" class="fas fa-volume-up text-xl"></i>
</div>
<!-- Main Game Container -->
<div class="max-w-4xl w-full">
<h1 class="text-5xl font-bold text-center mb-8 text-transparent bg-clip-text bg-gradient-to-r from-red-500 to-blue-500">
Tic-Tac-Toe Ultimate
</h1>
<div class="bg-gray-800 rounded-xl p-6 shadow-2xl mb-8">
<!-- Mode Selection Tabs -->
<div class="flex mb-6 border-b border-gray-700">
<button id="pvpTab" class="tab-btn flex-1 py-2 font-semibold tab-active">
<i class="fas fa-users mr-2"></i> Player vs Player
</button>
<button id="aiTab" class="tab-btn flex-1 py-2 font-semibold">
<i class="fas fa-robot mr-2"></i> Player vs AI
</button>
<button id="aivsaiTab" class="tab-btn flex-1 py-2 font-semibold">
<i class="fas fa-robot mr-2"></i><i class="fas fa-robot ml-1 mr-2"></i> AI vs AI
</button>
</div>
<!-- Tab Content -->
<div id="pvpContent" class="tab-content">
<div class="text-center mb-6">
<p class="text-gray-300 mb-4">Play against a friend on the same device</p>
<button id="startPvpBtn" class="px-6 py-3 bg-blue-600 hover:bg-blue-700 rounded-lg font-medium btn-pulse">
<i class="fas fa-play mr-2"></i> Start Game
</button>
</div>
</div>
<div id="aiContent" class="tab-content hidden">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<h3 class="text-lg font-semibold mb-3">Player (X)</h3>
<div class="bg-gray-700 p-4 rounded-lg">
<p class="text-gray-300 mb-3">You will play as X against the AI</p>
</div>
</div>
<div>
<h3 class="text-lg font-semibold mb-3">AI (O)</h3>
<div class="bg-gray-700 p-4 rounded-lg">
<p class="text-gray-300 mb-2">Select AI difficulty:</p>
<div class="grid grid-cols-1 gap-2">
<button data-difficulty="easy" class="difficulty-btn px-4 py-2 bg-green-600 hover:bg-green-700 rounded">
<i class="fas fa-baby mr-2"></i> Easy
</button>
<button data-difficulty="medium" class="difficulty-btn px-4 py-2 bg-yellow-600 hover:bg-yellow-700 rounded">
<i class="fas fa-user mr-2"></i> Medium
</button>
<button data-difficulty="hard" class="difficulty-btn px-4 py-2 bg-red-600 hover:bg-red-700 rounded">
<i class="fas fa-brain mr-2"></i> Hard
</button>
</div>
</div>
</div>
</div>
<div class="text-center">
<button id="startAiBtn" class="px-6 py-3 bg-purple-600 hover:bg-purple-700 rounded-lg font-medium">
<i class="fas fa-play mr-2"></i> Start Game
</button>
</div>
</div>
<div id="aivsaiContent" class="tab-content hidden">
<div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<h3 class="text-lg font-semibold mb-3">AI (X)</h3>
<div class="bg-gray-700 p-4 rounded-lg">
<p class="text-gray-300 mb-2">Select AI difficulty:</p>
<div class="grid grid-cols-1 gap-2">
<button data-difficulty="easy" data-ai="x" class="aivsai-difficulty-btn px-4 py-2 bg-green-600 hover:bg-green-700 rounded">
<i class="fas fa-baby mr-2"></i> Easy
</button>
<button data-difficulty="medium" data-ai="x" class="aivsai-difficulty-btn px-4 py-2 bg-yellow-600 hover:bg-yellow-700 rounded">
<i class="fas fa-user mr-2"></i> Medium
</button>
<button data-difficulty="hard" data-ai="x" class="aivsai-difficulty-btn px-4 py-2 bg-red-600 hover:bg-red-700 rounded">
<i class="fas fa-brain mr-2"></i> Hard
</button>
</div>
</div>
</div>
<div>
<h3 class="text-lg font-semibold mb-3">AI (O)</h3>
<div class="bg-gray-700 p-4 rounded-lg">
<p class="text-gray-300 mb-2">Select AI difficulty:</p>
<div class="grid grid-cols-1 gap-2">
<button data-difficulty="easy" data-ai="o" class="aivsai-difficulty-btn px-4 py-2 bg-green-600 hover:bg-green-700 rounded">
<i class="fas fa-baby mr-2"></i> Easy
</button>
<button data-difficulty="medium" data-ai="o" class="aivsai-difficulty-btn px-4 py-2 bg-yellow-600 hover:bg-yellow-700 rounded">
<i class="fas fa-user mr-2"></i> Medium
</button>
<button data-difficulty="hard" data-ai="o" class="aivsai-difficulty-btn px-4 py-2 bg-red-600 hover:bg-red-700 rounded">
<i class="fas fa-brain mr-2"></i> Hard
</button>
</div>
</div>
</div>
</div>
<div class="text-center">
<button id="startAivsaiBtn" class="px-6 py-3 bg-green-600 hover:bg-green-700 rounded-lg font-medium">
<i class="fas fa-play mr-2"></i> Start Game
</button>
</div>
</div>
<!-- Game Board (hidden initially) -->
<div id="gameBoard" class="hidden">
<!-- Game Status -->
<div id="gameStatus" class="text-center text-xl font-semibold mb-6 py-3 px-4 bg-gray-700 rounded-lg">
Player X's turn
</div>
<!-- Actual Board -->
<div class="grid grid-cols-3 gap-3 mb-6 aspect-square max-w-md mx-auto">
<!-- Cells will be generated by JavaScript -->
</div>
<!-- Game Controls -->
<div class="flex justify-center gap-4">
<button id="resetBtn" class="px-6 py-2 bg-gray-600 hover:bg-gray-500 rounded-lg font-medium">
<i class="fas fa-sync-alt mr-2"></i> Reset Game
</button>
<button id="autoPlayBtn" class="px-6 py-2 bg-indigo-600 hover:bg-indigo-500 rounded-lg font-medium hidden">
<i class="fas fa-play mr-2"></i> Auto Play
</button>
</div>
</div>
</div>
</div>
<!-- Winner Flash -->
<div id="winnerFlash" class="winner-flash hidden"></div>
<!-- Audio Elements -->
<audio id="clickSound" src="https://assets.mixkit.co/sfx/preview/mixkit-select-click-1109.mp3" preload="auto"></audio>
<audio id="winSound" src="https://assets.mixkit.co/sfx/preview/mixkit-winning-chimes-2015.mp3" preload="auto"></audio>
<audio id="drawSound" src="https://assets.mixkit.co/sfx/preview/mixkit-neutral-game-notification-951.mp3" preload="auto"></audio>
<audio id="bgMusic" loop src="https://assets.mixkit.co/music/preview/mixkit-game-show-suspense-waiting-668.mp3" preload="auto"></audio>
<script>
document.addEventListener('DOMContentLoaded', () => {
// Game state variables
let board = ['', '', '', '', '', '', '', '', ''];
let currentPlayer = 'X';
let gameActive = false;
let gameMode = null; // 'pvp', 'ai', 'aivsai'
let aiDifficulty = { x: 'medium', o: 'medium' }; // For AI vs AI mode
let playerAiDifficulty = 'medium'; // For Player vs AI mode
let aiPlaying = false;
let aiInterval = null;
let soundsEnabled = true;
// DOM elements
const gameStatusEl = document.getElementById('gameStatus');
const resetBtn = document.getElementById('resetBtn');
const autoPlayBtn = document.getElementById('autoPlayBtn');
const winnerFlash = document.getElementById('winnerFlash');
const gameBoardEl = document.getElementById('gameBoard');
const boardEl = document.querySelector('#gameBoard .grid');
// Tab elements
const pvpTab = document.getElementById('pvpTab');
const aiTab = document.getElementById('aiTab');
const aivsaiTab = document.getElementById('aivsaiTab');
const pvpContent = document.getElementById('pvpContent');
const aiContent = document.getElementById('aiContent');
const aivsaiContent = document.getElementById('aivsaiContent');
// Start buttons
const startPvpBtn = document.getElementById('startPvpBtn');
const startAiBtn = document.getElementById('startAiBtn');
const startAivsaiBtn = document.getElementById('startAivsaiBtn');
// Sound elements
const clickSound = document.getElementById('clickSound');
const winSound = document.getElementById('winSound');
const drawSound = document.getElementById('drawSound');
const bgMusic = document.getElementById('bgMusic');
const soundToggle = document.getElementById('soundToggle');
const soundIcon = document.getElementById('soundIcon');
// Create board cells
function createBoard() {
boardEl.innerHTML = '';
for (let i = 0; i < 9; i++) {
const cell = document.createElement('div');
cell.className = 'cell bg-gray-700 rounded-lg flex items-center justify-center text-6xl font-bold cursor-pointer transition-all duration-200 hover:bg-gray-600';
cell.dataset.index = i;
cell.addEventListener('click', () => handleCellClick(i));
boardEl.appendChild(cell);
}
}
// Tab switching
function switchTab(tab) {
// Reset active tabs
pvpTab.classList.remove('tab-active');
aiTab.classList.remove('tab-active');
aivsaiTab.classList.remove('tab-active');
pvpContent.classList.add('hidden');
aiContent.classList.add('hidden');
aivsaiContent.classList.add('hidden');
// Activate selected tab
if (tab === 'pvp') {
pvpTab.classList.add('tab-active');
pvpContent.classList.remove('hidden');
} else if (tab === 'ai') {
aiTab.classList.add('tab-active');
aiContent.classList.remove('hidden');
} else if (tab === 'aivsai') {
aivsaiTab.classList.add('tab-active');
aivsaiContent.classList.remove('hidden');
}
}
// Event listeners for tabs
pvpTab.addEventListener('click', () => switchTab('pvp'));
aiTab.addEventListener('click', () => switchTab('ai'));
aivsaiTab.addEventListener('click', () => switchTab('aivsai'));
// Event listeners for difficulty buttons (Player vs AI)
document.querySelectorAll('.difficulty-btn').forEach(btn => {
btn.addEventListener('click', function() {
// Remove active state from all buttons
document.querySelectorAll('.difficulty-btn').forEach(b => {
b.classList.remove('bg-green-700', 'bg-yellow-700', 'bg-red-700', 'ring-2', 'ring-green-400', 'ring-yellow-400', 'ring-red-400');
});
// Set active state for clicked button
const difficulty = this.dataset.difficulty;
playerAiDifficulty = difficulty;
if (difficulty === 'easy') {
this.classList.add('bg-green-700', 'ring-2', 'ring-green-400');
} else if (difficulty === 'medium') {
this.classList.add('bg-yellow-700', 'ring-2', 'ring-yellow-400');
} else if (difficulty === 'hard') {
this.classList.add('bg-red-700', 'ring-2', 'ring-red-400');
}
});
});
// Event listeners for difficulty buttons (AI vs AI)
document.querySelectorAll('.aivsai-difficulty-btn').forEach(btn => {
btn.addEventListener('click', function() {
// Remove active state from all buttons for this AI
const ai = this.dataset.ai;
document.querySelectorAll(`.aivsai-difficulty-btn[data-ai="${ai}"]`).forEach(b => {
b.classList.remove('bg-green-700', 'bg-yellow-700', 'bg-red-700', 'ring-2', 'ring-green-400', 'ring-yellow-400', 'ring-red-400');
});
// Set active state for clicked button
const difficulty = this.dataset.difficulty;
aiDifficulty[ai] = difficulty;
if (difficulty === 'easy') {
this.classList.add('bg-green-700', 'ring-2', 'ring-green-400');
} else if (difficulty === 'medium') {
this.classList.add('bg-yellow-700', 'ring-2', 'ring-yellow-400');
} else if (difficulty === 'hard') {
this.classList.add('bg-red-700', 'ring-2', 'ring-red-400');
}
});
});
// Start buttons
startPvpBtn.addEventListener('click', () => {
gameMode = 'pvp';
startGame();
});
startAiBtn.addEventListener('click', () => {
gameMode = 'ai';
startGame();
});
startAivsaiBtn.addEventListener('click', () => {
gameMode = 'aivsai';
startGame();
});
// Reset button
resetBtn.addEventListener('click', resetGame);
// Auto play button (for AI vs AI)
autoPlayBtn.addEventListener('click', toggleAutoPlay);
// Sound toggle
soundToggle.addEventListener('click', () => {
soundsEnabled = !soundsEnabled;
soundIcon.className = soundsEnabled ? 'fas fa-volume-up text-xl' : 'fas fa-volume-mute text-xl';
if (soundsEnabled) {
bgMusic.play().catch(e => console.log("Autoplay prevented"));
} else {
bgMusic.pause();
}
});
// Play sound
function playSound(sound) {
if (!soundsEnabled) return;
sound.currentTime = 0;
sound.play().catch(e => console.log("Sound play prevented"));
}
// Start a new game
function startGame() {
// Hide menu, show game board
pvpContent.classList.add('hidden');
aiContent.classList.add('hidden');
aivsaiContent.classList.add('hidden');
gameBoardEl.classList.remove('hidden');
// Create fresh board
createBoard();
const cells = document.querySelectorAll('.cell');
resetGame();
gameActive = true;
if (gameMode === 'aivsai') {
autoPlayBtn.classList.remove('hidden');
toggleAutoPlay();
} else {
autoPlayBtn.classList.add('hidden');
}
// Start background music
if (soundsEnabled) {
bgMusic.play().catch(e => console.log("Autoplay prevented"));
}
updateGameStatus();
}
// Reset the game
function resetGame() {
board = ['', '', '', '', '', '', '', '', ''];
currentPlayer = 'X';
gameActive = true;
aiPlaying = false;
if (aiInterval) {
clearInterval(aiInterval);
aiInterval = null;
autoPlayBtn.innerHTML = '<i class="fas fa-play mr-2"></i> Auto Play';
}
// Clear the board
const cells = document.querySelectorAll('.cell');
cells.forEach(cell => {
cell.textContent = '';
cell.classList.remove('x-color', 'o-color', 'highlight', 'cell-animate');
});
// Hide winner flash
winnerFlash.classList.add('hidden');
winnerFlash.classList.remove('bg-red-500', 'bg-blue-500');
// Reset background color
document.body.classList.remove('bg-red-900', 'bg-blue-900');
updateGameStatus();
}
// Toggle auto play for AI vs AI mode
function toggleAutoPlay() {
if (aiInterval) {
clearInterval(aiInterval);
aiInterval = null;
autoPlayBtn.innerHTML = '<i class="fas fa-play mr-2"></i> Auto Play';
} else {
aiInterval = setInterval(() => {
if (gameActive && gameMode === 'aivsai' && !aiPlaying) {
makeAIMove();
}
}, 800);
autoPlayBtn.innerHTML = '<i class="fas fa-pause mr-2"></i> Pause';
}
}
// Handle cell click
function handleCellClick(index) {
if (!gameActive || board[index] !== '' || aiPlaying) return;
// In AI mode, only allow human player to click when it's their turn
if (gameMode === 'ai' && currentPlayer === 'O') return;
// Play click sound
playSound(clickSound);
// Make the move
makeMove(index);
// If in AI mode and game is still active, let AI make a move
if (gameActive && gameMode === 'ai' && currentPlayer === 'O') {
setTimeout(() => {
makeAIMove();
}, 500);
}
}
// Make a move
function makeMove(index) {
if (!gameActive || board[index] !== '') return;
// Update board
board[index] = currentPlayer;
// Update UI
const cells = document.querySelectorAll('.cell');
const cell = cells[index];
cell.textContent = currentPlayer;
cell.classList.add(currentPlayer === 'X' ? 'x-color' : 'o-color', 'cell-animate');
// Check for winner or draw
const winner = checkWinner();
if (winner) {
handleGameEnd(winner);
} else if (!board.includes('')) {
handleGameEnd(null); // Draw
} else {
// Switch player
currentPlayer = currentPlayer === 'X' ? 'O' : 'X';
updateGameStatus();
}
}
// Make AI move
function makeAIMove() {
if (!gameActive || aiPlaying) return;
aiPlaying = true;
setTimeout(() => {
let moveIndex;
const difficulty = gameMode === 'aivsai' ?
aiDifficulty[currentPlayer.toLowerCase()] :
playerAiDifficulty;
switch (difficulty) {
case 'easy':
moveIndex = getRandomMove();
break;
case 'medium':
moveIndex = getMediumAIMove();
break;
case 'hard':
moveIndex = getHardAIMove();
break;
default:
moveIndex = getRandomMove();
}
// Play click sound for AI move
playSound(clickSound);
makeMove(moveIndex);
aiPlaying = false;
}, 500);
}
// Get a random move (for easy AI)
function getRandomMove() {
const emptyCells = board.map((cell, index) => cell === '' ? index : null).filter(val => val !== null);
return emptyCells[Math.floor(Math.random() * emptyCells.length)];
}
// Get medium AI move (can win or block)
function getMediumAIMove() {
// Check if AI can win in the next move
for (let i = 0; i < 9; i++) {
if (board[i] === '') {
board[i] = currentPlayer;
if (checkWinner() === currentPlayer) {
board[i] = '';
return i;
}
board[i] = '';
}
}
// Check if opponent can win in the next move and block
const opponent = currentPlayer === 'X' ? 'O' : 'X';
for (let i = 0; i < 9; i++) {
if (board[i] === '') {
board[i] = opponent;
if (checkWinner() === opponent) {
board[i] = '';
return i;
}
board[i] = '';
}
}
// Try to take center if available
if (board[4] === '') return 4;
// Otherwise make a random move
return getRandomMove();
}
// Get hard AI move (uses minimax algorithm)
function getHardAIMove() {
// Check if AI can win in the next move
for (let i = 0; i < 9; i++) {
if (board[i] === '') {
board[i] = currentPlayer;
if (checkWinner() === currentPlayer) {
board[i] = '';
return i;
}
board[i] = '';
}
}
// Check if opponent can win in the next move and block
const opponent = currentPlayer === 'X' ? 'O' : 'X';
for (let i = 0; i < 9; i++) {
if (board[i] === '') {
board[i] = opponent;
if (checkWinner() === opponent) {
board[i] = '';
return i;
}
board[i] = '';
}
}
// Try to take center if available
if (board[4] === '') return 4;
// Try to take a corner if available
const corners = [0, 2, 6, 8];
const availableCorners = corners.filter(i => board[i] === '');
if (availableCorners.length > 0) {
return availableCorners[Math.floor(Math.random() * availableCorners.length)];
}
// Take any available edge
const edges = [1, 3, 5, 7];
const availableEdges = edges.filter(i => board[i] === '');
if (availableEdges.length > 0) {
return availableEdges[Math.floor(Math.random() * availableEdges.length)];
}
// Fallback to random move (shouldn't happen)
return getRandomMove();
}
// Check for winner
function checkWinner() {
// Winning combinations
const winPatterns = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], // rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], // columns
[0, 4, 8], [2, 4, 6] // diagonals
];
// Check each winning pattern
for (const pattern of winPatterns) {
const [a, b, c] = pattern;
if (board[a] && board[a] === board[b] && board[a] === board[c]) {
// Highlight winning cells
const cells = document.querySelectorAll('.cell');
cells[a].classList.add('highlight');
cells[b].classList.add('highlight');
cells[c].classList.add('highlight');
return board[a];
}
}
return null;
}
// Handle game end
function handleGameEnd(winner) {
gameActive = false;
if (winner) {
// In AI vs AI mode, randomly decide the winner
if (gameMode === 'aivsai') {
winner = Math.random() < 0.5 ? 'X' : 'O';
// Fill a random winning pattern with the winner's symbol
const winPatterns = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], // rows
[0, 3, 6], [1, 4, 7], [2, 5, 8], // columns
[0, 4, 8], [2, 4, 6] // diagonals
];
const randomPattern = winPatterns[Math.floor(Math.random() * winPatterns.length)];
const cells = document.querySelectorAll('.cell');
randomPattern.forEach(i => {
board[i] = winner;
cells[i].textContent = winner;
cells[i].classList.add(winner === 'X' ? 'x-color' : 'o-color', 'highlight');
});
}
gameStatusEl.textContent = `Player ${winner} wins!`;
// Play win sound
playSound(winSound);
// Show winner flash and change background
winnerFlash.classList.remove('hidden');
winnerFlash.classList.add(winner === 'X' ? 'bg-red-500' : 'bg-blue-500');
document.body.classList.add(winner === 'X' ? 'bg-red-900' : 'bg-blue-900');
// Reset game after delay
setTimeout(resetGame, 3000);
} else {
gameStatusEl.textContent = "Game ended in a draw!";
// Play draw sound
playSound(drawSound);
// Reset game after delay
setTimeout(resetGame, 3000);
}
}
// Update game status text
function updateGameStatus() {
if (gameMode === 'pvp') {
gameStatusEl.textContent = `Player ${currentPlayer}'s turn`;
} else if (gameMode === 'ai') {
if (currentPlayer === 'X') {
gameStatusEl.textContent = "Your turn (X)";
} else {
gameStatusEl.textContent = "AI is thinking...";
}
} else if (gameMode === 'aivsai') {
gameStatusEl.textContent = `AI ${currentPlayer}'s turn`;
}
// Update status color based on current player
gameStatusEl.classList.remove('x-color', 'o-color');
if (gameActive) {
gameStatusEl.classList.add(currentPlayer === 'X' ? 'x-color' : 'o-color');
}
}
// Initialize the game
createBoard();
switchTab('pvp');
// Set medium difficulty as active by default
document.querySelector('.difficulty-btn[data-difficulty="medium"]').classList.add('bg-yellow-700', 'ring-2', 'ring-yellow-400');
document.querySelector('.aivsai-difficulty-btn[data-ai="x"][data-difficulty="medium"]').classList.add('bg-yellow-700', 'ring-2', 'ring-yellow-400');
document.querySelector('.aivsai-difficulty-btn[data-ai="o"][data-difficulty="medium"]').classList.add('bg-yellow-700', 'ring-2', 'ring-yellow-400');
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Joshua353/joshua" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>