<!DOCTYPE html>

<html lang="es">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Mi Torneo Escolar - Gestor Moderno</title>

    <script src="https://cdn.tailwindcss.com"></script>

    <!-- Librerías para QR y PDF -->

    <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>

    <link rel="preconnect" href="https://fonts.googleapis.com">

    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;900&display=swap" rel="stylesheet">

    <style>

        /* Estilo base y fondo animado */

        body {

            font-family: 'Inter', sans-serif;

            background-color: #0f0c29;

            background: linear-gradient(45deg, #0f0c29, #302b63, #24243e);

            background-size: 400% 400%;

            animation: gradientBG 15s ease infinite;

            color: #e0e0e0;

        }


        @keyframes gradientBG {

            0% { background-position: 0% 50%; }

            50% { background-position: 100% 50%; }

            100% { background-position: 0% 50%; }

        }


        /* Clases para gestionar vistas y animaciones */

        .view { display: none; }

        .view.active {

            display: block;

            animation: fadeIn 0.5s ease-in-out;

        }


        @keyframes fadeIn {

            from { opacity: 0; transform: translateY(10px); }

            to { opacity: 1; transform: translateY(0); }

        }

        

        /* Estilo mejorado para modales */

        .modal-backdrop {

            background-color: rgba(10, 10, 20, 0.5);

            backdrop-filter: blur(8px);

            -webkit-backdrop-filter: blur(8px);

            display: none;

        }

        .modal-backdrop.flex {

            display: flex;

            animation: fadeIn 0.3s ease;

        }

        .modal-content {

            animation: slideUp 0.4s ease-out;

        }


        @keyframes slideUp {

            from { transform: translateY(20px); opacity: 0; }

            to { transform: translateY(0); opacity: 1; }

        }


        /* Efecto "Glassmorphism" refinado */

        .glass-effect {

            background: rgba(36, 36, 62, 0.6);

            backdrop-filter: blur(12px);

            -webkit-backdrop-filter: blur(12px);

            border: 1px solid rgba(255, 255, 255, 0.1);

            box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37);

        }


        /* Estilo para pestañas activas */

        .tab-btn.active {

            border-color: #8B5CF6; /* violet-500 */

            color: #8B5CF6;

            background-color: rgba(139, 92, 246, 0.1);

        }

        

        /* Estilos para inputs y botones */

        .form-input {

            background-color: rgba(0,0,0,0.2);

            border: 1px solid rgba(255, 255, 255, 0.1);

            transition: all 0.3s ease;

        }

        .form-input:focus {

            outline: none;

            border-color: #8B5CF6;

            box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.4);

        }


        .btn-primary {

            background: linear-gradient(45deg, #8B5CF6, #EC4899);

            transition: all 0.3s ease;

            box-shadow: 0 4px 15px rgba(0,0,0,0.2);

        }

        .btn-primary:hover {

            transform: translateY(-2px);

            box-shadow: 0 6px 20px rgba(0,0,0,0.3);

        }

        .btn-primary:active {

            transform: translateY(0px) scale(0.98);

        }

        

        /* Estilos de impresión */

        @media print {

            body * { visibility: hidden; }

            #pdf-export-area, #pdf-export-area * { visibility: visible; }

            #pdf-export-area { position: absolute; left: 0; top: 0; width: 100%; }

            .no-print { display: none; }

        }

    </style>

</head>

<body>


    <div id="app" class="max-w-7xl mx-auto p-4 sm:p-6 lg:p-8 min-h-screen">


        <!-- Vista de Login / Bienvenida -->

        <div id="login-view" class="view active">

            <div class="max-w-md mx-auto mt-10 sm:mt-20 text-center">

                <h1 class="text-5xl font-black text-white uppercase tracking-wider" style="text-shadow: 0 0 15px rgba(236, 72, 153, 0.5);">Mi Torneo Escolar</h1>

                <p class="text-gray-400 mt-2 text-lg">La forma más fácil de gestionar tus torneos.</p>

                

                <div class="glass-effect p-8 rounded-2xl mt-8">

                    <div id="login-form-container">

                        <h2 class="text-2xl font-bold mb-6 text-white">Iniciar Sesión</h2>

                        <input type="text" id="login-username" placeholder="Nombre de Usuario" class="w-full form-input text-white rounded-md p-3 mb-4 placeholder-gray-400">

                        <input type="password" id="login-password" placeholder="Contraseña" class="w-full form-input text-white rounded-md p-3 mb-4 placeholder-gray-400">

                        <button id="login-btn" class="w-full btn-primary text-white font-bold py-3 rounded-lg">Ingresar</button>

                        <p class="text-sm text-gray-400 mt-4">¿No tienes cuenta? <a href="#" id="show-register-link" class="text-violet-400 hover:underline">Regístrate aquí</a></p>

                    </div>

                    <div id="register-form-container" class="hidden">

                        <h2 class="text-2xl font-bold mb-6 text-white">Crear Cuenta</h2>

                        <input type="text" id="register-username" placeholder="Nombre de Usuario (Nick Name)" class="w-full form-input text-white rounded-md p-3 mb-4 placeholder-gray-400">

                        <input type="password" id="register-password" placeholder="Contraseña" class="w-full form-input text-white rounded-md p-3 mb-4 placeholder-gray-400">

                        <button id="register-btn" class="w-full btn-primary text-white font-bold py-3 rounded-lg">Registrarse</button>

                        <p class="text-sm text-gray-400 mt-4">¿Ya tienes cuenta? <a href="#" id="show-login-link" class="text-violet-400 hover:underline">Inicia sesión</a></p>

                    </div>

                    <div class="mt-6 border-t border-gray-700 pt-6">

                        <p class="text-gray-400 mb-4">O puedes probar la aplicación sin registrarte:</p>

                        <button id="guest-btn" class="w-full bg-gray-600 text-white font-bold py-3 rounded-lg hover:bg-gray-700 transition-all duration-300">Entrar como Invitado</button>

                    </div>

                </div>

            </div>

        </div>


        <!-- Vista del Dashboard -->

        <div id="dashboard-view" class="view">

            <header class="mb-8 flex justify-between items-center">

                <div>

                    <h1 class="text-4xl font-black text-white">Mis Torneos</h1>

                    <p id="welcome-user" class="text-gray-400 mt-1"></p>

                </div>

                <button id="logout-btn" class="bg-red-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-red-700 transition-colors flex items-center space-x-2">

                    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M3 3a1 1 0 00-1 1v12a1 1 0 102 0V4a1 1 0 00-1-1zm10.293 9.293a1 1 0 001.414 1.414l3-3a1 1 0 000-1.414l-3-3a1 1 0 10-1.414 1.414L14.586 9H7a1 1 0 100 2h7.586l-1.293 1.293z" clip-rule="evenodd" /></svg>

                    <span>Cerrar Sesión</span>

                </button>

            </header>

            <div id="tournament-list" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6"></div>

            <div class="mt-8">

                <button id="go-to-create-btn" class="w-full sm:w-auto btn-primary text-white font-bold py-3 px-6 rounded-lg shadow-lg flex items-center justify-center">

                    <svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"></path></svg>

                    Crear Nuevo Torneo

                </button>

            </div>

        </div>


        <!-- Vista de Creación de Torneo -->

        <div id="create-tournament-view" class="view">

            <header class="mb-8">

                <button class="back-to-dashboard text-violet-400 hover:underline mb-4 no-print">&larr; Volver al Dashboard</button>

                <h1 class="text-4xl font-black text-white">Nuevo Torneo</h1>

            </header>

            <div class="glass-effect p-8 rounded-2xl">

                <!-- Wizard -->

                <div id="step-1">

                    <h2 class="text-2xl font-bold mb-2 text-white">Paso 1: Información</h2>

                    <p class="text-gray-400 mb-4">¡Vamos a empezar! Primero, dale un nombre a tu torneo y dinos qué deporte se jugará.</p>

                    <input type="text" id="tournament-name" placeholder="Nombre del Torneo" class="w-full form-input text-white rounded-md p-3 mb-4 placeholder-gray-400">

                    <input type="text" id="tournament-sport" placeholder="Deporte (ej. Fútbol, Voley, Basquet)" class="w-full form-input text-white rounded-md p-3 mb-4 placeholder-gray-400">

                    <button id="next-step-2-btn" class="w-full btn-primary text-white font-bold py-3 rounded-lg">Siguiente</button>

                </div>

                <div id="step-2" class="hidden">

                    <h2 class="text-2xl font-bold mb-2 text-white">Paso 2: Equipos</h2>

                    <p class="text-gray-400 mb-4">Ahora, añade todos los equipos que participarán. Escribe el nombre y pulsa "Añadir".</p>

                    <div class="flex mb-4"><input type="text" id="team-name-input" placeholder="Nombre del equipo" class="flex-grow form-input text-white rounded-l-md p-3 placeholder-gray-400"><button id="add-team-btn" class="bg-gray-600 px-4 rounded-r-md hover:bg-gray-500 text-white font-bold">Añadir</button></div>

                    <ul id="teams-list" class="space-y-2 mb-4 max-h-60 overflow-y-auto pr-2"></ul>

                    <div class="flex justify-between"><button id="back-step-1-btn" class="bg-gray-600 text-white py-2 px-4 rounded-lg hover:bg-gray-700">Anterior</button><button id="next-step-3-btn" class="btn-primary text-white py-2 px-4 rounded-lg">Siguiente</button></div>

                </div>

                <div id="step-3" class="hidden">

                    <h2 class="text-2xl font-bold mb-4 text-white">Paso 3: Formato</h2>

                    <select id="tournament-format" class="w-full form-input text-white rounded-md p-3 mb-4">

                        <option value="liga">Liga (Todos contra todos)</option>

                        <option value="eliminatoria">Eliminación Directa</option>

                    </select>

                    <div class="flex justify-between"><button id="back-step-2-btn" class="bg-gray-600 text-white py-2 px-4 rounded-lg hover:bg-gray-700">Anterior</button><button id="generate-fixture-btn" class="bg-blue-600 text-white font-bold py-2 px-4 rounded-lg hover:bg-blue-700">Generar y Guardar</button></div>

                </div>

            </div>

        </div>


        <!-- Vista de Gestión de Torneo -->

        <div id="manage-tournament-view" class="view">

            <header class="mb-6 flex justify-between items-center">

                <div>

                    <button class="back-to-dashboard text-violet-400 hover:underline mb-4 no-print">&larr; Volver al Dashboard</button>

                    <h1 id="manage-tournament-title" class="text-4xl font-black text-white"></h1>

                </div>

                <button id="show-podium-btn" class="hidden bg-yellow-400 text-yellow-900 font-bold py-2 px-4 rounded-lg shadow-md hover:bg-yellow-500 no-print flex items-center space-x-2 transition-transform hover:scale-105">

                    <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path d="M11.049 2.927c.3-.921 1.603-.921 1.902 0l1.519 4.674a1 1 0 00.95.69h4.915c.969 0 1.371 1.24.588 1.81l-3.976 2.888a1 1 0 00-.363 1.118l1.518 4.674c.3.922-.755 1.688-1.538 1.118l-3.976-2.888a1 1 0 00-1.176 0l-3.976 2.888c-.783.57-1.838-.197-1.538-1.118l1.518-4.674a1 1 0 00-.363-1.118l-3.976-2.888c-.783-.57-.38-1.81.588-1.81h4.914a1 1 0 00.951-.69l1.519-4.674z" /></svg>

                    <span>Ver Podio</span>

                </button>

            </header>

            <div class="border-b border-gray-700 mb-6 no-print"><nav class="-mb-px flex space-x-4"><button class="tab-btn whitespace-nowrap py-3 px-4 rounded-t-lg border-b-2 font-medium text-lg text-gray-400 hover:text-white border-transparent transition-colors" data-tab="partidos">Partidos</button><button class="tab-btn whitespace-nowrap py-3 px-4 rounded-t-lg border-b-2 font-medium text-lg text-gray-400 hover:text-white border-transparent transition-colors" data-tab="clasificacion">Clasificación</button><button class="tab-btn whitespace-nowrap py-3 px-4 rounded-t-lg border-b-2 font-medium text-lg text-gray-400 hover:text-white border-transparent transition-colors" data-tab="compartir">Compartir</button></nav></div>

            <div id="pdf-export-area" class="bg-transparent">

                <div id="tab-content-partidos" class="tab-content"></div>

                <div id="tab-content-clasificacion" class="tab-content hidden"></div>

            </div>

            <div id="tab-content-compartir" class="tab-content hidden">

                <div class="glass-effect p-8 rounded-2xl text-center max-w-lg mx-auto">

                    <h2 class="text-2xl font-bold mb-4 text-white">Compartir con Código QR</h2>

                    <p class="text-gray-400 mb-4">Los alumnos pueden escanear este código para ver el torneo en tiempo real.</p>

                    <div id="qrcode-container" class="flex justify-center mb-6 bg-white p-4 rounded-lg"></div>

                    <h2 class="text-2xl font-bold mt-8 mb-4 text-white">Exportar a PDF</h2>

                    <p class="text-gray-400 mb-4">Imprime el fixture o la clasificación en formato A4 para pegar en el colegio.</p>

                    <button id="export-pdf-btn" class="bg-red-600 text-white font-bold py-3 px-5 rounded-lg hover:bg-red-700 transition-colors">Imprimir PDF</button>

                </div>

            </div>

        </div>

        

        <!-- Vista Pública -->

        <div id="public-view" class="view"></div>


        <!-- Modal de Partido en Vivo (Standard) -->

        <div id="live-match-modal" class="modal-backdrop fixed inset-0 items-center justify-center z-50">

            <div class="glass-effect modal-content rounded-2xl p-8 w-full max-w-lg mx-4">

                <div id="standard-match-main-controls">

                    <div class="flex justify-between items-start">

                        <h2 class="text-3xl font-bold mb-6 text-white">Partido en Vivo</h2>

                        <div id="live-match-period" class="text-lg font-semibold bg-gray-900 px-3 py-1 rounded-md text-white">Tiempo: 1</div>

                    </div>

                    <div id="live-match-timer" class="text-7xl font-black font-mono text-center mb-6 text-white">00:00</div>

                    <div class="flex justify-center space-x-2 mb-8">

                        <button id="timer-start" class="bg-emerald-600 text-white px-4 py-2 rounded-lg flex items-center space-x-2 hover:bg-emerald-700"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" /></svg><span>Iniciar</span></button>

                        <button id="timer-pause" class="bg-yellow-500 text-white px-4 py-2 rounded-lg flex items-center space-x-2 hover:bg-yellow-600"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" /></svg><span>Pausar</span></button>

                        <button id="timer-reset" class="bg-gray-600 text-white px-4 py-2 rounded-lg flex items-center space-x-2 hover:bg-gray-700"><svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M4 2a1 1 0 011 1v2.101a7.002 7.002 0 0111.601 2.566 1 1 0 11-1.885.666A5.002 5.002 0 005.999 7H9a1 1 0 010 2H4a1 1 0 01-1-1V3a1 1 0 011-1zm10 10a1 1 0 011-1h5a1 1 0 011 1v5a1 1 0 11-2 0v-2.101a7.002 7.002 0 01-11.601-2.566 1 1 0 111.885-.666A5.002 5.002 0 0014.001 13H11a1 1 0 01-1-1z" clip-rule="evenodd" /></svg><span>Reiniciar</span></button>

                        <button id="timer-new-period" class="bg-blue-500 text-white px-4 py-2 rounded-lg hover:bg-blue-600">Nuevo Tiempo</button>

                    </div>

                    <div class="grid grid-cols-2 gap-6 text-center">

                        <div>

                            <h3 id="live-team1-name" class="text-xl font-bold mb-2 truncate text-white"></h3>

                            <div id="live-team1-score" class="text-8xl font-black mb-4 text-white">0</div>

                            <div class="flex justify-center space-x-3"><button class="score-btn bg-emerald-600 text-white w-14 h-14 rounded-full text-3xl font-bold hover:bg-emerald-700 transform hover:scale-110 transition-transform" data-team="1" data-op="add">+</button><button class="score-btn bg-red-600 text-white w-14 h-14 rounded-full text-3xl font-bold hover:bg-red-700 transform hover:scale-110 transition-transform" data-team="1" data-op="sub">-</button></div>

                        </div>

                        <div>

                            <h3 id="live-team2-name" class="text-xl font-bold mb-2 truncate text-white"></h3>

                            <div id="live-team2-score" class="text-8xl font-black mb-4 text-white">0</div>

                            <div class="flex justify-center space-x-3"><button class="score-btn bg-emerald-600 text-white w-14 h-14 rounded-full text-3xl font-bold hover:bg-emerald-700 transform hover:scale-110 transition-transform" data-team="2" data-op="add">+</button><button class="score-btn bg-red-600 text-white w-14 h-14 rounded-full text-3xl font-bold hover:bg-red-700 transform hover:scale-110 transition-transform" data-team="2" data-op="sub">-</button></div>

                        </div>

                    </div>

                </div>

                <!-- Sección de Penales / Opciones de Empate -->

                <div id="tiebreaker-options" class="hidden text-center">

                    <h3 class="text-xl font-bold mb-4 text-white">El partido ha terminado en empate</h3>

                    <p class="text-gray-400 mb-6">¿Cómo deseas definir el resultado?</p>

                    <div class="flex flex-col space-y-3">

                        <button id="start-penalty-btn" class="w-full bg-purple-600 text-white font-bold py-3 rounded-lg hover:bg-purple-700">Iniciar Penales</button>

                        <button id="finish-as-draw-btn" class="w-full bg-gray-600 text-white font-bold py-3 rounded-lg hover:bg-gray-700">Finalizar como Empate</button>

                    </div>

                </div>

                <div id="penalty-shootout-section" class="hidden mt-6 border-t border-gray-700 pt-6">

                    <h3 class="text-2xl font-bold text-center mb-4 text-white">Tanda de Penales</h3>

                    <div class="grid grid-cols-2 gap-6 text-center">

                        <div>

                            <div id="penalty-team1-score" class="text-5xl font-bold mb-4 text-white">0</div>

                            <div class="flex justify-center space-x-3"><button class="penalty-score-btn bg-emerald-600 text-white w-10 h-10 rounded-full text-xl hover:bg-emerald-700" data-team="1" data-op="add">+</button><button class="penalty-score-btn bg-red-600 text-white w-10 h-10 rounded-full text-xl hover:bg-red-700" data-team="1" data-op="sub">-</button></div>

                        </div>

                        <div>

                            <div id="penalty-team2-score" class="text-5xl font-bold mb-4 text-white">0</div>

                            <div class="flex justify-center space-x-3"><button class="penalty-score-btn bg-emerald-600 text-white w-10 h-10 rounded-full text-xl hover:bg-emerald-700" data-team="2" data-op="add">+</button><button class="penalty-score-btn bg-red-600 text-white w-10 h-10 rounded-full text-xl hover:bg-red-700" data-team="2" data-op="sub">-</button></div>

                        </div>

                    </div>

                </div>

                <div class="mt-8 text-center">

                    <button id="finish-match-btn" class="w-full bg-green-600 text-white font-bold py-3 rounded-lg hover:bg-green-700">Finalizar Partido</button>

                    <button id="cancel-match-btn" class="w-full mt-2 text-gray-400 hover:underline">Cancelar</button>

                </div>

            </div>

        </div>


        <!-- Modal de Partido de Voley -->

        <div id="volleyball-match-modal" class="modal-backdrop fixed inset-0 items-center justify-center z-50">

            <div class="glass-effect modal-content rounded-2xl p-8 w-full max-w-2xl mx-4">

                <div class="flex justify-between items-start mb-4">

                    <h2 class="text-3xl font-bold text-white">Partido de Voley</h2>

                    <div id="voley-sets-won" class="text-lg font-semibold text-white">Sets: 0 - 0</div>

                </div>

                <div id="voley-previous-sets" class="text-sm text-gray-400 mb-4 h-12 overflow-y-auto"></div>

                

                <div class="bg-gray-900 bg-opacity-50 p-4 rounded-lg">

                    <h3 id="voley-current-set-label" class="text-center font-bold mb-4 text-xl text-white">Set Actual: 1</h3>

                    <div class="grid grid-cols-2 gap-6 text-center">

                        <div>

                            <h3 id="voley-team1-name" class="text-xl font-bold mb-2 truncate text-white"></h3>

                            <div id="voley-team1-score" class="text-8xl font-black mb-4 text-white">0</div>

                            <div class="flex justify-center space-x-3"><button class="voley-score-btn bg-emerald-600 text-white w-14 h-14 rounded-full text-3xl hover:bg-emerald-700 transform hover:scale-110 transition-transform" data-team="1" data-op="add">+</button><button class="voley-score-btn bg-red-600 text-white w-14 h-14 rounded-full text-3xl hover:bg-red-700 transform hover:scale-110 transition-transform" data-team="1" data-op="sub">-</button></div>

                        </div>

                        <div>

                            <h3 id="voley-team2-name" class="text-xl font-bold mb-2 truncate text-white"></h3>

                            <div id="voley-team2-score" class="text-8xl font-black mb-4 text-white">0</div>

                            <div class="flex justify-center space-x-3"><button class="voley-score-btn bg-emerald-600 text-white w-14 h-14 rounded-full text-3xl hover:bg-emerald-700 transform hover:scale-110 transition-transform" data-team="2" data-op="add">+</button><button class="voley-score-btn bg-red-600 text-white w-14 h-14 rounded-full text-3xl hover:bg-red-700 transform hover:scale-110 transition-transform" data-team="2" data-op="sub">-</button></div>

                        </div>

                    </div>

                </div>


                <div class="mt-8 flex space-x-4">

                    <button id="voley-new-set-btn" class="w-full bg-blue-600 text-white font-bold py-3 rounded-lg hover:bg-blue-700">Finalizar Set y Empezar Nuevo</button>

                    <button id="voley-finish-match-btn" class="w-full bg-green-600 text-white font-bold py-3 rounded-lg hover:bg-green-700">Finalizar Partido</button>

                </div>

                <button id="voley-cancel-match-btn" class="w-full mt-2 text-gray-400 hover:underline">Cancelar</button>

            </div>

        </div>


        <!-- Modal de Podio -->

        <div id="podium-modal" class="modal-backdrop fixed inset-0 items-center justify-center z-50">

            <div class="glass-effect modal-content rounded-2xl p-8 w-full max-w-md mx-4 text-center">

                <h2 class="text-3xl font-bold text-white mb-6">🏆 Podio del Torneo 🏆</h2>

                <div class="space-y-4">

                    <div class="bg-yellow-400 p-4 rounded-lg border-2 border-yellow-500">

                        <p class="text-lg font-medium text-yellow-900">🥇 1er Puesto</p>

                        <p id="podium-first" class="text-2xl font-bold text-yellow-900"></p>

                    </div>

                    <div class="bg-gray-300 p-4 rounded-lg border-2 border-gray-400">

                        <p class="text-lg font-medium text-gray-800">🥈 2do Puesto</p>

                        <p id="podium-second" class="text-2xl font-bold text-gray-900"></p>

                    </div>

                    <div class="bg-yellow-600 p-4 rounded-lg border-2 border-yellow-700">

                        <p class="text-lg font-medium text-yellow-900">🥉 3er Puesto</p>

                        <p id="podium-third" class="text-2xl font-bold text-yellow-900"></p>

                    </div>

                </div>

                <button id="close-podium-btn" class="w-full mt-8 bg-gray-600 text-white font-bold py-2 rounded-lg hover:bg-gray-700">Cerrar</button>

            </div>

        </div>


        <!-- Modal Genérico para Alertas y Confirmaciones -->

        <div id="generic-modal" class="modal-backdrop fixed inset-0 items-center justify-center z-50">

            <div class="glass-effect modal-content rounded-2xl p-8 w-full max-w-sm mx-4 text-center">

                <h3 id="generic-modal-title" class="text-xl font-bold mb-4 text-white"></h3>

                <p id="generic-modal-message" class="text-gray-300 mb-6"></p>

                <div id="generic-modal-buttons" class="flex justify-center space-x-4">

                    <!-- Los botones se inyectan dinámicamente -->

                </div>

            </div>

        </div>


    </div>


    <script>

        document.addEventListener('DOMContentLoaded', () => {

            const App = {

                state: {

                    tournaments: [],

                    activeTournamentId: null,

                    currentUser: null, 

                    liveMatch: { 

                        tournamentId: null, matchId: null, roundIndex: null, 

                        score1: 0, score2: 0, 

                        penaltyScore1: 0, penaltyScore2: 0,

                        isPenaltyShootout: false,

                        timerInterval: null, timeSeconds: 0, period: 1, 

                        sets: [], currentSet: { score1: 0, score2: 0 } 

                    },

                },

                ui: {

                    views: { login: document.getElementById('login-view'), dashboard: document.getElementById('dashboard-view'), create: document.getElementById('create-tournament-view'), manage: document.getElementById('manage-tournament-view'), public: document.getElementById('public-view') },

                    liveMatchModal: document.getElementById('live-match-modal'),

                    volleyballMatchModal: document.getElementById('volleyball-match-modal'),

                    podiumModal: document.getElementById('podium-modal'),

                    genericModal: document.getElementById('generic-modal'),

                },

                init() {

                    this.attachEventListeners();

                    const params = new URLSearchParams(window.location.search);

                    if (params.get('user') && params.get('torneo')) {

                        this.handleRouting();

                    } else {

                        this.state.currentUser = sessionStorage.getItem('currentUser');

                        if (this.state.currentUser) {

                            this.loadTournaments();

                            this.renderDashboard();

                            this.showView('dashboard');

                        } else {

                            this.showView('login');

                        }

                    }

                    window.jsPDF = window.jspdf.jsPDF;

                },

                // --- MODAL SYSTEM ---

                showModal(title, message, buttons) {

                    document.getElementById('generic-modal-title').textContent = title;

                    document.getElementById('generic-modal-message').textContent = message;

                    const buttonsContainer = document.getElementById('generic-modal-buttons');

                    buttonsContainer.innerHTML = '';

                    buttons.forEach(btnConfig => {

                        const button = document.createElement('button');

                        button.textContent = btnConfig.text;

                        button.className = btnConfig.classes;

                        button.addEventListener('click', () => {

                            this.ui.genericModal.classList.remove('flex');

                            if (btnConfig.callback) {

                                btnConfig.callback();

                            }

                        });

                        buttonsContainer.appendChild(button);

                    });

                    this.ui.genericModal.classList.add('flex');

                },

                showAlert(message, title = 'Aviso') {

                    this.showModal(title, message, [

                        { text: 'Aceptar', classes: 'w-full btn-primary text-white font-bold py-2 px-4 rounded-lg' }

                    ]);

                },

                showConfirm(message, onConfirm, title = 'Confirmación') {

                    this.showModal(title, message, [

                        { text: 'Cancelar', classes: 'bg-gray-600 text-white font-bold py-2 px-4 rounded-lg hover:bg-gray-700' },

                        { text: 'Confirmar', classes: 'bg-red-600 text-white font-bold py-2 px-4 rounded-lg hover:bg-red-700', callback: onConfirm }

                    ]);

                },

                // --- VIEW MANAGEMENT ---

                showView(viewName) {

                    Object.values(this.ui.views).forEach(v => v.classList.remove('active'));

                    this.ui.views[viewName].classList.add('active');

                    window.scrollTo(0, 0);

                },

                handleRouting() {

                    const params = new URLSearchParams(window.location.search);

                    const username = params.get('user');

                    const tournamentId = params.get('torneo');

                    if (username && tournamentId) {

                        this.renderPublicView(username, tournamentId);

                    } else {

                        this.showView('login');

                    }

                },

                // --- DATA MANAGEMENT (LOCALSTORAGE) ---

                loadTournaments() {

                    if (!this.state.currentUser || this.state.currentUser === 'Invitado') {

                        this.state.tournaments = [];

                        return;

                    }

                    const data = localStorage.getItem(`tournaments_${this.state.currentUser}`);

                    this.state.tournaments = data ? JSON.parse(data) : [];

                },

                saveTournaments() {

                    if (!this.state.currentUser || this.state.currentUser === 'Invitado') return;

                    localStorage.setItem(`tournaments_${this.state.currentUser}`, JSON.stringify(this.state.tournaments));

                },

                // --- RENDERING ---

                renderDashboard() {

                    document.getElementById('welcome-user').textContent = `Bienvenido, ${this.state.currentUser}`;

                    const list = document.getElementById('tournament-list');

                    list.innerHTML = '';

                    if (this.state.tournaments.length === 0) {

                        list.innerHTML = `<div class="col-span-full text-center text-gray-400 p-10 glass-effect rounded-2xl">

                            <h3 class="text-xl font-bold text-white">¡Es hora de empezar!</h3>

                            <p>Aún no has creado ningún torneo. Haz clic en el botón de abajo para crear el primero.</p>

                        </div>`;

                        return;

                    }

                    this.state.tournaments.forEach(t => {

                        const card = document.createElement('div');

                        card.className = 'glass-effect p-6 rounded-2xl flex flex-col justify-between transition-all duration-300 hover:border-violet-500 border-t-4 border-t-violet-500/50';

                        card.dataset.id = t.id;

                        let formatText = t.format === 'liga' ? 'Liga' : 'Eliminación Directa';

                        card.innerHTML = `

                            <div>

                                <div class="flex justify-between items-start">

                                    <h3 class="font-bold text-lg text-white flex-grow pr-2">${t.name}</h3>

                                    <button class="edit-tournament-btn p-1 text-gray-400 hover:text-violet-400 flex-shrink-0" data-action="edit-name">

                                        <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path d="M17.414 2.586a2 2 0 00-2.828 0L7 10.172V13h2.828l7.586-7.586a2 2 0 000-2.828z" /><path fill-rule="evenodd" d="M2 6a2 2 0 012-2h4a1 1 0 010 2H4v10h10v-4a1 1 0 112 0v4a2 2 0 01-2 2H4a2 2 0 01-2-2V6z" clip-rule="evenodd" /></svg>

                                    </button>

                                </div>

                                <p class="text-sm text-gray-400">${t.sport}</p>

                                <div class="mt-4 flex justify-between items-center text-xs text-gray-500">

                                    <span>👥 ${t.teams.length} Equipos</span>

                                    <span>📅 ${t.creationDate}</span>

                                </div>

                            </div>

                            <div class="mt-4 pt-4 border-t border-gray-700 flex flex-col space-y-2">

                                <button class="w-full btn-primary text-white font-semibold py-2 px-4 rounded-lg" data-action="view">Iniciar Torneo</button>

                                <div class="flex justify-between items-center">

                                    <span class="inline-block bg-gray-700 text-gray-300 text-xs font-semibold px-2.5 py-0.5 rounded-full">${formatText}</span>

                                    <button class="delete-tournament-btn text-red-500 hover:text-red-400 text-sm font-semibold p-1 rounded-md" data-action="delete">

                                        <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" /></svg>

                                    </button>

                                </div>

                            </div>`;

                        list.appendChild(card);

                    });

                },

                renderManageView() {

                    const tournament = this.state.tournaments.find(t => t.id === this.state.activeTournamentId);

                    if (!tournament) return;

                    document.getElementById('manage-tournament-title').textContent = tournament.name;

                    const podiumBtn = document.getElementById('show-podium-btn');

                    

                    let isFinished = false;

                    if (tournament.format === 'liga') {

                        isFinished = tournament.rounds.every(round => round.matches.every(match => match.score1 !== null || (match.sets && match.sets.length > 0)));

                    } else {

                        isFinished = tournament.isFinished || false;

                    }

                    

                    podiumBtn.classList.toggle('hidden', !isFinished);


                    const initialTab = 'partidos';

                    document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));

                    document.querySelector(`.tab-btn[data-tab="${initialTab}"]`).classList.add('active');

                    document.querySelectorAll('.tab-content').forEach(content => content.classList.add('hidden'));

                    document.getElementById(`tab-content-${initialTab}`).classList.remove('hidden');

                    document.querySelector('.tab-btn[data-tab="clasificacion"]').style.display = tournament.format === 'liga' ? 'inline-block' : 'none';

                    this.renderMatches(tournament);

                    this.renderClassification(tournament);

                    this.renderShareTab(tournament);

                },

                renderMatches(tournament) {

                    const container = document.getElementById('tab-content-partidos');

                    if (tournament.format === 'eliminatoria') {

                        container.innerHTML = this.renderBracketHTML(tournament, "Cuadro Principal");

                    } else {

                        let html = '';

                        tournament.rounds.forEach((round, index) => {

                            html += `<h3 class="text-2xl font-bold mt-6 mb-3 text-white">Jornada ${index + 1}</h3><div class="space-y-3">`;

                            round.matches.forEach(match => {

                                const isVoley = tournament.sport.toLowerCase().includes('voley');

                                const isPlayed = isVoley ? (match.sets && match.sets.length > 0) : match.score1 !== null;

                                let centerContent = '';

                                let team1Display = `<span class="font-bold text-right w-2/5 text-lg">${match.team1}</span>`;

                                let team2Display = `<span class="font-bold text-left w-2/5 text-lg">${match.team2}</span>`;


                                if (isPlayed) {

                                    let resultText = '';

                                    let winner = null;

                                    if(isVoley){

                                        let setsWon1 = 0, setsWon2 = 0;

                                        match.sets.forEach(set => {

                                            if (set.score1 > set.score2) setsWon1++; else setsWon2++;

                                        });

                                        resultText = `<span class="text-sm">Sets: ${match.sets.map(s => `${s.score1}-${s.score2}`).join(', ')}</span>`;

                                        if (setsWon1 > setsWon2) winner = match.team1;

                                        if (setsWon2 > setsWon1) winner = match.team2;

                                    } else {

                                        resultText = `<span class="text-xl font-bold">${match.score1} - ${match.score2}</span>`;

                                        if (match.penaltyScore1 !== null && match.penaltyScore1 !== undefined) {

                                            resultText += ` <span class="text-sm text-gray-400">(Pen: ${match.penaltyScore1}-${match.penaltyScore2})</span>`;

                                            if(match.penaltyScore1 > match.penaltyScore2) winner = match.team1;

                                            if(match.penaltyScore2 > match.penaltyScore1) winner = match.team2;

                                        } else {

                                            if (match.score1 > match.score2) winner = match.team1;

                                            if (match.score2 > match.score1) winner = match.team2;

                                        }

                                    }


                                    if (winner) {

                                        if (winner === match.team1) {

                                            team1Display = `<span class="font-bold text-right w-2/5 text-lg text-emerald-400">${match.team1} (G)</span>`;

                                            team2Display = `<span class="font-bold text-left w-2/5 text-lg text-gray-400">${match.team2} (P)</span>`;

                                        } else {

                                            team1Display = `<span class="font-bold text-right w-2/5 text-lg text-gray-400">${match.team1} (P)</span>`;

                                            team2Display = `<span class="font-bold text-left w-2/5 text-lg text-emerald-400">${match.team2} (G)</span>`;

                                        }

                                    }

                                    

                                    centerContent = `<div class="text-center">

                                                        <div>${resultText}</div>

                                                        <div class="text-xs text-emerald-400 font-semibold mt-1">Finalizado</div>

                                                    </div>`;

                                } else {

                                    centerContent = `<button class="bg-violet-600 text-white px-4 py-1 rounded-md text-sm font-semibold hover:bg-violet-700">Jugar</button>`;

                                }

                                html += `<div class="glass-effect p-4 rounded-lg flex items-center justify-between cursor-pointer hover:border-violet-500" data-match-id="${match.id}" data-round-index="${index}">

                                    ${team1Display}

                                    <div class="text-center w-1/5 text-white">${centerContent}</div>

                                    ${team2Display}

                                </div>`;

                            });

                            html += `</div>`;

                        });

                        container.innerHTML = html;

                    }

                },

                renderBracketHTML(tournament, title = "Cuadro Principal") {

                    let html = `<h2 class="text-3xl font-black text-white text-center mb-4">${title}</h2>`;

                    html += '<div class="flex space-x-4 overflow-x-auto p-4">';

                    const isVoley = tournament.sport.toLowerCase().includes('voley');

                    const roundsData = tournament.rounds;


                    roundsData.forEach((round, roundIndex) => {

                        html += `<div class="flex flex-col justify-around min-w-[240px]">

                                    <h3 class="text-center font-bold mb-4 text-white text-xl">Ronda ${roundIndex + 1}</h3>`;

                        if (tournament.roundByes && tournament.roundByes[roundIndex]) {

                            html += `<div class="text-center text-sm text-gray-400 mb-4 p-2 glass-effect rounded-md">Descansa: <span class="font-semibold text-white">${tournament.roundByes[roundIndex]}</span></div>`;

                        }

                        html += `<div class="space-y-8">`;

                        round.matches.forEach(match => {

                            const isPlayed = isVoley ? (match.sets && match.sets.length > 0) : match.score1 !== null;

                            const canPlay = match.team1 && match.team2;

                            

                            let score1Display = '', score2Display = '';

                            let winnerTeam = null;


                            if (isPlayed) {

                                if (isVoley) {

                                    let setsWon1 = 0, setsWon2 = 0;

                                    match.sets.forEach(set => {

                                        if (set.score1 > set.score2) setsWon1++; else setsWon2++;

                                    });

                                    score1Display = setsWon1;

                                    score2Display = setsWon2;

                                    if (setsWon1 > setsWon2) winnerTeam = match.team1;

                                    if (setsWon2 > setsWon1) winnerTeam = match.team2;

                                } else {

                                    score1Display = match.score1;

                                    score2Display = match.score2;

                                    if (match.penaltyScore1 !== null && match.penaltyScore1 !== undefined) {

                                        if (match.penaltyScore1 > match.penaltyScore2) winnerTeam = match.team1;

                                        if (match.penaltyScore2 > match.penaltyScore1) winnerTeam = match.team2;

                                    } else {

                                        if (match.score1 > match.score2) winnerTeam = match.team1;

                                        if (match.score2 > match.score1) winnerTeam = match.team2;

                                    }

                                }

                            }


                            let team1Text = match.team1 || '<i>Por definir</i>';

                            let team2Text = match.team2 || '<i>Por definir</i>';


                            if (winnerTeam) {

                                if (winnerTeam === match.team1) {

                                    team1Text += ' (G)';

                                    team2Text += ' (P)';

                                } else {

                                    team1Text += ' (P)';

                                    team2Text += ' (G)';

                                }

                            }


                            const team1HTML = `<div class="flex justify-between items-center ${winnerTeam === match.team1 ? 'font-bold text-white' : 'text-gray-300'}"><span>${team1Text}</span><span class="font-black text-lg">${isPlayed ? score1Display : ''}</span></div>`;

                            const team2HTML = `<div class="flex justify-between items-center ${winnerTeam === match.team2 ? 'font-bold text-white' : 'text-gray-300'}"><span>${team2Text}</span><span class="font-black text-lg">${isPlayed ? score2Display : ''}</span></div>`;

                            

                            let separatorHTML;

                            if (isPlayed) {

                                let details = '';

                                if (isVoley) {

                                    details = `Sets: ${match.sets.map(s => `${s.score1}-${s.score2}`).join(', ')}`;

                                } else if (match.penaltyScore1 !== null && match.penaltyScore1 !== undefined) {

                                    details = `(Pen: ${match.penaltyScore1}-${match.penaltyScore2})`;

                                }

                                separatorHTML = `<div class="text-center text-xs text-emerald-400 font-semibold my-1">Finalizado <span class="block text-gray-400 font-normal">${details}</span></div>`;

                            } else if (canPlay) {

                                separatorHTML = `<div class="text-center my-1"><button class="bg-violet-600 text-white px-3 py-0.5 rounded text-xs font-semibold hover:bg-violet-700">Jugar</button></div>`;

                            } else {

                                separatorHTML = `<hr class="my-1 border-gray-700">`;

                            }


                            html += `<div class="glass-effect p-3 rounded-lg cursor-pointer hover:border-violet-500" data-match-id="${match.id}" data-round-index="${roundIndex}">

                                        ${team1HTML}

                                        ${separatorHTML}

                                        ${team2HTML}

                                    </div>`;

                        });

                        html += `</div></div>`;

                    });

                    html += '</div>';


                    if (tournament.thirdPlaceMatch) {

                        const match = tournament.thirdPlaceMatch;

                        const isPlayed = isVoley ? (match.sets && match.sets.length > 0) : match.score1 !== null;

                        const canPlay = match.team1 && match.team2;


                        let score1Display = '', score2Display = '';

                        let winnerTeam = null;


                        if (isPlayed) {

                            if (isVoley) {

                                let setsWon1 = 0, setsWon2 = 0;

                                match.sets.forEach(set => {

                                    if (set.score1 > set.score2) setsWon1++; else setsWon2++;

                                });

                                score1Display = setsWon1;

                                score2Display = setsWon2;

                                if (setsWon1 > setsWon2) winnerTeam = match.team1;

                                if (setsWon2 > setsWon1) winnerTeam = match.team2;

                            } else {

                                score1Display = match.score1;

                                score2Display = match.score2;

                                if (match.penaltyScore1 !== null) {

                                    if (match.penaltyScore1 > match.penaltyScore2) winnerTeam = match.team1;

                                    if (match.penaltyScore2 > match.penaltyScore1) winnerTeam = match.team2;

                                } else {

                                    if (match.score1 > match.score2) winnerTeam = match.team1;

                                    if (match.score2 > match.score1) winnerTeam = match.team2;

                                }

                            }

                        }

                        

                        let team1Text = match.team1 || '<i>Por definir</i>';

                        let team2Text = match.team2 || '<i>Por definir</i>';


                        if (winnerTeam) {

                            if (winnerTeam === match.team1) {

                                team1Text += ' (G)';

                                team2Text += ' (P)';

                            } else {

                                team1Text += ' (P)';

                                team2Text += ' (G)';

                            }

                        }


                        const team1HTML = `<div class="flex justify-between items-center ${winnerTeam === match.team1 ? 'font-bold text-white' : 'text-gray-300'}"><span>${team1Text}</span><span class="font-black text-lg">${isPlayed ? score1Display : ''}</span></div>`;

                        const team2HTML = `<div class="flex justify-between items-center ${winnerTeam === match.team2 ? 'font-bold text-white' : 'text-gray-300'}"><span>${team2Text}</span><span class="font-black text-lg">${isPlayed ? score2Display : ''}</span></div>`;

                        

                        let separatorHTML;

                        if (isPlayed) {

                            let details = '';

                            if (isVoley) {

                                details = `Sets: ${match.sets.map(s => `${s.score1}-${s.score2}`).join(', ')}`;

                            } else if (match.penaltyScore1 !== null) {

                                details = `(Pen: ${match.penaltyScore1}-${match.penaltyScore2})`;

                            }

                            separatorHTML = `<div class="text-center text-xs text-emerald-400 font-semibold my-1">Finalizado <span class="block text-gray-400 font-normal">${details}</span></div>`;

                        } else if (canPlay) {

                            separatorHTML = `<div class="text-center my-1"><button class="bg-violet-600 text-white px-3 py-0.5 rounded text-xs font-semibold hover:bg-violet-700">Jugar</button></div>`;

                        } else {

                            separatorHTML = `<hr class="my-1 border-gray-700">`;

                        }


                        html += `<div class="mt-8 p-4">

                                    <h3 class="text-center font-bold mb-4 text-white text-xl">Partido por el 3er Puesto</h3>

                                    <div class="glass-effect p-3 rounded-lg cursor-pointer hover:border-violet-500 max-w-xs mx-auto" data-match-id="${match.id}" data-round-index="${match.roundIndex}">

                                        ${team1HTML}

                                        ${separatorHTML}

                                        ${team2HTML}

                                    </div>

                                </div>`;

                    }

                    return html;

                },

                getLeagueStandingsHTML(tournament) {

                    const stats = {};

                    tournament.teams.forEach(team => { stats[team] = { pj: 0, pg: 0, pe: 0, pp: 0, gf: 0, gc: 0, dg: 0, pts: 0 }; });

                    tournament.rounds.forEach(round => {

                        round.matches.forEach(match => {

                            const isVoley = tournament.sport.toLowerCase().includes('voley');

                            const isPlayed = isVoley ? (match.sets && match.sets.length > 0) : match.score1 !== null;


                            if (isPlayed) {

                                const t1 = match.team1, t2 = match.team2;

                                stats[t1].pj++; stats[t2].pj++;


                                if (isVoley) {

                                    let setsWon1 = 0, setsWon2 = 0;

                                    match.sets.forEach(set => {

                                        stats[t1].gf += set.score1;

                                        stats[t2].gf += set.score2;

                                        stats[t1].gc += set.score2;

                                        stats[t2].gc += set.score1;

                                        if (set.score1 > set.score2) setsWon1++; else setsWon2++;

                                    });

                                    

                                    if (setsWon1 > setsWon2) {

                                        stats[t1].pg++;

                                        stats[t2].pp++;

                                        stats[t1].pts += 3;

                                    } else if (setsWon2 > setsWon1) {

                                        stats[t2].pg++;

                                        stats[t1].pp++;

                                        stats[t2].pts += 3;

                                    } else {

                                        stats[t1].pe++;

                                        stats[t2].pe++;

                                        stats[t1].pts += 1;

                                        stats[t2].pts += 1;

                                    }

                                } else {

                                    const s1 = match.score1, s2 = match.score2;

                                    stats[t1].gf += s1; stats[t2].gf += s2;

                                    stats[t1].gc += s2; stats[t2].gc += s1;


                                    if (match.penaltyScore1 !== null && match.penaltyScore1 !== undefined) { 

                                        const winner = match.penaltyScore1 > match.penaltyScore2 ? t1 : t2;

                                        const loser = winner === t1 ? t2 : t1;

                                        stats[winner].pg++;

                                        stats[loser].pp++;

                                        stats[winner].pts += 3;

                                    } else if (s1 > s2) {

                                        stats[t1].pg++; stats[t2].pp++; stats[t1].pts += 3;

                                    } else if (s2 > s1) {

                                        stats[t2].pg++; stats[t1].pp++; stats[t2].pts += 3;

                                    } else {

                                        stats[t1].pe++; stats[t2].pe++; stats[t1].pts++; stats[t2].pts++;

                                    }

                                }

                            }

                        });

                    });

                    Object.keys(stats).forEach(t => { stats[t].dg = stats[t].gf - stats[t].gc; });

                    const sorted = Object.entries(stats).sort(([,a], [,b]) => b.pts - a.pts || b.dg - a.dg || b.gf - a.gf);

                    let table = `<div class="overflow-x-auto glass-effect rounded-xl"><table class="min-w-full">

                        <thead class="bg-gray-900 bg-opacity-50"><tr>

                            <th class="p-3 text-left text-xs font-medium uppercase text-gray-300">Equipo</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">PTS</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">PJ</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">PG</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">PE</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">PP</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">GF</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">GC</th><th class="p-3 text-center text-xs font-medium uppercase text-gray-300">DG</th>

                        </tr></thead><tbody>`;

                    sorted.forEach(([team, data]) => {

                        table += `<tr class="border-t border-gray-700">

                            <td class="p-3 font-medium text-white">${team}</td><td class="p-3 text-center font-bold text-violet-400">${data.pts}</td><td class="p-3 text-center">${data.pj}</td><td class="p-3 text-center">${data.pg}</td><td class="p-3 text-center">${data.pe}</td><td class="p-3 text-center">${data.pp}</td><td class="p-3 text-center">${data.gf}</td><td class="p-3 text-center">${data.gc}</td><td class="p-3 text-center">${data.dg}</td>

                        </tr>`;

                    });

                    table += `</tbody></table></div>`;

                    return table;

                },

                renderClassification(tournament) {

                    const container = document.getElementById('tab-content-clasificacion');

                    if (tournament.format !== 'liga') {

                        container.innerHTML = '';

                        return;

                    }

                    container.innerHTML = this.getLeagueStandingsHTML(tournament);

                },

                renderShareTab(tournament) {

                    const qrContainer = document.getElementById('qrcode-container');

                    qrContainer.innerHTML = '';

                    const publicUrl = `${window.location.origin}${window.location.pathname}?user=${this.state.currentUser}&torneo=${tournament.id}`;

                    new QRCode(qrContainer, { text: publicUrl, width: 128, height: 128 });

                },

                renderPublicView(username, tournamentId) {

                    const allTournaments = [];

                    const users = JSON.parse(localStorage.getItem('users_v2')) || [];

                    const targetUser = users.find(u => u.username === username);

                    if (!targetUser) {

                        this.ui.views.public.innerHTML = `<p class="text-center text-red-500">Usuario no encontrado.</p>`;

                        this.showView('public');

                        return;

                    }


                    const userTournaments = JSON.parse(localStorage.getItem(`tournaments_${username}`)) || [];

                    const tournament = userTournaments.find(t => t.id === tournamentId);

                    

                    if (!tournament) { 

                        this.ui.views.public.innerHTML = `<p class="text-center text-red-500">Torneo no encontrado.</p>`; 

                        this.showView('public');

                        return; 

                    }

                    

                    let mainContentHTML = '';

                    let title = '';


                    if (tournament.format === 'liga') {

                        mainContentHTML = this.getLeagueStandingsHTML(tournament);

                        title = 'Clasificación';

                    } else if (tournament.format === 'eliminatoria') {

                        mainContentHTML = this.renderBracketHTML(tournament, "Cuadro del Torneo");

                        title = 'Cuadro del Torneo';

                    }


                    this.ui.views.public.innerHTML = `

                        <header class="mb-8 text-center"><h1 class="text-4xl font-bold text-white">${tournament.name}</h1><p class="text-xl text-gray-400 mt-1">${tournament.sport}</p></header>

                        <div class="space-y-8"><div><h2 class="text-2xl font-semibold mb-4 border-b border-gray-700 pb-2 text-white">${title}</h2>${mainContentHTML}</div></div>`;

                    this.showView('public');

                },

                openLiveMatchModal(tournamentId, roundIndex, matchId, bracketType) {

                    const tournament = this.state.tournaments.find(t => t.id === tournamentId);

                    let match;


                    if (tournament.format === 'eliminatoria') {

                        match = (matchId === 'third_place') ? tournament.thirdPlaceMatch : tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                    } else { // Liga

                        match = tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                    }

                    

                    if (!match || !match.team1 || !match.team2 || (match.score1 !== null || (match.sets && match.sets.length > 0))) return;


                    this.state.liveMatch = { tournamentId, roundIndex, matchId, bracketType, score1: 0, score2: 0, penaltyScore1: 0, penaltyScore2: 0, isPenaltyShootout: false, timerInterval: null, timeSeconds: 0, period: 1, sets: [], currentSet: { score1: 0, score2: 0 } };

                    

                    if (tournament.sport.toLowerCase().includes('voley')) {

                        document.getElementById('voley-team1-name').textContent = match.team1;

                        document.getElementById('voley-team2-name').textContent = match.team2;

                        this.updateVoleyModal();

                        this.ui.volleyballMatchModal.classList.add('flex');

                    } else {

                        document.getElementById('live-team1-name').textContent = match.team1;

                        document.getElementById('live-team2-name').textContent = match.team2;

                        document.getElementById('live-team1-score').textContent = 0;

                        document.getElementById('live-team2-score').textContent = 0;

                        document.getElementById('penalty-team1-score').textContent = 0;

                        document.getElementById('penalty-team2-score').textContent = 0;

                        document.getElementById('penalty-shootout-section').classList.add('hidden');

                        document.getElementById('tiebreaker-options').classList.add('hidden');

                        document.getElementById('standard-match-main-controls').classList.remove('hidden');

                        document.getElementById('finish-match-btn').textContent = 'Finalizar Partido';

                        document.getElementById('finish-match-btn').classList.remove('hidden');

                        document.getElementById('live-match-period').textContent = `Tiempo: 1`;

                        this.updateTimerDisplay();

                        this.ui.liveMatchModal.classList.add('flex');

                    }

                },

                closeLiveMatchModal() {

                    clearInterval(this.state.liveMatch.timerInterval);

                    this.ui.liveMatchModal.classList.remove('flex');

                    this.ui.volleyballMatchModal.classList.remove('flex');

                },

                updateTimerDisplay() {

                    const minutes = Math.floor(this.state.liveMatch.timeSeconds / 60).toString().padStart(2, '0');

                    const seconds = (this.state.liveMatch.timeSeconds % 60).toString().padStart(2, '0');

                    document.getElementById('live-match-timer').textContent = `${minutes}:${seconds}`;

                },

                updateVoleyModal() {

                    const { sets, currentSet } = this.state.liveMatch;

                    document.getElementById('voley-team1-score').textContent = currentSet.score1;

                    document.getElementById('voley-team2-score').textContent = currentSet.score2;

                    document.getElementById('voley-current-set-label').textContent = `Set Actual: ${sets.length + 1}`;

                    

                    let setsWon1 = 0, setsWon2 = 0;

                    sets.forEach(set => {

                        if (set.score1 > set.score2) setsWon1++;

                        else setsWon2++;

                    });

                    document.getElementById('voley-sets-won').textContent = `Sets: ${setsWon1} - ${setsWon2}`;

                    

                    document.getElementById('voley-previous-sets').innerHTML = sets.map((s, i) => `Set ${i+1}: ${s.score1}-${s.score2}`).join(' | ');

                },

                showPodium(tournament) {

                    let first = 'No definido', second = 'No definido', third = 'No definido';


                    if (tournament.format === 'liga') {

                        const standingsHTML = this.getLeagueStandingsHTML(tournament);

                        const div = document.createElement('div');

                        div.innerHTML = standingsHTML;

                        const rows = div.querySelectorAll('tbody tr');

                        first = rows[0] ? rows[0].cells[0].textContent : 'No definido';

                        second = rows[1] ? rows[1].cells[0].textContent : 'No definido';

                        third = rows[2] ? rows[2].cells[0].textContent : 'No definido';

                    } else if (tournament.format === 'eliminatoria') {

                        first = tournament.winner || 'No definido';

                        second = tournament.runnerUp || 'No definido';

                        third = tournament.thirdPlace || 'No definido';

                    }

                    

                    document.getElementById('podium-first').textContent = first;

                    document.getElementById('podium-second').textContent = second;

                    document.getElementById('podium-third').textContent = third;

                    this.ui.podiumModal.classList.add('flex');

                },

                // --- FIXTURE GENERATION & LOGIC ---

                generateFixture(teams, format) {

                    if (format === 'liga') return { rounds: this.generateRoundRobin(teams) };

                    if (format === 'eliminatoria') return this.generateSingleElimination(teams);

                },

                generateRoundRobin(teams) {

                    const rounds = [];

                    let teamList = [...teams];

                    if (teamList.length % 2 !== 0) teamList.push("DESCANSA");

                    const numRounds = teamList.length - 1;

                    for (let i = 0; i < numRounds; i++) {

                        const round = { matches: [] };

                        for (let j = 0; j < teamList.length / 2; j++) {

                            const team1 = teamList[j], team2 = teamList[teamList.length - 1 - j];

                            if (team1 !== "DESCANSA" && team2 !== "DESCANSA") {

                                round.matches.push({ id: `r${i}m${j}`, roundIndex: i, team1, team2, score1: null, score2: null, sets: [], penaltyScore1: null, penaltyScore2: null });

                            }

                        }

                        rounds.push(round);

                        teamList.splice(1, 0, teamList.pop());

                    }

                    return rounds;

                },

                generateSingleElimination(teams) {

                    let teamList = [...teams].sort(() => 0.5 - Math.random());

                    let byeTeam = null;

                    let teamsThatHadBye = [];


                    if (teamList.length % 2 !== 0) {

                        const byeIndex = Math.floor(Math.random() * teamList.length);

                        byeTeam = teamList.splice(byeIndex, 1)[0];

                        teamsThatHadBye.push(byeTeam);

                    }

                    const firstRoundMatches = [];

                    for (let i = 0; i < teamList.length; i += 2) {

                        firstRoundMatches.push({ id: `r0m${i/2}`, roundIndex: 0, team1: teamList[i], team2: teamList[i+1], score1: null, score2: null, sets: [], penaltyScore1: null, penaltyScore2: null });

                    }

                    return { 

                        rounds: [{ matches: firstRoundMatches }], 

                        roundByes: { 0: byeTeam }, 

                        thirdPlaceMatch: null,

                        thirdPlaceWinner: null,

                        teamsThatHadBye: teamsThatHadBye

                    };

                },

                // =================================================================

                // BUG FIX: Replaced the entire updateBrackets function

                // =================================================================

                updateBrackets(tournament, finishedMatch) {

                    if (tournament.format !== 'eliminatoria') return;


                    const isVoley = tournament.sport.toLowerCase().includes('voley');


                    const getMatchResult = (match) => {

                        let winner = null;

                        let loser = null;


                        if (isVoley) {

                            // For voley, score1 and score2 are set counts.

                            if (match.score1 > match.score2) {

                                winner = match.team1;

                                loser = match.team2;

                            } else {

                                winner = match.team2;

                                loser = match.team1;

                            }

                        } else {

                            // For other sports

                            if (match.penaltyScore1 !== null && match.penaltyScore1 !== undefined) {

                                if (match.penaltyScore1 > match.penaltyScore2) {

                                    winner = match.team1;

                                    loser = match.team2;

                                } else {

                                    winner = match.team2;

                                    loser = match.team1;

                                }

                            } else if (match.score1 !== match.score2) {

                                if (match.score1 > match.score2) {

                                    winner = match.team1;

                                    loser = match.team2;

                                } else {

                                    winner = match.team2;

                                    loser = match.team1;

                                }

                            }

                        }

                        return { winner, loser };

                    };


                    const currentRoundIndex = parseInt(finishedMatch.roundIndex);

                    // Handle third place match finish

                    if (currentRoundIndex === -1) { 

                        tournament.thirdPlace = getMatchResult(finishedMatch).winner;

                        return;

                    }


                    const currentRound = tournament.rounds[currentRoundIndex];

                    // Check if all matches in the current round are finished

                    if (!currentRound.matches.every(m => m.score1 !== null)) {

                        return; 

                    }


                    const winners = currentRound.matches.map(m => getMatchResult(m).winner);


                    if (tournament.roundByes && tournament.roundByes[currentRoundIndex]) {

                        winners.push(tournament.roundByes[currentRoundIndex]);

                    }


                    // Check for tournament end (final match finished)

                    if (winners.length === 1 && tournament.rounds.length === currentRoundIndex + 1) {

                        tournament.winner = winners[0];

                        const finalMatch = currentRound.matches[0];

                        tournament.runnerUp = getMatchResult(finalMatch).loser;

                        tournament.isFinished = true;

                        if (!tournament.thirdPlaceMatch && tournament.thirdPlaceWinner) {

                            tournament.thirdPlace = tournament.thirdPlaceWinner;

                        }

                        return;

                    }


                    const nextRoundIndex = currentRoundIndex + 1;

                    let nextRoundParticipants = [...winners];

                    let nextBye = null;


                    // Handle byes for the next round

                    if (nextRoundParticipants.length % 2 !== 0 && nextRoundParticipants.length > 1) {

                        let eligibleForBye = nextRoundParticipants.filter(team => !tournament.teamsThatHadBye.includes(team));

                        if (eligibleForBye.length === 0) {

                            eligibleForBye = nextRoundParticipants;

                        }

                        const byeIndex = Math.floor(Math.random() * eligibleForBye.length);

                        nextBye = eligibleForBye[byeIndex];

                        tournament.teamsThatHadBye.push(nextBye);

                        nextRoundParticipants = nextRoundParticipants.filter(team => team !== nextBye);

                    }

                    tournament.roundByes[nextRoundIndex] = nextBye;


                    // Create matches for the next round

                    const nextRoundMatches = [];

                    for (let i = 0; i < nextRoundParticipants.length; i += 2) {

                        nextRoundMatches.push({

                            id: `r${nextRoundIndex}m${i/2}`,

                            roundIndex: nextRoundIndex,

                            team1: nextRoundParticipants[i],

                            team2: nextRoundParticipants[i+1] || null,

                            score1: null, score2: null,

                            sets: [], // Ensure sets is always present for new matches

                            penaltyScore1: null, penaltyScore2: null

                        });

                    }

                    if (nextRoundMatches.length > 0) {

                        if (tournament.rounds.length === nextRoundIndex) {

                            tournament.rounds.push({ matches: nextRoundMatches });

                        } else {

                            tournament.rounds[nextRoundIndex].matches.push(...nextRoundMatches);

                        }

                    }

                    

                    // Create third place match after semifinals

                    if (winners.length === 2 && currentRound.matches.length === 2) { // Semifinal round

                        const losers = currentRound.matches.map(m => getMatchResult(m).loser);

                        tournament.thirdPlaceMatch = { 

                            id: 'third_place', 

                            roundIndex: -1, 

                            team1: losers[0], 

                            team2: losers[1], 

                            score1: null, score2: null,

                            sets: [], // FIX: Added missing sets property

                            penaltyScore1: null, penaltyScore2: null

                        };

                    } else if (winners.length === 2 && currentRound.matches.length === 1) { // Case where one semifinalist had a bye

                        const loser = getMatchResult(currentRound.matches[0]).loser;

                        tournament.thirdPlaceWinner = loser; // This team is 3rd or 4th, but no match is played

                    }

                },

                // --- EVENT LISTENERS ---

                attachEventListeners() {

                    // Login/Register

                    document.getElementById('show-register-link').addEventListener('click', (e) => {

                        e.preventDefault();

                        document.getElementById('login-form-container').classList.add('hidden');

                        document.getElementById('register-form-container').classList.remove('hidden');

                    });

                    document.getElementById('show-login-link').addEventListener('click', (e) => {

                        e.preventDefault();

                        document.getElementById('register-form-container').classList.add('hidden');

                        document.getElementById('login-form-container').classList.remove('hidden');

                    });

                    document.getElementById('register-btn').addEventListener('click', () => {

                        const username = document.getElementById('register-username').value;

                        const password = document.getElementById('register-password').value;

                        if (!username || !password) { this.showAlert('Por favor, completa todos los campos.'); return; }

                        let users = JSON.parse(localStorage.getItem('users_v2')) || [];

                        if (users.find(u => u.username === username)) { this.showAlert('Este nombre de usuario ya está en uso.'); return; }

                        users.push({ username, password });

                        localStorage.setItem('users_v2', JSON.stringify(users));

                        this.showAlert('¡Registro exitoso! Ahora puedes iniciar sesión.', 'Éxito');

                        document.getElementById('show-login-link').click();

                    });

                    document.getElementById('login-btn').addEventListener('click', () => {

                        const username = document.getElementById('login-username').value;

                        const password = document.getElementById('login-password').value;

                        let users = JSON.parse(localStorage.getItem('users_v2')) || [];

                        const foundUser = users.find(u => u.username === username && u.password === password);


                        if (foundUser) {

                            this.state.currentUser = foundUser.username;

                            sessionStorage.setItem('currentUser', foundUser.username);

                            this.loadTournaments();

                            this.renderDashboard();

                            this.showView('dashboard');

                        } else {

                            this.showAlert('Usuario o contraseña incorrectos.', 'Error de Acceso');

                        }

                    });

                    document.getElementById('guest-btn').addEventListener('click', () => {

                        this.showAlert("Ingresarás como invitado. Los torneos que crees no se guardarán al cerrar la sesión. Para guardar tu progreso, por favor regístrate.");

                        this.state.currentUser = 'Invitado';

                        sessionStorage.setItem('currentUser', 'Invitado');

                        this.loadTournaments();

                        this.renderDashboard();

                        this.showView('dashboard');

                    });

                    document.getElementById('logout-btn').addEventListener('click', () => {

                        this.state.currentUser = null;

                        sessionStorage.removeItem('currentUser');

                        this.state.tournaments = [];

                        this.showView('login');

                    });


                    // Dashboard

                    document.getElementById('tournament-list').addEventListener('click', (e) => {

                        const button = e.target.closest('button');

                        const card = e.target.closest('[data-id]');

                        if (!card) return;

                        

                        const tournamentId = card.dataset.id;

                        const action = button ? button.dataset.action : e.target.closest('[data-action]')?.dataset.action;


                        if (action === 'delete') {

                            e.stopPropagation();

                            this.showConfirm('¿Estás seguro de que quieres eliminar este torneo?', () => {

                                this.state.tournaments = this.state.tournaments.filter(t => t.id !== tournamentId);

                                this.saveTournaments();

                                this.renderDashboard();

                            });

                        } else if (action === 'edit-name') {

                            e.stopPropagation();

                            const h3 = card.querySelector('h3');

                            const currentName = h3.textContent;

                            h3.innerHTML = `<input type="text" class="w-full bg-gray-900 border border-violet-500 rounded p-1 text-lg font-bold text-white" value="${currentName}">`;

                            const input = h3.querySelector('input');

                            input.focus();

                            input.select();

                            

                            const saveName = () => {

                                const newName = input.value.trim();

                                if (newName && newName !== currentName) {

                                    const tournament = this.state.tournaments.find(t => t.id === tournamentId);

                                    tournament.name = newName;

                                    this.saveTournaments();

                                    h3.textContent = newName;

                                } else {

                                    h3.textContent = currentName;

                                }

                            };


                            input.addEventListener('blur', saveName, { once: true });

                            input.addEventListener('keydown', (ev) => {

                                if (ev.key === 'Enter') {

                                    input.blur();

                                } else if (ev.key === 'Escape') {

                                    h3.textContent = currentName;

                                    input.removeEventListener('blur', saveName);

                                }

                            });

                        } else if (action === 'view') {

                            this.state.activeTournamentId = tournamentId;

                            this.renderManageView();

                            this.showView('manage');

                        }

                    });


                    // Create Tournament & Navigation

                    document.getElementById('go-to-create-btn').addEventListener('click', () => this.showView('create'));

                    document.querySelectorAll('.back-to-dashboard').forEach(btn => btn.addEventListener('click', () => this.showView('dashboard')));

                    document.getElementById('next-step-2-btn').addEventListener('click', () => { document.getElementById('step-1').classList.add('hidden'); document.getElementById('step-2').classList.remove('hidden'); });

                    document.getElementById('back-step-1-btn').addEventListener('click', () => { document.getElementById('step-2').classList.add('hidden'); document.getElementById('step-1').classList.remove('hidden'); });

                    document.getElementById('next-step-3-btn').addEventListener('click', () => {

                        const teams = Array.from(document.getElementById('teams-list').children);

                        if (teams.length < 2) {

                            this.showAlert('Debes añadir al menos 2 equipos para continuar.');

                            return;

                        }

                        this.showConfirm(

                            `Has añadido ${teams.length} equipos. Una vez generado el fixture, no podrás cambiar la lista de equipos. ¿Estás seguro de que quieres continuar?`,

                            () => {

                                document.getElementById('step-2').classList.add('hidden');

                                document.getElementById('step-3').classList.remove('hidden');

                            },

                            'Revisión Final'

                        );

                    });

                    document.getElementById('back-step-2-btn').addEventListener('click', () => { document.getElementById('step-3').classList.add('hidden'); document.getElementById('step-2').classList.remove('hidden'); });

                    document.getElementById('add-team-btn').addEventListener('click', () => {

                        const input = document.getElementById('team-name-input');

                        if (input.value.trim()) {

                            const li = document.createElement('li');

                            li.className = 'flex justify-between items-center bg-gray-800 p-2 rounded-md text-white';

                            li.innerHTML = `<span>${input.value.trim()}</span><button class="remove-team-btn text-red-500 hover:text-red-400 font-bold">X</button>`;

                            document.getElementById('teams-list').appendChild(li);

                            input.value = '';

                        }

                    });

                    document.getElementById('teams-list').addEventListener('click', e => { if (e.target.classList.contains('remove-team-btn')) e.target.parentElement.remove(); });

                    document.getElementById('generate-fixture-btn').addEventListener('click', () => {

                        const teams = Array.from(document.getElementById('teams-list').children).map(li => li.firstElementChild.textContent);

                        if (teams.length < 2) { this.showAlert('Necesitas al menos 2 equipos.'); return; }

                        const newTournament = {

                            id: `t_${Date.now()}`,

                            name: document.getElementById('tournament-name').value || 'Sin Título',

                            sport: document.getElementById('tournament-sport').value || 'Deporte',

                            teams,

                            format: document.getElementById('tournament-format').value,

                            creationDate: new Date().toLocaleDateString('es-ES'),

                            ...this.generateFixture(teams, document.getElementById('tournament-format').value)

                        };

                        this.state.tournaments.push(newTournament);

                        this.saveTournaments();

                        this.renderDashboard();

                        this.showView('dashboard');

                        document.getElementById('create-tournament-view').querySelectorAll('input[type="text"]').forEach(i => i.value = '');

                        document.getElementById('teams-list').innerHTML = '';

                        document.getElementById('step-3').classList.add('hidden'); document.getElementById('step-1').classList.remove('hidden');

                    });

                    

                    // Manage View Tabs & Matches

                    document.querySelector('.tab-btn').parentElement.addEventListener('click', e => {

                        if (e.target.classList.contains('tab-btn')) {

                            const tab = e.target.dataset.tab;

                            document.querySelectorAll('.tab-btn').forEach(btn => btn.classList.remove('active'));

                            e.target.classList.add('active');

                            document.querySelectorAll('.tab-content').forEach(c => c.classList.add('hidden'));

                            document.getElementById(`tab-content-${tab}`).classList.remove('hidden');

                            document.getElementById(`pdf-export-area`).querySelector('#tab-content-partidos').style.display = (tab === 'partidos') ? 'block' : 'none';

                            document.getElementById(`pdf-export-area`).querySelector('#tab-content-clasificacion').style.display = (tab === 'clasificacion') ? 'block' : 'none';

                        }

                    });

                    document.getElementById('tab-content-partidos').addEventListener('click', e => {

                        const matchDiv = e.target.closest('[data-match-id]');

                        if (matchDiv) {

                            const bracketType = matchDiv.dataset.bracketType;

                            this.openLiveMatchModal(this.state.activeTournamentId, matchDiv.dataset.roundIndex, matchDiv.dataset.matchId, bracketType);

                        }

                    });


                    // Standard Modal Listeners

                    document.getElementById('timer-start').addEventListener('click', () => {

                        if (!this.state.liveMatch.timerInterval) this.state.liveMatch.timerInterval = setInterval(() => { this.state.liveMatch.timeSeconds++; this.updateTimerDisplay(); }, 1000);

                    });

                    document.getElementById('timer-pause').addEventListener('click', () => { clearInterval(this.state.liveMatch.timerInterval); this.state.liveMatch.timerInterval = null; });

                    document.getElementById('timer-reset').addEventListener('click', () => {

                        clearInterval(this.state.liveMatch.timerInterval);

                        this.state.liveMatch.timerInterval = null;

                        this.state.liveMatch.timeSeconds = 0;

                        this.state.liveMatch.period = 1;

                        document.getElementById('live-match-period').textContent = `Tiempo: 1`;

                        this.updateTimerDisplay();

                    });

                    document.getElementById('timer-new-period').addEventListener('click', () => {

                        clearInterval(this.state.liveMatch.timerInterval);

                        this.state.liveMatch.timerInterval = null;

                        this.state.liveMatch.timeSeconds = 0;

                        this.state.liveMatch.period++;

                        document.getElementById('live-match-period').textContent = `Tiempo: ${this.state.liveMatch.period}`;

                        this.updateTimerDisplay();

                    });

                    this.ui.liveMatchModal.addEventListener('click', e => {

                        const target = e.target;

                        if (target.classList.contains('score-btn') || target.classList.contains('penalty-score-btn')) {

                            const isPenalty = target.classList.contains('penalty-score-btn');

                            const teamNum = target.dataset.team;

                            const op = target.dataset.op;

                            const scoreKey = isPenalty ? `penaltyScore${teamNum}` : `score${teamNum}`;

                            const scoreEl = document.getElementById(isPenalty ? `penalty-team${teamNum}-score` : `live-team${teamNum}-score`);

                            

                            if (op === 'add') this.state.liveMatch[scoreKey]++;

                            else if (op === 'sub' && this.state.liveMatch[scoreKey] > 0) this.state.liveMatch[scoreKey]--;

                            

                            scoreEl.textContent = this.state.liveMatch[scoreKey];

                        }

                    });

                    document.getElementById('finish-match-btn').addEventListener('click', () => {

                        this.showConfirm("¿Estás seguro de finalizar el partido? Esta acción guardará el resultado y no se podrá deshacer.", () => {

                            const { tournamentId, score1, score2, isPenaltyShootout, roundIndex, matchId, bracketType } = this.state.liveMatch;

                            const tournament = this.state.tournaments.find(t => t.id === tournamentId);

                            const sport = tournament.sport.toLowerCase();

                            const noPenaltySports = ['voley', 'basquet', 'baloncesto'];

                            const needsTiebreaker = !noPenaltySports.some(s => sport.includes(s));


                            if (score1 === score2 && needsTiebreaker && !isPenaltyShootout) {

                                document.getElementById('standard-match-main-controls').classList.add('hidden');

                                document.getElementById('tiebreaker-options').classList.remove('hidden');

                                document.getElementById('finish-match-btn').classList.add('hidden');

                                return;

                            }


                            let match;

                            if (tournament.format === 'eliminatoria') {

                                match = (matchId === 'third_place') ? tournament.thirdPlaceMatch : tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                            } else {

                                match = tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                            }

                            

                            match.score1 = score1;

                            match.score2 = score2;

                            if (isPenaltyShootout) {

                                match.penaltyScore1 = this.state.liveMatch.penaltyScore1;

                                match.penaltyScore2 = this.state.liveMatch.penaltyScore2;

                            }


                            this.updateBrackets(tournament, match);

                            this.saveTournaments();

                            this.renderManageView();

                            this.closeLiveMatchModal();

                        }, "Finalizar Partido");

                    });

                    document.getElementById('start-penalty-btn').addEventListener('click', () => {

                        this.state.liveMatch.isPenaltyShootout = true;

                        document.getElementById('tiebreaker-options').classList.add('hidden');

                        document.getElementById('penalty-shootout-section').classList.remove('hidden');

                        const finishBtn = document.getElementById('finish-match-btn');

                        finishBtn.textContent = 'Finalizar Penales';

                        finishBtn.classList.remove('hidden');

                    });

                    document.getElementById('finish-as-draw-btn').addEventListener('click', () => {

                        const { tournamentId, roundIndex, matchId, score1, score2 } = this.state.liveMatch;

                        const tournament = this.state.tournaments.find(t => t.id === tournamentId);

                        let match = (matchId === 'third_place') ? tournament.thirdPlaceMatch : tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                        match.score1 = score1;

                        match.score2 = score2;

                        match.penaltyScore1 = null;

                        match.penaltyScore2 = null;

                        this.updateBrackets(tournament, match);

                        this.saveTournaments();

                        this.renderManageView();

                        this.closeLiveMatchModal();

                    });

                    document.getElementById('cancel-match-btn').addEventListener('click', () => this.closeLiveMatchModal());


                    // Voley Modal Listeners

                    this.ui.volleyballMatchModal.addEventListener('click', e => {

                        if (e.target.classList.contains('voley-score-btn')) {

                            const teamNum = e.target.dataset.team;

                            const op = e.target.dataset.op;

                            const scoreKey = `score${teamNum}`;

                            if (op === 'add') this.state.liveMatch.currentSet[scoreKey]++;

                            else if (op === 'sub' && this.state.liveMatch.currentSet[scoreKey] > 0) this.state.liveMatch.currentSet[scoreKey]--;

                            this.updateVoleyModal();

                        }

                    });

                    document.getElementById('voley-new-set-btn').addEventListener('click', () => {

                        this.state.liveMatch.sets.push({...this.state.liveMatch.currentSet});

                        this.state.liveMatch.currentSet = { score1: 0, score2: 0 };

                        this.updateVoleyModal();

                    });

                    document.getElementById('voley-finish-match-btn').addEventListener('click', () => {

                        this.showConfirm("¿Estás seguro de finalizar el partido? Esta acción guardará el resultado y no se podrá deshacer.", () => {

                            const { tournamentId, roundIndex, matchId, sets, currentSet, bracketType } = this.state.liveMatch;

                            const finalSets = [...sets];

                            if(currentSet.score1 > 0 || currentSet.score2 > 0) {

                                finalSets.push({...currentSet});

                            }


                            const tournament = this.state.tournaments.find(t => t.id === tournamentId);

                            let match;

                            if (tournament.format === 'eliminatoria') {

                                match = (matchId === 'third_place') ? tournament.thirdPlaceMatch : tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                            } else {

                                match = tournament.rounds[roundIndex].matches.find(m => m.id === matchId);

                            }

                            

                            match.sets = finalSets;

                            let setsWon1 = 0, setsWon2 = 0;

                            match.sets.forEach(set => {

                                if(set.score1 > set.score2) setsWon1++; else setsWon2++;

                            });


                            match.score1 = setsWon1;

                            match.score2 = setsWon2;


                            this.updateBrackets(tournament, match);

                            this.saveTournaments();

                            this.renderManageView();

                            this.closeLiveMatchModal();

                        }, "Finalizar Partido");

                    });

                    document.getElementById('voley-cancel-match-btn').addEventListener('click', () => this.closeLiveMatchModal());


                    // Podium & Export Listeners

                    document.getElementById('show-podium-btn').addEventListener('click', () => {

                        const tournament = this.state.tournaments.find(t => t.id === this.state.activeTournamentId);

                        this.showPodium(tournament);

                    });

                    document.getElementById('close-podium-btn').addEventListener('click', () => {

                        this.ui.podiumModal.classList.remove('flex');

                    });

                    document.getElementById('export-pdf-btn').addEventListener('click', () => {

                        const activeTabContent = document.querySelector('#pdf-export-area .tab-content:not(.hidden)');

                        if (!activeTabContent || !activeTabContent.hasChildNodes()) {

                            this.showAlert("No hay contenido visible para exportar en esta pestaña.", "Error de Exportación");

                            return;

                        }

                        const { jsPDF } = window.jspdf;

                        html2canvas(activeTabContent, { scale: 2, backgroundColor: '#0f0c29' }).then(canvas => {

                            const imgData = canvas.toDataURL('image/png');

                            const pdf = new jsPDF('p', 'mm', 'a4');

                            const pdfWidth = pdf.internal.pageSize.getWidth();

                            const canvasWidth = canvas.width;

                            const canvasHeight = canvas.height;

                            const ratio = canvasWidth / canvasHeight;

                            const width = pdfWidth - 20; // Add some margin

                            const height = width / ratio;

                            pdf.addImage(imgData, 'PNG', 10, 10, width, height);

                            pdf.save("torneo.pdf");

                        });

                    });

                }

            };

            App.init();

        });

    </script>

</body>

</html>