Spaces:
Running
Running
<html lang="en" class=""> <!-- Start without 'dark' class --> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Italian Brainrot - Soundboard</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> | |
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap'); | |
/* Base styles */ | |
body { | |
font-family: 'Poppins', sans-serif; | |
/* Smooth transition for theme changes */ | |
@apply transition-colors duration-300 ease-in-out; | |
} | |
/* Light theme base */ | |
body { | |
background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%); | |
} | |
/* Dark theme base */ | |
.dark body { | |
background: linear-gradient(135deg, #1f2937 0%, #111827 100%); /* Dark gradient */ | |
} | |
.character-card { | |
transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); | |
perspective: 1000px; | |
@apply transition-colors duration-300 ease-in-out; /* Transition background */ | |
} | |
.character-card:hover { | |
transform: translateY(-8px); | |
/* Enhanced hover shadow for both themes */ | |
@apply shadow-xl dark:shadow-2xl dark:shadow-indigo-500/20; | |
} | |
/* Specific light/dark styles will be applied via Tailwind classes directly */ | |
.image-container { | |
/* Keep the gradient or simplify */ | |
background: linear-gradient(145deg, #ffffff, #e6e6e6); | |
box-shadow: 0 4px 15px rgba(0,0,0,0.08); | |
@apply transition-colors duration-300 ease-in-out; | |
} | |
.dark .image-container { | |
background: linear-gradient(145deg, #4b5563, #374151); /* Darker bg for image */ | |
box-shadow: 0 4px 15px rgba(0,0,0,0.2); | |
} | |
.play-btn { | |
transition: all 0.2s ease; | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
} | |
.play-btn.playing { | |
background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); /* Red gradient for playing */ | |
} | |
.play-btn:hover { | |
transform: translateY(-2px); | |
box-shadow: 0 5px 15px rgba(118, 75, 162, 0.4); | |
} | |
.play-btn.playing:hover { | |
box-shadow: 0 5px 15px rgba(239, 68, 68, 0.4); /* Red shadow */ | |
} | |
.play-btn:active { | |
transform: translateY(0); | |
} | |
.gradient-text { | |
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
-webkit-background-clip: text; | |
background-clip: text; | |
color: transparent; | |
} | |
/* Optional: Slightly adjust gradient text for dark mode if needed */ | |
/* .dark .gradient-text { ... } */ | |
.header-divider { | |
height: 4px; | |
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); | |
@apply transition-all duration-300 ease-in-out; | |
} | |
.dark .header-divider { | |
background: linear-gradient(90deg, #818cf8 0%, #a78bfa 100%); /* Brighter gradient for dark */ | |
} | |
/* Theme toggle button */ | |
#theme-toggle { | |
@apply fixed top-5 right-5 z-50; | |
@apply w-12 h-12 rounded-full ; | |
@apply flex items-center justify-center; | |
@apply bg-white/80 dark:bg-gray-800/80 backdrop-blur-sm; /* Semi-transparent background */ | |
@apply text-gray-600 dark:text-gray-300; | |
@apply hover:bg-white dark:hover:bg-gray-700; | |
@apply shadow-md hover:shadow-lg; | |
@apply transition-all duration-300 ease-in-out; | |
@apply cursor-pointer; | |
} | |
#theme-toggle i { | |
@apply text-xl; | |
} | |
@media (max-width: 640px) { | |
.character-name { | |
font-size: 1rem; /* Already adjusted */ | |
} | |
#theme-toggle { | |
@apply top-3 right-3 w-10 h-10; /* Smaller on mobile */ | |
} | |
#theme-toggle i { | |
@apply text-lg; | |
} | |
} | |
</style> | |
</head> | |
<body class="min-h-screen"> <!-- Body class will be updated by JS --> | |
<!-- Theme Toggle Button --> | |
<button id="theme-toggle" aria-label="Toggle dark mode"> | |
<i class="fas fa-moon"></i> <!-- Moon icon for light theme --> | |
<i class="fas fa-sun hidden"></i> <!-- Sun icon for dark theme --> | |
</button> | |
<div class="container mx-auto px-4 py-12 md:py-16"> | |
<!-- Header --> | |
<header class="text-center mb-12 md:mb-16"> | |
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold gradient-text mb-3">Italian Brainrot</h1> | |
<div class="header-divider w-32 md:w-40 mx-auto rounded-full mb-6"></div> | |
<p class="text-lg text-gray-600 dark:text-gray-400 max-w-2xl mx-auto"> | |
Discover the magical sounds of Italian Brainrot characters | |
</p> | |
</header> | |
<!-- Character Grid --> | |
<div id="characterGrid" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8"> | |
<!-- Character cards will be injected here by JS --> | |
</div> | |
</div> | |
<!-- Embedded Character Data --> | |
<script> | |
const characterData = | |
{ | |
"Bombardiro Crocodilo": { | |
"image_path": "./assets/Bombardiro_Crocodilo.png", | |
"audio_path": "./assets/Bombardiro_Crocodilo.wav" | |
}, | |
"Tralalero Tralala": { | |
"image_path": "./assets/Tralalero_Tralala.png", | |
"audio_path": "./assets/Tralalero_Tralala.wav" | |
}, | |
"Bombombini Gusini": { | |
"image_path": "./assets/Bombombini_Gusini.png", | |
"audio_path": "./assets/Bombombini_Gusini.wav" | |
}, | |
"Tung Tung Tung Tung Tung Tung Tung Tung Tung Sahur": { | |
"image_path": "./assets/Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Sahur.png", | |
"audio_path": "./assets/Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Sahur.wav" | |
}, | |
"Brr Brr Patapim": { | |
"image_path": "./assets/Brr_Brr_Patapim.png", | |
"audio_path": "./assets/Brr_Brr_Patapim.wav" | |
}, | |
"Cappuccino Assassino": { | |
"image_path": "./assets/Cappuccino_Assassino.png", | |
"audio_path": "./assets/Cappuccino_Assassino.wav" | |
}, | |
"Lirili Larila": { | |
"image_path": "./assets/Lirili_Larila.png", | |
"audio_path": "./assets/Lirili_Larila.wav" | |
}, | |
"Trulimero Trulichina": { | |
"image_path": "./assets/Trulimero_Trulichina.png", | |
"audio_path": "./assets/Trulimero_Trulichina.wav" | |
}, | |
"Boneca Ambalabu": { | |
"image_path": "./assets/Boneca_Ambalabu.png", | |
"audio_path": "./assets/Boneca_Ambalabu.wav" | |
}, | |
"Chimpanzini Bananini": { | |
"image_path": "./assets/Chimpanzini_Bananini.png", | |
"audio_path": "./assets/Chimpanzini_Bananini.wav" | |
}, | |
"Bananita Dolfinita": { | |
"image_path": "./assets/Bananita_Dolfinita.png", | |
"audio_path": "./assets/Bananita_Dolfinita.wav" | |
}, | |
"Bluberini Octopusini": { | |
"image_path": "./assets/Bluberini_Octopusini.png", | |
"audio_path": "./assets/Bluberini_Octopusini.wav" | |
}, | |
"Bobrito Bandito": { | |
"image_path": "./assets/Bobrito_Bandito.png", | |
"audio_path": "./assets/Bobrito_Bandito.wav" | |
}, | |
"Brri Brri Bicus Dicus": { | |
"image_path": "./assets/Brri_Brri_Bicus_Dicus.png", | |
"audio_path": "./assets/Brri_Brri_Bicus_Dicus.wav" | |
}, | |
"Burbaloni Luliloli": { | |
"image_path": "./assets/Burbaloni_Luliloli.png", | |
"audio_path": "./assets/Burbaloni_Luliloli.wav" | |
}, | |
"Chimpanzini Ananasini": { | |
"image_path": "./assets/Chimpanzini_Ananasini.png", | |
"audio_path": "./assets/Chimpanzini_Ananasini.wav" | |
}, | |
"Chimpanzini Cocosini": { | |
"image_path": "./assets/Chimpanzini_Cocosini.png", | |
"audio_path": "./assets/Chimpanzini_Cocosini.wav" | |
}, | |
"Cocofanto Elefanto": { | |
"image_path": "./assets/Cocofanto_Elefanto.png", | |
"audio_path": "./assets/Cocofanto_Elefanto.wav" | |
}, | |
"Frigo Camello Buffo Fardelo": { | |
"image_path": "./assets/Frigo Camello Buffo Fardelo.png", | |
"audio_path": "./assets/Frigo Camello Buffo Fardelo.wav" | |
}, | |
"Giraffe Celeste": { | |
"image_path": "./assets/Giraffe_Celeste.png", | |
"audio_path": "./assets/Giraffe_Celeste.wav" | |
}, | |
"Glorbo Fruttodrillo": { | |
"image_path": "./assets/Glorbo_Fruttodrillo.png", | |
"audio_path": "./assets/Glorbo_Fruttodrillo.wav" | |
}, | |
"IL Cacto Hipopotoma": { | |
"image_path": "./assets/il_cacto_hipopotoma.png", | |
"audio_path": "./assets/il_cacto_hipopotoma.wav" | |
}, | |
"La Vaca Saturno Saturnita": { | |
"image_path": "./assets/La_Vaca_Saturno_Saturnita.png", | |
"audio_path": "./assets/La_Vaca_Saturno_Saturnita.wav" | |
}, | |
"Trippi Troppi Troppa Trippa": { | |
"image_path": "./assets/Trippi_Troppi_Troppa_Trippa.png", | |
"audio_path": "./assets/Trippi_Troppi_Troppa_Trippa.wav" | |
} | |
} | |
; | |
const characterGrid = document.getElementById('characterGrid'); | |
const themeToggleButton = document.getElementById('theme-toggle'); | |
const sunIcon = themeToggleButton.querySelector('.fa-sun'); | |
const moonIcon = themeToggleButton.querySelector('.fa-moon'); | |
const htmlElement = document.documentElement; // Target <html> for dark class | |
let currentlyPlayingAudio = null; | |
let currentlyPlayingButton = null; | |
// Function to apply the theme | |
function applyTheme(theme) { | |
if (theme === 'dark') { | |
htmlElement.classList.add('dark'); | |
moonIcon.classList.add('hidden'); | |
sunIcon.classList.remove('hidden'); | |
localStorage.setItem('theme', 'dark'); | |
} else { | |
htmlElement.classList.remove('dark'); | |
moonIcon.classList.remove('hidden'); | |
sunIcon.classList.add('hidden'); | |
localStorage.setItem('theme', 'light'); | |
} | |
} | |
// Function to toggle the theme | |
function toggleTheme() { | |
const currentTheme = htmlElement.classList.contains('dark') ? 'dark' : 'light'; | |
applyTheme(currentTheme === 'dark' ? 'light' : 'dark'); | |
} | |
// Function to load and display characters | |
function loadCharacters() { | |
characterGrid.innerHTML = ''; // Clear existing | |
Object.entries(characterData).forEach(([name, data]) => { | |
const card = document.createElement('div'); | |
// Apply base and dark mode classes using Tailwind | |
card.className = ` | |
character-card | |
bg-white dark:bg-gray-800 | |
rounded-2xl overflow-hidden | |
shadow-md hover:shadow-xl dark:hover:shadow-2xl dark:hover:shadow-indigo-500/20 | |
border border-gray-200 dark:border-gray-700/50 | |
flex flex-col items-center p-6 | |
transition-all duration-300 ease-in-out | |
`; | |
// Image container | |
const imageContainer = document.createElement('div'); | |
imageContainer.className = ` | |
image-container mb-5 w-40 h-40 lg:w-44 lg:h-44 | |
flex items-center justify-center | |
rounded-2xl overflow-hidden | |
border-4 border-white/50 dark:border-gray-700/50 | |
`; // Added slightly larger size on larger screens and border | |
const image = document.createElement('img'); | |
image.src = data.image_path.replace(/\\/g, '/'); | |
image.alt = name; | |
image.className = 'w-full h-full object-cover'; | |
image.onerror = () => { // Basic error handling for images | |
image.src = 'placeholder.png'; // Provide a fallback image path | |
console.warn(`Image not found: ${data.image_path}`); | |
}; | |
imageContainer.appendChild(image); | |
// Character name | |
const nameElement = document.createElement('h3'); | |
nameElement.className = ` | |
character-name text-lg md:text-xl font-semibold | |
text-gray-800 dark:text-gray-100 | |
mb-4 text-center transition-colors duration-300 | |
`; | |
nameElement.textContent = name; | |
// Play/Pause button | |
const playButton = document.createElement('button'); | |
playButton.className = ` | |
play-btn text-white font-medium py-2.5 px-7 | |
rounded-full flex items-center justify-center | |
w-32 /* Fixed width for consistency */ | |
`; | |
const playIcon = document.createElement('i'); | |
playIcon.className = 'fas fa-play mr-2'; // Start with play | |
playButton.appendChild(playIcon); | |
playButton.appendChild(document.createTextNode('Play')); | |
// Audio element (keep it hidden) | |
const audio = new Audio(data.audio_path.replace(/\\/g, '/')); | |
audio.preload = 'metadata'; // Improve loading slightly | |
audio.style.display = 'none'; | |
audio.onerror = () => { | |
console.error(`Error loading audio: ${data.audio_path}`); | |
playButton.disabled = true; // Disable button if audio fails | |
playButton.textContent = 'Error'; | |
playButton.classList.add('opacity-50', 'cursor-not-allowed'); | |
}; | |
// --- Refined Play/Pause Logic --- | |
playButton.addEventListener('click', () => { | |
// If this audio is currently playing, pause it | |
if (currentlyPlayingAudio === audio) { | |
audio.pause(); | |
currentlyPlayingAudio = null; | |
currentlyPlayingButton = null; | |
// Reset this button visually | |
playButton.innerHTML = '<i class="fas fa-play mr-2"></i>Play'; | |
playButton.classList.remove('playing'); | |
} else { | |
// If another audio is playing, stop it first | |
if (currentlyPlayingAudio) { | |
currentlyPlayingAudio.pause(); | |
currentlyPlayingAudio.currentTime = 0; // Reset time | |
// Reset the *other* button visually | |
if (currentlyPlayingButton) { | |
currentlyPlayingButton.innerHTML = '<i class="fas fa-play mr-2"></i>Play'; | |
currentlyPlayingButton.classList.remove('playing'); | |
} | |
} | |
// Now play this audio | |
audio.currentTime = 0; | |
audio.play().catch(e => console.error("Audio play failed:", e)); // Catch potential play errors | |
currentlyPlayingAudio = audio; | |
currentlyPlayingButton = playButton; | |
// Update this button visually to 'Pause' | |
playButton.innerHTML = '<i class="fas fa-pause mr-2"></i>Pause'; | |
playButton.classList.add('playing'); | |
} | |
}); | |
// When audio naturally ends, reset the button | |
audio.addEventListener('ended', () => { | |
if (currentlyPlayingAudio === audio) { // Ensure it's the one that just ended | |
playButton.innerHTML = '<i class="fas fa-play mr-2"></i>Play'; | |
playButton.classList.remove('playing'); | |
currentlyPlayingAudio = null; | |
currentlyPlayingButton = null; | |
} | |
}); | |
// --- End Refined Play/Pause Logic --- | |
// Assemble the card | |
card.appendChild(imageContainer); | |
card.appendChild(nameElement); | |
card.appendChild(playButton); | |
card.appendChild(audio); // Add hidden audio element | |
// Add card to the grid | |
characterGrid.appendChild(card); | |
}); | |
} | |
// --- Initialization --- | |
// 1. Set initial theme based on localStorage or system preference | |
const savedTheme = localStorage.getItem('theme'); | |
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | |
if (savedTheme) { | |
applyTheme(savedTheme); | |
} else if (prefersDark) { | |
applyTheme('dark'); | |
} else { | |
applyTheme('light'); // Default to light | |
} | |
// 2. Add listener for the theme toggle button | |
themeToggleButton.addEventListener('click', toggleTheme); | |
// 3. Load characters when the page loads | |
window.addEventListener('DOMContentLoaded', loadCharacters); | |
</script> | |
</body> | |
</html> |