77:function epg_programs_36h($dns,$user,$pass,$sid){
78-    if(!$sid) return [];
79-    $e = api_xtream($dns,$user,$pass,"get_short_epg","&stream_id=".$sid."&limit=160");
80-    $list = $e["epg_listings"] ?? $e["epg_list"] ?? [];
81-    if(!$list || !is_array($list)) return [];
82-
83-    $decode = function($v){
84-        $v = trim((string)$v);
85-        if($v === "") return "Sin información";
86-        $d = base64_decode($v,true);
87-        if($d !== false && trim($d)!=="") return trim($d);
88-        return $v;
89-    };
90-
91-    $now = time();
92-    $max = $now + 36*3600;
93-    $out = [];
94-
95-    foreach($list as $it){
96-        $st = intval($it["start_timestamp"] ?? 0);
97-        $en = intval($it["stop_timestamp"] ?? $it["end_timestamp"] ?? 0);
98-        if($st<=0 || $en<=$st) continue;
99-        if($en<$now || $st>$max) continue;
100-        $out[] = [
101-            "title"=>$decode($it["title"] ?? "Sin información"),
102-            "start"=>$st,
103-            "end"=>$en
104-        ];
105-    }
106-    return $out;
107-}
108-
109-function pz_hora36($ts){
110-    return $ts>0 ? date("H:i",$ts) : "";
111-}
112-
113-$cats = api_xtream($dns,$user,$pass,"get_live_categories");
114-$cat  = $_GET["cat"] ?? "";
115-$stream = $_GET["stream"] ?? "";
116-
117-if(!$cat && count($cats)){
118-    $cat = $cats[0]["category_id"] ?? "";
119-}
120-
121-$channels = api_xtream($dns,$user,$pass,"get_live_streams", $cat ? "&category_id=".urlencode($cat) : "");
122-
123-$selected = null;
124-foreach($channels as $c){
125-    if((string)($c["stream_id"] ?? "") === (string)$stream){
126-        $selected = $c;
127-        break;
128-    }
129-}
130-if(!$selected && count($channels)){
131-    $selected = $channels[0];
132-    $stream = $selected["stream_id"] ?? "";
133-}
134-
135-$keepEpg = isset($_GET["epg_refresh"]) ? "&epg_refresh=".urlencode($_GET["epg_refresh"]) : "";
136-
137-$playUrl = $selected ? rtrim($dns,"/")."/live/".$user."/".$pass."/".$selected["stream_id"].".m3u8" : "";
138-
139-$epgNow = "Sin información";
140-$epgNext = "Sin información";
141-$topStartTs = 0;
142-$topEndTs = 0;
143-$topNextStartTs = 0;
144-$topNextEndTs = 0;
145-
146-if($selected){
147-    $epg = api_xtream(
148-        $dns,
149-        $user,
150-        $pass,
151-        "get_short_epg",
152-        "&stream_id=".$selected["stream_id"]."&limit=6"
153-    );
154-
155-    $topList = $epg["epg_listings"] ?? $epg["epg_list"] ?? [];
156-
157-    $decodeTop = function($v){
158-        $v = trim((string)$v);
159-        $d = base64_decode($v, true);
160-        return ($d !== false && trim($d) !== "") ? trim($d) : $v;
161-    };
162-
163-    $getTsTop = function($it, $keys){
164-        foreach($keys as $k){
165-            if(isset($it[$k]) && $it[$k] !== ""){
166-                if(is_numeric($it[$k])) return intval($it[$k]);
167-                $t = strtotime($it[$k]);
168-                if($t) return intval($t);
169-            }
170-        }
171-        return 0;
172-    };
173-
174-    if(!empty($topList[0])){
175-        $epgNow = $decodeTop($topList[0]["title"] ?? "Sin información");
176-        $topStartTs = $getTsTop($topList[0], ["start_timestamp","start","start_time"]);
177-        $topEndTs = $getTsTop($topList[0], ["stop_timestamp","end_timestamp","end","stop","end_time"]);
178-    }
179-
180-    if(!empty($topList[1])){
181-        $epgNext = $decodeTop($topList[1]["title"] ?? "Sin información");
182-        $topNextStartTs = $getTsTop($topList[1], ["start_timestamp","start","start_time"]);
183-        $topNextEndTs = $getTsTop($topList[1], ["stop_timestamp","end_timestamp","end","stop","end_time"]);
184-    }
185-}
186-
187-?>
188-<!doctype html>
189-<html>
190-<head>
191-<meta charset="utf-8">
192-<meta name="viewport" content="width=1920,height=1080,initial-scale=1">
193-<title>Puntoz TV Clean</title>
194-<style>
195-*{box-sizing:border-box}
196-body{margin:0;background:#05080d;color:white;font-family:Arial,Helvetica,sans-serif;overflow:hidden}
197-.app{width:1920px;height:1080px;display:grid;grid-template-columns:240px 440px 1fr;background:#101820;padding:35px 20px;background:rgba(0,0,0,.45)}
