| Current Path : /home/seto/888mirror.pm/ |
| Current File : /home/seto/888mirror.pm/landing.php |
<?php
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/helpers.php';
$slug = preg_replace('/[^a-z0-9-]/', '', strtolower(trim($_GET['slug'] ?? '')));
$is_preview = !empty($_GET['preview']);
if (!$slug) { header('Location: /'); exit(); }
$stmt = db()->prepare("SELECT * FROM landings WHERE slug = ?");
$stmt->execute([$slug]);
$landing = $stmt->fetch();
if (!$landing) { header('Location: /'); exit(); }
if (!$is_preview && $landing['status'] !== 'active') { header('Location: /'); exit(); }
// Определения шаблонов
$templates = [
'dark-premium' => [
'label' => 'Dark Premium',
'--body-bg' => '#0f1117',
'--card-bg' => '#1a1d2e',
'--card-border' => 'rgba(255,255,255,.07)',
'--text' => '#e0e6f0',
'--muted' => '#6b7a99',
'--accent' => '#f0c040',
'--green' => '#34d399',
'--cta' => 'linear-gradient(135deg,#ff6b00,#ff8c00)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#1d3a2a,#1a4030)',
'--bonus-border' => 'rgba(52,211,153,.2)',
'--header-bg' => 'rgba(15,17,23,.97)',
'--header-border'=> 'rgba(255,255,255,.07)',
'--dropdown-bg' => '#1e2235',
'--star-off' => '#2e3350',
'--pos-muted' => '#3d4560',
'--pos-top' => '#f0c040',
'--sep' => 'rgba(255,255,255,.08)',
'--footer-border'=> 'rgba(255,255,255,.06)',
'--footer-text' => '#4a5568',
'--input-border' => 'rgba(255,255,255,.12)',
],
'light-minimal' => [
'label' => 'Light Minimal',
'--body-bg' => '#f1f5f9',
'--card-bg' => '#ffffff',
'--card-border' => 'rgba(0,0,0,.08)',
'--text' => '#1e293b',
'--muted' => '#64748b',
'--accent' => '#2563eb',
'--green' => '#059669',
'--cta' => 'linear-gradient(135deg,#2563eb,#1d4ed8)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#ecfdf5,#d1fae5)',
'--bonus-border' => 'rgba(5,150,105,.25)',
'--header-bg' => 'rgba(255,255,255,.97)',
'--header-border'=> 'rgba(0,0,0,.08)',
'--dropdown-bg' => '#ffffff',
'--star-off' => '#e2e8f0',
'--pos-muted' => '#cbd5e1',
'--pos-top' => '#f59e0b',
'--sep' => 'rgba(0,0,0,.08)',
'--footer-border'=> 'rgba(0,0,0,.06)',
'--footer-text' => '#94a3b8',
'--input-border' => 'rgba(0,0,0,.15)',
],
'neon' => [
'label' => 'Neon Contrast',
'--body-bg' => '#060612',
'--card-bg' => '#0d0d2b',
'--card-border' => 'rgba(124,58,237,.25)',
'--text' => '#e2e8ff',
'--muted' => '#7075a0',
'--accent' => '#a78bfa',
'--green' => '#22d3ee',
'--cta' => 'linear-gradient(135deg,#7c3aed,#4f46e5)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#0d1040,#0a0a2a)',
'--bonus-border' => 'rgba(34,211,238,.25)',
'--header-bg' => 'rgba(6,6,18,.97)',
'--header-border'=> 'rgba(124,58,237,.25)',
'--dropdown-bg' => '#0d0d2b',
'--star-off' => '#1a1a3a',
'--pos-muted' => '#2d2d5e',
'--pos-top' => '#a78bfa',
'--sep' => 'rgba(124,58,237,.2)',
'--footer-border'=> 'rgba(124,58,237,.1)',
'--footer-text' => '#4a5568',
'--input-border' => 'rgba(124,58,237,.3)',
],
'classic' => [
'label' => 'Classic Casino',
'--body-bg' => '#0d1f15',
'--card-bg' => '#112b1e',
'--card-border' => 'rgba(34,197,94,.15)',
'--text' => '#e0f2e9',
'--muted' => '#5a8a6a',
'--accent' => '#fbbf24',
'--green' => '#22c55e',
'--cta' => 'linear-gradient(135deg,#16a34a,#15803d)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#052e16,#14532d)',
'--bonus-border' => 'rgba(34,197,94,.3)',
'--header-bg' => 'rgba(13,31,21,.97)',
'--header-border'=> 'rgba(34,197,94,.15)',
'--dropdown-bg' => '#112b1e',
'--star-off' => '#0a2010',
'--pos-muted' => '#1a4a2e',
'--pos-top' => '#fbbf24',
'--sep' => 'rgba(34,197,94,.1)',
'--footer-border'=> 'rgba(34,197,94,.08)',
'--footer-text' => '#4a5568',
'--input-border' => 'rgba(34,197,94,.2)',
],
'table-dark' => [
'label' => 'Table Dark',
'--body-bg' => '#0f1117',
'--card-bg' => '#1a1d2e',
'--card-border' => 'rgba(255,255,255,.07)',
'--text' => '#e0e6f0',
'--muted' => '#6b7a99',
'--accent' => '#f0c040',
'--green' => '#34d399',
'--cta' => 'linear-gradient(135deg,#ff6b00,#ff8c00)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#1d3a2a,#1a4030)',
'--bonus-border' => 'rgba(52,211,153,.2)',
'--header-bg' => 'rgba(15,17,23,.97)',
'--header-border'=> 'rgba(255,255,255,.07)',
'--dropdown-bg' => '#1e2235',
'--star-off' => '#2e3350',
'--pos-muted' => '#3d4560',
'--pos-top' => '#f0c040',
'--sep' => 'rgba(255,255,255,.08)',
'--footer-border'=> 'rgba(255,255,255,.06)',
'--footer-text' => '#4a5568',
'--input-border' => 'rgba(255,255,255,.12)',
],
'table-light' => [
'label' => 'Table Light',
'--body-bg' => '#f1f5f9',
'--card-bg' => '#ffffff',
'--card-border' => 'rgba(0,0,0,.08)',
'--text' => '#1e293b',
'--muted' => '#64748b',
'--accent' => '#2563eb',
'--green' => '#059669',
'--cta' => 'linear-gradient(135deg,#2563eb,#1d4ed8)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#ecfdf5,#d1fae5)',
'--bonus-border' => 'rgba(5,150,105,.25)',
'--header-bg' => 'rgba(255,255,255,.97)',
'--header-border'=> 'rgba(0,0,0,.08)',
'--dropdown-bg' => '#ffffff',
'--star-off' => '#e2e8f0',
'--pos-muted' => '#cbd5e1',
'--pos-top' => '#f59e0b',
'--sep' => 'rgba(0,0,0,.08)',
'--footer-border'=> 'rgba(0,0,0,.06)',
'--footer-text' => '#94a3b8',
'--input-border' => 'rgba(0,0,0,.15)',
],
'row-dark' => [
'label' => 'Row Dark',
'--body-bg' => '#0f1117',
'--card-bg' => '#1a1d2e',
'--card-border' => 'rgba(255,255,255,.07)',
'--text' => '#e0e6f0',
'--muted' => '#6b7a99',
'--accent' => '#f0c040',
'--green' => '#34d399',
'--cta' => 'linear-gradient(135deg,#ff6b00,#ff8c00)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#1d3a2a,#1a4030)',
'--bonus-border' => 'rgba(52,211,153,.2)',
'--header-bg' => 'rgba(15,17,23,.97)',
'--header-border'=> 'rgba(255,255,255,.07)',
'--dropdown-bg' => '#1e2235',
'--star-off' => '#2e3350',
'--pos-muted' => '#3d4560',
'--pos-top' => '#f0c040',
'--sep' => 'rgba(255,255,255,.08)',
'--footer-border'=> 'rgba(255,255,255,.06)',
'--footer-text' => '#4a5568',
'--input-border' => 'rgba(255,255,255,.12)',
],
'row-light' => [
'label' => 'Row Light',
'--body-bg' => '#f1f5f9',
'--card-bg' => '#ffffff',
'--card-border' => 'rgba(0,0,0,.08)',
'--text' => '#1e293b',
'--muted' => '#64748b',
'--accent' => '#2563eb',
'--green' => '#059669',
'--cta' => 'linear-gradient(135deg,#2563eb,#1d4ed8)',
'--cta-text' => '#fff',
'--bonus-bg' => 'linear-gradient(135deg,#ecfdf5,#d1fae5)',
'--bonus-border' => 'rgba(5,150,105,.25)',
'--header-bg' => 'rgba(255,255,255,.97)',
'--header-border'=> 'rgba(0,0,0,.08)',
'--dropdown-bg' => '#ffffff',
'--star-off' => '#e2e8f0',
'--pos-muted' => '#cbd5e1',
'--pos-top' => '#f59e0b',
'--sep' => 'rgba(0,0,0,.08)',
'--footer-border'=> 'rgba(0,0,0,.06)',
'--footer-text' => '#94a3b8',
'--input-border' => 'rgba(0,0,0,.15)',
],
];
$tpl = $templates[$landing['template']] ?? $templates['dark-premium'];
$tpl_vars = '';
foreach ($tpl as $k => $v) {
if (str_starts_with($k, '--')) $tpl_vars .= "$k:$v;";
}
$layout_type = match(true) {
str_starts_with($landing['template'], 'table-') => 'table',
str_starts_with($landing['template'], 'row-') => 'row',
default => 'cards',
};
// GEO + язык через api.php (zTDS)
$z_country = $z_lang = $z_bot = '';
ob_start();
if (file_exists(__DIR__ . '/api.php')) include __DIR__ . '/api.php';
ob_end_clean();
$country = (!empty($z_country) && $z_country !== '-') ? strtolower($z_country) : '';
$lang = (!empty($z_lang) && $z_lang !== '-') ? strtolower(substr($z_lang, 0, 2)) : 'en';
$active_langs = db()->query("SELECT code FROM languages WHERE is_active=1")->fetchAll(PDO::FETCH_COLUMN);
if (!in_array($lang, $active_langs)) $lang = 'en';
if (!empty($_GET['lang'])) {
$gl = strtolower(substr(preg_replace('/[^a-zA-Z]/', '', $_GET['lang']), 0, 2));
if (in_array($gl, $active_langs)) $lang = $gl;
}
if (isset($_GET['country'])) {
$country = strtolower(substr(preg_replace('/[^a-zA-Z]/', '', $_GET['country']), 0, 10));
}
// Бренды — логика как в index.php: страна посетителя определяет порядок
$db = db();
$lim = (int)($landing['brand_limit'] ?? 0);
$geo_brands = $global_brands = [];
if ($country) {
$st = $db->prepare("SELECT DISTINCT b.* FROM brands b JOIN brand_countries bc ON bc.brand_id=b.id
WHERE b.status='active' AND bc.country_code=? ORDER BY b.is_featured DESC, b.weight DESC");
$st->execute([$country]);
$geo_brands = $st->fetchAll();
}
// Глобальный блок — только бренды с 'en' или 'crypto', не показанные выше
$geo_ids = array_column($geo_brands, 'id');
if ($geo_ids) {
$not_in = implode(',', array_map('intval', $geo_ids));
$global_brands = $db->query("SELECT DISTINCT b.* FROM brands b JOIN brand_countries bc ON bc.brand_id=b.id
WHERE b.status='active' AND bc.country_code IN ('en','crypto') AND b.id NOT IN ($not_in)
ORDER BY b.is_featured DESC, b.weight DESC")->fetchAll();
} else {
$global_brands = $db->query("SELECT DISTINCT b.* FROM brands b JOIN brand_countries bc ON bc.brand_id=b.id
WHERE b.status='active' AND bc.country_code IN ('en','crypto')
ORDER BY b.is_featured DESC, b.weight DESC")->fetchAll();
}
$brands = array_merge($geo_brands, $global_brands);
$geo_brand_ids = array_flip(array_column($geo_brands, 'id'));
if ($lim > 0) $brands = array_slice($brands, 0, $lim);
// Запись показов
$is_bot = is_bot_request() || ($z_bot !== '' && $z_bot !== '-');
$db->prepare("INSERT INTO access_log (type, ip, country, language, user_agent, path) VALUES (?,?,?,?,?,?)")
->execute([
$is_bot ? 'bot' : 'real',
$_SERVER['REMOTE_ADDR'] ?? '',
$country ?: '-',
$lang,
$_SERVER['HTTP_USER_AGENT'] ?? '',
'/' . ($landing['slug'] ?? ''),
]);
$visitor_ip = $_SERVER['REMOTE_ADDR'] ?? '';
if (!empty($brands) && !$is_bot && !is_excluded_ip($visitor_ip) && !is_duplicate_visit($visitor_ip)) {
$visit_id = bin2hex(random_bytes(8));
$ref = referrer_domain() ?: null;
$st_imp = $db->prepare("INSERT INTO stats (brand_id, country, language, event_type, landing_id, visit_id, referrer, ip) VALUES (?,?,?,'impression',?,?,?,?)");
foreach ($brands as $b) {
$st_imp->execute([$b['id'], $country ?: '-', $lang, (int)$landing['id'], $visit_id, $ref, $visitor_ip]);
}
}
// Переводы
$brand_ids = array_column($brands, 'id');
$translations = [];
if ($brand_ids) {
$in = implode(',', $brand_ids);
$rows = $db->prepare("SELECT * FROM brand_translations WHERE brand_id IN ($in) AND language_code=?");
$rows->execute([$lang]);
foreach ($rows->fetchAll() as $t) $translations[$t['brand_id']] = $t;
$missing = array_diff($brand_ids, array_keys($translations));
if ($missing && $lang !== 'en') {
$in2 = implode(',', $missing);
$rows2 = $db->query("SELECT * FROM brand_translations WHERE brand_id IN ($in2) AND language_code='en'");
foreach ($rows2->fetchAll() as $t) $translations[$t['brand_id']] = $t;
}
}
// Страны брендов
$brand_countries = [];
if ($brand_ids) {
$in_c = implode(',', $brand_ids);
foreach ($db->query("SELECT brand_id, country_code FROM brand_countries WHERE brand_id IN ($in_c)")->fetchAll() as $r) {
$brand_countries[$r['brand_id']][] = $r['country_code'];
}
}
$switcher_langs = db()->query("SELECT code, name FROM languages WHERE is_active=1 ORDER BY code")->fetchAll();
$lang_names = array_column($switcher_langs, 'name', 'code');
$current_lang_name = $lang_names[$lang] ?? strtoupper($lang);
$switcher_countries = db()->query("
SELECT DISTINCT bc.country_code FROM brand_countries bc
JOIN brands b ON b.id=bc.brand_id
WHERE b.status='active' AND bc.country_code!='en' AND length(bc.country_code)=2
")->fetchAll(PDO::FETCH_COLUMN);
usort($switcher_countries, fn($a, $b) => strcasecmp(country_name($a), country_name($b)));
$site_name = setting('site_name') ?: '888mirror.pm';
// Перевод контента лендинга: ищем по языку посетителя → EN → базовые поля
$tr_stmt = db()->prepare("SELECT * FROM landing_translations WHERE landing_id=? AND language_code=?");
$tr_stmt->execute([$landing['id'], $lang]);
$ltr = $tr_stmt->fetch();
if (!$ltr && $lang !== 'en') {
$tr_stmt->execute([$landing['id'], 'en']);
$ltr = $tr_stmt->fetch();
}
$page_title = (($ltr['meta_title'] ?? '') ?: ($ltr['h1'] ?? '') ?: $landing['meta_title'] ?: $landing['h1'] ?: $landing['name']) . ' — ' . $site_name;
$page_desc = ($ltr['meta_description'] ?? '') ?: ($landing['meta_description'] ?? '');
$h1_text = ($ltr['h1'] ?? '') ?: ($landing['h1'] ?: $landing['name']);
$subtitle = ($ltr['subtitle'] ?? '') ?: ($landing['subtitle'] ?? '');
$cta_text = ($ltr['cta_text'] ?? '') ?: ($landing['cta_text'] ?: 'Get Bonus →');
$footer_txt = ($ltr['footer_text'] ?? '') ?: ($landing['footer_text'] ?: '© ' . date('Y') . ' ' . $site_name . ' — 18+ | Gamble responsibly');
$body_text = ($ltr['body_text'] ?? '') ?: ($landing['body_text'] ?? '');
$is_light = $landing['template'] === 'light-minimal';
?>
<!DOCTYPE html>
<html lang="<?= h($lang) ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="/favicon.svg" type="image/svg+xml">
<title><?= h($page_title) ?></title>
<?php if ($page_desc): ?><meta name="description" content="<?= h($page_desc) ?>"><?php endif ?>
<meta property="og:title" content="<?= h($page_title) ?>">
<?php if ($page_desc): ?><meta property="og:description" content="<?= h($page_desc) ?>"><?php endif ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
<?php if ($is_preview): ?>
<div style="background:#f59e0b;color:#000;text-align:center;padding:6px 12px;font-size:12px;font-weight:700;position:fixed;top:0;left:0;right:0;z-index:9999">
PREVIEW — статус: <?= h($landing['status']) ?> — <a href="/<?= h($slug) ?>" style="color:#000">открыть боевую</a>
</div>
<?php endif ?>
<style>
:root { <?= $tpl_vars ?> }
*, *::before, *::after { box-sizing: border-box; }
body {
font-family: 'Inter', sans-serif;
background: var(--body-bg);
color: var(--text);
min-height: 100vh;
}
.site-header {
padding: 16px 0 12px;
border-bottom: 1px solid var(--header-border);
background: var(--header-bg);
backdrop-filter: blur(8px);
position: sticky; top: 0; z-index: 100;
margin-bottom: 28px;
}
.site-logo { font-size: 1.2rem; font-weight: 800; color: var(--accent); text-decoration: none; }
.site-logo span { color: var(--text); }
.sw-btn {
background: rgba(128,128,128,.08);
border: 1px solid var(--input-border);
color: var(--muted);
font-size: 12px; font-weight: 500;
padding: 5px 12px; border-radius: 20px;
white-space: nowrap; cursor: pointer;
transition: border-color .2s, background .2s;
}
.sw-btn:hover { border-color: var(--accent); color: var(--accent); }
.sw-btn::after { content: ' ▾'; font-size: 10px; opacity: .6; }
.dropdown-menu {
background: var(--dropdown-bg);
border: 1px solid var(--input-border);
border-radius: 10px;
box-shadow: 0 8px 32px rgba(0,0,0,.4);
padding: 6px; max-height: 300px; overflow-y: auto;
}
.dropdown-item { color: var(--muted); border-radius: 6px; font-size: 13px; padding: 6px 10px; }
.dropdown-item:hover, .dropdown-item:focus { background: rgba(128,128,128,.1); color: var(--accent); }
.dropdown-item.active { background: rgba(128,128,128,.15); color: var(--accent); }
.dropdown-divider { border-color: var(--sep); margin: 4px 0; }
.page-heading { font-size: 1.5rem; font-weight: 800; color: var(--text); margin: 0 0 4px; }
.page-sub { font-size: 13px; color: var(--muted); }
/* Cards */
.brand-card {
background: var(--card-bg);
border: 1px solid var(--card-border);
border-radius: 14px; margin-bottom: 14px;
position: relative; overflow: hidden;
transition: transform .22s, box-shadow .22s, border-color .22s;
}
.brand-card:hover {
transform: translateY(-5px);
box-shadow: 0 18px 52px rgba(0,0,0,.5);
border-color: var(--accent);
}
.brand-card::after {
content: ''; position: absolute; top: 0; bottom: 0; width: 45%;
background: linear-gradient(90deg,transparent,rgba(255,255,255,.03),transparent);
animation: shimmer 3.5s ease-in-out infinite;
pointer-events: none;
}
@keyframes shimmer { 0%{left:-50%} 100%{left:130%} }
.card-inner { padding: 18px 18px 16px; position: relative; z-index: 1; }
.brand-identity { width: 145px; flex-shrink: 0; }
.pos-num { font-size: 11px; font-weight: 700; color: var(--pos-muted); line-height: 1; margin-bottom: 7px; }
.pos-num.top3 { color: var(--pos-top); }
.logo-pill { background: #ffffff; border-radius: 10px; padding: 8px 12px; display: flex; align-items: center; justify-content: center; width: 120px; height: 80px; }
.brand-logo { max-width: 104px; max-height: 64px; width: auto; height: auto; object-fit: contain; }
.logo-placeholder { width: 120px; height: 80px; background: rgba(128,128,128,.1); border-radius: 10px; display: flex; align-items: center; justify-content: center; font-size: 11px; color: var(--muted); text-align: center; padding: 6px; }
.brand-name-row { display: flex; align-items: center; gap: 6px; margin-top: 8px; flex-wrap: wrap; }
.brand-name { font-size: 13px; font-weight: 700; color: var(--text); }
.brand-year { font-size: 10px; color: var(--muted); margin-top: 2px; }
.star-rating { color: var(--accent); font-size: 12px; white-space: nowrap; margin-top: 4px; }
.star-off { color: var(--star-off); }
.bonus-block { background: var(--bonus-bg); border: 1px solid var(--bonus-border); border-radius: 10px; padding: 10px 14px; }
.bonus-label { font-size: 9px; font-weight: 600; text-transform: uppercase; color: var(--green); letter-spacing: 1px; }
.bonus-amount { font-size: 1.15rem; font-weight: 800; color: var(--accent); line-height: 1.2; }
.bonus-spins { font-size: 12px; color: var(--green); margin-top: 2px; }
.games-count { font-size: 12px; color: var(--muted); margin-top: 6px; }
.adv-list { list-style: none; padding: 0; margin: 0; }
.adv-list li { font-size: 12px; color: var(--muted); padding: 2px 0 2px 14px; position: relative; }
.adv-list li::before { content: '✓'; position: absolute; left: 0; color: var(--green); font-weight: 700; }
.meta-item { font-size: 11px; color: var(--muted); margin-top: 4px; }
.get-bonus-btn {
display: inline-block;
background: var(--cta); color: var(--cta-text);
font-weight: 700; font-size: 14px;
padding: 11px 22px; border-radius: 10px;
text-decoration: none; white-space: nowrap;
transition: transform .15s, box-shadow .15s;
border: none; cursor: pointer;
}
.get-bonus-btn:hover { transform: scale(1.04); color: var(--cta-text); }
.badge-overlay { position: absolute; top: 10px; right: 10px; z-index: 5; font-size: 10px; padding: 3px 8px; border-radius: 20px; font-weight: 600; text-transform: uppercase; }
.badge-best { background: var(--accent); color: #1a1a00; }
.badge-new { background: #4f46e5; color: #fff; }
.badge-free { background: #059669; color: #fff; }
/* Flags */
.flags-strip { display: flex; align-items: center; flex-wrap: nowrap; gap: 3px; padding: 8px 18px 10px; border-top: 1px solid var(--sep); position: relative; z-index: 1; }
.flags-strip img { border-radius: 2px; opacity: .75; transition: opacity .15s; flex-shrink: 0; }
.flags-strip img:hover { opacity: 1; }
.flags-more { font-size: 10px; color: var(--muted); white-space: nowrap; margin-left: 2px; cursor: pointer; padding: 2px 5px; border-radius: 4px; border: 1px solid var(--input-border); background: rgba(128,128,128,.04); transition: background .15s; user-select: none; }
.flags-more:hover { color: var(--accent); border-color: var(--accent); }
.flags-popup { display: none; position: absolute; bottom: calc(100% + 6px); left: 18px; background: var(--dropdown-bg); border: 1px solid var(--input-border); border-radius: 10px; padding: 10px 12px; box-shadow: 0 8px 32px rgba(0,0,0,.5); z-index: 100; max-width: 320px; flex-wrap: wrap; gap: 4px; }
.flags-popup.open { display: flex; }
/* Global sep */
.global-sep { display: flex; align-items: center; gap: 14px; margin: 28px 0 20px; font-size: 13px; font-weight: 600; color: var(--muted); letter-spacing: .2px; }
.global-sep hr { flex: 1; border: none; height: 1px; background: linear-gradient(90deg, transparent, var(--sep), transparent); margin: 0; opacity: 1; }
.global-sep .sep-label { background: rgba(128,128,128,.06); border: 1px solid var(--input-border); border-radius: 20px; padding: 5px 16px; white-space: nowrap; }
/* Body text block */
.body-text-block { color: var(--muted); font-size: 13px; line-height: 1.7; margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--sep); }
.site-footer { border-top: 1px solid var(--footer-border); margin-top: 40px; padding: 20px 0; font-size: 12px; color: var(--footer-text); text-align: center; }
.mobile-pos { font-size: 10px; font-weight: 700; color: var(--pos-muted); flex-shrink: 0; line-height: 1; }
.mobile-pos.top3 { color: var(--pos-top); }
@media (max-width: 767px) {
.brand-card { border-radius: 10px; margin-bottom: 10px; }
.card-inner { padding: 10px 12px; }
.desktop-card { display: none !important; }
.mobile-row { display: flex; align-items: center; gap: 10px; }
.flags-strip { display: none; }
.logo-pill { width: 80px; height: 54px; padding: 5px 8px; border-radius: 8px; flex-shrink: 0; }
.brand-logo { max-width: 68px; max-height: 44px; }
.logo-placeholder { width: 74px; height: 50px; border-radius: 8px; flex-shrink: 0; }
.mobile-name { font-size: 13px; font-weight: 700; color: var(--text); flex: 1; min-width: 0; overflow: hidden; }
.mobile-bonus { font-size: 11px; color: var(--accent); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; margin-top: 2px; }
.get-bonus-btn { font-size: 12px; padding: 9px 12px; border-radius: 8px; white-space: nowrap; flex-shrink: 0; }
.badge-overlay { font-size: 9px; padding: 2px 6px; top: 8px; right: 8px; }
.global-sep { margin: 16px 0 12px; font-size: 12px; }
.global-sep .sep-label { padding: 4px 12px; }
.page-heading { font-size: 1.25rem; }
}
@media (min-width: 768px) {
.mobile-row { display: none; }
.desktop-card { display: flex; align-items: center; gap: 16px; }
}
/* === TABLE LAYOUT === */
.brands-table-wrap { background: var(--card-bg); border: 1px solid var(--card-border); border-radius: 14px; overflow: hidden; }
.brands-table { width: 100%; border-collapse: collapse; }
.brands-table thead th {
border-bottom: 2px solid var(--sep);
color: var(--muted); font-size: 11px; font-weight: 600;
text-transform: uppercase; letter-spacing: .6px;
padding: 12px 16px; background: rgba(128,128,128,.04);
}
.brands-table tbody tr { border-bottom: 1px solid var(--sep); transition: background .15s; }
.brands-table tbody tr:last-child { border-bottom: none; }
.brands-table tbody tr:hover { background: rgba(128,128,128,.05); }
.brands-table td { padding: 14px 16px; vertical-align: middle; }
.tbl-rank { font-size: 17px; font-weight: 800; color: var(--pos-muted); width: 44px; text-align: center; }
.tbl-rank.top3 { color: var(--pos-top); }
.tbl-brand-col { display: flex; align-items: center; gap: 12px; min-width: 150px; }
.tbl-logo-pill { background: #ffffff; border-radius: 8px; padding: 5px 8px; display: flex; align-items: center; justify-content: center; width: 80px; height: 52px; flex-shrink: 0; }
.tbl-logo-pill img { max-width: 68px; max-height: 42px; width: auto; height: auto; object-fit: contain; }
.tbl-brand-col .logo-ph { width: 80px; height: 52px; background: rgba(128,128,128,.1); border-radius: 8px; display:flex; align-items:center; justify-content:center; font-size:9px; color:var(--muted); flex-shrink:0; }
.tbl-name { font-size: 14px; font-weight: 600; color: var(--text); }
.tbl-stars { font-size: 11px; color: var(--accent); white-space: nowrap; }
.tbl-bonus-val { font-size: 15px; font-weight: 700; color: var(--accent); }
.tbl-spins { font-size: 12px; color: var(--green); margin-top: 2px; }
.tbl-cta { text-align: right; white-space: nowrap; }
@media (max-width: 767px) {
.tbl-hide-m { display: none; }
.brands-table td { padding: 10px 8px; }
.tbl-rank { width: 28px; font-size: 13px; }
.tbl-logo-pill { width: 52px; height: 36px; padding: 3px 5px; border-radius: 6px; }
.tbl-logo-pill img { max-width: 44px; max-height: 28px; }
.tbl-brand-col .logo-ph { width: 52px; height: 36px; }
.tbl-bonus-val { font-size: 13px; }
.get-bonus-btn { font-size: 11px; padding: 7px 10px; }
}
/* === ROW LAYOUT === */
.row-card {
background: var(--card-bg); border: 1px solid var(--card-border);
border-radius: 14px; display: flex; align-items: stretch;
margin-bottom: 12px; overflow: hidden;
transition: transform .2s, box-shadow .2s, border-color .2s;
position: relative;
}
.row-card:hover { transform: translateY(-2px); box-shadow: 0 10px 36px rgba(0,0,0,.3); border-color: var(--accent); }
.row-rank { width: 40px; flex-shrink: 0; display:flex; align-items:center; justify-content:center; font-size: 15px; font-weight: 800; color: var(--pos-muted); border-right: 1px solid var(--sep); }
.row-rank.top3 { color: var(--pos-top); }
.row-logo-col { width: 140px; flex-shrink: 0; display:flex; flex-direction:column; align-items:center; justify-content:center; gap: 8px; padding: 16px 10px; border-right: 1px solid var(--sep); }
.row-logo-pill { background: #ffffff; border-radius: 10px; padding: 8px 10px; display: flex; align-items: center; justify-content: center; width: 110px; height: 74px; }
.row-logo-pill img { max-width: 94px; max-height: 58px; width: auto; height: auto; object-fit: contain; }
.row-logo-col .logo-ph { width: 110px; height: 74px; background: rgba(128,128,128,.1); border-radius: 10px; display:flex; align-items:center; justify-content:center; font-size:9px; color:var(--muted); }
.row-logo-col .row-stars { font-size: 12px; color: var(--accent); white-space: nowrap; }
.row-info { flex: 1; padding: 16px 20px; min-width: 0; display:flex; flex-direction:column; justify-content:center; }
.row-info h3 { font-size: 15px; font-weight: 700; color: var(--text); margin: 0 0 6px; }
.row-adv { list-style: none; padding: 0; margin: 0; }
.row-adv li { font-size: 12px; color: var(--muted); padding: 1px 0 1px 14px; position: relative; }
.row-adv li::before { content: '✓'; position: absolute; left: 0; color: var(--green); font-weight: 700; }
.row-bonus-col { width: 170px; flex-shrink: 0; padding: 16px 14px; border-left: 1px solid var(--sep); display:flex; flex-direction:column; justify-content:center; }
.row-bonus-amt { font-size: 16px; font-weight: 800; color: var(--accent); }
.row-bonus-spins { font-size: 12px; color: var(--green); margin-top: 2px; }
.row-bonus-label { font-size: 9px; font-weight: 600; text-transform: uppercase; color: var(--muted); letter-spacing: .8px; margin-bottom: 4px; }
.row-cta-col { width: 140px; flex-shrink: 0; padding: 16px 14px; border-left: 1px solid var(--sep); display:flex; align-items:center; justify-content:center; }
.row-badge { position: absolute; top: 8px; right: 8px; font-size: 10px; padding: 2px 7px; border-radius: 20px; font-weight: 600; text-transform: uppercase; z-index: 2; }
@media (max-width: 767px) {
.row-card { flex-wrap: wrap; }
.row-rank { width: 100%; height: 28px; border-right: none; border-bottom: 1px solid var(--sep); font-size: 12px; justify-content: flex-start; padding: 0 12px; }
.row-logo-col { width: 90px; border-right: none; padding: 12px 8px; }
.row-info { width: calc(100% - 90px); padding: 12px 12px 12px; border-bottom: 1px solid var(--sep); }
.row-bonus-col { width: 50%; border-left: none; border-top: 1px solid var(--sep); padding: 10px 14px; }
.row-cta-col { width: 50%; border-top: 1px solid var(--sep); padding: 10px 14px; }
}
</style>
</head>
<body<?= $is_preview ? ' style="padding-top:32px"' : '' ?>>
<header class="site-header">
<div class="container" style="max-width:920px">
<div class="d-flex align-items-center justify-content-between gap-2 flex-wrap">
<a class="site-logo" href="?lang=<?= h($lang) ?><?= $country ? '&country='.h($country) : '' ?>"><?= h($site_name) ?></a>
<div class="d-flex align-items-center gap-2 flex-wrap">
<div class="dropdown">
<button class="sw-btn" data-bs-toggle="dropdown" style="max-width:130px;overflow:hidden;text-overflow:ellipsis">
Lang: <?= h($current_lang_name) ?>
</button>
<ul class="dropdown-menu dropdown-menu-end" style="min-width:160px">
<?php foreach ($switcher_langs as $sl): ?>
<li><a class="dropdown-item <?= $sl['code']===$lang?'active':'' ?>"
href="?lang=<?= h($sl['code']) ?><?= $country?'&country='.h($country):'' ?>">
<?= h($sl['name']) ?></a></li>
<?php endforeach ?>
</ul>
</div>
<div class="dropdown">
<button class="sw-btn d-flex align-items-center gap-1" data-bs-toggle="dropdown">
<?php if ($country === 'crypto'): ?>💎 Crypto
<?php elseif ($country === 'en'): ?>🌐 Global
<?php elseif ($country): ?>
📍
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($country) ?>.svg" width="16" height="12" style="border-radius:2px">
<?= h(strtoupper($country)) ?>
<?php else: ?>📍 All regions<?php endif ?>
</button>
<ul class="dropdown-menu dropdown-menu-end" style="min-width:170px">
<li><a class="dropdown-item <?= !$country?'active':'' ?>" href="?lang=<?= h($lang) ?>">🌍 All regions</a></li>
<li><hr class="dropdown-divider"></li>
<?php foreach ($switcher_countries as $cc): ?>
<li><a class="dropdown-item d-flex align-items-center gap-2 <?= $cc===$country?'active':'' ?>"
href="?country=<?= h($cc) ?>&lang=<?= h($lang) ?>">
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($cc) ?>.svg" width="18" height="14" style="border-radius:2px;flex-shrink:0" alt="<?= h(country_name($cc)) ?>">
<span><?= h(country_name($cc)) ?></span>
</a></li>
<?php endforeach ?>
<li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item <?= $country==='en'?'active':'' ?>" href="?country=en&lang=<?= h($lang) ?>">🌐 Global</a></li>
<li><a class="dropdown-item <?= $country==='crypto'?'active':'' ?>" href="?country=crypto&lang=<?= h($lang) ?>">💎 Crypto</a></li>
</ul>
</div>
</div>
</div>
</div>
</header>
<div class="container" style="max-width:920px">
<div class="mb-4">
<h1 class="page-heading"><?= h($h1_text) ?>
<?php if ($country === 'crypto'): ?><span style="font-size:1.2rem">💎</span>
<?php elseif ($country === 'en'): ?><span style="font-size:1.2rem">🌐</span>
<?php elseif ($country): ?>
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($country) ?>.svg" width="26" height="20" style="border-radius:3px;vertical-align:middle" data-cc-flag="<?= h($country) ?>" alt="<?= h(strtoupper($country)) ?>">
<?php else: ?><span style="font-size:1.2rem">🌍</span>
<?php endif ?>
</h1>
<?php if ($subtitle): ?><p class="page-sub"><?= h($subtitle) ?></p><?php endif ?>
</div>
<?php if ($layout_type === 'table'): ?>
<!-- TABLE LAYOUT -->
<div class="brands-table-wrap">
<div class="table-responsive">
<table class="brands-table">
<thead><tr>
<th style="width:44px">#</th>
<th>Casino</th>
<th>Welcome Bonus</th>
<th class="tbl-hide-m">Rating</th>
<th class="text-end"></th>
</tr></thead>
<tbody>
<?php
$card_index = 0;
$showed_sep = false;
foreach ($brands as $brand):
$t = $translations[$brand['id']] ?? [];
$stars = max(1, min(5, (int)ceil($brand['weight'] / 20)));
$is_global = !empty($geo_brands) && !isset($geo_brand_ids[$brand['id']]);
$card_index++;
if ($is_global && !$showed_sep): $showed_sep = true; ?>
<tr><td colspan="5" style="padding:10px 16px;border-bottom:1px solid var(--sep)">
<div class="global-sep" style="margin:0"><hr><span class="sep-label">🌍 Also available globally</span><hr></div>
</td></tr>
<?php endif; ?>
<tr>
<td><div class="tbl-rank <?= $card_index<=3?'top3':'' ?>">#<?= $card_index ?></div></td>
<td>
<div class="tbl-brand-col">
<?php if ($brand['logo']): ?>
<div class="tbl-logo-pill">
<img src="<?= h($brand['logo']) ?>" alt="<?= h($brand['name']) ?>">
</div>
<?php else: ?>
<div class="logo-ph"><?= h(substr($brand['name'],0,3)) ?></div>
<?php endif ?>
<div>
<div class="tbl-name"><?= h($brand['name']) ?></div>
<div class="tbl-stars"><?php for($i=1;$i<=5;$i++): ?><span <?= $i>$stars?'style="color:var(--star-off)"':'' ?>>★</span><?php endfor ?></div>
</div>
</div>
</td>
<td>
<?php if (!empty($t['bonus'])): ?>
<div class="tbl-bonus-val"><?= h($t['bonus']) ?></div>
<?php if (!empty($t['free_spins'])): ?><div class="tbl-spins">+<?= h($t['free_spins']) ?></div><?php endif ?>
<?php else: ?><span style="color:var(--muted)">—</span><?php endif ?>
</td>
<td class="tbl-hide-m">
<div style="font-size:13px;color:var(--accent)"><?php for($i=1;$i<=5;$i++): ?><span <?= $i>$stars?'style="color:var(--star-off)"':'' ?>>★</span><?php endfor ?></div>
<?php if (!empty($t['games_count'])): ?><div style="font-size:11px;color:var(--muted);margin-top:2px">🎮 <?= h($t['games_count']) ?></div><?php endif ?>
</td>
<td class="tbl-cta">
<a href="/click.php?id=<?= (int)$brand['id'] ?>&l=<?= (int)$landing['id'] ?>"
class="get-bonus-btn" target="_blank" rel="noopener noreferrer"><?= h($cta_text) ?></a>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
</div>
</div>
<?php elseif ($layout_type === 'row'): ?>
<!-- ROW LAYOUT -->
<?php
$showed_sep = false;
$card_index = 0;
foreach ($brands as $brand):
$t = $translations[$brand['id']] ?? [];
$adv = !empty($t['advantages']) ? json_decode_safe($t['advantages']) : [];
$is_global = !empty($geo_brands) && !isset($geo_brand_ids[$brand['id']]);
$stars = max(1, min(5, (int)ceil($brand['weight'] / 20)));
$card_index++;
if ($is_global && !$showed_sep): $showed_sep = true; ?>
<div class="global-sep"><hr><span class="sep-label">🌍 Also available globally</span><hr></div>
<?php endif; ?>
<div class="row-card">
<?php if ($brand['badge']): $bc = match($brand['badge']){'best'=>'badge-best badge-overlay','new'=>'badge-new badge-overlay','free'=>'badge-free badge-overlay',default=>''}; ?>
<span class="row-badge <?= $bc ?>"><?= $brand['badge']==='best'?'⭐ Best':($brand['badge']==='new'?'New':'Free') ?></span>
<?php endif ?>
<div class="row-rank <?= $card_index<=3?'top3':'' ?>">#<?= $card_index ?></div>
<div class="row-logo-col">
<?php if ($brand['logo']): ?>
<div class="row-logo-pill">
<img src="<?= h($brand['logo']) ?>" alt="<?= h($brand['name']) ?>">
</div>
<?php else: ?>
<div class="logo-ph"><?= h(substr($brand['name'],0,3)) ?></div>
<?php endif ?>
<div class="row-stars"><?php for($i=1;$i<=5;$i++): ?><span <?= $i>$stars?'style="color:var(--star-off)"':'' ?>>★</span><?php endfor ?></div>
</div>
<div class="row-info">
<h3><?= h($brand['name']) ?></h3>
<?php if ($adv): ?>
<ul class="row-adv"><?php foreach(array_slice($adv,0,3) as $a): ?><li><?= h($a) ?></li><?php endforeach ?></ul>
<?php endif ?>
<?php if (!empty($t['license'])): ?><div style="font-size:11px;color:var(--muted);margin-top:4px">🔒 <?= h($t['license']) ?></div><?php endif ?>
</div>
<div class="row-bonus-col">
<div class="row-bonus-label">Welcome Bonus</div>
<?php if (!empty($t['bonus'])): ?>
<div class="row-bonus-amt"><?= h($t['bonus']) ?></div>
<?php if (!empty($t['free_spins'])): ?><div class="row-bonus-spins">+<?= h($t['free_spins']) ?></div><?php endif ?>
<?php else: ?><span style="color:var(--muted)">—</span><?php endif ?>
</div>
<div class="row-cta-col">
<a href="/click.php?id=<?= (int)$brand['id'] ?>&l=<?= (int)$landing['id'] ?>"
class="get-bonus-btn" target="_blank" rel="noopener noreferrer"><?= h($cta_text) ?></a>
</div>
</div>
<?php endforeach ?>
<?php else: ?>
<!-- CARDS LAYOUT (original) -->
<?php
$showed_sep = false;
$card_index = 0;
foreach ($brands as $brand):
$t = $translations[$brand['id']] ?? [];
$adv = !empty($t['advantages']) ? json_decode_safe($t['advantages']) : [];
$is_global = !empty($geo_brands) && !isset($geo_brand_ids[$brand['id']]);
$card_index++;
$stars = max(1, min(5, (int)ceil($brand['weight'] / 20)));
$bcodes = $brand_countries[$brand['id']] ?? [];
if ($is_global && !$showed_sep): $showed_sep = true; ?>
<div class="global-sep"><hr><span class="sep-label">🌍 Also available globally</span><hr></div>
<?php endif; ?>
<div class="brand-card" data-idx="<?= $card_index - 1 ?>">
<?php if ($brand['badge']): $bc = match($brand['badge']){'best'=>'badge-best','new'=>'badge-new','free'=>'badge-free',default=>''}; ?>
<span class="badge-overlay <?= $bc ?>"><?= $brand['badge'] === 'best' ? '⭐ Best' : ($brand['badge'] === 'new' ? 'New' : 'Free') ?></span>
<?php endif ?>
<div class="card-inner">
<div class="desktop-card">
<div class="brand-identity">
<div class="pos-num <?= $card_index <= 3 ? 'top3' : '' ?>">#<?= $card_index ?></div>
<?php if ($brand['logo']): ?>
<div class="logo-pill">
<img src="<?= h($brand['logo']) ?>" class="brand-logo" alt="<?= h($brand['name']) ?>">
</div>
<?php else: ?>
<div class="logo-placeholder"><?= h($brand['name']) ?></div>
<?php endif ?>
<div class="brand-name-row">
<span class="brand-name"><?= h($brand['name']) ?></span>
</div>
<div class="star-rating"><?php for ($i=1;$i<=5;$i++): ?><span class="<?= $i<=$stars?'':'star-off' ?>">★</span><?php endfor ?></div>
<?php if ($brand['year_founded']): ?><div class="brand-year">Est. <?= (int)$brand['year_founded'] ?></div><?php endif ?>
</div>
<div style="width:200px;flex-shrink:0">
<?php if (!empty($t['bonus'])): ?>
<div class="bonus-block">
<div class="bonus-label">Welcome Bonus</div>
<div class="bonus-amount"><?= h($t['bonus']) ?></div>
<?php if (!empty($t['free_spins'])): ?><div class="bonus-spins">+ <?= h($t['free_spins']) ?></div><?php endif ?>
</div>
<?php endif ?>
<?php if (!empty($t['games_count'])): ?><div class="games-count">🎮 <?= h($t['games_count']) ?> games</div><?php endif ?>
</div>
<div style="flex:1;min-width:0">
<?php if ($adv): ?>
<ul class="adv-list"><?php foreach (array_slice($adv,0,4) as $a): ?><li><?= h($a) ?></li><?php endforeach ?></ul>
<?php endif ?>
<?php if (!empty($t['license'])): ?><div class="meta-item">🔒 <?= h($t['license']) ?></div><?php endif ?>
<?php if (!empty($t['min_withdraw']) || !empty($t['max_withdraw'])): ?>
<div class="meta-item">💳 <?= h($t['min_withdraw']??'') ?><?= !empty($t['max_withdraw'])?' — '.h($t['max_withdraw']):'' ?></div>
<?php endif ?>
</div>
<div style="flex-shrink:0;text-align:center">
<a href="/click.php?id=<?= (int)$brand['id'] ?>&l=<?= (int)$landing['id'] ?>"
class="get-bonus-btn" target="_blank" rel="noopener noreferrer">
<?= h($cta_text) ?>
</a>
<?php if (!empty($t['currencies'])):
$cur_all = array_map('trim', explode(',', $t['currencies']));
$cur_show = array_slice($cur_all, 0, 5);
$cur_rest = count($cur_all) - count($cur_show);
?><div class="meta-item mt-2"><?= h(implode(', ', $cur_show)) ?><?= $cur_rest > 0 ? ' <span style="opacity:.6">+' . $cur_rest . '</span>' : '' ?></div><?php endif ?>
</div>
</div>
<div class="mobile-row">
<span class="mobile-pos <?= $card_index <= 3 ? 'top3' : '' ?>">#<?= $card_index ?></span>
<?php if ($brand['logo']): ?>
<div class="logo-pill">
<img src="<?= h($brand['logo']) ?>" class="brand-logo" alt="<?= h($brand['name']) ?>">
</div>
<?php else: ?>
<div class="logo-placeholder"><?= h(substr($brand['name'],0,3)) ?></div>
<?php endif ?>
<div class="mobile-name">
<div><?= h($brand['name']) ?></div>
<?php if (!empty($t['bonus'])): ?><div class="mobile-bonus"><?= h($t['bonus']) ?></div><?php endif ?>
</div>
<a href="/click.php?id=<?= (int)$brand['id'] ?>&l=<?= (int)$landing['id'] ?>"
class="get-bonus-btn" target="_blank" rel="noopener noreferrer">
Bonus →
</a>
</div>
</div>
<?php
$real_flags = array_filter($bcodes, fn($c) => strlen($c)===2 && $c!=='en');
$has_crypto = in_array('crypto', $bcodes);
$has_global = in_array('en', $bcodes);
if ($country && strlen($country)===2 && in_array($country, $real_flags)) {
$real_flags = array_merge([$country], array_filter($real_flags, fn($c)=>$c!==$country));
}
$all_f = array_values($real_flags);
$extra_d = max(0, count($all_f) - 20);
$extra_m = max(0, count($all_f) - 8);
if ($all_f || $has_crypto || $has_global):
$uid = 'fp_'.(int)$brand['id'];
?>
<div class="flags-strip">
<?php if ($has_crypto): ?><span title="Crypto" style="font-size:13px">💎</span><?php endif ?>
<?php if ($has_global): ?><span title="Global" style="font-size:13px">🌐</span><?php endif ?>
<?php $popup_f = []; foreach ($all_f as $fi => $cc):
if ($fi >= 20) { $popup_f[] = $cc; continue; }
$cls = $fi >= 8 ? 'd-none d-md-inline' : '';
$is_sel = ($cc === $country);
?>
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($cc) ?>.svg" width="16" height="12"
data-cc-flag="<?= h($cc) ?>" alt="<?= h(strtoupper($cc)) ?>"
<?= $cls ? 'class="'.$cls.'"' : '' ?>
<?= $is_sel ? 'style="opacity:1;box-shadow:0 0 0 1px var(--accent);border-radius:2px"' : '' ?>>
<?php endforeach ?>
<?php if ($extra_d > 0): ?><span class="flags-more d-none d-md-inline" onclick="toggleFP('<?= $uid ?>')">+<?= $extra_d ?> more</span><?php endif ?>
<?php if ($extra_m > 0): ?><span class="flags-more d-md-none" onclick="toggleFP('<?= $uid ?>')">+<?= $extra_m ?> more</span><?php endif ?>
<?php if ($popup_f): ?>
<div class="flags-popup" id="<?= $uid ?>">
<?php foreach ($popup_f as $cc): ?>
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($cc) ?>.svg" width="16" height="12" data-cc-flag="<?= h($cc) ?>" alt="<?= h(strtoupper($cc)) ?>" style="border-radius:2px;opacity:.8">
<?php endforeach ?>
</div>
<?php endif ?>
</div>
<?php endif ?>
</div>
<?php endforeach ?>
<?php endif ?>
<?php if (empty($brands)): ?><div class="text-center py-5" style="color:var(--muted)">No offers available.</div><?php endif ?>
<?php if ($body_text): ?>
<div class="body-text-block">
<?php foreach (explode("\n", $body_text) as $line): ?>
<?php if (trim($line)): ?><p><?= h(trim($line)) ?></p><?php endif ?>
<?php endforeach ?>
</div>
<?php endif ?>
</div>
<footer class="site-footer"><?= $footer_txt ?></footer>
<?= render_footer() ?>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
<script>
function toggleFP(id) {
var p = document.getElementById(id);
if (p) p.classList.toggle('open');
}
document.addEventListener('click', function(e) {
if (!e.target.classList.contains('flags-more')) {
document.querySelectorAll('.flags-popup.open').forEach(function(p){ p.classList.remove('open'); });
}
});
(function(){
var style = document.createElement('style'), rules = '';
document.querySelectorAll('.brand-card').forEach(function(c,i){
c.dataset.idx = i;
rules += '.brand-card[data-idx="'+i+'"]::after{animation-delay:'+(i*.4).toFixed(1)+'s}\n';
});
style.textContent = rules;
document.head.appendChild(style);
})();
var uiLang = navigator.language || 'en';
document.querySelectorAll('[data-cc-flag]').forEach(function(img){
try { var n=new Intl.DisplayNames([uiLang],{type:'region'}), v=n.of(img.getAttribute('data-cc-flag').toUpperCase()); if(v){img.alt=v;img.title=v;} } catch(e){}
});
</script>
</body>
</html>