=== FUNCIONES EPG ===
<?php
if(!isset($_GET["epg_refresh"])) $_GET["epg_refresh"]="1";
session_start();
date_default_timezone_set("America/Santiago");

$dns  = $_SESSION["dns"]  ?? "http://puntoz.live:2082";
$user = $_SESSION["user"] ?? "admintoc";
$pass = $_SESSION["pass"] ?? "pyk12345";

function api_xtream($dns,$user,$pass,$action,$extra=""){
    $url = rtrim($dns,"/")."/player_api.php?username=".urlencode($user)."&password=".urlencode($pass)."&action=".$action.$extra;
    $json = @file_get_contents($url);
    $data = json_decode($json,true);
    return is_array($data) ? $data : [];
}


function epg_titles($dns,$user,$pass,$sid){
    if(!$sid) return ["No information","No information","","","",""];

    $e = api_xtream($dns,$user,$pass,"get_short_epg","&stream_id=".$sid."&limit=6");
    $list = $e["epg_listings"] ?? $e["epg_list"] ?? [];

    if(!$list || !is_array($list)) return ["No information","No information","","","",""];

    $nowTs = time();
    $actual = $list[0] ?? [];
    $siguiente = $list[1] ?? [];

    foreach($list as $i=>$it){
        $st = intval($it["start_timestamp"] ?? 0);
        $en = intval($it["stop_timestamp"] ?? $it["end_timestamp"] ?? 0);

        if($st > 0 && $en > $st && $nowTs >= $st && $nowTs < $en){
            $actual = $it;
            $siguiente = $list[$i+1] ?? [];
            break;
        }
    }

    $decode = function($v){
        $v = trim((string)$v);
        if($v === "") return "No information";

        $d = base64_decode($v,true);
        if($d !== false && trim($d) !== "") return trim($d);

        return $v;
    };

    $nowTitle = $decode($actual["title"] ?? "No information");
    $nextTitle = $decode($siguiente["title"] ?? "No information");

    $nowStart = (string)intval($actual["start_timestamp"] ?? 0);
    $nowEnd = (string)intval($actual["stop_timestamp"] ?? $actual["end_timestamp"] ?? 0);

    $nextStart = (string)intval($siguiente["start_timestamp"] ?? 0);
    $nextEnd = (string)intval($siguiente["stop_timestamp"] ?? $siguiente["end_timestamp"] ?? 0);

    $thirdTitle = $decode($list[2]["title"] ?? "No information");
$fourthTitle = $decode($list[3]["title"] ?? "No information");
return [$nowTitle,$nextTitle,$nowStart,$nowEnd,$nextStart,$nextEnd,$thirdTitle,$fourthTitle];
}


function epg_grid_titles($dns,$user,$pass,$sid){
    $r = epg_titles($dns,$user,$pass,$sid);
    return [
        $r[0] ?? "No information",
        $r[1] ?? "No information",
        $r[6] ?? "No information",
        $r[7] ?? "No information"
    ];
}


function epg_programs_36h($dns,$user,$pass,$sid){
    if(!$sid) return [];
    $e = api_xtream($dns,$user,$pass,"get_short_epg","&stream_id=".$sid."&limit=160");
    $list = $e["epg_listings"] ?? $e["epg_list"] ?? [];
    if(!$list || !is_array($list)) return [];

    $decode = function($v){
        $v = trim((string)$v);
        if($v === "") return "Sin información";
        $d = base64_decode($v,true);
        if($d !== false && trim($d)!=="") return trim($d);
        return $v;
    };

    $now = time();
    $max = $now + 36*3600;
    $out = [];

    foreach($list as $it){
        $st = intval($it["start_timestamp"] ?? 0);
        $en = intval($it["stop_timestamp"] ?? $it["end_timestamp"] ?? 0);
        if($st<=0 || $en<=$st) continue;
        if($en<$now || $st>$max) continue;
        $out[] = [
            "title"=>$decode($it["title"] ?? "Sin información"),
            "start"=>$st,
            "end"=>$en
        ];
    }
    return $out;
}

function pz_hora36($ts){
    return $ts>0 ? date("H:i",$ts) : "";
}

$cats = api_xtream($dns,$user,$pass,"get_live_categories");
$cat  = $_GET["cat"] ?? "";
$stream = $_GET["stream"] ?? "";

if(!$cat && count($cats)){
    $cat = $cats[0]["category_id"] ?? "";
}


=== EPG CANAL SELECCIONADO ===
$keepEpg = isset($_GET["epg_refresh"]) ? "&epg_refresh=".urlencode($_GET["epg_refresh"]) : "";

$playUrl = $selected ? rtrim($dns,"/")."/live/".$user."/".$pass."/".$selected["stream_id"].".m3u8" : "";

$epgNow = "Sin información";
$epgNext = "Sin información";

if($selected){
    $epg = api_xtream(
        $dns,
        $user,
        $pass,
        "get_short_epg",
        "&stream_id=".$selected["stream_id"]."&limit=2"
    );

    if(!empty($epg["epg_listings"][0]["title"])){
        $epgNow = base64_decode($epg["epg_listings"][0]["title"]);
    }

    if(!empty($epg["epg_listings"][1]["title"])){
        $epgNext = base64_decode($epg["epg_listings"][1]["title"]);
    }

    if (!function_exists("pz_epg_ts_top")) {
        function pz_epg_ts_top($item, $tipo) {
            $keys = $tipo === "start"
                ? ["start_timestamp","start","start_time"]
                : ["end_timestamp","stop_timestamp","end","stop","end_time"];
            foreach($keys as $k){
                if(isset($item[$k]) && $item[$k] !== ""){

=== TOP DERECHO ===
</head>
<body>


<div class="app">
    <aside class="side">
        <div class="logo"><span>puntoz</span> TV</div>
        <div class="nav active navFocus">▣ TV EN VIVO</div>
        <div class="nav navFocus">⌂ Inicio</div>
        <div class="nav navFocus">🎬 Movies</div>
        <div class="nav navFocus">▤ TV Shows</div>
        <div class="nav navFocus">⚙ Settings</div>
    </aside>

    <section class="cats">
        <h1>All playlists</h1>
        <a class="cat navFocus <?=$cat===''?'active':''?>" href="tv_clean.php">All channels</a>
        <?php foreach($cats as $c): ?>
        <a class="cat navFocus <?=((string)$cat===(string)$c["category_id"])?'active':''?>" href="tv_clean.php?cat=<?=urlencode($c["category_id"])?><?=$keepEpg?>">
            <?=htmlspecialchars($c["category_name"] ?? "Sin nombre")?>
        </a>
        <?php endforeach; ?>
    </section>

    <main class="main">
        <section class="top">
            <div class="videoBox navFocus" tabindex="0">
                <?php if($playUrl): ?>
                <video id="mainVideo" class="navFocus" tabindex="0" autoplay playsinline src="<?=htmlspecialchars($playUrl)?>"></video>
                <?php endif; ?>
            </div>
            <div class="info"><a class="refreshEpg navFocus" href="<?=htmlspecialchars($_SERVER["PHP_SELF"])?>?<?=htmlspecialchars(http_build_query(array_merge($_GET, ["epg_refresh"=>time()])))?>">↻ Actualizar EPG</a>
<?php if(isset($_GET["epg_refresh"])): ?><div class="toast">Guía actualizada OK</div><?php endif; ?>
            <?php
              $nowTitle = $epgTop[0] ?? $epgNow ?? "No information";
              $nextTitle = $epgTop[1] ?? $epgNext ?? "No information";
              $startTs = intval($epgTop[2] ?? 0);
              $endTs = intval($epgTop[3] ?? 0);
              $nextStartTs = intval($epgTop[4] ?? 0);
              $nextEndTs = intval($epgTop[5] ?? 0);
              $nowTs = time();

              $progress = 0;
              $remainMin = 0;
              if ($startTs > 0 && $endTs > $startTs) {
                  $progress = max(0, min(100, intval((($nowTs - $startTs) / ($endTs - $startTs)) * 100)));
                  $remainMin = max(0, intval(ceil(($endTs - $nowTs) / 60)));
              }

              if (!function_exists("pz_hora_epg")) {
                function pz_hora_epg($ts) {

=== ROWS EPG ===
            <h2 id="channelTitle"><?=htmlspecialchars($selected["name"] ?? "Sin canal")?></h2>
            <div class="epgDetail">
              <div class="epgDate"><?=$fechaBonita?></div>

              <div class="epgLabelNow">AHORA</div>
              <div class="epgProgramNow"><?=htmlspecialchars($nowTitle)?></div>
              <?php if ($startTs > 0 && $endTs > 0): ?>
              <div class="epgTimeSimple"><?=pz_hora_epg($startTs)?> - <?=pz_hora_epg($endTs)?></div>
              <?php endif; ?>
              <div class="epgBarLine">
                <div class="epgBarMini"><div class="epgBarFill" style="width:<?=$progress?>%"></div></div>
                <span><?=$remainMin?> min</span>
              </div>

              <div class="epgLabelNext">SIGUE</div>
              <div class="epgProgramNext"><?=htmlspecialchars($nextTitle)?></div>
              <div class="epgNextTime"><?=pz_hora_epg($nextStartTs)?> - <?=pz_hora_epg($nextEndTs)?></div>
            </div>
            </div>
        </section>

        
<section class="timebar36">
    <div class="timeDate"><?=date("D, d M, H:i")?></div>
    <div class="timeScroll" id="timeScroll">
        <?php for($h=0;$h<=36;$h++): ?>
            <div class="hourCell"><?=date("H:i", time()+($h*3600))?></div>
        <?php endfor; ?>
    </div>
</section>

<section class="grid36Wrap" id="grid36Wrap">
    <?php foreach($channels as $idx=>$c):
        $is=((string)$stream===(string)$c["stream_id"]);
        $programs = epg_programs_36h($dns,$user,$pass,$c["stream_id"]);
        $rowStart = time();
        $pxPerMin = 4;
    ?>
    <a class="row row36 navFocus <?=$is?'active':''?>"
       data-play="<?=htmlspecialchars(trim($dns,"/")."/live/".$user."/".$pass."/".$c["stream_id"].".m3u8")?>"
       data-name="<?=htmlspecialchars($c["name"] ?? "Canal")?>"
       data-logo="<?=htmlspecialchars($c["stream_icon"] ?? "")?>"
       data-now="<?=htmlspecialchars($epgNow ?? "No information")?>"
       data-next="<?=htmlspecialchars($epgNext ?? "No information")?>"
       href="tv_clean.php?cat=<?=urlencode($cat)?>&stream=<?=urlencode($c["stream_id"])?><?=$keepEpg?>">
        <div class="ch ch36">
            <span class="chanNum"><?=intval($idx)+1?></span>
            <?php if(!empty($c["stream_icon"])): ?><img src="<?=htmlspecialchars($c["stream_icon"])?>"><?php endif; ?>
            <span class="chanName"><?=htmlspecialchars($c["name"] ?? "Canal")?></span>
        </div>
        <div class="track36">
