https://cdn.tailwindcss.com
tailwind.config = {
theme: {
extend: {
fontFamily: {
sans: [‘Inter’, ‘sans-serif’],
},
colors: {
‘primary’: ‘#4f46e5’, // Indigo 600
‘secondary’: ‘#f97316’, // Orange 500
‘town’: ‘#22c55e’, // Green 500
‘impostor’: ‘#ef4444’, // Red 500
‘vote’: ‘#3b82f6’, // Blue 500
}
}
}
}
/* Estilo base para el cuerpo */
body {
background-color: #f3f4f6;
min-height: 100vh;
}
/* Clase para un botón interactivo y bonito */
.game-button {
transition: all 0.15s ease-in-out;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1);
}
.game-button:hover {
transform: translateY(-1px);
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
}
.game-button:active {
transform: translateY(1px);
box-shadow: none;
}
/* Estilo para el gran temporizador */
#countdownDisplay {
font-size: 5rem;
line-height: 1;
font-weight: 700;
}
/* Clases de animación */
.fade-in {
animation: fadeIn 0.5s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* Estilos del Toggle Switch para la pista del impostor */
.toggle-switch input:checked + .slider {
background-color: #4f46e5; /* Primary color */
}
.toggle-switch input:checked + .slider:before {
transform: translateX(26px);
}
.slider {
transition: .4s;
}
.slider:before {
transition: .4s;
}
El Juego del Impostor
Descubre al impostor que no sabe la palabra clave.
1. Configuración del Juego
— Elige una categoría —
1
2. Edita la Lista de Jugadores
¡Es hora de ver tu rol!
¡DEBATE INICIADO!
El primer jugador en ser observado es:
segundos restantes para la fase de acusación.
¡FASE DE ACUSACIÓN!
El pueblo debe votar por el jugador que cree que es el impostor.
¡REVELACIÓN FINAL!
El jugador más votado fue:
La Palabra Secreta era:
|
Categoría:
ROLES:
// — CONFIGURACIÓN DEL JUEGO: LISTA DE CATEGORÍAS Y PALABRAS (100 por Categoría) —
const CATEGORY_DATA = {
“Personajes de Disney”: [
“Mickey Mouse”, “Minnie Mouse”, “Pato Donald”, “Goofy”, “Pluto”, “Cenicienta”, “Blancanieves”, “Bella”, “Bestia”, “Ariel”,
“Aladdín”, “Jasmín”, “Simba”, “Nala”, “Mufasa”, “Timón”, “Pumba”, “Woody”, “Buzz Lightyear”, “Jessie”,
“Sulley”, “Mike Wazowski”, “Nemo”, “Dory”, “Marlin”, “Peter Pan”, “Campanita”, “Capitán Garfio”, “Maléfica”, “Hércules”,
“Megara”, “Mushu”, “Mulan”, “Pocahontas”, “John Smith”, “Tarzán”, “Jane Porter”, “Quasimodo”, “Esmeralda”, “Aurora”,
“Príncipe Felipe”, “Cruella de Vil”, “Mary Poppins”, “Gepetto”, “Pinocho”, “Hada Azul”, “Elsa”, “Anna”, “Olaf”, “Kristoff”,
“Sven”, “Rapunzel”, “Flynn Rider”, “Tiana”, “Naveen”, “Dr. Facilier”, “Moana”, “Maui”, “Vaiana”, “Tamatoa”,
“Coco”, “Miguel Rivera”, “Héctor”, “Mama Coco”, “Ray”, “Mama Odie”, “Giselle”, “Phillip”, “Malvada Reina”, “Dumbo”,
“Bambi”, “Faline”, “Tramp”, “Lady”, “Stitch”, “Lilo”, “Angel”, “Kenai”, “Koda”, “Bolt”,
“Wall-E”, “Eva”, “Alegría”, “Tristeza”, “Furia”, “Miedo”, “Desagrado”, “Riley”, “Carl Fredricksen”, “Russell”,
“Dug”, “Edna Moda”, “Mr. Increíble”, “Elastigirl”, “Violeta”, “Dash”, “Jack-Jack”, “Merida”, “Lord Macintosh”, “King Fergus”,
“Raya”, “Sisu”, “Boun”, “Namaari”, “Gato Cheshire”, “Reina de Corazones”, “Sombrerero Loco”, “Alice”
],
“Personajes famosos”: [
“Messi”, “Taylor Swift”, “Elon Musk”, “Marie Curie”, “Leonardo da Vinci”, “Barack Obama”, “Shakira”, “Cristiano Ronaldo”, “Frida Kahlo”, “Stephen Hawking”,
“Albert Einstein”, “Michael Jackson”, “Marilyn Monroe”, “Nelson Mandela”, “Oprah Winfrey”, “Bill Gates”, “Reina Isabel II”, “Muhammad Ali”, “Vincent van Gogh”, “Jane Austen”,
“Walt Disney”, “Jeff Bezos”, “Malala Yousafzai”, “Elvis Presley”, “Neil Armstrong”, “Coco Chanel”, “Winston Churchill”, “Serena Williams”, “Martin Luther King Jr.”, “Beyoncé”,
“Mahatma Gandhi”, “Dalai Lama”, “Steve Jobs”, “J.K. Rowling”, “Brad Pitt”, “Angelina Jolie”, “Warren Buffett”, “Abraham Lincoln”, “Madre Teresa”, “Galileo Galilei”,
“Amelia Earhart”, “Nikola Tesla”, “Pablo Picasso”, “Lionel Richie”, “Mark Zuckerberg”, “Tom Hanks”, “Michelle Obama”, “Roger Federer”, “Isaac Newton”, “Adele”,
“Stephen King”, “Jackie Chan”, “Donald Trump”, “Kim Kardashian”, “Scarlett Johansson”, “Meryl Streep”, “Jack Nicholson”, “Audrey Hepburn”, “Bruce Lee”, “Diego Maradona”,
“Usain Bolt”, “Lebron James”, “Lady Gaga”, “Keanu Reeves”, “Emma Watson”, “Ryan Gosling”, “Jennifer Lawrence”, “Chris Evans”, “Robert Downey Jr.”, “Margot Robbie”,
“Dwayne Johnson”, “Zendaya”, “Timothée Chalamet”, “Billie Eilish”, “The Weeknd”, “Ariana Grande”, “Ed Sheeran”, “Dua Lipa”, “Chris Hemsworth”, “Gal Gadot”,
“Tom Cruise”, “Will Smith”, “Halle Berry”, “George Clooney”, “Julia Roberts”, “Matt Damon”, “Ben Affleck”, “Steven Spielberg”, “Quentin Tarantino”, “Alfred Hitchcock”,
“Jane Goodall”, “Jacques Cousteau”, “Rosa Parks”, “Helen Keller”, “Anne Frank”, “George Orwell”, “J.R.R. Tolkien”, “C.S. Lewis”, “Maya Angelou”, “Princesa Diana”,
“Vladimir Putin”, “Angela Merkel”, “Fidel Castro”, “Che Guevara”, “Malcom X”, “Beethoven”, “Mozart”, “Shakespeare”, “Platón”, “Sócrates”
],
“Personajes místicos”: [
“Elfa”, “Vampiro”, “Hombre Lobo”, “Minotauro”, “Quimera”, “Fénix”, “Sirena”, “Golem”, “Kraken”, “Banshee”,
“Dragón”, “Bruja”, “Mago”, “Hada”, “Gnomo”, “Ogro”, “Centauro”, “Grifo”, “Esfinge”, “Cíclope”,
“Zombie”, “Fantasma”, “Momia”, “Ángel”, “Demonio”, “Duende”, “Troll”, “Medusa”, “Hidra”, “Sátiro”,
“Licántropo”, “Naga”, “Titán”, “Valkiria”, “Yeti”, “Wendigo”, “Chupacabras”, “Náyade”, “Dríada”, “Íncubo”,
“Súcubo”, “Genio”, “Djinn”, “Elementales”, “Silfo”, “Salamandra”, “Ondina”, “Caronte”, “Cerbero”, “Harpía”,
“Lich”, “Nigromante”, “Orco”, “Goblin”, “Gigante”, “Kobold”, “Muñeco Vudú”, “Sombra”, “Golem de Piedra”, “Basilisco”,
“Manticora”, “Pegaso”, “Unicornio”, “Roc”, “Yacaré”, “Gárgola”, “Hombre Polilla”, “Pie Grande”, “Nessie”, “Dama Blanca”,
“El Dorado”, “Atlantes”, “Fauno”, “Minerva”, “Apolo”, “Zeus”, “Hades”, “Poseidón”, “Afrodita”, “Ares”,
“Odín”, “Thor”, “Loki”, “Anubis”, “Ra”, “Isis”, “Osiris”, “Kitsune”, “Jiangshi”, “Yokai”,
“La Llorona”, “El Coco”, “El Silbón”, “Duende Rojo”, “Piel Roja”, “Hombre de Jengibre”, “Papá Noel”, “Conejo de Pascua”, “Cupido”, “Jezabel”
],
“Marcas y logos”: [
“Coca-Cola”, “Nike”, “Apple”, “Amazon”, “Mercedes-Benz”, “Netflix”, “Starbucks”, “Google”, “Ferrari”, “Disney”,
“Microsoft”, “Samsung”, “Toyota”, “BMW”, “McDonald’s”, “Pepsi”, “Adidas”, “Sony”, “Chanel”, “Gucci”,
“Louis Vuitton”, “Lego”, “Nintendo”, “Intel”, “Visa”, “Mastercard”, “Ford”, “Chevrolet”, “IKEA”, “Zara”,
“H&M”, “Spotify”, “YouTube”, “Twitter”, “Facebook”, “Instagram”, “Snapchat”, “TikTok”, “eBay”, “PayPal”,
“Uber”, “Airbnb”, “Tesla”, “Boeing”, “SpaceX”, “NASA”, “CNN”, “BBC”, “Audi”, “Porsche”,
“Lamborghini”, “Fiat”, “Honda”, “Subway”, “KFC”, “Burger King”, “Domino’s”, “Pizza Hut”, “Oracle”, “SAP”,
“Cisco”, “Dell”, “HP”, “Canon”, “Nikon”, “Rolex”, “Cartier”, “Omega”, “Gillette”, “Pampers”,
“Dove”, “Nivea”, “Colgate”, “Oral-B”, “Red Bull”, “Monster”, “Coca-Cola Zero”, “Fanta”, “Sprite”, “Nestlé”,
“Kellogg’s”, “Barbie”, “Hot Wheels”, “Fisher-Price”, “Mattel”, “Hasbro”, “Warner Bros”, “Paramount”, “Marvel”, “DC Comics”,
“Pixar”, “DreamWorks”, “Adobe”, “Autodesk”, “Unity”, “Epic Games”, “Rockstar Games”, “Blizzard”, “Valve”, “Steam”
],
“Países y ciudades”: [
“Tokio”, “París”, “México”, “Brasil”, “Egipto”, “Sídney”, “Nueva York”, “Berlín”, “Argentina”, “Londres”,
“Roma”, “Madrid”, “Barcelona”, “Seúl”, “Pekín”, “Shanghái”, “Dubái”, “Moscú”, “Río de Janeiro”, “Toronto”,
“Vancouver”, “Chicago”, “Los Ángeles”, “San Francisco”, “Miami”, “Boston”, “Houston”, “Dallas”, “Filadelfia”, “Seattle”,
“Atenas”, “Estambul”, “El Cairo”, “Bangkok”, “Singapur”, “Hong Kong”, “Mumbai”, “Delhi”, “Yakarta”, “Manila”,
“Kuala Lumpur”, “Lisboa”, “Ámsterdam”, “Viena”, “Praga”, “Budapest”, “Varsovia”, “Dublín”, “Edimburgo”, “Copenhague”,
“Oslo”, “Estocolmo”, “Helsinki”, “Zúrich”, “Ginebra”, “Bruselas”, “Berlín”, “Hamburgo”, “Múnich”, “Frankfurt”,
“Venecia”, “Florencia”, “Milán”, “Nápoles”, “Chile”, “Perú”, “Colombia”, “Venezuela”, “Ecuador”, “Bolivia”,
“Uruguay”, “Paraguay”, “Cuba”, “Puerto Rico”, “República Dominicana”, “Japón”, “Corea del Sur”, “China”, “India”, “Rusia”,
“Canadá”, “Australia”, “Alemania”, “Francia”, “Italia”, “España”, “Reino Unido”, “Portugal”, “Suiza”, “Grecia”,
“Marruecos”, “Sudáfrica”, “Kenia”, “Nigeria”, “Arabia Saudita”, “Irán”, “Irak”, “Israel”, “Vietnam”, “Tailandia”
],
“Colores y formas”: [
“Rojo”, “Azul”, “Amarillo”, “Verde”, “Naranja”, “Morado”, “Rosa”, “Negro”, “Blanco”, “Gris”,
“Violeta”, “Turquesa”, “Cian”, “Magenta”, “Dorado”, “Plateado”, “Bronce”, “Beige”, “Marrón”, “Fucsia”,
“Lima”, “Lavanda”, “Índigo”, “Rubí”, “Esmeralda”, “Zafiro”, “Ámbar”, “Ocre”, “Salmón”, “Coral”,
“Crema”, “Carbón”, “Perla”, “Transparente”, “Opaco”, “Brillante”, “Mate”, “Rayado”, “Cuadriculado”, “Estrellado”,
“Círculo”, “Cuadrado”, “Triángulo”, “Rectángulo”, “Óvalo”, “Rombo”, “Pentágono”, “Hexágono”, “Octágono”, “Esfera”,
“Cubo”, “Pirámide”, “Cilindro”, “Cono”, “Toroide”, “Trapecio”, “Paralelogramo”, “Elipse”, “Punto”, “Línea”,
“Curva”, “Zigzag”, “Espiral”, “Onda”, “Flecha”, “Corazón”, “Estrella”, “Media Luna”, “Cruz”, “Diamante”,
“Gota”, “Relámpago”, “Nube”, “Sol”, “Flor”, “Hoja”, “Arco”, “Célula”, “Átomo”, “Molécula”,
“Fractal”, “Simetría”, “Asimetría”, “Volumen”, “Superficie”, “Profundidad”, “Plano”, “Vertical”, “Horizontal”, “Diagonal”,
“Polígono”, “Poliedro”, “Bicolor”, “Tricolor”, “Monocromo”, “Acuarela”, “Pastel”, “Neón”, “Tierra”, “Marfil”
],
“Emociones y sentimientos”: [
“Alegría”, “Tristeza”, “Miedo”, “Enojo”, “Amor”, “Sorpresa”, “Calma”, “Ansiedad”, “Euforia”, “Aburrimiento”,
“Felicidad”, “Paz”, “Contento”, “Satisfacción”, “Placer”, “Orgullo”, “Admiración”, “Gratitud”, “Esperanza”, “Optimismo”,
“Melancolía”, “Desesperación”, “Angustia”, “Soledad”, “Pesar”, “Decepción”, “Nostalgia”, “Vulnerabilidad”, “Vergüenza”, “Culpa”,
“Ira”, “Rabia”, “Odio”, “Resentimiento”, “Frustración”, “Celos”, “Envidia”, “Desprecio”, “Hostilidad”, “Agresión”,
“Terror”, “Pánico”, “Alarma”, “Inseguridad”, “Preocupación”, “Tensión”, “Estrés”, “Vértigo”, “Fobia”, “Shock”,
“Pasión”, “Deseo”, “Cariño”, “Ternura”, “Compasión”, “Empatía”, “Lealtad”, “Devoción”, “Atracción”, “Intimidad”,
“Confusión”, “Asombro”, “Estupefacción”, “Duda”, “Curiosidad”, “Interés”, “Inquietud”, “Excitement”, “Vibración”, “Hilaridad”,
“Serenidad”, “Aceptación”, “Resignación”, “Perdón”, “Alivio”, “Confort”, “Tranquilidad”, “Relajación”, “Meditación”, “Equilibrio”,
“Indiferencia”, “Apatía”, “Hastío”, “Tedio”, “Desinterés”, “Frialdad”, “Neutralidad”, “Impasibilidad”, “Desgano”, “Monotonía”,
“Entusiasmo”, “Fuerza”, “Valentía”, “Determinación”, “Concentración”, “Compromiso”, “Inspiración”, “Motivación”, “Júbilo”, “Extasis”
],
“Cultura de internet”: [
“Meme”, “Hashtag”, “Influencer”, “Troll”, “Selfie”, “Streaming”, “Podcast”, “Viral”, “Emoji”, “GIF”,
“Vlogger”, “Gamer”, “E-sports”, “Twitch”, “Discord”, “Red Social”, “Algoritmo”, “Bot”, “Spam”, “Phishing”,
“Ciberacoso”, “Deepfake”, “Reels”, “Shorts”, “Thumbnail”, “Clickbait”, “Baneo”, “Seguidor”, “Like”, “Compartir”,
“Trending Topic”, “Unboxing”, “ASMR”, “Challenge”, “Fandom”, “OTP”, “Cringe”, “Epic Fail”, “POV”, “NSFW”,
“Bait-and-switch”, “Lo-Fi”, “Bit”, “NFT”, “Criptomoneda”, “Blockchain”, “Metaverso”, “Avatar”, “Realidad Virtual”, “Realidad Aumentada”,
“Mod”, “Hack”, “Cheats”, “Easter Egg”, “Pixel”, “Lag”, “Ping”, “Servidor”, “Banda Ancha”, “Fibra Óptica”,
“URL”, “Dominio”, “Hosting”, “Firewall”, “VPN”, “Cloud Computing”, “Big Data”, “Inteligencia Artificial”, “Machine Learning”, “DDoS”,
“Captcha”, “Two-Factor Auth”, “Password Manager”, “Dark Web”, “Anonimato”, “Vaporwave”, “Aesthetic”, “Cosplay”, “Fan Art”, “Fan Fiction”,
“Crowdfunding”, “Kickstarter”, “GoFundMe”, “Pet-fluencer”, “Zoomer”, “Boomer”, “Millennial”, “Gen Z”, “Cancel Culture”, “Ship”,
“Doppelgänger”, “Griefer”, “Loot Box”, “Early Access”, “Beta”, “Alpha”, “Patch”, “Update”, “Bug”, “Glitch”
],
“Cocina y comida”: [
“Pizza”, “Tacos”, “Sushi”, “Pasta”, “Hamburguesa”, “Ensalada”, “Curry”, “Paella”, “Sopa”, “Queso”,
“Baguette”, “Croissant”, “Tiramisú”, “Churros”, “Guacamole”, “Ceviche”, “Asado”, “Barbacoa”, “Empanada”, “Arepa”,
“Wok”, “Ramen”, “Dim Sum”, “Pad Thai”, “Falafel”, “Hummus”, “Kebab”, “Moussaka”, “Lasagna”, “Risotto”,
“Gnocchi”, “Pesto”, “Boloñesa”, “Focaccia”, “Donut”, “Muffin”, “Pancakes”, “Waffles”, “Crepes”, “Gelato”,
“Chocolate”, “Vainilla”, “Fresa”, “Limón”, “Naranja”, “Manzana”, “Plátano”, “Aguacate”, “Tomate”, “Cebolla”,
“Ajo”, “Pimienta”, “Sal”, “Azúcar”, “Miel”, “Vinagre”, “Aceite”, “Mantequilla”, “Huevo”, “Leche”,
“Yogur”, “Pollo”, “Carne”, “Pescado”, “Marisco”, “Atún”, “Salmón”, “Camarón”, “Cordero”, “Cerdo”,
“Vino”, “Cerveza”, “Café”, “Té”, “Zumo”, “Agua”, “Refresco”, “Coctel”, “Batido”, “Smoothie”,
“Picante”, “Dulce”, “Salado”, “Amargo”, “Umami”, “Fritura”, “Horneado”, “Asado”, “Hervido”, “Vapor”,
“Olla”, “Sartén”, “Cuchillo”, “Tenedor”, “Cuchara”, “Copa”, “Plato”, “Bandeja”, “Receta”, “Chef”
],
“Películas y series de TV”: [
“Titanic”, “Star Wars”, “El Padrino”, “Friends”, “Breaking Bad”, “Stranger Things”, “Game of Thrones”, “Matrix”, “Harry Potter”, “Toy Story”,
“Pulp Fiction”, “El Señor de los Anillos”, “Jurassic Park”, “Forrest Gump”, “Inception”, “Avatar”, “Terminator”, “Alien”, “Gladiator”, “Casablanca”,
“La La Land”, “Parásitos”, “Joker”, “Vengadores”, “Spider-Man”, “Batman”, “Wonder Woman”, “Superman”, “Los Simpson”, “South Park”,
“The Office”, “Seinfeld”, “Lost”, “House”, “Grey’s Anatomy”, “The Big Bang Theory”, “How I Met Your Mother”, “Glee”, “Euphoria”, “Succession”,
“The Crown”, “Peaky Blinders”, “Chernobyl”, “Ozark”, “Narcos”, “Vikingos”, “The Witcher”, “Squid Game”, “Money Heist”, “Dark”,
“Élite”, “Outlander”, “The Mandalorian”, “Black Mirror”, “Doctor Who”, “Sherlock”, “Fargo”, “True Detective”, “Westworld”, “Fleabag”,
“E.T.”, “Indiana Jones”, “Regreso al Futuro”, “El Rey León”, “Aladdin”, “La Sirenita”, “Frozen”, “Moana”, “Coco”, “Encanto”,
“Interstellar”, “Gravity”, “Dunkerque”, “1917”, “Bohemian Rhapsody”, “Rocketman”, “Whiplash”, “Birdman”, “Drive”, “Mad Max”,
“El Viaje de Chihiro”, “Mi Vecino Totoro”, “Akira”, “Your Name”, “El Caballero Oscuro”, “Origen”, “Misión Imposible”, “Rápidos y Furiosos”, “Rocky”, “Tiburón”,
“Psicosis”, “El Exorcista”, “El Resplandor”, “Sexto Sentido”, “Saw”, “It”, “Get Out”, “Blade Runner”, “Dune”, “Arrival”
],
“Música y bandas”: [
“Rock”, “Pop”, “Jazz”, “Clásica”, “Reguetón”, “Hip Hop”, “Metal”, “Cumbia”, “Salsa”, “Bachata”,
“Tango”, “Blues”, “Folk”, “Country”, “Electrónica”, “Indie”, “Gospel”, “Punk”, “Ska”, “Reggae”,
“Madonna”, “Queen”, “Beatles”, “Nirvana”, “Metallica”, “AC/DC”, “Guns N’ Roses”, “Coldplay”, “U2”, “Radiohead”,
“Oasis”, “Red Hot Chili Peppers”, “Foo Fighters”, “Green Day”, “The Rolling Stones”, “Bob Marley”, “Elvis Presley”, “Frank Sinatra”, “Ella Fitzgerald”, “Louis Armstrong”,
“Mozart”, “Beethoven”, “Bach”, “Chopin”, “Vivaldi”, “Tchaikovsky”, “Debussy”, “Ravel”, “Stravinsky”, “Handel”,
“Bad Bunny”, “J Balvin”, “Maluma”, “Daddy Yankee”, “Karol G”, “Rosalía”, “C. Tangana”, “Shakira”, “Enrique Iglesias”, “Ricky Martin”,
“Eminem”, “Snoop Dogg”, “Jay-Z”, “Kendrick Lamar”, “Drake”, “Cardi B”, “Nicki Minaj”, “The Notorious B.I.G.”, “Tupac”, “Run-DMC”,
“Adele”, “Beyoncé”, “Lady Gaga”, “Taylor Swift”, “Ed Sheeran”, “Bruno Mars”, “Rihanna”, “Dua Lipa”, “Ariana Grande”, “The Weeknd”,
“Batería”, “Guitarra”, “Bajo”, “Piano”, “Violín”, “Trompeta”, “Saxofón”, “Flauta”, “Micrófono”, “Amplificador”,
“Concierto”, “Festival”, “Álbum”, “Sencillo”, “Letra”, “Melodía”, “Ritmo”, “Armonía”, “Acorde”, “Pista”
],
“Ocupaciones”: [
“Doctor”, “Profesor”, “Ingeniero”, “Chef”, “Bombero”, “Policía”, “Abogado”, “Artista”, “Periodista”, “Programador”,
“Arquitecto”, “Mecánico”, “Electricista”, “Fontanero”, “Carpintero”, “Agricultor”, “Pescador”, “Minero”, “Cajero”, “Mesero”,
“Bailarín”, “Músico”, “Actor”, “Director”, “Diseñador”, “Fotógrafo”, “Escultor”, “Pintor”, “Modelo”, “Piloto”,
“Azafata”, “Enfermero”, “Terapeuta”, “Farmacéutico”, “Veterinario”, “Dentista”, “Psicólogo”, “Contador”, “Administrador”, “Secretario”,
“Investigador”, “Científico”, “Astrónomo”, “Geólogo”, “Biólogo”, “Químico”, “Matemático”, “Físico”, “Historiador”, “Filósofo”,
“Deportista”, “Entrenador”, “Árbitro”, “Juez”, “Sacerdote”, “Monja”, “Pastor”, “Rabino”, “Imán”, “Chamán”,
“Soldado”, “Oficial”, “Detectiv”, “Guardia de seguridad”, “Cartero”, “Bibliotecario”, “Traductor”, “Editor”, “Escritor”, “Crítico”,
“Comercial”, “Vendedor”, “Gerente”, “Director General”, “Emprendedor”, “Inversor”, “Banquero”, “Corredor de bolsa”, “Agente de bienes raíces”, “Consultor”,
“Maestro de obras”, “Albañil”, “Jardinero”, “Barbero”, “Peluquero”, “Sastre”, “Zapatero”, “Joyero”, “Relojero”, “Cerrajero”,
“Taxista”, “Camionero”, “Repartidor”, “Marinero”, “Cazador”, “Rescatista”, “Voluntario”, “Político”, “Diplomático”, “Jefe de Estado”
],
“Escuela y educación”: [
“Examen”, “Tarea”, “Pizarra”, “Libro”, “Profesor”, “Estudiante”, “Mochila”, “Recreo”, “Matemáticas”, “Historia”,
“Geografía”, “Ciencias”, “Literatura”, “Idioma”, “Física”, “Química”, “Biología”, “Deportes”, “Arte”, “Música”,
“Aula”, “Biblioteca”, “Laboratorio”, “Gimnasio”, “Cafetería”, “Patio”, “Director”, “Tutor”, “Consejero”, “Campana”,
“Bolígrafo”, “Lápiz”, “Cuaderno”, “Goma”, “Regla”, “Compás”, “Calculadora”, “Archivador”, “Resaltador”, “Post-it”,
“Diploma”, “Título”, “Graduación”, “Universidad”, “Colegio”, “Escuela Primaria”, “Secundaria”, “Bachillerato”, “Preescolar”, “Doctorado”,
“Beca”, “Préstamo Estudiantil”, “Matrícula”, “Crédito”, “Semestre”, “Trimestre”, “Clase”, “Conferencia”, “Seminario”, “Taller”,
“Investigación”, “Tesis”, “Monografía”, “Ensayo”, “Informe”, “Presentación”, “Debate”, “Disertación”, “Puntos”, “Calificación”,
“Aprobado”, “Reprobado”, “Sobresaliente”, “Notable”, “Suficiente”, “Insuficiente”, “Recuperación”, “Extraordinario”, “Asistencia”, “Ausencia”,
“Puntualidad”, “Disciplina”, “Compañero”, “Amigo”, “Bullying”, “Uniforme”, “Manual”, “Mapa”, “Globo Terráqueo”, “Microscopio”,
“Telescopio”, “Ecuación”, “Fórmula”, “Hipótesis”, “Teorema”, “Biografía”, “Poema”, “Novela”, “Teatro”, “Ensayo Académico”
],
“Pasatiempos y actividades”: [
“Leer”, “Correr”, “Pintar”, “Cocinar”, “Viajar”, “Nadar”, “Jugar Videojuegos”, “Acampar”, “Coleccionar”, “Pescar”,
“Caminata”, “Ciclismo”, “Senderismo”, “Jardinería”, “Tejer”, “Coser”, “Bordar”, “Esculpir”, “Fotografía”, “Dibujar”,
“Cantar”, “Bailar”, “Tocar un instrumento”, “Escribir”, “Poesía”, “Cine”, “Teatro”, “Ópera”, “Museo”, “Galería”,
“Ajedrez”, “Damas”, “Póker”, “Monopolio”, “Scrabble”, “Juegos de Mesa”, “Cartas”, “Rompecabezas”, “Sudoku”, “Crucigrama”,
“Yoga”, “Pilates”, “Gimnasia”, “Levantamiento de pesas”, “Boxeo”, “Judo”, “Karate”, “Esgrima”, “Tiro con arco”, “Escalada”,
“Observación de aves”, “Astronomía”, “Filatelia”, “Numismática”, “Modelismo”, “Radioaficionado”, “Programación”, “Robótica”, “Electrónica”, “Carpintería”,
“Caza”, “Montar a caballo”, “Esquí”, “Snowboard”, “Surf”, “Vela”, “Kayak”, “Buceo”, “Snorkel”, “Patinaje”,
“Voluntariado”, “Meditación”, “Aprender un idioma”, “Bloguear”, “Podcasting”, “Vlogging”, “Tatuar”, “Graffiti”, “Bricolaje”, “Cata de vinos”,
“Cervecería casera”, “Repostería”, “Panadería”, “Costura”, “Maquillaje”, “Cosméticos”, “Moda”, “Estilismo”, “Decoración”, “Manualidades”
],
“Deportes”: [
“Fútbol”, “Baloncesto”, “Tenis”, “Natación”, “Atletismo”, “Ciclismo”, “Golf”, “Boxeo”, “Béisbol”, “Rugby”,
“Voleibol”, “Balonmano”, “Hockey”, “Fórmula 1”, “Motociclismo”, “Esquí”, “Snowboard”, “Surf”, “Skateboarding”, “Gimnasia”,
“Judo”, “Karate”, “Taekwondo”, “Lucha Libre”, “Esgrima”, “Tiro con arco”, “Escalada”, “Remo”, “Vela”, “Polo”,
“Críquet”, “Bádminton”, “Squash”, “Tenis de Mesa”, “Softbol”, “Fútbol Americano”, “Lacrosse”, “Waterpolo”, “Clavados”, “Saltos”,
“Maratón”, “Triatlón”, “Decatlón”, “Salto de longitud”, “Salto de altura”, “Jabalina”, “Disco”, “Martillo”, “Carrera de vallas”, “Relevos”,
“Cancha”, “Pista”, “Campo”, “Portería”, “Canasta”, “Red”, “Raqueta”, “Bate”, “Palo”, “Pelota”,
“Árbitro”, “Entrenador”, “Capitán”, “Equipo”, “Rival”, “Aficionado”, “Estadio”, “Olimpiadas”, “Mundial”, “Copa”,
“Medalla”, “Trofeo”, “Goles”, “Puntos”, “Tanto”, “Falta”, “Penalti”, “Tiempo Extra”, “Descanso”, “Calentamiento”,
“Estiramiento”, “Lesión”, “Fisioterapia”, “Nutrición”, “Dieta”, “Suplemento”, “Dopaje”, “Récord”, “Marca”, “Liga”,
“Campeonato”, “Torneo”, “Pase”, “Tiro”, “Driblar”, “Bloqueo”, “Defensa”, “Ataque”, “Táctica”, “Estrategia”
],
“Picante (atrevida pícara algo arriesgada para subir la atención y las risas)”: [
“Tanga”, “Lencería”, “Fantasía”, “Azote”, “Fetiche”, “Cama”, “Beso negro”, “Swinger”, “Orgasmo”, “Vibrador”,
“Stripper”, “Desnudo”, “Masturbación”, “BDSM”, “Dominación”, “Sumisión”, “Sado”, “Masoquismo”, “Exhibicionismo”, “Voyeurismo”,
“Trío”, “Cuarteto”, “Poliamor”, “Relación Abierta”, “Infidelidad”, “Aventura”, “Amante”, “Secreto”, “Prohibido”, “Tabú”,
“Kamastura”, “Cincuenta sombras”, “Juguetes”, “Látigo”, “Esposas”, “Corpiño”, “Tacones”, “Medias”, “Portaligas”, “Lubricante”,
“Condón”, “Pastilla”, “ETS”, “Clamidia”, “Sífilis”, “Gonorrea”, “Herpes”, “VIH”, “Test”, “Prevención”,
“Sexo Oral”, “Sexo Anal”, “Kamasutra”, “Posición”, “Gemidos”, “Sudor”, “Aliento”, “Aroma”, “Piel”, “Labios”,
“Senos”, “Pezones”, “Culo”, “Muslos”, “Entrepierna”, “Clítoris”, “Pene”, “Vagina”, “Testículos”, “Lengua”,
“Beso francés”, “Chupetón”, “Mordida”, “Caricias”, “Masaje”, “Ataque”, “Conquista”, “Seducción”, “Deseo”, “Apetito”,
“Cita a ciegas”, “Swipe”, “Match”, “Tinder”, “Grindr”, “OnlyFans”, “Pornografía”, “Erótica”, “Novela”, “Película”,
“Bikini”, “Microfibra”, “Encaje”, “Cuero”, “Goma”, “Uniforme”, “Rol”, “Disfraces”, “Gozar”, “Caliente”
]
};
// Variables globales
let players = [];
let roles = [];
let selectedCategoryKey = ”;
let secretWord = ”;
let gamePhase = ‘setup’;
let currentPlayerIndex = 0;
let countdownInterval;
let timeLeft = 120;
let votes = {};
let votingPlayers = [];
let currentVoterIndex = 0;
let numImpostors = 1;
let votesCastByPlayer = {};
let impostorHintEnabled = true; // NUEVA VARIABLE: Pista de categoría activa por defecto
// Referencias a elementos del DOM
const input = document.getElementById(‘playerNameInput’);
const addButton = document.getElementById(‘addPlayerButton’);
const startButton = document.getElementById(‘startGameButton’);
const playerListContainer = document.getElementById(‘playerList’);
const minPlayersAlert = document.getElementById(‘minPlayersAlert’);
const categorySelect = document.getElementById(‘categorySelect’);
const impostorCountSelect = document.getElementById(‘impostorCountSelect’);
const impostorHintToggle = document.getElementById(‘impostorHintToggle’); // NUEVO TOGGLE
const skipTimerButton = document.getElementById(‘skipTimerButton’);
const setupPhase = document.getElementById(‘setupPhase’);
const rolePhase = document.getElementById(‘rolePhase’);
const countdownPhase = document.getElementById(‘countdownPhase’);
const votingPhase = document.getElementById(‘votingPhase’);
const gameStartedPhase = document.getElementById(‘gameStartedPhase’);
const currentPlayerDisplay = document.getElementById(‘currentPlayerDisplay’);
const viewRoleButton = document.getElementById(‘viewRoleButton’);
const roleRevealBox = document.getElementById(‘roleRevealBox’);
const revealedRole = document.getElementById(‘revealedRole’);
const nextPlayerButton = document.getElementById(‘nextPlayerButton’);
const secretCategoryBox = document.getElementById(‘secretCategoryBox’);
const secretCategoryLabel = document.getElementById(‘secretCategoryLabel’);
const secretCategoryName = document.getElementById(‘secretCategoryName’);
const countdownDisplay = document.getElementById(‘countdownDisplay’);
const randomPlayerDisplay = document.getElementById(‘randomPlayerDisplay’);
const finalSecretWord = document.getElementById(‘finalSecretWord’);
const finalCategoryName = document.getElementById(‘finalCategoryName’);
const finalVotedPlayer = document.getElementById(‘finalVotedPlayer’);
const finalRoleList = document.getElementById(‘finalRoleList’);
const voteButtonsContainer = document.getElementById(‘voteButtonsContainer’);
const voteResultDisplay = document.getElementById(‘voteResultDisplay’);
const votedPlayerDisplay = document.getElementById(‘votedPlayerDisplay’);
const revealResultsButton = document.getElementById(‘revealResultsButton’);
const replaySameSettingsButton = document.getElementById(‘replaySameSettingsButton’);
const restartTotalButton = document.getElementById(‘restartTotalButton’);
// — Funciones de Utilidad —
// Mezcla un array (Algoritmo de Fisher-Yates)
function shuffleArray(array) {
for (let i = array.length – 1; i > 0; i–) {
const j = Math.floor(Math.random() * (i + 1));
[array[i], array[j]] = [array[j], array[i]];
}
}
// Muestra u oculta las fases
function setPhase(newPhase) {
gamePhase = newPhase;
// Ocultar todas
setupPhase.classList.add(‘hidden’);
rolePhase.classList.add(‘hidden’);
countdownPhase.classList.add(‘hidden’);
votingPhase.classList.add(‘hidden’);
gameStartedPhase.classList.add(‘hidden’);
// Mostrar la correcta
if (newPhase === ‘setup’) {
setupPhase.classList.remove(‘hidden’);
} else if (newPhase === ‘roleViewing’) {
rolePhase.classList.remove(‘hidden’);
} else if (newPhase === ‘countdown’) {
countdownPhase.classList.remove(‘hidden’);
} else if (newPhase === ‘voting’) {
votingPhase.classList.remove(‘hidden’);
} else if (newPhase === ‘started’) {
gameStartedPhase.classList.remove(‘hidden’);
}
}
// Función para formatear el tiempo a MM:SS
function formatTime(totalSeconds) {
const minutes = Math.floor(totalSeconds / 60);
const seconds = totalSeconds % 60;
return `${minutes.toString().padStart(2, ‘0’)}:${seconds.toString().padStart(2, ‘0’)}`;
}
// — Funcionalidad de Reinicio Rápido y Total —
function quickReplay() {
// Se mantienen: players, selectedCategoryKey, numImpostors, impostorHintEnabled
// 1. Re-asignar roles y nueva palabra secreta
assignRoles(false); // No necesita leer la pista, ya está guardada
// 2. Pasar directamente a la fase de visualización de roles (Role Viewing)
setPhase(‘roleViewing’);
currentPlayerIndex = 0;
updateRoleViewingUI();
}
// Función de Reinicio Total (Modificada para mantener la lista de jugadores Y la categoría)
function totalRestart() {
// Se mantienen: players (lista de jugadores), selectedCategoryKey (categoría elegida)
// 1. Limpiar todos los datos específicos del juego
roles = [];
secretWord = ”;
currentPlayerIndex = 0;
votes = {};
votingPlayers = [];
currentVoterIndex = 0;
votesCastByPlayer = {};
// Si el temporizador estaba activo, detenerlo
if (countdownInterval) {
clearInterval(countdownInterval);
countdownInterval = null;
}
// 2. Reiniciar los elementos de configuración de la UI
// Leer la configuración actual de los selectores
numImpostors = parseInt(impostorCountSelect.value);
impostorHintEnabled = impostorHintToggle.checked;
// Resetear el selector de impostores, aunque updatePlayerList() ya lo hace
impostorCountSelect.innerHTML = ‘1’;
// 3. Volver a la fase de configuración
updatePlayerList(); // Re-renderiza la lista de jugadores y actualiza el selector de impostores
checkCanStartGame(); // Actualiza el estado del botón
setPhase(‘setup’);
}
// — Fase de Configuración (Setup) —
function fillCategoryDropdown() {
// Guardar la selección actual si existe para mantenerla después de la reconstrucción
const currentSelection = categorySelect.value;
// Limpiar opciones anteriores por si acaso
categorySelect.innerHTML = ‘– Elige una categoría –‘;
// Añadir la categoría aleatoria al inicio
const randomOption = document.createElement(‘option’);
randomOption.value = ‘Misterio Total (Aleatoria)’;
randomOption.textContent = ‘🎲 ¡Misterio Total! (Aleatoria)’;
categorySelect.appendChild(randomOption);
const keys = Object.keys(CATEGORY_DATA);
keys.forEach(key => {
const option = document.createElement(‘option’);
option.value = key;
option.textContent = key;
categorySelect.appendChild(option);
});
// Intentar restaurar la selección anterior si todavía existe
if (currentSelection && categorySelect.querySelector(`option[value=”${currentSelection}”]`)) {
categorySelect.value = currentSelection;
}
}
function updatePlayerList() {
playerListContainer.innerHTML = ”;
players.forEach((player, index) => {
const playerElement = document.createElement(‘div’);
playerElement.className = ‘flex justify-between items-center p-3 bg-gray-50 rounded-lg border border-gray-200’;
playerElement.innerHTML = `
${player}
`;
playerListContainer.appendChild(playerElement);
});
updateImpostorSelector();
checkCanStartGame();
}
function updateImpostorSelector() {
const playerCount = players.length;
const maxImpostors = playerCount – 2;
impostorCountSelect.innerHTML = ”;
impostorCountSelect.disabled = playerCount < 3;
if (playerCount < 3) {
impostorCountSelect.innerHTML = 'Min. 3 jugadores’;
} else {
// Capturar el valor actual (si existe) antes de borrar y re-crear
const currentImpostorCount = parseInt(impostorCountSelect.value) || 1;
let newImpostorCount = 1;
for (let i = 1; i = 1 && currentImpostorCount = 3;
const categorySelected = categorySelect.value !== “”;
const maxImpostors = players.length – 2;
const impostorCount = parseInt(impostorCountSelect.value);
const impostorCountValid = minPlayersMet && impostorCount >= 1 && impostorCount <= maxImpostors;
const isValid = minPlayersMet && categorySelected && impostorCountValid;
startButton.disabled = !isValid;
minPlayersAlert.classList.toggle('hidden', isValid);
if (!minPlayersMet) {
minPlayersAlert.textContent = `Se necesitan al menos 3 jugadores (tienes ${players.length}).`;
} else if (!categorySelected) {
minPlayersAlert.textContent = '¡Falta seleccionar una Categoría Secreta!';
} else if (!impostorCountValid) {
minPlayersAlert.textContent = `Máximo de impostores permitido: ${maxImpostors}.`;
} else {
minPlayersAlert.textContent = '';
}
startButton.textContent = isValid ? 'Comenzar Asignación de Roles' : 'Falta Configuración';
}
function addPlayer() {
const name = input.value.trim();
if (name && !players.includes(name)) {
players.push(name);
input.value = '';
updatePlayerList();
} else if (players.includes(name)) {
console.error('El nombre ya ha sido añadido.');
}
}
function assignRoles(readHintSetting = true) {
// Guardar configuración actual
selectedCategoryKey = categorySelect.value;
numImpostors = parseInt(impostorCountSelect.value);
if (readHintSetting) {
impostorHintEnabled = impostorHintToggle.checked; // Leer el estado del toggle
}
if (players.length k !== ‘Misterio Total (Aleatoria)’);
// Seleccionar una categoría aleatoria para el juego
const randomCategoryIndex = Math.floor(Math.random() * validCategories.length);
categoryToUse = validCategories[randomCategoryIndex];
}
// Obtener la lista de palabras de la categoría final seleccionada (sea la original o la aleatoria)
const wordList = CATEGORY_DATA[categoryToUse];
// Fallback en caso de error (aunque la data ya tiene palabras)
if (!wordList || wordList.length === 0) {
secretWord = “Palabra clave (Error)”;
selectedCategoryKey = “General”;
return;
}
// Seleccionar la palabra de la lista usando Math.random() – ¡Aquí se genera la aleatoriedad!
const randomIndex = Math.floor(Math.random() * wordList.length);
secretWord = wordList[randomIndex];
// Actualizar la clave seleccionada para que se muestre correctamente al final del juego.
selectedCategoryKey = categoryToUse;
// 3. Reiniciar el objeto de votos
votes = {};
players.forEach(p => votes[p] = 0);
}
// — Fase de Visualización de Roles —
function updateRoleViewingUI() {
if (currentPlayerIndex {
timeLeft–;
countdownDisplay.textContent = formatTime(timeLeft);
// Efecto de color para los últimos 10 segundos
if (timeLeft 0) {
countdownDisplay.classList.add(‘text-impostor’);
} else if (timeLeft {
votes[p] = 0;
votesCastByPlayer[p] = 0;
});
// 2. Mostrar el selector de botones
updateVotingUI();
}
function updateVotingUI() {
voteButtonsContainer.innerHTML = ”;
// Si ya todos los jugadores han emitido su número de votos requerido, ir al conteo.
// Ojo: La condición correcta es verificar si el último jugador ya votó.
if (currentVoterIndex >= votingPlayers.length) {
tallyVotes();
return;
}
const currentVoter = votingPlayers[currentVoterIndex];
// Asegurarse de que votesCastByPlayer[currentVoter] esté inicializado
votesCastByPlayer[currentVoter] = votesCastByPlayer[currentVoter] || 0;
const votesLeft = numImpostors – votesCastByPlayer[currentVoter];
// Mensaje para el votante actual
voteResultDisplay.classList.remove(‘hidden’);
votedPlayerDisplay.textContent = `${currentVoter}, tienes ${votesLeft} voto${votesLeft === 1 ? ” : ‘s’} restante${votesLeft === 1 ? ” : ‘s’} para acusar.`;
votedPlayerDisplay.classList.add(‘text-primary’);
votedPlayerDisplay.classList.remove(‘text-vote’);
// Generar botones para CADA jugador
players.forEach(player => {
const button = document.createElement(‘button’);
button.textContent = player;
button.dataset.votedFor = player;
button.className = ‘game-button bg-vote text-white p-4 rounded-lg font-bold text-lg hover:bg-blue-600’;
button.addEventListener(‘click’, handleVote);
voteButtonsContainer.appendChild(button);
});
}
function handleVote(event) {
const votedFor = event.target.dataset.votedFor;
if (!votedFor) return;
const currentVoter = votingPlayers[currentVoterIndex];
// 1. Registrar el voto
votes[votedFor] = (votes[votedFor] || 0) + 1;
// 2. Contar el voto emitido por el jugador actual
votesCastByPlayer[currentVoter]++;
const votesLeft = numImpostors – votesCastByPlayer[currentVoter];
// 3. Mostrar voto registrado
votedPlayerDisplay.textContent = `${currentVoter} ha votado por ${votedFor}. Le quedan ${votesLeft} voto${votesLeft === 1 ? ” : ‘s’}.`;
votedPlayerDisplay.classList.remove(‘text-primary’);
votedPlayerDisplay.classList.add(‘text-vote’);
// 4. Desactivar botones temporalmente para simular el turno
Array.from(voteButtonsContainer.querySelectorAll(‘button’)).forEach(btn => btn.disabled = true);
// 5. Pausa simulada y actualización
setTimeout(() => {
// Verificar si el jugador actual ha agotado sus votos
if (votesCastByPlayer[currentVoter] >= numImpostors) {
// Si ya no tiene votos, pasamos al siguiente jugador
currentVoterIndex++;
}
// Habilitar botones de nuevo antes de actualizar la UI si aún hay jugadores por votar
Array.from(voteButtonsContainer.querySelectorAll(‘button’)).forEach(btn => btn.disabled = false);
// Actualizar la UI, ya sea con el mismo votante o el siguiente
updateVotingUI();
}, 1500); // Esperar 1.5 segundos antes de actualizar al siguiente turno
}
function tallyVotes() {
// Encontrar al jugador con más votos
let maxVotes = -1;
let votedPlayer = ‘Nadie’;
let tiedPlayers = [];
for (const player in votes) {
if (votes[player] > maxVotes) {
maxVotes = votes[player];
votedPlayer = player;
tiedPlayers = [player]; // Reiniciar empate
} else if (votes[player] === maxVotes && maxVotes > 0) {
tiedPlayers.push(player); // Añadir al empate
}
}
let finalAccused = votedPlayer;
// Manejar Empate
if (tiedPlayers.length > 1) {
finalAccused = tiedPlayers.join(‘ y ‘) + ‘ (EMPATE)’;
} else if (maxVotes === 0) {
finalAccused = ‘Nadie’;
}
// Mostrar resultado de la votación
votedPlayerDisplay.textContent = `El jugador más votado es: ${finalAccused} (Total: ${maxVotes} voto${maxVotes === 1 ? ” : ‘s’})`;
votedPlayerDisplay.classList.add(‘text-impostor’);
// Almacenar el resultado para la fase final
// Solo tomar el primer nombre o ‘Nadie’ si hay empate o cero votos
finalVotedPlayer.textContent = finalAccused.split(‘ (‘)[0];
// Mostrar botón para revelar el final
revealResultsButton.classList.remove(‘hidden’);
voteButtonsContainer.innerHTML = ”; // Limpiar botones
}
// — Fase Final de Revelación —
function showFinalResults() {
setPhase(‘started’);
// 1. Mostrar la Palabra Secreta y Categoría
finalSecretWord.textContent = secretWord;
finalCategoryName.textContent = selectedCategoryKey;
// 2. Mostrar la lista final de roles
finalRoleList.innerHTML = ”;
players.forEach((player, index) => {
const role = roles[index];
const isImpostor = role === ‘Impostor’;
const roleElement = document.createElement(‘p’);
roleElement.className = `p-1 rounded-lg ${isImpostor ? ‘bg-impostor/10 text-impostor font-bold’ : ‘text-town font-medium’}`;
roleElement.innerHTML = `${player}: ${role}`;
finalRoleList.appendChild(roleElement);
});
}
// — Event Listeners —
// 1. Añadir jugador al presionar botón o Enter
addButton.addEventListener(‘click’, addPlayer);
input.addEventListener(‘keypress’, (e) => {
if (e.key === ‘Enter’) {
e.preventDefault();
addPlayer();
}
});
// 2. Evento de cambio en la selección de categoría y el contador de impostores
categorySelect.addEventListener(‘change’, checkCanStartGame);
impostorCountSelect.addEventListener(‘change’, checkCanStartGame);
// 3. Iniciar el juego/asignación de roles
startButton.addEventListener(‘click’, () => {
assignRoles();
setPhase(‘roleViewing’);
currentPlayerIndex = 0;
updateRoleViewingUI();
});
// 4. Eliminar jugador
playerListContainer.addEventListener(‘click’, (e) => {
if (e.target.classList.contains(‘remove-player-btn’)) {
const index = parseInt(e.target.dataset.index);
removePlayer(index);
}
});
// 5. Ver rol
viewRoleButton.addEventListener(‘click’, viewRole);
// 6. Siguiente jugador (o comenzar fase de debate)
nextPlayerButton.addEventListener(‘click’, nextPlayer);
// 7. Botón para saltar el temporizador
skipTimerButton.addEventListener(‘click’, () => {
if (countdownInterval) clearInterval(countdownInterval);
startVotingPhase();
});
// 8. Botón de la nueva fase de votación a la revelación final
revealResultsButton.addEventListener(‘click’, showFinalResults);
// 9. Botón de Reinicio Rápido
replaySameSettingsButton.addEventListener(‘click’, quickReplay);
// 10. Botón de Reinicio Total (Mantiene jugadores Y categoría)
restartTotalButton.addEventListener(‘click’, totalRestart);
// 11. Toggle de Pista para el Impostor (No afecta el inicio, solo la revelación)
impostorHintToggle.addEventListener(‘change’, () => {
impostorHintEnabled = impostorHintToggle.checked;
});
// Inicialización al cargar la página
window.onload = () => {
fillCategoryDropdown(); // Llenar el dropdown de categorías
setPhase(‘setup’);
updatePlayerList();
// Si hay una categoría guardada (útil para recargas), establecerla.
if (selectedCategoryKey) {
categorySelect.value = selectedCategoryKey;
checkCanStartGame();
}
// Asegurarse de que el estado del toggle refleje el valor inicial
impostorHintToggle.checked = impostorHintEnabled;
};