<?php
/**
 * TG4G English listings (/en/listings)
 * Mirror of /var/www/tg4g/public/listings.php — same data, English UI.
 * Shares the `listings` table; only the labels, hero, filter chrome are translated.
 *
 * Deploy to: /var/www/tg4g/public/en/listings.php
 *
 * URL examples:
 *   /en/listings?cat=vps&country=US&p_max=20
 *   /en/listings?export=csv&cat=payment
 */
declare(strict_types=1);

require_once __DIR__ . '/i18n.php';

$cfg = require '/var/www/tg4g/config.php';
$db = $cfg['database'];
$dsn = 'mysql:host=' . $db['host'] . ';port=' . ($db['port'] ?? 3306) . ';dbname=' . $db['database'] . ';charset=utf8mb4';
$pdo = new PDO($dsn, $db['username'], $db['password'], [
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// ============ Category profiles (English labels via t()) ============
$PROFILES = [
    'vps' => [
        'label' => 'VPS', 'icon' => '🖥',
        'desc'  => t('cat_desc.vps'),
        'filters' => ['search','network','location','config','price','rating','cn','refund','pay'],
        'cols'    => ['fav','provider','network','cpu','ram','disk','bw','location','price','rating','cn','pay','source','updated','cta'],
        'sort'    => 'price_monthly_usd',
        'quick_subs' => ['KVM','OpenVZ','LXC','Web Hosting','VPS','Cloud VPS','Shared Hosting','Dedicated Servers','Proxy Hosting','Domain Registration'],
    ],
    'dedicated' => [
        'label' => 'Dedicated', 'icon' => '🗄',
        'desc'  => t('cat_desc.dedicated'),
        'filters' => ['search','location','config','price','rating','pay'],
        'cols'    => ['fav','provider','cpu','ram','disk','bw','location','price','rating','pay','source','updated','cta'],
        'sort'    => 'price_monthly_usd',
        'quick_subs' => ['Intel','AMD','GPU','Storage','High-bandwidth','Colocation'],
    ],
    'cdn' => [
        'label' => 'CDN', 'icon' => '🌐',
        'desc'  => t('cat_desc.cdn'),
        'filters' => ['search','price','rating','pay'],
        'cols'    => ['fav','provider','location','price','rating','pay','source','updated','cta'],
        'sort'    => 'price_monthly_usd',
        'quick_subs' => ['CDN','Content Delivery','DDoS Protection','Edge Compute','Static Acceleration','Video CDN'],
    ],
    'payment' => [
        'label' => 'Payments', 'icon' => '💳',
        'desc'  => t('cat_desc.payment'),
        'filters' => ['search','sub','hq','rating'],
        'cols'    => ['fav','provider','sub','hq','price','rating','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Payment Processor','Payment Gateway','Virtual Card','Crypto Payments','Retail Banking','Neobank','Insurance','Wealth Management'],
    ],
    'proxy' => [
        'label' => 'Proxies', 'icon' => '🔌',
        'desc'  => t('cat_desc.proxy'),
        'filters' => ['search','sub','hq','price','rating'],
        'cols'    => ['fav','provider','sub','hq','price','rating','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Residential Proxy','Datacenter Proxy','Mobile Proxy','Rotating Proxy','VPN','SOCKS5'],
    ],
    'domain' => [
        'label' => 'Domains', 'icon' => '🌍',
        'desc'  => t('cat_desc.domain'),
        'filters' => ['search','price','rating','pay'],
        'cols'    => ['fav','provider','price','rating','pay','source','updated','cta'],
        'sort'    => 'price_yearly_usd',
        'quick_subs' => ['Domain Registration','Domain Registrar','Auction','Parking','Transfer-in','TLD','SSL Certificate'],
    ],
    'saas' => [
        'label' => 'SaaS', 'icon' => '⚙',
        'desc'  => t('cat_desc.saas'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['CRM','Project Management','Email Marketing','Customer Support','HR','Accounting','Collaboration','Documents','Video Conferencing','Property Mgmt','Event Mgmt','Web Hosting','Digital Agency','Web Dev'],
    ],
    'ai' => [
        'label' => 'AI Apps', 'icon' => '🤖',
        'desc'  => t('cat_desc.ai'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['LLM','API','AI Chat','AI Writing','AI Image','AI Voice','AI Video','ML','Automation','Agent'],
    ],
    'edu' => [
        'label' => 'Education', 'icon' => '📚',
        'desc'  => t('cat_desc.edu'),
        'filters' => ['search','sub','hq','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Programming','Design','Business','Language','Exam Prep','Online Courses','MOOC','Tutoring','Academic','Early Education'],
    ],
    'dev' => [
        'label' => 'Dev Tools', 'icon' => '🔧',
        'desc'  => t('cat_desc.dev'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Frontend','Backend','Mobile App','DevOps','API','SDK','Database','Testing','Monitoring','Version Control','Low-code','WordPress','AI Coding','Web Dev'],
    ],
    'crypto' => [
        'label' => 'Crypto', 'icon' => '💰',
        'desc'  => t('cat_desc.crypto'),
        'filters' => ['search','sub','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Exchange','Wallet','Lending','Staking','NFT','Analytics','Explorer','Meme','Airdrop','DeFi','Derivatives'],
    ],
    'marketing' => [
        'label' => 'Marketing & SEO', 'icon' => '📈',
        'desc'  => t('cat_desc.marketing'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['SEO','Digital Marketing','Performance Marketing','Content Marketing','Email Marketing','Social Media','Affiliate','Cashback','Ads','Influencer'],
    ],
    'design' => [
        'label' => 'Design & Creative', 'icon' => '🎨',
        'desc'  => t('cat_desc.design'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['UI Design','UX Design','Logo','Graphic Design','Video Editing','Photo Editing','3D','Fonts','Illustration','Stock Assets','Prototyping'],
    ],
    'security' => [
        'label' => 'Security', 'icon' => '🛡',
        'desc'  => t('cat_desc.security'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['SSL','Firewall','Password Mgr','2FA','Antivirus','Pen Testing','IAM','DDoS','Audit'],
    ],
    'biz' => [
        'label' => 'Incorp & Compliance', 'icon' => '📋',
        'desc'  => t('cat_desc.biz'),
        'filters' => ['search','sub','hq','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Company Registration','Business License','Virtual Address','Registered Agent','Offshore','Compliance','Accounting','Tax Filing','Legal'],
    ],
    'comm' => [
        'label' => 'Comms & Email', 'icon' => '✉',
        'desc'  => t('cat_desc.comm'),
        'filters' => ['search','sub','price','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Email','SMS','OTP','VoIP','IM','Video Conferencing','Newsletter','Support'],
    ],
    'ec' => [
        'label' => 'E-commerce', 'icon' => '🛒',
        'desc'  => t('cat_desc.ec'),
        'filters' => ['search','sub','rating','cn'],
        'cols'    => ['fav','provider','sub','hq','price','rating','cn','source','updated','cta'],
        'sort'    => 'rating_avg',
        'quick_subs' => ['Shopify','Standalone Store','Cross-border','Dropshipping','Apparel','Beauty','Electronics','Home Goods','Auto Parts','Pets','Food Delivery','Restaurants','Jewelry','Furniture'],
    ],
];

// ============ Params (mirror of Chinese version) ============
$cat        = $_GET['cat'] ?? 'vps';
if (!isset($PROFILES[$cat])) $cat = 'vps';
$profile    = $PROFILES[$cat];

$sub        = $_GET['sub'] ?? '';
$nets       = (array)($_GET['net'] ?? []);
$countries  = (array)($_GET['country'] ?? []);
$hqs        = (array)($_GET['hq'] ?? []);
$pays       = (array)($_GET['pay'] ?? []);
$disktype   = $_GET['disk_type'] ?? '';
$cpu_min    = isset($_GET['cpu']) ? (int)$_GET['cpu'] : 0;
$ram_min    = isset($_GET['ram']) ? (float)$_GET['ram'] : 0;
$disk_min   = isset($_GET['disk']) ? (int)$_GET['disk'] : 0;
$bw_min     = isset($_GET['bw']) ? (float)$_GET['bw'] : 0;
$price_min  = isset($_GET['p_min']) ? (float)$_GET['p_min'] : 0;
$price_max  = isset($_GET['p_max']) ? (float)$_GET['p_max'] : 0;
$rating_min = isset($_GET['rating']) ? (float)$_GET['rating'] : 0;
$refund_min = isset($_GET['refund']) ? (int)$_GET['refund'] : 0;
$cn_min     = isset($_GET['cn']) ? (int)$_GET['cn'] : 0;
$q          = trim((string)($_GET['q'] ?? ''));
$sort       = $_GET['sort'] ?? $profile['sort'];
$dir        = ($_GET['dir'] ?? 'asc') === 'desc' ? 'desc' : 'asc';
$page       = max(1, (int)($_GET['page'] ?? 1));
$per        = min(500, max(10, (int)($_GET['per'] ?? 50)));
$export     = $_GET['export'] ?? '';

$sort_white = ['price_monthly_usd','price_yearly_usd','provider','cpu_cores','ram_gb','disk_gb','bandwidth_tb','rating_avg','review_count','refund_days','plan_name','network','location_country','cn_friendly','updated_at','id'];
if (!in_array($sort, $sort_white, true)) $sort = $profile['sort'];

// ============ WHERE ============
$where = ['is_active = 1', 'category = :cat'];
$params = [':cat' => $cat];

if ($sub !== '') { $where[] = 'sub_category LIKE :sub'; $params[':sub'] = '%' . $sub . '%'; }
foreach (['net'=>['network',$nets,'LIKE'], 'country'=>['location_country',$countries,'='], 'hq'=>['hq_country',$hqs,'='], 'pay'=>['payment_methods',$pays,'LIKE']] as $pfx => [$col,$vals,$op]) {
    if (!$vals) continue;
    $ph = [];
    foreach ($vals as $i => $v) {
        $key = ":{$pfx}{$i}";
        if ($op === 'LIKE') { $ph[] = "$col LIKE $key"; $params[$key] = '%'.$v.'%'; }
        else                { $ph[] = "$col = $key"; $params[$key] = $v; }
    }
    $where[] = '(' . implode(' OR ', $ph) . ')';
}
if ($disktype !== '') { $where[] = 'disk_type = :dt'; $params[':dt'] = $disktype; }
if ($cpu_min > 0)   { $where[] = 'cpu_cores >= :cpum';  $params[':cpum'] = $cpu_min; }
if ($ram_min > 0)   { $where[] = 'ram_gb >= :ramm';     $params[':ramm'] = $ram_min; }
if ($disk_min > 0)  { $where[] = 'disk_gb >= :diskm';   $params[':diskm'] = $disk_min; }
if ($bw_min > 0)    { $where[] = 'bandwidth_tb >= :bwm';$params[':bwm'] = $bw_min; }
if ($price_min > 0) { $where[] = 'price_monthly_usd >= :pmin'; $params[':pmin'] = $price_min; }
if ($price_max > 0) { $where[] = 'price_monthly_usd > 0 AND price_monthly_usd <= :pmax'; $params[':pmax'] = $price_max; }
if ($rating_min > 0){ $where[] = 'rating_avg >= :ratm'; $params[':ratm'] = $rating_min; }
if ($refund_min > 0){ $where[] = 'refund_days >= :rfdm'; $params[':rfdm'] = $refund_min; }
if ($cn_min > 0)    { $where[] = 'cn_friendly >= :cnm'; $params[':cnm'] = $cn_min; }
if ($q !== '')      { $where[] = '(provider LIKE :q OR plan_name LIKE :q OR notes LIKE :q)'; $params[':q'] = '%'.$q.'%'; }
$where_sql = implode(' AND ', $where);

// Counts
$st = $pdo->prepare("SELECT COUNT(*) AS n FROM listings WHERE $where_sql");
$st->execute($params);
$total = (int)$st->fetch()['n'];
$pages = max(1, (int)ceil($total / $per));
if ($page > $pages) $page = $pages;
$offset = ($page - 1) * $per;

$st = $pdo->prepare("SELECT * FROM listings WHERE $where_sql ORDER BY ($sort = 0) ASC, $sort $dir, id ASC LIMIT $per OFFSET $offset");
$st->execute($params);
$rows = $st->fetchAll();

// ============ CSV export ============
if ($export === 'csv') {
    $st2 = $pdo->prepare("SELECT * FROM listings WHERE $where_sql ORDER BY ($sort = 0) ASC, $sort $dir, id ASC");
    $st2->execute($params);
    $all = $st2->fetchAll();
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="tg4g_en_' . $cat . '_' . date('Ymd_His') . '.csv"');
    echo "\xEF\xBB\xBF";
    $out = fopen('php://output', 'w');
    $hdr_cols = ['id','category','sub_category','provider','hq_country','plan_name','network','cpu_cores','cpu_model','ram_gb','disk_gb','disk_type','bandwidth_tb','port_mbps','location_country','location_city','price_display','price_monthly_usd','price_yearly_usd','payment_methods','refund_days','virt_type','os_supported','rating_avg','review_count','cn_friendly','data_source','badge','notes','affiliate_url','official_url','updated_at'];
    fputcsv($out, $hdr_cols);
    foreach ($all as $r) {
        $line = [];
        foreach ($hdr_cols as $col) $line[] = $r[$col] ?? '';
        fputcsv($out, $line);
    }
    fclose($out);
    exit;
}

// ============ Metadata for facets ============
function dcol($pdo, $col, $cat) {
    $st = $pdo->prepare("SELECT DISTINCT $col AS v FROM listings WHERE is_active=1 AND category=:c AND $col IS NOT NULL AND $col<>'' ORDER BY $col");
    $st->execute([':c' => $cat]);
    return array_column($st->fetchAll(), 'v');
}
$all_nets = dcol($pdo, 'network', $cat);
$all_loc_countries = dcol($pdo, 'location_country', $cat);
$all_hq_countries = dcol($pdo, 'hq_country', $cat);
$all_disktypes = dcol($pdo, 'disk_type', $cat);
$all_subs = dcol($pdo, 'sub_category', $cat);

$cat_counts_st = $pdo->query("SELECT category, COUNT(*) AS n FROM listings WHERE is_active=1 GROUP BY category");
$cat_counts = [];
foreach ($cat_counts_st->fetchAll() as $r) $cat_counts[$r['category']] = (int)$r['n'];

$last_st = $pdo->query("SELECT MAX(updated_at) AS latest FROM listings WHERE is_active=1");
$dataset_updated = $last_st->fetch()['latest'] ?? '';

$sub_counts = [];
$sc_st = $pdo->prepare("SELECT sub_category AS s, COUNT(*) AS n FROM listings WHERE is_active=1 AND category=:c GROUP BY sub_category");
$sc_st->execute([':c' => $cat]);
foreach ($sc_st->fetchAll() as $r) $sub_counts[$r['s']] = (int)$r['n'];

// ============ Helpers ============
function h($s) { return htmlspecialchars((string)($s ?? ''), ENT_QUOTES|ENT_HTML5, 'UTF-8'); }
function build_url($overrides = []) {
    $qs = array_merge($_GET, $overrides);
    foreach ($overrides as $k => $v) if ($v === '' || $v === null || $v === []) unset($qs[$k]);
    return '/en/listings?' . http_build_query($qs);
}
function sl($field, $label, $cs, $cd) {
    $nd = ($cs === $field && $cd === 'asc') ? 'desc' : 'asc';
    $arr = ($cs === $field) ? ($cd === 'asc' ? ' ▲' : ' ▼') : '';
    return '<a class="sl" href="' . h(build_url(['sort' => $field, 'dir' => $nd, 'page' => 1])) . '">' . h($label) . $arr . '</a>';
}
function fmt_price($r) {
    if ($r['price_monthly_usd'] > 0) return '$' . number_format((float)$r['price_monthly_usd'], 2);
    if ($r['price_display']) return h($r['price_display']);
    return '-';
}
function cn_stars($n) {
    $n = (int)$n;
    if ($n <= 0) return '-';
    return str_repeat('★', $n) . str_repeat('☆', max(0, 3 - $n));
}
$net_class = function($n) {
    if (str_contains($n ?: '', 'CN2 GIA')) return 'n-cn2gia';
    if (str_contains($n ?: '', 'CN2')) return 'n-cn2gt';
    if (str_contains($n ?: '', 'BGP')) return 'n-bgp';
    if (str_contains($n ?: '', 'Anycast')) return 'n-anycast';
    return 'n-other';
};

// Build hreflang pairs for current URL (en here, zh-CN sibling)
$qs_no_path = $_GET;
$zh_url = 'https://tg4g.com/listings?' . http_build_query($qs_no_path);
$en_url = 'https://tg4g.com/en/listings?' . http_build_query($qs_no_path);
?><!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title><?= h($profile['label']) ?> Directory - <?= number_format($total) ?> filterable entries | TG4G</title>
<meta name="description" content="<?= h($profile['desc']) ?>. <?= number_format($total) ?>+ vendors, real pricing, live updates.">
<link rel="canonical" href="<?= h($en_url) ?>">
<link rel="alternate" hreflang="en"    href="<?= h($en_url) ?>">
<link rel="alternate" hreflang="zh-CN" href="<?= h($zh_url) ?>">
<link rel="alternate" hreflang="x-default" href="<?= h($en_url) ?>">
<style>
*{box-sizing:border-box}
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Inter,sans-serif;margin:0;background:#f5f7fa;color:#1e293b;font-size:12px}
header{background:linear-gradient(135deg,#0f172a,#1e3a8a);color:#f1f5f9;padding:0}
.topnav{max-width:1600px;margin:0 auto;padding:0 16px;display:flex;align-items:stretch;flex-wrap:wrap}
.brand{display:flex;align-items:center;padding:11px 18px 11px 0;font-size:17px;font-weight:700;color:#fff;text-decoration:none;border-right:1px solid rgba(255,255,255,.1);margin-right:8px;white-space:nowrap}
.brand .b-sub{font-size:10px;font-weight:400;color:#94a3b8;margin-left:8px}
.nav-item{display:flex;align-items:center;padding:0 13px;color:#cbd5e1;text-decoration:none;font-size:12px;font-weight:500;border-bottom:3px solid transparent;transition:all .15s;line-height:1}
.nav-item:hover{color:#fff;background:rgba(255,255,255,.05)}
.nav-item.on{color:#fff;background:rgba(255,255,255,.08);border-bottom-color:#60a5fa}
.nav-icon{font-size:14px;margin-right:5px}
.nav-count{font-size:10px;background:rgba(255,255,255,.12);padding:1px 6px;border-radius:8px;margin-left:5px}
.nav-item.on .nav-count{background:#60a5fa;color:#0f172a;font-weight:700}
.upd-info{margin-left:auto;display:flex;align-items:center;padding:0 8px;color:#94a3b8;font-size:10px}
.lang-switch{padding:0 10px;display:flex;align-items:center;border-left:1px solid rgba(255,255,255,.1)}
.lang-switch a{color:#cbd5e1;text-decoration:none;font-size:11px;padding:2px 6px;border-radius:3px}
.lang-switch a.on{background:#60a5fa;color:#0f172a;font-weight:700}
.cat-hero{background:#fff;padding:12px 16px;border-bottom:1px solid #e2e8f0}
.cat-hero h2{margin:0;font-size:17px;color:#0f172a;display:inline-block}
.cat-hero h2 .cnt{color:#2563eb;margin-left:6px}
.cat-hero .desc{display:inline-block;margin-left:14px;font-size:12px;color:#64748b}
.container{max-width:1600px;margin:0 auto;padding:8px}
.sub-tabs{background:#fff;border-radius:5px;margin-bottom:6px;padding:5px 10px;box-shadow:0 1px 2px rgba(0,0,0,.06);display:flex;flex-wrap:wrap;gap:3px;align-items:center;font-size:11px}
.sub-tab{padding:3px 10px;background:#fff;color:#64748b;border:1px solid #cbd5e1;border-radius:10px;text-decoration:none;font-size:11px}
.sub-tab:hover{background:#f1f5f9}
.sub-tab.on{background:#475569;color:#fff;border-color:#334155}
.filters{background:#fff;padding:7px 10px;border-radius:5px;margin-bottom:6px;box-shadow:0 1px 2px rgba(0,0,0,.06)}
.fr{display:flex;flex-wrap:wrap;gap:4px;align-items:center;margin-bottom:5px;padding-bottom:5px;border-bottom:1px dashed #e2e8f0}
.fr:last-child{border-bottom:0;margin-bottom:0;padding-bottom:0}
.fl{font-size:10px;color:#64748b;font-weight:600;min-width:60px}
.chip{display:inline-block;padding:2px 7px;background:#f1f5f9;color:#475569;border-radius:10px;text-decoration:none;font-size:10px;border:1px solid transparent;cursor:pointer}
.chip:hover{background:#e0e7ff}
.chip.on{background:#2563eb;color:#fff;border-color:#1d4ed8}
.filters input,.filters select{padding:2px 5px;border:1px solid #cbd5e1;border-radius:3px;font-size:11px;height:23px}
.filters input[type=number]{width:60px}
.q-input{width:180px!important}
.btn{padding:3px 10px;background:#16a34a;color:#fff;border:0;border-radius:3px;cursor:pointer;font-size:11px;font-weight:600;text-decoration:none;display:inline-block}
.btn-clear{background:#fee2e2;color:#991b1b;padding:3px 8px}
.btn-export{background:#0891b2;color:#fff;padding:3px 8px}
.meta{padding:3px 0;color:#475569;font-size:11px;margin-bottom:3px;display:flex;justify-content:space-between;align-items:center}
.meta strong{color:#0f172a}
.tw{background:#fff;border-radius:5px;overflow:auto;box-shadow:0 1px 2px rgba(0,0,0,.06)}
table{width:100%;border-collapse:collapse;min-width:900px}
thead th{background:#1e293b;color:#f1f5f9;padding:5px 6px;text-align:left;font-size:10px;font-weight:600;white-space:nowrap;position:sticky;top:0;z-index:1}
thead th a.sl{color:#f1f5f9;text-decoration:none}
thead th a.sl:hover{color:#93c5fd}
tbody td{padding:4px 6px;border-bottom:1px solid #e2e8f0;vertical-align:top;font-size:11px}
tbody tr:hover{background:#f8fafc}
.prov{font-weight:600;color:#0f172a;font-size:12px}
.pln{color:#64748b;font-size:10px}
.network{display:inline-block;padding:1px 5px;border-radius:2px;font-size:9px;font-weight:600;white-space:nowrap}
.n-cn2gia{background:#fef3c7;color:#92400e}
.n-cn2gt{background:#dbeafe;color:#1e40af}
.n-bgp{background:#e0e7ff;color:#3730a3}
.n-anycast{background:#f3e8ff;color:#6b21a8}
.n-other{background:#f1f5f9;color:#475569}
.spec{color:#1e293b;font-weight:500}
.sub-text{color:#94a3b8;font-size:9px}
.price{font-weight:700;color:#16a34a;font-size:12px;white-space:nowrap}
.price small{color:#94a3b8;font-weight:400;font-size:9px;display:block}
.rating{color:#f59e0b;font-weight:600}
.cn-stars{color:#f59e0b;font-size:11px;letter-spacing:-1px;font-weight:bold}
.source{display:inline-block;padding:0 4px;border-radius:2px;font-size:9px;font-weight:600}
.src-manual{background:#dcfce7;color:#166534}
.src-hybrid_scan{background:#dbeafe;color:#1e40af}
.src-google_ai_mode{background:#fef3c7;color:#92400e}
.src-public{background:#f1f5f9;color:#475569}
.updt{font-size:10px;color:#64748b;white-space:nowrap}
.cta{display:inline-block;padding:3px 9px;background:#2563eb;color:#fff;text-decoration:none;border-radius:3px;font-weight:600;font-size:10px;white-space:nowrap}
.cta:hover{background:#1d4ed8}
.bdg{display:inline-block;padding:0 4px;border-radius:2px;font-size:9px;margin-left:2px;background:#fee2e2;color:#991b1b;font-weight:600}
.pay-icons{font-size:9px;color:#64748b}
.pagi{display:flex;gap:3px;align-items:center;justify-content:center;padding:14px 0}
.pagi a,.pagi span{padding:4px 9px;border-radius:3px;text-decoration:none;font-size:11px;background:#fff;color:#475569;border:1px solid #cbd5e1}
.pagi a:hover{background:#e0e7ff}
.pagi .current{background:#2563eb;color:#fff;border-color:#1d4ed8}
.pagi .disabled{opacity:.4;pointer-events:none}
@media (max-width:700px){.topnav{padding:0 8px}.brand{padding:8px 8px 8px 0;font-size:15px}.nav-item{padding:8px;font-size:11px}.nav-count{display:none}.upd-info{display:none}.container{padding:4px}.fl{min-width:auto}table{font-size:10px}thead th,tbody td{padding:3px 4px}}
</style>
</head>
<body>

<header>
  <div class="topnav">
    <a class="brand" href="/en/listings">🚀 TG4G <span class="b-sub"><?= h(t('海外资源清单')) ?></span></a>
    <?php foreach ($PROFILES as $pck => $pcv):
      $active = $cat === $pck;
      $cnt = $cat_counts[$pck] ?? 0;
      ?>
      <a class="nav-item <?= $active ? 'on' : '' ?>" href="/en/listings?cat=<?= h($pck) ?>">
        <span class="nav-icon"><?= $pcv['icon'] ?></span><?= h($pcv['label']) ?>
        <span class="nav-count"><?= $cnt ?></span>
      </a>
    <?php endforeach; ?>
    <div class="lang-switch">
      <a class="on" href="<?= h($en_url) ?>" rel="alternate" hreflang="en">EN</a>
      <a href="<?= h($zh_url) ?>" rel="alternate" hreflang="zh-CN">中</a>
    </div>
    <div class="upd-info"><?= h(t('数据集最新')) ?>: <?= h(rel_time_en($dataset_updated)) ?></div>
  </div>
</header>

<div class="cat-hero">
  <div class="container" style="padding:0">
    <h2><?= $profile['icon'] ?> <?= h($profile['label']) ?><span class="cnt">(<?= number_format($total) ?>)</span></h2>
    <span class="desc"><?= h($profile['desc']) ?></span>
  </div>
</div>

<div class="container">

<?php if ($all_subs): ?>
<?php
  $real_subs = array_values(array_filter($all_subs));
  $sub_sorted = $sub_counts;
  arsort($sub_sorted);
?>
<div class="sub-tabs">
  <span class="fl"><?= h(t('细分')) ?>:</span>
  <a class="sub-tab <?= $sub === '' ? 'on' : '' ?>" href="<?= h(build_url(['sub' => '', 'page' => 1])) ?>"><?= h(t('全部')) ?> <span style="opacity:.7"><?= number_format($total) ?></span></a>
  <?php if (count($real_subs) <= 30): ?>
    <?php foreach ($real_subs as $s): ?>
      <a class="sub-tab <?= $sub === $s ? 'on' : '' ?>" href="<?= h(build_url(['sub' => $s, 'page' => 1])) ?>"><?= h(tsub($s)) ?> <span style="opacity:.7"><?= $sub_counts[$s] ?? 0 ?></span></a>
    <?php endforeach; ?>
  <?php else: ?>
    <input type="search" list="sub_list_<?= h($cat) ?>" value="<?= h($sub) ?>"
           placeholder="🔍 <?= h(sprintf(t('搜索 %d 个细分(支持模糊匹配)...'), count($real_subs))) ?>"
           style="padding:5px 10px;border:1px solid #cbd5e1;border-radius:4px;font-size:12px;width:280px;margin-left:6px;vertical-align:middle"
           onchange="const u=new URL(location);if(this.value)u.searchParams.set('sub',this.value);else u.searchParams.delete('sub');u.searchParams.set('page','1');location.href=u" />
    <datalist id="sub_list_<?= h($cat) ?>">
      <?php foreach ($sub_sorted as $s => $n): if(!$s) continue; ?>
        <option value="<?= h($s) ?>"><?= $n ?></option>
      <?php endforeach; ?>
    </datalist>
    <?php if ($sub): ?>
      <a href="<?= h(build_url(['sub' => '', 'page' => 1])) ?>" style="margin-left:6px;color:#dc2626;font-size:11px;text-decoration:none">✕ Clear [<?= h(tsub($sub)) ?>]</a>
    <?php endif; ?>
    <?php if (!empty($profile['quick_subs'])): ?>
    <div style="margin-top:6px;line-height:1.8">
      <span class="fl" style="color:#94a3b8;font-size:11px">📌 <?= h(t('常用细分')) ?>:</span>
      <?php foreach ($profile['quick_subs'] as $qs): ?>
        <a class="sub-tab <?= strcasecmp($sub, $qs) === 0 ? 'on' : '' ?>"
           href="<?= h(build_url(['sub' => $qs, 'page' => 1])) ?>"><?= h($qs) ?></a>
      <?php endforeach; ?>
    </div>
    <?php endif; ?>
  <?php endif; ?>
</div>
<?php endif; ?>

<form class="filters" method="get" action="/en/listings" id="ff">
  <input type="hidden" name="cat" value="<?= h($cat) ?>">
  <?php if ($sub): ?><input type="hidden" name="sub" value="<?= h($sub) ?>"><?php endif; ?>
  <input type="hidden" name="sort" value="<?= h($sort) ?>">
  <input type="hidden" name="dir" value="<?= h($dir) ?>">
  <input type="hidden" name="per" value="<?= h((string)$per) ?>">

  <?php if (in_array('search', $profile['filters'], true)): ?>
  <div class="fr">
    <input class="q-input" type="search" name="q" value="<?= h($q) ?>" placeholder="🔍 Search <?= h($profile['label']) ?>..." />
    <button type="submit" class="btn"><?= h(t('应用')) ?></button>
    <a class="btn btn-clear" href="/en/listings?cat=<?= h($cat) ?>"><?= h(t('清空')) ?></a>
    <span style="flex:1"></span>
    <a class="btn btn-export" href="<?= h(build_url(['export' => 'csv'])) ?>">⬇ <?= h(t('导出 CSV')) ?></a>
  </div>
  <?php endif; ?>

  <?php if (in_array('network', $profile['filters'], true) && $all_nets): ?>
  <div class="fr">
    <span class="fl"><?= h(t('网络')) ?></span>
    <?php foreach ($all_nets as $n): if(!$n) continue; ?>
      <label class="chip <?= in_array($n, $nets, true) ? 'on' : '' ?>">
        <input type="checkbox" name="net[]" value="<?= h($n) ?>" <?= in_array($n, $nets, true) ? 'checked' : '' ?> style="display:none" onchange="document.getElementById('ff').submit()">
        <?= h($n) ?>
      </label>
    <?php endforeach; ?>
  </div>
  <?php endif; ?>

  <?php if (in_array('location', $profile['filters'], true) && $all_loc_countries): ?>
  <div class="fr">
    <span class="fl"><?= h(t('机房')) ?></span>
    <?php foreach ($all_loc_countries as $n): if(!$n) continue; ?>
      <label class="chip <?= in_array($n, $countries, true) ? 'on' : '' ?>">
        <input type="checkbox" name="country[]" value="<?= h($n) ?>" <?= in_array($n, $countries, true) ? 'checked' : '' ?> style="display:none" onchange="document.getElementById('ff').submit()">
        <?= h($n) ?>
      </label>
    <?php endforeach; ?>
  </div>
  <?php endif; ?>

  <?php if (in_array('hq', $profile['filters'], true) && $all_hq_countries): ?>
  <div class="fr">
    <span class="fl"><?= h(t('总部')) ?></span>
    <?php foreach ($all_hq_countries as $n): if(!$n) continue; ?>
      <label class="chip <?= in_array($n, $hqs, true) ? 'on' : '' ?>">
        <input type="checkbox" name="hq[]" value="<?= h($n) ?>" <?= in_array($n, $hqs, true) ? 'checked' : '' ?> style="display:none" onchange="document.getElementById('ff').submit()">
        <?= h($n) ?>
      </label>
    <?php endforeach; ?>
  </div>
  <?php endif; ?>

  <?php if (in_array('config', $profile['filters'], true)): ?>
  <div class="fr">
    <span class="fl"><?= h(t('配置')) ?></span>
    <label>CPU≥
      <select name="cpu" onchange="document.getElementById('ff').submit()">
        <option value="0"><?= h(t('不限')) ?></option>
        <?php foreach ([1,2,4,8,16] as $v): ?><option value="<?= $v ?>" <?= $cpu_min===$v?'selected':'' ?>><?= $v ?>+</option><?php endforeach; ?>
      </select>
    </label>
    <label>RAM≥
      <select name="ram" onchange="document.getElementById('ff').submit()">
        <option value="0"><?= h(t('不限')) ?></option>
        <?php foreach ([1,2,4,8,16,32,64] as $v): ?><option value="<?= $v ?>" <?= abs($ram_min-$v)<0.01?'selected':'' ?>><?= $v ?>G+</option><?php endforeach; ?>
      </select>
    </label>
    <label>Disk≥
      <select name="disk" onchange="document.getElementById('ff').submit()">
        <option value="0"><?= h(t('不限')) ?></option>
        <?php foreach ([20,50,100,500,1000] as $v): ?><option value="<?= $v ?>" <?= $disk_min===$v?'selected':'' ?>><?= $v>=1000?($v/1000).'T':$v.'G' ?>+</option><?php endforeach; ?>
      </select>
    </label>
    <label>BW≥
      <select name="bw" onchange="document.getElementById('ff').submit()">
        <option value="0"><?= h(t('不限')) ?></option>
        <?php foreach ([1,5,10,20] as $v): ?><option value="<?= $v ?>" <?= abs($bw_min-$v)<0.01?'selected':'' ?>><?= $v ?>TB+</option><?php endforeach; ?>
      </select>
    </label>
    <?php if ($all_disktypes): ?>
    <label><?= h(t('硬盘类型')) ?>
      <select name="disk_type" onchange="document.getElementById('ff').submit()">
        <option value=""><?= h(t('不限')) ?></option>
        <?php foreach ($all_disktypes as $dt): if(!$dt) continue; ?>
          <option value="<?= h($dt) ?>" <?= $disktype===$dt?'selected':'' ?>><?= h($dt) ?></option>
        <?php endforeach; ?>
      </select>
    </label>
    <?php endif; ?>
  </div>
  <?php endif; ?>

  <div class="fr">
    <?php if (in_array('price', $profile['filters'], true)): ?>
    <span class="fl"><?= h(t('月付 $')) ?></span>
    <input type="number" name="p_min" value="<?= $price_min>0?$price_min:'' ?>" min="0" step="0.5" placeholder="min" />
    <span>-</span>
    <input type="number" name="p_max" value="<?= $price_max>0?$price_max:'' ?>" min="0" step="0.5" placeholder="max" />
    <button type="submit" class="btn" style="padding:2px 7px"><?= h(t('应用')) ?></button>
    <?php endif; ?>

    <?php if (in_array('rating', $profile['filters'], true)): ?>
    <span class="fl" style="margin-left:10px"><?= h(t('评分≥')) ?></span>
    <select name="rating" onchange="document.getElementById('ff').submit()">
      <option value="0"><?= h(t('不限')) ?></option>
      <?php foreach ([6,7,8,9] as $v): ?><option value="<?= $v ?>" <?= abs($rating_min-$v)<0.01?'selected':'' ?>><?= $v ?>+</option><?php endforeach; ?>
    </select>
    <?php endif; ?>

    <?php if (in_array('cn', $profile['filters'], true)): ?>
    <span class="fl" style="margin-left:10px"><?= h(t('CN 友好≥')) ?></span>
    <select name="cn" onchange="document.getElementById('ff').submit()">
      <option value="0"><?= h(t('不限')) ?></option>
      <option value="1" <?= $cn_min===1?'selected':'' ?>>★+</option>
      <option value="2" <?= $cn_min===2?'selected':'' ?>>★★+</option>
      <option value="3" <?= $cn_min===3?'selected':'' ?>>★★★</option>
    </select>
    <?php endif; ?>

    <?php if (in_array('refund', $profile['filters'], true)): ?>
    <span class="fl" style="margin-left:10px"><?= h(t('退款≥')) ?></span>
    <select name="refund" onchange="document.getElementById('ff').submit()">
      <option value="0"><?= h(t('不限')) ?></option>
      <?php foreach ([3,7,14,30] as $v): ?><option value="<?= $v ?>" <?= $refund_min===$v?'selected':'' ?>><?= $v ?>d+</option><?php endforeach; ?>
    </select>
    <?php endif; ?>

    <?php if (in_array('pay', $profile['filters'], true)): ?>
    <span class="fl" style="margin-left:10px">Pay</span>
    <?php foreach (['alipay'=>'Alipay','usdt'=>'USDT','paypal'=>'PayPal','cc'=>'Card','wire'=>'Wire','btc'=>'BTC'] as $pk => $pl): ?>
      <label class="chip <?= in_array($pk, $pays, true) ? 'on' : '' ?>">
        <input type="checkbox" name="pay[]" value="<?= h($pk) ?>" <?= in_array($pk, $pays, true) ? 'checked' : '' ?> style="display:none" onchange="document.getElementById('ff').submit()">
        <?= h($pl) ?>
      </label>
    <?php endforeach; ?>
    <?php endif; ?>
  </div>
</form>

<div class="meta">
  <div><?= h(t('共')) ?> <strong><?= number_format($total) ?></strong> <?= h($profile['label']) ?> · <?= h(t('第')) ?> <strong><?= $page ?></strong>/<strong><?= $pages ?></strong> · <?= h(t('每页')) ?>
    <select onchange="location.href='<?= h(build_url(['per' => ''])) ?>&per='+this.value">
      <?php foreach ([25,50,100,200] as $pp): ?><option value="<?= $pp ?>" <?= $per===$pp?'selected':'' ?>><?= $pp ?></option><?php endforeach; ?>
    </select>
  </div>
  <div style="font-size:10px;color:#94a3b8"><?= h(t('按')) ?> <strong><?= h(t('sort_label.' . $sort)) ?></strong> <?= $dir==='asc'?h(t('升')):h(t('降')) ?> <?= h(t('序 · 点击表头切换')) ?></div>
</div>

<div class="tw">
<table id="listTable">
<thead>
<tr>
<?php
$col_headers = [
    'fav'      => '<th data-col="fav" style="width:24px"></th>',
    'provider' => '<th data-col="provider">' . h(t('商家/套餐')) . '</th>',
    'sub'      => '<th data-col="sub">' . h(t('类型')) . '</th>',
    'hq'       => '<th data-col="hq">' . h(t('总部')) . '</th>',
    'network'  => '<th data-col="network">' . h(t('网络')) . '</th>',
    'cpu'      => '<th data-col="cpu">' . sl('cpu_cores','CPU',$sort,$dir) . '</th>',
    'ram'      => '<th data-col="ram">' . sl('ram_gb','RAM',$sort,$dir) . '</th>',
    'disk'     => '<th data-col="disk">' . sl('disk_gb','Disk',$sort,$dir) . '</th>',
    'bw'       => '<th data-col="bw">' . sl('bandwidth_tb','BW',$sort,$dir) . '</th>',
    'location' => '<th data-col="location">' . sl('location_country','DC',$sort,$dir) . '</th>',
    'price'    => '<th data-col="price">' . sl('price_monthly_usd','Monthly',$sort,$dir) . '</th>',
    'rating'   => '<th data-col="rating">' . sl('rating_avg','Rating',$sort,$dir) . '</th>',
    'cn'       => '<th data-col="cn">' . sl('cn_friendly','CN',$sort,$dir) . '</th>',
    'refund'   => '<th data-col="refund">' . sl('refund_days','Refund',$sort,$dir) . '</th>',
    'pay'      => '<th data-col="pay">Pay</th>',
    'virt'     => '<th data-col="virt">Virt</th>',
    'os'       => '<th data-col="os">OS</th>',
    'source'   => '<th data-col="source">Src</th>',
    'updated'  => '<th data-col="updated">' . sl('updated_at','Updated',$sort,$dir) . '</th>',
    'cta'      => '<th data-col="cta">Buy</th>',
];
foreach ($profile['cols'] as $c) echo $col_headers[$c] ?? '';
?>
</tr>
</thead>
<tbody>
<?php foreach ($rows as $r):
    $cta_url = $r['affiliate_url'] ?: $r['official_url'] ?: '#';
    $is_external = $cta_url !== '#';
?>
<tr data-id="<?= $r['id'] ?>">
<?php foreach ($profile['cols'] as $c):
    switch ($c):
      case 'fav': ?>
        <td data-col="fav"></td>
      <?php break; case 'provider': ?>
        <td data-col="provider">
          <div class="prov"><a href="/en/listing/<?= (int)$r['id'] ?>" style="color:#0f172a;text-decoration:none;border-bottom:1px dotted #94a3b8" title="View <?= h($r['provider']) ?> details"><?= h($r['provider']) ?></a><?php if($r['badge']):?><span class="bdg"><?= h($r['badge']) ?></span><?php endif;?></div>
          <div class="pln"><?= h($r['plan_name']) ?><?php if($r['hq_country'] && !in_array('hq',$profile['cols'],true)):?> · HQ <?= h($r['hq_country']) ?><?php endif;?></div>
        </td>
      <?php break; case 'sub': ?>
        <td data-col="sub"><?= h(tsub($r['sub_category'] ?: '-')) ?></td>
      <?php break; case 'hq': ?>
        <td data-col="hq"><?= h($r['hq_country'] ?: '-') ?></td>
      <?php break; case 'network': ?>
        <td data-col="network"><?php if($r['network']):?><span class="network <?= $net_class($r['network']) ?>"><?= h($r['network']) ?></span><?php else: echo '-'; endif;?></td>
      <?php break; case 'cpu': ?>
        <td data-col="cpu">
          <?php if($r['cpu_cores']>0):?>
            <span class="spec"><?= (int)$r['cpu_cores'] ?>C</span>
            <?php if($r['cpu_model']):?><div class="sub-text"><?= h(substr($r['cpu_model'],0,16)) ?></div><?php endif;?>
          <?php else: echo '-'; endif;?>
        </td>
      <?php break; case 'ram': ?>
        <td data-col="ram"><?php if($r['ram_gb']>0): echo '<span class="spec">'.((float)$r['ram_gb']>=1 ? (int)$r['ram_gb'].'G' : (int)($r['ram_gb']*1024).'M').'</span>'; else: echo '-'; endif;?></td>
      <?php break; case 'disk': ?>
        <td data-col="disk">
          <?php if($r['disk_gb']>0):?>
            <span class="spec"><?= (int)$r['disk_gb']>=1000 ? round($r['disk_gb']/1000,1).'T' : (int)$r['disk_gb'].'G' ?></span>
            <?php if($r['disk_type']):?><div class="sub-text"><?= h($r['disk_type']) ?></div><?php endif;?>
          <?php else: echo '-'; endif;?>
        </td>
      <?php break; case 'bw': ?>
        <td data-col="bw">
          <?php if($r['bandwidth_tb']>0 && $r['bandwidth_tb']<9000):?>
            <span class="spec"><?= (float)$r['bandwidth_tb']>=1 ? (int)$r['bandwidth_tb'].'T' : (int)($r['bandwidth_tb']*1000).'G' ?></span>
          <?php elseif($r['bandwidth_tb']>=9000): echo '<span class="spec">∞</span>'; else: echo '-'; endif;?>
          <?php if($r['port_mbps']>0):?><div class="sub-text"><?= $r['port_mbps']>=1000 ? round($r['port_mbps']/1000).'G' : $r['port_mbps'].'M' ?></div><?php endif;?>
        </td>
      <?php break; case 'location': ?>
        <td data-col="location">
          <?php if($r['location_country']):?>
            <span class="spec"><?= h($r['location_country']) ?></span>
            <?php if($r['location_city']):?><div class="sub-text"><?= h(substr($r['location_city'],0,22)) ?></div><?php endif;?>
          <?php else: echo '-'; endif;?>
        </td>
      <?php break; case 'price': ?>
        <td data-col="price">
          <span class="price"><?= fmt_price($r) ?>
            <?php if($r['price_yearly_usd']>0):?><small>$<?= number_format((float)$r['price_yearly_usd'],0) ?>/yr</small><?php endif;?>
          </span>
        </td>
      <?php break; case 'rating': ?>
        <td data-col="rating"><span class="rating"><?= $r['rating_avg']>0?number_format((float)$r['rating_avg'],1):'-' ?></span><?php if($r['review_count']>0):?><div class="sub-text"><?= (int)$r['review_count'] ?></div><?php endif;?></td>
      <?php break; case 'cn': ?>
        <td data-col="cn"><span class="cn-stars"><?= cn_stars($r['cn_friendly']) ?></span></td>
      <?php break; case 'refund': ?>
        <td data-col="refund"><?php
          if($r['refund_days']>0) echo (int)$r['refund_days'].'d';
          elseif(in_array($r['category'],['vps','dedicated'],true)) echo '<span style="color:#dc2626;font-size:10px">'.h(t('不退')).'</span>';
          else echo '-';
        ?></td>
      <?php break; case 'pay': ?>
        <td data-col="pay"><span class="pay-icons"><?= h($r['payment_methods'] ?: '-') ?></span></td>
      <?php break; case 'virt': ?>
        <td data-col="virt"><?= h($r['virt_type'] ?: '-') ?></td>
      <?php break; case 'os': ?>
        <td data-col="os"><?= h($r['os_supported'] ?: '-') ?></td>
      <?php break; case 'source': ?>
        <td data-col="source"><span class="source src-<?= h($r['data_source'] ?: 'manual') ?>"><?= h(src_label_en($r['data_source'] ?: 'manual')) ?></span></td>
      <?php break; case 'updated': ?>
        <td data-col="updated"><span class="updt"><?= h(rel_time_en($r['updated_at'])) ?></span></td>
      <?php break; case 'cta': ?>
        <td data-col="cta"><?php if($is_external):?><a class="cta" href="<?= h($cta_url) ?>" target="_blank" rel="nofollow noopener sponsored">Buy</a><?php else:?><span class="cta" style="background:#94a3b8;cursor:default">Contact</span><?php endif;?></td>
      <?php break;
    endswitch;
endforeach;
?>
</tr>
<?php endforeach; ?>
<?php if(!$rows):?>
<tr><td colspan="<?= count($profile['cols']) ?>" style="text-align:center;padding:40px;color:#94a3b8">No matching <?= h($profile['label']) ?> entries. <a href="/en/listings?cat=<?= h($cat) ?>">Clear filters and retry</a></td></tr>
<?php endif;?>
</tbody>
</table>
</div>

<?php if($pages>1):?>
<div class="pagi">
  <a href="<?= h(build_url(['page'=>1])) ?>" class="<?= $page<=1?'disabled':'' ?>"><?= h(t('« 首页')) ?></a>
  <a href="<?= h(build_url(['page'=>max(1,$page-1)])) ?>" class="<?= $page<=1?'disabled':'' ?>"><?= h(t('‹ 上一页')) ?></a>
  <?php $start=max(1,$page-3);$end=min($pages,$page+3);for($i=$start;$i<=$end;$i++):
    if($i===$page):?><span class="current"><?= $i ?></span>
    <?php else:?><a href="<?= h(build_url(['page'=>$i])) ?>"><?= $i ?></a><?php endif;
  endfor;?>
  <a href="<?= h(build_url(['page'=>$page+1])) ?>" class="<?= $page>=$pages?'disabled':'' ?>"><?= h(t('下一页 ›')) ?></a>
  <a href="<?= h(build_url(['page'=>$pages])) ?>" class="<?= $page>=$pages?'disabled':'' ?>"><?= h(t('尾页 »')) ?></a>
</div>
<?php endif;?>

<div style="text-align:center;padding:14px;color:#94a3b8;font-size:10px">
  <?= h(t('数据基于公开信息整理 · 价格以官网为准 · 部分链接为联盟 (rel="sponsored") · 反馈')) ?>: <a href="mailto:tg4g@duck.com" style="color:#2563eb">tg4g@duck.com</a> · <a href="<?= h($zh_url) ?>" rel="alternate" hreflang="zh-CN" style="color:#2563eb">中文版</a>
</div>

</div>
</body>
</html>
