<?php
/* ─── Handler POST: guardar respuestas (llamado desde javascript.js sendAnswers) ─── */
if (isset($_REQUEST['myData']) && $_REQUEST['myData'] != '') {
    include_once "config.php";
    include_once "session.php";
    session_create();
    _saveAnswers();
    exit;
}

/* ─── Includes y setup ──────────────────────────────────────────────────────────── */
include_once "config.php";
include_once "session.php";
session_create();

/* ─── cUSER: parsear del URL o auto-generar ─────────────────────────────────────── */
$URLParts = explode("/", explode('?', $_SERVER['REQUEST_URI'], 2)[0]);
$_rawUser = isset($URLParts[3]) ? strtolower($URLParts[3]) : "auto";

if ($_rawUser == "auto") {
    if (empty($_SESSION['kpnUser'])) {
        $_SESSION['kpnUser'] = "auto_" . generate_string("0123456789abcdef", 30);
    }
    define('cUSER', $_SESSION['kpnUser']);
} elseif ($_rawUser == "last") {
    define('cUSER', !empty($_SESSION['kpnUser']) ? $_SESSION['kpnUser'] : "auto_" . generate_string("0123456789abcdef", 30));
} else {
    define('cUSER', $_rawUser);
    $_SESSION['kpnUser'] = cUSER;
}

/* ─── isKpN: modo Kopernica original (arranca en pregunta 0) ────────────────────── */
$isKpN = (isset($_REQUEST["i"]) && ($_REQUEST["i"] === "true" || $_REQUEST["i"] === "1")) ? "true" : "false";

/* ─── goto: retomar desde una pregunta concreta ─────────────────────────────────── */
$goto = isset($_REQUEST["goto"]) ? intval($_REQUEST["goto"]) : "";

/* ─── Función get(): wrapper unificado de params y traducciones ─────────────────── */
function get($key) {
    if (isset($_REQUEST[$key])) return $_REQUEST[$key];
    switch ($key) {
        case "tests":     return cTEST;
        case "myData":    return null;
        case "almostthere": return get_Text("almostthere");
        default:          return get_Text($key);
    }
}

/* ─── URL malformada: si no hay owner ni test, mostrar error ────────────────────── */
if (cOWNER == "" && cTEST == "" && !isset($_REQUEST['myData'])) {
    // Redirigir al panel de admin para URL raíz
    header("Location: /redbox/");
    exit;
}

if (cOWNER == "" || cTEST == "") {
    include_once "malformedurl_module.php";
    exit;
}

/* ─── Cuotas ─────────────────────────────────────────────────────────────────────── */
include_once "qQuota_module.php";

/* ─── Clase pollData: renderizado del test ──────────────────────────────────────── */
class pollData {

    private $link;
    private $dbname;
    public  $actualQuestion = 0;
    public  $ConscienceLevel  = 1;
    public  $ConscienceMemory = [''];

    public $maxUsers     = 0;
    public $estado       = 1;
    public $curUsers     = 0;
    public $URLComplete  = "";
    public $URLScreenOut = "";
    public $URLCuotasFull = "";
    public $legalText    = "";

    public function __construct() {
        list($host, $user, $pass, $dbname) = explode('|', DB_MAIN);
        $this->link   = mysqli_connect($host, $user, $pass, $dbname);
        $this->dbname = $dbname;
        if ($this->link) {
            $this->link->set_charset("utf8mb4");
            $this->_loadTestConfig();
        }
    }

    private function _loadTestConfig() {
        $stmt = mysqli_prepare($this->link,
            "SELECT * FROM Q2_Groups WHERE nonUniqueID = ? AND Type = 'Test' LIMIT 1");
        if (!$stmt) return;
        $t = cTEST;
        mysqli_stmt_bind_param($stmt, 's', $t);
        mysqli_stmt_execute($stmt);
        $row = $stmt->get_result()->fetch_assoc();
        mysqli_stmt_close($stmt);
        if ($row) {
            $this->maxUsers      = (int)($row['maxUsers']   ?? 0);
            $this->URLComplete   = $row['URLComplete']  ?? "";
            $this->URLScreenOut  = $row['URLScreenOut'] ?? "";
            $this->URLCuotasFull = $row['URLCuotasFull'] ?? "";
            $this->legalText     = $row['Legal'] ?? "";
            $this->estado        = (int)($row['estado'] ?? 1);
            $this->_countCurrentUsers();
        }
    }

    private function _countCurrentUsers() {
        $stmt = mysqli_prepare($this->link,
            "SELECT COUNT(DISTINCT datetimecode) AS n FROM Q3_Answers WHERE Test = ? AND owner = ?");
        if (!$stmt) return;
        $t = cTEST; $o = cOWNER;
        mysqli_stmt_bind_param($stmt, 'ss', $t, $o);
        mysqli_stmt_execute($stmt);
        $row = $stmt->get_result()->fetch_assoc();
        mysqli_stmt_close($stmt);
        $this->curUsers = (int)($row['n'] ?? 0);
    }

    /* Emite variables JS sobre el estado del test */
    public function printUserLimitVars($testName) {
        echo "var maxUsers = " . $this->maxUsers . ";\n";
        echo "var curUsers = " . $this->curUsers . ";\n";
        echo "var estado   = " . json_encode($this->estado) . ";\n";
        echo "var maximilesComplete   = " . json_encode($this->URLComplete)   . ";\n";
        echo "var maximilesScreenOut  = " . json_encode($this->URLScreenOut)  . ";\n";
        echo "var maximilesCuotasFull = " . json_encode($this->URLCuotasFull) . ";\n";
        echo "var legalText           = " . json_encode($this->legalText)     . ";\n";
    }

    /* Obtiene los hijos directos de un grupo */
    public function getGroupChilds($linkID) {
        $stmt = mysqli_prepare($this->link,
            "SELECT * FROM Q2_Groups WHERE nonUniqueID = ? ORDER BY _Order ASC");
        if (!$stmt) return [];
        mysqli_stmt_bind_param($stmt, 's', $linkID);  // linkID IS the nonUniqueID of children
        mysqli_stmt_execute($stmt);
        $results = [];
        $res = $stmt->get_result();
        while ($row = $res->fetch_assoc()) $results[] = $row;
        mysqli_stmt_close($stmt);
        return $results;
    }

    /* Recorre el árbol recursivamente y renderiza preguntas */
    public function getGroupHeritage($products, $isRoot = true) {
        foreach ($products as $product) {
            $linkID = $product['LinkID'] ?? '';
            $children = $this->getGroupChilds($linkID);

            foreach ($children as $child) {
                if ($child['Type'] == 'Question') {
                    $qData = $this->_getQuestionData($child['LinkID']);
                    if ($qData) {
                        $this->actualQuestion++;
                        $this->ConscienceMemory[$this->ConscienceLevel] = $linkID . "_params";
                        $this->renderQuestion($qData, $child, $linkID);
                    }
                } elseif ($child['Type'] == 'Group') {
                    $this->ConscienceLevel++;
                    $this->ConscienceMemory[$this->ConscienceLevel] = $child['LinkID'] . "_params";
                    $this->getGroupHeritage([$child], false);
                    $this->ConscienceLevel--;
                }
            }
        }
    }

    private function _getQuestionData($uniqueID) {
        $stmt = mysqli_prepare($this->link,
            "SELECT * FROM Q1_Directory WHERE UniqueID = ? LIMIT 1");
        if (!$stmt) return null;
        mysqli_stmt_bind_param($stmt, 's', $uniqueID);
        mysqli_stmt_execute($stmt);
        $row = $stmt->get_result()->fetch_assoc();
        mysqli_stmt_close($stmt);
        return $row;
    }

    /* Renderiza el HTML de una pregunta según su tipo */
    public function renderQuestion($q, $groupRow, $parentID) {
        $n       = $this->actualQuestion;
        $type    = strtolower($q['QuestionType'] ?? 'shortquestion');
        $uid     = htmlspecialchars($q['UniqueID'] ?? '');
        $title   = htmlspecialchars($q['Title'] ?? '', ENT_QUOTES);
        $text    = htmlspecialchars($q['QuestionText'] ?? '', ENT_QUOTES);
        $help    = htmlspecialchars($q['Help'] ?? '', ENT_QUOTES);
        $mediaURL = $q['MediaURL'] ?? '';
        $answers  = $q['Answers'] ?? '';
        $minA    = (int)($q['minAnswers'] ?? 1);
        $maxA    = (int)($q['maxAnswers'] ?? 1);
        $timeout = (int)($q['timeout'] ?? 0);
        $emojis  = $q['Emojis'] ?? '';
        $rows    = (int)($q['rows'] ?? 0);
        $cols    = (int)($q['columns'] ?? 0);
        $random  = $q['randomAnswers'] ?? '0';
        $cond    = htmlspecialchars($groupRow['condition'] ?? '', ENT_QUOTES);
        $pre     = htmlspecialchars($groupRow['preScript'] ?? '', ENT_QUOTES);
        $post    = htmlspecialchars($groupRow['postScript'] ?? '', ENT_QUOTES);
        $route   = implode(',', array_filter($this->ConscienceMemory)) . ',' . $n;
        $parent  = $parentID . "_params";

        // Prefijo de bloque para captura biométrica
        $blockPfx = match($type) {
            'video', 'videomarker' => 'BV',
            'image', 'imageclick'  => 'BI',
            'smartarray'           => 'BS',
            'ayuda'                => 'BE',
            'eyecalib'             => 'BQ',
            default                => 'BQ',
        };

        echo "<div class='actualQuestion' id='a{$n}'\n";
        echo "     data-type='{$type}' data-questiontype='{$type}'\n";
        echo "     data-uniqueid='{$uid}' data-parent='{$parent}'\n";
        echo "     data-user='" . htmlspecialchars(cUSER, ENT_QUOTES) . "'\n";
        echo "     data-route='" . htmlspecialchars($route, ENT_QUOTES) . "'\n";
        echo "     data-condition='{$cond}'\n";
        echo "     data-prescript='{$pre}' data-postscript='{$post}'\n";
        echo "     data-timeout='{$timeout}' data-minanswers='{$minA}' data-maxanswers='{$maxA}'\n";
        echo "     data-blockprefix='{$blockPfx}'\n";
        echo "     style='display:none'>\n";

        // Tipos media: sin cabecera de texto, widget a pantalla completa
        $isMedia = in_array($type, ['video','videomarker','image','imageclick']);

        if ($isMedia) {
            echo "  <div class='questionPartQuestion media-fullscreen' id='h{$n}'>\n";
            echo "    <p class='warning' id='warning{$n}'></p>\n";
            echo $this->_renderWidget($n, $type, $answers, $mediaURL, $minA, $maxA,
                                      $timeout, $emojis, $rows, $cols, $random, $q);
            echo "  </div>\n";
        } else {
            echo "  <div class='questionPartQuestion' id='h{$n}'>\n";
            if ($title) echo "    <h2 id='tTitle{$n}'>{$title}</h2>\n";
            if ($text)  echo "    <div id='tQuestion{$n}' class='tQuestion'>{$text}</div>\n";
            if ($help)  echo "    <div id='tHelp{$n}' class='help'>{$help}</div>\n";
            echo "    <p class='warning' id='warning{$n}'></p>\n";
            echo $this->_renderWidget($n, $type, $answers, $mediaURL, $minA, $maxA,
                                      $timeout, $emojis, $rows, $cols, $random, $q);
            echo "  </div>\n";
        }

        // Sección KPN (modo isKPN)
        echo "  <div id='j{$n}' style='display:none'>\n";
        echo "    <div class='circle'><img src='/circles/" . htmlspecialchars(circleQuestion) . "' alt=''></div>\n";
        echo "  </div>\n";
        echo "  <div id='k{$n}' style='display:none'></div>\n";

        echo "</div>\n";
    }

    private function _renderWidget($n, $type, $answers, $mediaURL, $minA, $maxA,
                                   $timeout, $emojis, $rows, $cols, $random, $q) {
        // Variables disponibles en cada plantilla questions/q_*.php:
        //   $n, $type, $opts, $answers, $mediaURL, $minA, $maxA,
        //   $timeout, $emojis, $rows, $cols, $random, $q, $this
        $opts = $this->_parseOptions($answers, $random === '1');

        $tpl = __DIR__ . "/screens/questions/q_{$type}.php";
        if (!file_exists($tpl)) {
            $tpl = __DIR__ . "/screens/questions/q_default.php";
        }

        ob_start();
        include $tpl;
        return ob_get_clean();
    }

    private function _parseOptions($answersStr, $shuffle = false) {
        if (empty($answersStr)) return [];
        $raw = explode("|", $answersStr);
        $opts = [];
        foreach ($raw as $r) {
            $r = trim($r);
            if ($r === '') continue;
            $parts = explode("=", $r);
            $label = $parts[0] ?? $r;
            $value = $parts[1] ?? $label;
            $order = isset($parts[2]) ? (float)$parts[2] : count($opts);
            $opts[] = [$label, $value, $order];
        }
        if ($shuffle) {
            usort($opts, fn($a, $b) => ($a[2] + mt_rand()/mt_getrandmax()) <=> ($b[2] + mt_rand()/mt_getrandmax()));
        } else {
            usort($opts, fn($a, $b) => $a[2] <=> $b[2]);
        }
        return $opts;
    }

    /* Guarda las respuestas en Q3_Answers */
    public function saveData() {
        $raw = $_REQUEST['myData'] ?? '';
        if (empty($raw)) return;

        $tracker   = $_REQUEST['tracker']  ?? '';
        $test      = $_REQUEST['curTest']  ?? cTEST;
        $owner     = $_REQUEST['curOwner'] ?? cOWNER;
        $datetimeCode = cUSER . ' ' . ($_SERVER['REMOTE_ADDR'] ?? '');

        $lines = explode("\n", trim($raw));
        foreach ($lines as $line) {
            $line = trim($line);
            if (empty($line)) continue;
            $fields = explode("\t", $line);
            if (count($fields) < 3) continue;

            if (($fields[0] ?? '') === 'Answer' && ($fields[1] ?? '') === 'CRC32') continue; // skip header row
            $answer   = $fields[0] ?? '';
            $user     = $fields[1] ?? cUSER;
            $uniqueID = $fields[2] ?? '';
            $qtype    = $fields[4] ?? '';
            $route    = $fields[5] ?? '';
            $order    = (int)($fields[6] ?? 0);
            $datetime = $fields[7] ?? date('Y-m-d H:i:s');
            $ip       = $_SERVER['REMOTE_ADDR'] ?? '';
            $plat     = substr($fields[10] ?? '', 0, 16);
            $scr      = substr($fields[11] ?? '', 0, 10);
            $crc      = $user . ' ' . $ip;

            $stmt = mysqli_prepare($this->link,
                "INSERT INTO Q3_Answers (Test, UniqueID, Answer, _CRC32, owner, datetimecode, IP, _Type, Route, _Order, platform, screen)
                 VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
                 ON DUPLICATE KEY UPDATE Answer = VALUES(Answer)");
            if (!$stmt) continue;
            mysqli_stmt_bind_param($stmt, 'sssssssssiss',
                $test, $uniqueID, $answer, $crc, $owner,
                $datetime, $ip, $qtype, $route, $order, $plat, $scr);
            mysqli_stmt_execute($stmt);
            mysqli_stmt_close($stmt);
        }

        // Guardar trackerData en Q4_Tracker si viene
        if (!empty($tracker)) {
            $tlines = explode("\n", trim($tracker));
            foreach ($tlines as $tline) {
                $tline = trim($tline);
                if (empty($tline)) continue;
                $tf = explode("\t", $tline);
                if (count($tf) < 6) continue;
                $tTest = $tf[0]; $tUser = $tf[1]; $tUID = $tf[2];
                $tTime = $tf[3]; $tX = $tf[4]; $tY = $tf[5];
                $stmt = mysqli_prepare($this->link,
                    "INSERT INTO Q4_Tracker (Test, User, UniqueID, KPI, Value, TimeOffset, owner)
                     VALUES (?, ?, ?, 'GazeX', ?, ?, ?)");
                if ($stmt) {
                    mysqli_stmt_bind_param($stmt, 'sssdds', $tTest, $tUser, $tUID, $tX, $tTime, $owner);
                    mysqli_stmt_execute($stmt);
                    mysqli_stmt_close($stmt);
                }
                $stmt = mysqli_prepare($this->link,
                    "INSERT INTO Q4_Tracker (Test, User, UniqueID, KPI, Value, TimeOffset, owner)
                     VALUES (?, ?, ?, 'GazeY', ?, ?, ?)");
                if ($stmt) {
                    mysqli_stmt_bind_param($stmt, 'sssdds', $tTest, $tUser, $tUID, $tY, $tTime, $owner);
                    mysqli_stmt_execute($stmt);
                    mysqli_stmt_close($stmt);
                }
            }
        }
        echo json_encode(["status" => "ok", "saved" => count($lines)]);
    }
}

/* ─── Función de guardado independiente (para el POST handler al inicio) ─────────── */
function _saveAnswers() {
    include_once "config.php";
    list($host, $user, $pass, $dbname) = explode('|', DB_MAIN);
    $link = mysqli_connect($host, $user, $pass, $dbname);
    if (!$link) { echo json_encode(["status" => "error"]); return; }
    $link->set_charset("utf8mb4");

    $raw    = $_REQUEST['myData']   ?? '';
    $owner  = $_REQUEST['curOwner'] ?? '';
    $test   = $_REQUEST['curTest']  ?? '';
    $user_  = isset($_SESSION['kpnUser']) ? $_SESSION['kpnUser'] : "unknown";

    $lines = explode("\n", trim($raw));
    $saved = 0;
    foreach ($lines as $line) {
        $line = trim($line);
        if (empty($line)) continue;
        $f = explode("\t", $line);
        if (count($f) < 3) continue;
        if (($f[0] ?? '') === 'Answer' && ($f[1] ?? '') === 'CRC32') continue; // skip header row
        $answer = $f[0] ?? '';
        $u      = $f[1] ?? $user_;
        $uid    = $f[2] ?? '';
        $type   = $f[4] ?? '';
        $route  = $f[5] ?? '';
        $order  = (int)($f[6] ?? 0);
        $dt     = $f[7] ?? date('Y-m-d H:i:s');
        $plat   = substr($f[10] ?? '', 0, 16);
        $scr    = substr($f[11] ?? '', 0, 10);
        $ip     = $_SERVER['REMOTE_ADDR'] ?? '';
        $crc    = $u . ' ' . $ip;
        $stmt = mysqli_prepare($link,
            "INSERT INTO Q3_Answers (Test, UniqueID, Answer, _CRC32, owner, datetimecode, IP, _Type, Route, _Order, platform, screen)
             VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
             ON DUPLICATE KEY UPDATE Answer = VALUES(Answer)");
        if (!$stmt) continue;
        mysqli_stmt_bind_param($stmt, 'sssssssssiss',
            $test, $uid, $answer, $crc, $owner, $dt, $ip, $type, $route, $order, $plat, $scr);
        mysqli_stmt_execute($stmt);
        mysqli_stmt_close($stmt);
        $saved++;
    }
    mysqli_close($link);
    echo json_encode(["status" => "ok", "saved" => $saved]);
}

/* ─── Instanciar pollData ─────────────────────────────────────────────────────────── */
$myData = new pollData();

/* ─── Obtener estructura del test para renderizado ──────────────────────────────── */
list($_dbHost, $_dbUser, $_dbPass, $_dbName) = explode('|', DB_MAIN);
$_link = mysqli_connect($_dbHost, $_dbUser, $_dbPass, $_dbName);
$_testRoot = [];
if ($_link) {
    $_link->set_charset("utf8mb4");
    $_stmt = mysqli_prepare($_link,
        "SELECT * FROM Q2_Groups WHERE nonUniqueID = ? AND Type = 'Test' LIMIT 1");
    if ($_stmt) {
        $_t = cTEST;
        mysqli_stmt_bind_param($_stmt, 's', $_t);
        mysqli_stmt_execute($_stmt);
        $_testRoot = $_stmt->get_result()->fetch_assoc();
        mysqli_stmt_close($_stmt);
    }
}

/* ─── HTML ──────────────────────────────────────────────────────────────────────── */
?>
<!DOCTYPE html>
<html lang="<?php echo LANG; ?>">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <title>Kopernica</title>
    <link rel="icon" type="image/png" href="/favicon.png" sizes="32x32">
    <link rel="stylesheet" href="/styles.css?v=<?php echo VERSION; ?>">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" crossorigin="anonymous" referrerpolicy="no-referrer">
    <link rel="stylesheet" href="/css/forzar-horizontal.css">
    <script src="/js2/jquery.min.js"></script>
    <script src="/js/eyetracker.js"></script>
</head>
<body id="body" class="<?php echo cMODE; ?>">

<!-- ── Cámara ──────────────────────────────────────────────────────────────── -->
<video id="video" playsinline autoplay muted style="display:none"></video>
<canvas id="canvas" style="display:none"></canvas>
<canvas id="snap"   style="display:none"></canvas>
<div id="dot" style="visibility:hidden; position:fixed; width:16px; height:16px; border-radius:50%;
     background:rgba(0,130,200,0.7); pointer-events:none; z-index:999999;
     transform:translate(-50%,-50%);"></div>

<!-- ── Variables JS críticas ANTES de los módulos del body ────────────────── -->
<script>
// Variables needed by quality_module.php and other body modules before main script
var cMODE    = <?php echo json_encode(cMODE);  ?>;
var cTEST    = <?php echo json_encode(cTEST);  ?>;
var cOWNER   = <?php echo json_encode(cOWNER); ?>;
var cUSER    = <?php echo json_encode(cUSER);  ?>;
var DOMAIN   = <?php echo json_encode(DOMAIN); ?>;
var goto     = <?php echo json_encode((string)$goto); ?>;
var mandatoryWebcam          = <?php echo json_encode(mandatoryWebcam); ?>;
var doEyetrackerCalibration  = <?php echo json_encode(doEyetrackerCalibration); ?>;
var doBaseline               = <?php echo json_encode(doBaseline); ?>;
var showLegalText             = <?php echo json_encode(showLegalText); ?>;
var autoInit   = false;
var exclusive  = (mandatoryWebcam === 'true');
var canResize  = false;
var isKPN      = false;
var questionTypePrefix = "BB";

// ── Control de pantallas ──────────────────────────────────────────────────────
function screenLegalAccept() {
    var ls = document.getElementById('legal-section');
    var ss = document.getElementById('start-section');
    if (ls) ls.style.display = 'none';
    if (ss) ss.style.display = 'block';
    if (skipCalibration) {
        // Saltar el botón "Iniciar" — arrancar cámara y test automáticamente.
        // El pequeño delay deja que el DOM se actualice antes de la init de cámara.
        setTimeout(function() { handleCameraStart(); }, 300);
    }
}
function screenLegalDecline() {
    var bc = document.getElementById('background-cover');
    var ld = document.getElementById('lopdat');
    if (bc) bc.style.display = 'none';
    if (ld) {
        ld.style.cssText = 'display:flex; align-items:center; justify-content:center; padding:0;';
        ld.innerHTML = '<div class="presentacion">'
            + '<h2 style="color:#cc0000;">Acceso denegado</h2>'
            + '<p>Ha rechazado los términos. No puede continuar con el test.</p></div>';
    }
}
// handleCameraStart(): called by the start button
// background-cover stays visible until acepto() hides it when the test starts.
// #camQuality (face centering) appears ON TOP (z-index:920000) while background-cover is still shown.
async function handleCameraStart() {
    // Show loading state inside background-cover while camera initializes
    var ss = document.getElementById('start-section');
    var ls = document.getElementById('legal-section');
    if (ss) ss.style.display = 'none';
    if (ls) ls.style.display = 'none';
    var mx = document.getElementById('maximiles');
    if (mx) mx.innerHTML = '<div id="cam-loading"><div class="spinner"></div>' +
        '<p>Iniciando cámara...</p></div>';

    if (cMODE === 'cuanti') {
        document.getElementById('background-cover').style.display = 'none';
        startWCapt();
        return;
    }

    // skipCalibration: saltar toda la inicialización de cámara, WASM y calibración.
    if (skipCalibration) {
        if (typeof initRan !== 'undefined') initRan = true;
        if (typeof browserIdentity === 'function') browserIdentity();
        startWCapt();
        return;
    }

    // Request camera — shared stream for tracker and image capture
    var camOk = false;
    if (typeof KPNGaze !== 'undefined') {
        try {
            camOk = await KPNGaze.initCamera();
            var stream = KPNGaze.getStream();
            if (stream) {
                var v1 = document.getElementById('video');
                var v2 = document.getElementById('_kpn_preview_video');
                if (v1) v1.srcObject = stream;
                if (v2) v2.srcObject = stream;
                window.stream = stream;
            }
        } catch(e) { console.warn('KPNGaze.initCamera failed:', e); }
    }
    if (!camOk) {
        try {
            var s = await navigator.mediaDevices.getUserMedia({audio:false, video:{width:640,height:480}});
            window.stream = s;
            var v = document.getElementById('video');
            var p = document.getElementById('_kpn_preview_video');
            if (v) v.srcObject = s;
            if (p) p.srcObject = s;
            camOk = true;
        } catch(e) {
            if (mandatoryWebcam === 'true') { badEnd(typeof badEndNoCam !== 'undefined' ? badEndNoCam : 'No camera'); return; }
        }
    }

    // Marcar la cámara como inicializada para que record() no llame init() de nuevo.
    // init() de javascript.js llama getUserMedia() que crearía un stream conflictivo
    // con el que ya tiene MediaPipe. Al poner initRan=true se salta ese segundo init.
    if (typeof initRan !== 'undefined') initRan = true;
    if (typeof browserIdentity === 'function') browserIdentity();

    // background-cover still visible here.
    // startFaceCentering() shows #camQuality on top (z-index:920000).
    // After face centering: calibrator redirect OR acepto() hides background-cover.
    if (typeof startFaceCentering === 'function') await startFaceCentering();
}

// ── Contador footer: visible cuando maxQuestions > 0 ─────────────────────────
document.addEventListener('DOMContentLoaded', function() {
    var cEl = document.getElementById('question-counter');
    var mEl = document.getElementById('maxQuestions');
    if (cEl && mEl) {
        new MutationObserver(function() {
            if (parseInt(mEl.textContent) > 0) cEl.style.visibility = 'visible';
        }).observe(mEl, {childList:true, characterData:true, subtree:true});
    }
});

// hideBaseline() está definida en javascript.js — llama a red() que activa
// correctamente la primera pregunta sin avanzar automáticamente a la segunda.

</script>

<!-- ── Pantallas de flujo (templates en screens/) ─────────────────────────── -->

<!-- Pantalla 1: Texto legal + Pantalla de inicio (dentro de #background-cover) -->
<div id="background-cover" class="background-cover" style="display:block; overflow-y:auto;">
    <div id="maximiles">
        <?php if (showLegalText == 'true'): ?>
            <?php include_once "screens/screen_legal.php"; ?>
            <!-- screen_start se inyecta dentro del #start-section abierto por screen_legal.php -->
            <?php include_once "screens/screen_start.php"; ?>
            </div><!-- cierre #start-section -->
        <?php else: ?>
            <?php include_once "screens/screen_start.php"; ?>
        <?php endif; ?>
    </div>
</div>

<!-- Pantalla 2: Centrado de rostro (activado por startFaceCentering() desde startWCapt) -->
<?php if (cMODE != 'cuanti') { include_once "quality_module.php"; } ?>

<!-- Pantalla 3: Preguntas del test -->
<div id="page" class="<?php echo cMODE; ?>">

    <!-- Calibracion del eyetracker (dentro del 16:9) -->
    <?php include_once "screens/screen_eyecalib_inline.php"; ?>

    <!-- #Start: pantalla de Baseline (círculo) — oculta hasta que acepto()+cambioBloque("BB00") la activa -->
    <?php include_once "screens/screen_baseline.php"; ?>

    <?php
    if (!empty($_testRoot)) {
        $myData->getGroupHeritage([$_testRoot], true);
    }
    ?>
    <div id="End" style="display:none"></div>
</div>

<!-- Pantalla 4: Finalización / subida de imágenes (template) -->
<?php include_once "screens/screen_ended.php"; ?>

<!-- Pantalla 5: Rechazo LOPDAT (template) -->
<?php include_once "screens/screen_lopdat.php"; ?>



<!-- ── Navegación ─────────────────────────────────────────────────────────── -->
<?php include_once "screens/screen_navigation.php"; ?>

<!-- ── Footer ─────────────────────────────────────────────────────────────── -->
<?php include_once "screens/screen_footer.php"; ?>

<!-- ── Debug panel ────────────────────────────────────────────────────────── -->
<?php include_once "screens/screen_debug.php"; ?>

<!-- ── Script principal (PHP+JS inline) ──────────────────────────────────── -->
<script>
<?php
/* Variables de texto globales */
$textKeys = ['camera_error','noCamError','noCamWarning','camNotOff','prueba_abortada',
             'imposible_camera','imageProblemsWarning',
             'almostthere','instructions_emo','instructions_cuanti',
             'face_iloc','face_out','face_in','face_iloc_text','face_out_text','face_in_text',
             'ini_calib','calib_start','invalid_url','important','url_malformed',
             'url_notadminpage','continuar',
             'debeResponder','debeResponderMin'];
foreach ($textKeys as $k) {
    echo "var " . $k . " = " . json_encode(get_Text($k)) . ";\n";
}
// Keys that conflict with function names go in a T.* namespace
echo "var T = T || {};\n";
echo "T.send = " . json_encode(get_Text('send')) . ";\n";
echo "T.next = " . json_encode(get_Text('next')) . ";\n";
echo "T.back = " . json_encode(get_Text('back')) . ";\n";
echo "T.start = " . json_encode(get_Text('start')) . ";\n";
// Missing variables that javascript.js expects
echo "var cuota = " . json_encode((int)($myData->maxUsers)) . ";\n";
echo "var tipoBadEnd = \"\";\n";
echo "var badEndNoCam = " . json_encode(get_Text('badEndNoCam')) . ";\n";
?>
var cTEST   = <?php echo json_encode(cTEST);   ?>;
var cOWNER  = <?php echo json_encode(cOWNER);  ?>;
var cUSER   = <?php echo json_encode(cUSER);   ?>;
var cMODE   = <?php echo json_encode(cMODE);   ?>;
var DOMAIN  = <?php echo json_encode(DOMAIN);  ?>;
var cNotify = <?php echo json_encode(defined('cNotify') ? cNotify : ''); ?>;
var cLANG   = <?php echo json_encode(defined('cLANG')   ? cLANG   : 'false'); ?>;
var goto   = <?php echo json_encode((string)$goto); ?>;
var mandatoryWebcam          = <?php echo json_encode(mandatoryWebcam); ?>;
var doEyetrackerCalibration  = <?php echo json_encode(doEyetrackerCalibration); ?>;
var doBaseline               = <?php echo json_encode(doBaseline); ?>;
var showLegalText            = <?php echo json_encode(showLegalText); ?>;
<?php $myData->printUserLimitVars(cTEST); ?>
<?php include "javascript.js"; ?>
</script>

<script src="/js/eyecalib_inline.js?v=<?php echo VERSION; ?>"></script>
<?php include 'screens/screen_forzar_horizontal.php'; ?>
<script src="/js/forzar-horizontal.js"></script>
</body>
</html>
