<?php
/**
 * votacion_proyeccion.php — Sprint 9A rev4
 * Pantalla de proyección en vivo.
 * - Cambios de estado vía AJAX (no sale de la página)
 * - "Presentar Resultados" → resultados.php misma pestaña
 * - Modal de confirmación integrado (sin browser confirm)
 */
session_set_cookie_params(86400);
session_save_path("/home/evolucionamos/public_html/mejora/sessions");
session_start();
if (empty($_SESSION['adm']) || ($_SESSION['role'] != 1 && $_SESSION['role'] != 3)) {
    header("Location: index.php"); exit;
}
require_once '../app/helpers/csrf.php';
require_once '../app/models/votacion.php';
require_once '../app/models/datos.php';

$model = new \app\models\votacion();
$vid   = isset($_GET['vid']) ? (int)$_GET['vid'] : 0;
if (!$vid) { header("Location: resultados.php"); exit; }
$v = $model->obtener($vid);
if (!$v)  { header("Location: resultados.php"); exit; }

$estado    = $v->estado ?? 'abierta';
$csrfToken = generarCSRF(); // token para AJAX
// Sprint UX: título asamblea desde config general
$datosConf = (new \app\models\datos())->obtenerDatos();
$tituloAsamblea = !empty($datosConf->titulo) ? $datosConf->titulo : $v->titulo;
?>
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Proyección — <?php echo htmlspecialchars($v->titulo); ?></title>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet">
    <style>
        *, *::before, *::after { margin:0; padding:0; box-sizing:border-box; }

        :root {
            --azul-corp:  #04548c;
            --azul-medio: #2b5a9e;
            --cyan:       #17c1e8;
            --verde:      #28a745;
            --rojo:       #dc3545;
            --naranja:    #fd7e14;
            --gris-claro: #f4f7fb;
            --gris-borde: #dee2e6;
            --texto:      #1a2b45;
            --subtexto:   #6c7a8d;
        }

        body {
            font-family: 'Inter', 'Segoe UI', sans-serif;
            background: #fff;
            color: var(--texto);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            padding-bottom: 68px;
        }

        /* ── HEADER ────────────────────────────────────────── */
        .proy-header {
            background: #fff;
            border-bottom: 3px solid var(--cyan);
            padding: 12px 40px;
            display: flex;
            justify-content: space-between;
            align-items: center;
            box-shadow: 0 2px 8px rgba(4,84,140,.08);
            flex-shrink: 0;
        }
        .proy-logo { height: 44px; object-fit: contain; }

        .live-badge {
            display: flex; align-items: center; gap: 8px;
            border-radius: 30px; padding: 6px 18px;
            font-weight: 700; font-size: .8em;
            letter-spacing: 1.5px;
        }
        .live-badge.votando {
            background: #eaf9f0; border: 1.5px solid var(--verde); color: #1a7a3a;
        }
        .live-badge.cerrada-badge {
            background: #fff8e6; border: 1.5px solid var(--naranja); color: #7c4f00;
        }
        .live-badge.finalizada-badge {
            background: #e8f0fe; border: 1.5px solid var(--azul-medio); color: var(--azul-medio);
        }
        .live-dot {
            width: 9px; height: 9px; border-radius: 50%;
            animation: pulse-dot 1.2s infinite;
        }
        .live-badge.votando .live-dot       { background: var(--verde); }
        .live-badge.cerrada-badge .live-dot  { background: var(--naranja); animation: none; }
        .live-badge.finalizada-badge .live-dot { background: var(--azul-medio); animation: none; }
        @keyframes pulse-dot {
            0%,100% { opacity:1; transform:scale(1); }
            50%     { opacity:.35; transform:scale(1.55); }
        }

        .proy-timer {
            font-size: 1.45em; font-weight: 800;
            color: var(--azul-corp);
            font-variant-numeric: tabular-nums;
            letter-spacing: 3px;
        }

        /* ── TÍTULO ─────────────────────────────────────────── */
        .proy-title-block {
            text-align: center;
            padding: 36px 48px 16px;
            background: #fff;
            flex-shrink: 0;
        }
        .proy-titulo {
            font-size: clamp(1.6em, 3.2vw, 2.6em);
            font-weight: 900;
            color: var(--azul-corp);
            text-transform: uppercase;
            letter-spacing: 2px;
            line-height: 1.1;
        }
        /* Pregunta destacada en proyección */
        .proy-pregunta-box {
            display: inline-block;
            margin-top: 14px;
            background: linear-gradient(135deg,#f0f8ff,#e8f4fd);
            border-left: 6px solid var(--cyan);
            border-radius: 0 14px 14px 0;
            padding: 13px 28px;
            max-width: 860px;
            text-align: left;
            font-size: clamp(1em, 2vw, 1.6em);
            font-weight: 700;
            color: #1a2b45;
            box-shadow: 0 3px 14px rgba(23,193,232,.14);
        }
        .proy-subtitulo {
            font-size: clamp(.75em, 1.2vw, 1em);
            color: var(--subtexto);
            margin-top: 6px;
            font-weight: 500;
        }
        .proy-divider {
            width: 56px; height: 4px;
            background: linear-gradient(90deg, var(--azul-corp), var(--cyan));
            border-radius: 4px;
            margin: 14px auto 0;
        }

        /* ── KPIs ───────────────────────────────────────────── */
        .proy-kpis {
            display: flex;
            justify-content: center;
            gap: clamp(14px, 2.2vw, 32px);
            padding: 32px 40px 20px;
            flex-wrap: wrap;
            flex: 1;
            align-items: center;
            background: var(--gris-claro);
        }
        .kpi-box {
            background: #fff;
            border: 1.5px solid var(--gris-borde);
            border-top: 4px solid var(--azul-corp);
            border-radius: 12px;
            padding: clamp(22px, 2.8vw, 42px) clamp(24px, 3vw, 50px);
            text-align: center;
            flex: 1 1 0;
            min-width: 0;
            max-width: none;
            box-shadow: 0 4px 20px rgba(4,84,140,.07);
        }
        .kpi-box.participacion { border-top-color: var(--cyan); }
        .kpi-icon { width:34px; height:34px; margin:0 auto 12px; opacity:.5; }
        .kpi-icon svg { width:100%; height:100%; }
        .kpi-num {
            font-size: clamp(2.4em, 4vw, 3.8em);
            font-weight: 900;
            color: var(--azul-corp);
            line-height: 1;
            letter-spacing: -1px;
            font-variant-numeric: tabular-nums;
        }
        .kpi-box.participacion .kpi-num {
            color: #0a8fa8;
        }
        .kpi-lbl {
            font-size: clamp(.6em, 1vw, .75em);
            color: var(--subtexto);
            text-transform: uppercase;
            letter-spacing: 2px;
            margin-top: 8px;
            font-weight: 600;
        }

        /* ── BARRA PROGRESO ─────────────────────────────────── */
        .proy-progress-wrap { background: var(--gris-claro); padding: 0 72px 36px; flex-shrink:0; }
        .proy-progress-label {
            display: flex; justify-content: space-between;
            font-size: .72em; color: var(--subtexto);
            margin-bottom: 7px; text-transform: uppercase;
            letter-spacing: 1.5px; font-weight: 600;
        }
        .proy-progress-bg { background: #e2e8f0; border-radius: 20px; height: 12px; overflow: hidden; }
        .proy-progress-fill {
            height: 100%;
            background: linear-gradient(90deg, var(--azul-corp), var(--cyan));
            border-radius: 20px;
            transition: width 1.2s ease-in-out;
            min-width: 3px;
        }

        /* ── FOOTER ─────────────────────────────────────────── */
        .proy-footer {
            text-align: center; padding: 8px;
            font-size: .68em; color: #b0bac8;
            background: #fff;
            border-top: 1px solid var(--gris-borde);
            flex-shrink:0;
        }

        /* ── BARRA DE CONTROL (fixed bottom) ────────────────── */
        .ctrl-bar {
            position: fixed; bottom: 0; left: 0; right: 0;
            background: rgba(255,255,255,0.97);
            border-top: 2px solid var(--gris-borde);
            padding: 9px 20px;
            display: flex; align-items: center;
            gap: 7px; flex-wrap: wrap;
            backdrop-filter: blur(10px);
            box-shadow: 0 -4px 18px rgba(0,0,0,.09);
            z-index: 100;
        }

        .ctrl-btn {
            padding: 8px 16px;
            font-size: .78em; font-weight: 600;
            border-radius: 7px;
            cursor: pointer; text-decoration: none;
            border: 1.5px solid var(--gris-borde);
            background: #fff; color: var(--texto);
            display: inline-flex; align-items: center; gap: 6px;
            transition: background .15s, border-color .15s, opacity .15s;
            white-space: nowrap; font-family: inherit;
            user-select: none;
        }
        .ctrl-btn:hover  { background: var(--gris-claro); border-color: #adb5bd; }
        .ctrl-btn:active { opacity: .8; }

        .btn-nav { color: var(--subtexto); font-size: .75em; }

        .btn-cerrar    { background:#fff1f2; border-color:#f5c2c7; color:#842029; }
        .btn-cerrar:hover { background:#f8d7da; }

        .btn-finalizar { background:#e8f0fe; border-color:#b6ccfe; color:var(--azul-medio); }
        .btn-finalizar:hover { background:#d0e2fd; }

        .btn-presentar {
            background: var(--azul-corp); border-color: var(--azul-corp);
            color: #fff; font-size: .82em; padding: 9px 20px;
        }
        .btn-presentar:hover { background: var(--azul-medio); border-color: var(--azul-medio); color:#fff; }

        .btn-disabled {
            background: #f8f9fa; border-color: #e9ecef;
            color: #ced4da; cursor: not-allowed; pointer-events: none;
        }

        .btn-loading {
            opacity: .7; pointer-events: none; cursor: wait;
        }

        .sep { width:1px; height:24px; background: var(--gris-borde); margin: 0 4px; }

        .ctrl-info {
            margin-left: auto;
            font-size: .68em; color: #adb5bd;
            white-space: nowrap;
        }
        #ultimo-update { color: var(--azul-corp); font-weight: 600; }

        /* ── MODAL CONFIRMACIÓN ──────────────────────────────── */
        .modal-overlay {
            display: none;
            position: fixed; inset: 0;
            background: rgba(15,30,55,.45);
            z-index: 200;
            align-items: center; justify-content: center;
        }
        .modal-overlay.show { display: flex; }
        .modal-box {
            background: #fff;
            border-radius: 14px;
            padding: 32px 36px;
            max-width: 420px; width: 90%;
            box-shadow: 0 20px 60px rgba(0,0,0,.2);
            text-align: center;
        }
        .modal-icon {
            width: 52px; height: 52px;
            border-radius: 50%;
            display: flex; align-items: center; justify-content: center;
            margin: 0 auto 16px;
            font-size: 1.4em;
        }
        .modal-icon.cerrar    { background: #fff1f2; color: var(--rojo); }
        .modal-icon.finalizar { background: #e8f0fe; color: var(--azul-medio); }
        .modal-title { font-size: 1.15em; font-weight: 700; color: var(--texto); margin-bottom: 8px; }
        .modal-desc  { font-size: .88em; color: var(--subtexto); margin-bottom: 24px; line-height: 1.5; }
        .modal-btns  { display: flex; gap: 10px; justify-content: center; }
        .modal-cancel {
            padding: 9px 22px; border-radius: 8px;
            border: 1.5px solid var(--gris-borde);
            background: #fff; color: var(--subtexto);
            font-weight: 600; cursor: pointer; font-family: inherit; font-size: .88em;
        }
        .modal-cancel:hover { background: var(--gris-claro); }
        .modal-confirm {
            padding: 9px 22px; border-radius: 8px;
            border: none; color: #fff;
            font-weight: 700; cursor: pointer; font-family: inherit; font-size: .88em;
        }
        .modal-confirm.rojo  { background: var(--rojo); }
        .modal-confirm.azul  { background: var(--azul-corp); }
        .modal-confirm:hover { opacity: .88; }

        /* ── SPINNER inicial ─────────────────────────────────── */
        #loading-overlay {
            position: fixed; inset: 0; background: #fff;
            display: flex; align-items: center; justify-content: center;
            z-index: 9999; transition: opacity .35s;
        }
        .spinner {
            width: 44px; height: 44px;
            border: 4px solid #e2e8f0;
            border-top-color: var(--azul-corp);
            border-radius: 50%;
            animation: spin .7s linear infinite;
        }
        @keyframes spin { to { transform: rotate(360deg); } }

        /* ── TOAST notificación ──────────────────────────────── */
        #toast {
            position: fixed; top: 20px; left: 50%; transform: translateX(-50%);
            background: var(--texto); color: #fff;
            padding: 10px 24px; border-radius: 30px;
            font-size: .82em; font-weight: 600;
            z-index: 300;
            opacity: 0; transition: opacity .25s;
            pointer-events: none;
        }
        #toast.show { opacity: 1; }
        #toast.error { background: var(--rojo); }
    </style>
</head>
<body>

<div id="loading-overlay"><div class="spinner"></div></div>
<div id="toast"></div>

<!-- ── MODAL ──────────────────────────────────────────────── -->
<div class="modal-overlay" id="modal">
    <div class="modal-box">
        <div class="modal-icon" id="modal-icon"></div>
        <div class="modal-title" id="modal-title"></div>
        <div class="modal-desc"  id="modal-desc"></div>
        <div class="modal-btns">
            <button class="modal-cancel" onclick="cerrarModal()">Cancelar</button>
            <button class="modal-confirm" id="modal-confirm-btn" onclick="ejecutarAccion()"></button>
        </div>
    </div>
</div>

<!-- ── HEADER ─────────────────────────────────────────────── -->
<div class="proy-header">
    <img src="../assets/images/logo.png" class="proy-logo" alt="FONDOENERGIA">

    <?php if ($estado === 'abierta'): ?>
        <div class="live-badge votando">
            <div class="live-dot"></div> EN VIVO
        </div>
    <?php elseif ($estado === 'cerrada'): ?>
        <div class="live-badge cerrada-badge">
            <div class="live-dot"></div> CERRADA
        </div>
    <?php else: ?>
        <div class="live-badge finalizada-badge">
            <div class="live-dot"></div> FINALIZADA
        </div>
    <?php endif; ?>

    <div class="proy-timer" id="reloj-duracion">00:00:00</div>
</div>

<!-- ── TÍTULO ─────────────────────────────────────────────── -->
<div class="proy-title-block">
    <div class="proy-titulo"><?php echo htmlspecialchars($tituloAsamblea); ?></div>
    <?php if (!empty($v->pregunta)): ?>
        <div class="proy-pregunta-box"><?php echo htmlspecialchars($v->pregunta); ?></div>
    <?php else: ?>
        <div class="proy-subtitulo"><?php echo htmlspecialchars($v->titulo); ?></div>
    <?php endif; ?>
    <div class="proy-divider"></div>
</div>

<!-- ── KPIs ───────────────────────────────────────────────── -->
<div class="proy-kpis">

    <div class="kpi-box">
        <div class="kpi-icon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
                <rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/>
            </svg>
        </div>
        <div class="kpi-num" id="kpi-votos">—</div>
        <div class="kpi-lbl">Votos Emitidos</div>
    </div>

    <div class="kpi-box">
        <div class="kpi-icon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
                <path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>
            </svg>
        </div>
        <div class="kpi-num" id="kpi-votaron">—</div>
        <div class="kpi-lbl">Delegados Votaron</div>
    </div>

    <div class="kpi-box participacion">
        <div class="kpi-icon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
                <line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/>
            </svg>
        </div>
        <div class="kpi-num" id="kpi-participacion">—</div>
        <div class="kpi-lbl">Participación</div>
    </div>

    <div class="kpi-box">
        <div class="kpi-icon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
                <rect x="2" y="7" width="20" height="14" rx="2"/><path d="M16 21V5a2 2 0 0 0-2-2h-4a2 2 0 0 0-2 2v16"/>
            </svg>
        </div>
        <div class="kpi-num" id="kpi-censo">—</div>
        <div class="kpi-lbl">Censo Electoral</div>
    </div>

</div>

<!-- ── BARRA PROGRESO ─────────────────────────────────────── -->
<div class="proy-progress-wrap">
    <div class="proy-progress-label">
        <span>Progreso de participación</span>
        <span id="prog-pct-label">0%</span>
    </div>
    <div class="proy-progress-bg">
        <div class="proy-progress-fill" id="prog-fill" style="width:0%;"></div>
    </div>
</div>

<div class="proy-footer">FYCLS S.A.S — Brújula Virtual | Sistema de Votación Híbrida</div>

<!-- ── BARRA DE CONTROL ───────────────────────────────────── -->
<div class="ctrl-bar">

    <!-- Navegación -->
    <a href="admin.php" class="ctrl-btn btn-nav" style="font-weight:700;color:var(--azul-medio);border-color:var(--azul-medio);">
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M15 18l-6-6 6-6"/></svg>
        Panel
    </a>
    <a href="resultados.php" class="ctrl-btn btn-nav">Control</a>
    <a href="votacion_detalle.php?id=<?php echo $vid; ?>" class="ctrl-btn btn-nav">Gestionar</a>
    <button onclick="toggleFullscreen()" class="ctrl-btn btn-nav">
        <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/></svg>
        Pantalla completa
    </button>

    <div class="sep"></div>

    <!-- Botones de acción según estado (renderizados por JS) -->
    <div id="action-buttons">
        <?php if ($estado === 'abierta'): ?>
            <button id="btn-cerrar" class="ctrl-btn btn-cerrar"
                    onclick="pedirConfirmacion('cerrar')">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="9" x2="15" y2="15"/><line x1="15" y1="9" x2="9" y2="15"/></svg>
                Cerrar Votación
            </button>
            <button class="ctrl-btn btn-disabled">Presentar Resultados</button>

        <?php elseif ($estado === 'cerrada'): ?>
            <button id="btn-reabrir" class="ctrl-btn"
                    style="background:#eaf9f0;border-color:#84d9a8;color:#1a7a3a;"
                    onclick="pedirConfirmacion('reabrir')">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.6"/></svg>
                Reabrir
            </button>
            <button id="btn-finalizar" class="ctrl-btn btn-finalizar"
                    onclick="pedirConfirmacion('finalizar')">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>
                Finalizar Votación
            </button>
            <button class="ctrl-btn btn-disabled">Presentar Resultados</button>

        <?php else: ?>
            <button class="ctrl-btn btn-presentar"
                    onclick="presentarResultados()">
                <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polygon points="5 3 19 12 5 21 5 3"/></svg>
                Presentar Resultados
            </button>

        <?php endif; ?>
    </div>

    <div class="ctrl-info" style="display:none;">Actualización cada 2 s &nbsp;|&nbsp; Última: <span id="ultimo-update">—</span></div>
</div>

<script>
const VID        = <?php echo $vid; ?>;
let CSRF_TOKEN   = <?php echo json_encode($csrfToken); ?>; // hotfix: let para refresh
let ESTADO_ACTUAL = <?php echo json_encode($estado); ?>; // 'abierta' | 'cerrada' | 'finalizada'
const AJAX_LIVE  = 'ajax_resultados_live.php?vid=' + VID;
const AJAX_EST   = 'ajax_estado_votacion.php';
let fechaApertura = <?php echo ($v->fecha_apertura ? json_encode($v->fecha_apertura) : 'null'); ?>;
let fechaCierre   = <?php echo ($v->fecha_cierre   ? json_encode($v->fecha_cierre)   : 'null'); ?>;
let timerInterval = null;
let accionPendiente = null; // 'cerrar' | 'finalizar'

/* ── Duración formateada ────────────────────────────────── */
function formatearSegundos(seg) {
    seg = Math.max(0, Math.floor(seg));
    const h = String(Math.floor(seg / 3600)).padStart(2, '0');
    const m = String(Math.floor(seg % 3600 / 60)).padStart(2, '0');
    const s = String(seg % 60).padStart(2, '0');
    return h + ':' + m + ':' + s;
}

function parseFechaServidor(str) {
    // Formato: "YYYY-MM-DD HH:MM:SS" — Colombia UTC-5
    if (!str) return null;
    const p = str.match(/(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/);
    if (!p) return null;
    return new Date(Date.UTC(+p[1], +p[2]-1, +p[3], +p[4]+5, +p[5], +p[6]));
}

/* ── Cronómetro ─────────────────────────────────────────── */
function iniciarCronometro(fechaStr) {
    if (!fechaStr || timerInterval) return;
    const inicio = parseFechaServidor(fechaStr);
    if (!inicio) return;
    timerInterval = setInterval(() => {
        const diff = Math.floor((Date.now() - inicio) / 1000);
        document.getElementById('reloj-duracion').textContent = formatearSegundos(diff);
    }, 1000);
}

function mostrarDuracionFija(apertura, cierre) {
    // Muestra la duración fija cuando la votación ya no está abierta
    const ini = parseFechaServidor(apertura);
    const fin = parseFechaServidor(cierre);
    if (!ini) return;
    const seg = fin ? Math.floor((fin - ini) / 1000) : 0;
    document.getElementById('reloj-duracion').textContent = formatearSegundos(seg);
}

/* ── Fetch datos live ───────────────────────────────────── */
function fetchDatos() {
    fetch(AJAX_LIVE)
        .then(r => r.json())
        .then(data => {
        // HOTFIX: mantener CSRF_TOKEN fresco para acciones de larga duración
        if (data && data.csrf_token) { CSRF_TOKEN = data.csrf_token; }

            if (data.error) return;
            const pct = data.participacion;
            document.getElementById('kpi-votos').textContent         = Number(data.total_votos).toLocaleString('es-CO');
            document.getElementById('kpi-votaron').textContent       = Number(data.votaron).toLocaleString('es-CO');
            document.getElementById('kpi-participacion').textContent = pct + '%';
            document.getElementById('kpi-censo').textContent         = Number(data.censo_total).toLocaleString('es-CO');
            document.getElementById('prog-fill').style.width         = Math.min(pct, 100) + '%';
            document.getElementById('prog-pct-label').textContent    = pct + '%';
            document.getElementById('ultimo-update').textContent     = data.timestamp;
            if (data.votacion?.estado === 'abierta') {
                if (!timerInterval && data.votacion?.fecha_apertura)
                    iniciarCronometro(data.votacion.fecha_apertura);
            } else {
                // Votación cerrada o finalizada — congelar en duración real
                if (timerInterval) {
                    clearInterval(timerInterval);
                    timerInterval = null;
                    // Mostrar duración fija usando fecha_cierre del servidor
                    const ap = data.votacion?.fecha_apertura;
                    const ci = data.votacion?.fecha_cierre;
                    mostrarDuracionFija(ap, ci);
                }
            }
            const ov = document.getElementById('loading-overlay');
            if (ov) { ov.style.opacity = '0'; setTimeout(() => ov.remove(), 350); }
        })
        .catch(() => {});
}

/* ── Modal de confirmación ──────────────────────────────── */
function pedirConfirmacion(accion) {
    accionPendiente = accion;
    const icon = document.getElementById('modal-icon');
    const title = document.getElementById('modal-title');
    const desc  = document.getElementById('modal-desc');
    const btn   = document.getElementById('modal-confirm-btn');

    if (accion === 'cerrar') {
        icon.className = 'modal-icon cerrar';
        icon.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><rect x="3" y="3" width="18" height="18" rx="2"/><line x1="9" y1="9" x2="15" y2="15"/><line x1="15" y1="9" x2="9" y2="15"/></svg>';
        title.textContent = '¿Cerrar la votación?';
        desc.textContent  = 'Los delegados no podrán seguir emitiendo votos. Podrás reabrirla o finalizarla después.';
        btn.textContent   = 'Cerrar Votación';
        btn.className     = 'modal-confirm rojo';
    } else if (accion === 'reabrir') {
        icon.className = 'modal-icon';
        icon.style.cssText = 'background:#eaf9f0;color:#1a7a3a;width:52px;height:52px;border-radius:50%;display:flex;align-items:center;justify-content:center;margin:0 auto 16px;font-size:1.4em;';
        icon.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="#1a7a3a" stroke-width="2.5"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 .49-4.6"/></svg>';
        title.textContent = '¿Reabrir la votación?';
        desc.textContent  = 'La votación volverá a estado Abierta y los delegados podrán seguir votando.';
        btn.textContent   = 'Reabrir';
        btn.className     = 'modal-confirm';
        btn.style.background = '#28a745';
    } else {
        icon.className = 'modal-icon finalizar';
        icon.style.cssText = '';
        icon.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><polyline points="20 6 9 17 4 12"/></svg>';
        title.textContent = '¿Finalizar la votación?';
        desc.textContent  = 'Esta acción es definitiva. La votación quedará cerrada y podrás presentar los resultados a la asamblea.';
        btn.textContent   = 'Finalizar';
        btn.className     = 'modal-confirm azul';
        btn.style.background = '';
    }

    document.getElementById('modal').classList.add('show');
}

function cerrarModal() {
    document.getElementById('modal').classList.remove('show');
    accionPendiente = null;
}

/* ── Ejecutar cambio de estado vía AJAX ─────────────────── */
function ejecutarAccion() {
    if (!accionPendiente) return;
    const accion = accionPendiente; // guardar antes de que cerrarModal() lo resetee a null
    cerrarModal();

    // Detener timer inmediatamente si se cierra o finaliza — Sprint 16
    if (accion === 'cerrar' || accion === 'finalizar') {
        if (typeof timerInterval !== 'undefined' && timerInterval) {
            clearInterval(timerInterval);
            timerInterval = null;
        }
    }

    const nuevoEstado = accion === 'cerrar' ? 'cerrada' : (accion === 'reabrir' ? 'abierta' : 'finalizada');
    const btnId       = accion === 'cerrar' ? 'btn-cerrar' : (accion === 'reabrir' ? 'btn-reabrir' : 'btn-finalizar');
    const btn         = document.getElementById(btnId);
    if (btn) { btn.classList.add('btn-loading'); btn.textContent = 'Procesando…'; }

    const body = new URLSearchParams({
        vid:        VID,
        estado:     nuevoEstado,
        csrf_token: CSRF_TOKEN
    });

    fetch(AJAX_EST, { method: 'POST', body })
        .then(r => {
            // Capturar texto crudo para diagnosticar si no es JSON válido
            return r.text().then(txt => {
                try {
                    return JSON.parse(txt);
                } catch(e) {
                    // Respuesta no es JSON — mostrar primeros 120 chars para debug
                    const preview = txt.replace(/<[^>]+>/g,'').trim().substring(0,120);
                    console.error('[BRUJULA] Respuesta no JSON:', txt);
                    return { ok: false, msg: 'Respuesta inesperada del servidor: ' + preview };
                }
            });
        })
        .then(data => {
            if (data.ok) {
                mostrarToast('✓ Listo. Actualizando pantalla…', false);
                setTimeout(() => location.reload(), 900);
            } else {
                mostrarToast('Error: ' + (data.msg || 'Inténtalo de nuevo'), true);
                if (btn) { btn.classList.remove('btn-loading'); btn.textContent = accionPendiente === 'cerrar' ? 'Cerrar Votación' : 'Finalizar Votación'; }
            }
        })
        .catch(err => {
            console.error('[BRUJULA] fetch error:', err);
            mostrarToast('Error de red: ' + err.message, true);
            if (btn) btn.classList.remove('btn-loading');
        });

    accionPendiente = null;
}

/* ── Presentar resultados (misma pestaña) ───────────────── */
function presentarResultados() {
    window.location.href = 'zona.php?vid=' + VID;
}

/* ── Toast ──────────────────────────────────────────────── */
function mostrarToast(msg, esError) {
    const t = document.getElementById('toast');
    t.textContent = msg;
    t.className   = 'show' + (esError ? ' error' : '');
    clearTimeout(t._timer);
    t._timer = setTimeout(() => { t.className = ''; }, 2800);
}

/* ── Fullscreen ─────────────────────────────────────────── */
function toggleFullscreen() {
    !document.fullscreenElement
        ? document.documentElement.requestFullscreen().catch(() => {})
        : document.exitFullscreen();
}

/* ── ESC cierra modal ───────────────────────────────────── */
document.addEventListener('keydown', e => {
    if (e.key === 'Escape') cerrarModal();
});

/* ── Init ───────────────────────────────────────────────── */
if (ESTADO_ACTUAL === 'abierta') {
    if (fechaApertura) iniciarCronometro(fechaApertura);
} else {
    // Votación cerrada/finalizada — mostrar duración fija
    mostrarDuracionFija(fechaApertura, fechaCierre);
}
fetchDatos();
setInterval(fetchDatos, 2000);

/* ── Keepalive sesión — Fix 15C ─────────────────────────── */
// Ping cada 4 minutos para evitar que el GC de PHP cierre la sesión
// durante asambleas largas (default gc_maxlifetime = 24 min)
setInterval(function() {
    fetch('keepalive.php')
        .then(function(r){ return r.json(); })
        .then(function(d){
            if (!d.ok) {
                // Sesión expiró a pesar del keepalive — recargar para re-autenticar
                console.warn('[BRUJULA] Sesión expirada, recargando...');
                location.reload();
            }
        })
        .catch(function(){});
}, 60000); // 1 minuto — sin cierre de sesión en proyección

</script>
</body>
</html>
