| Current Path : /home/seto/888mirror.pm/ |
| Current File : /home/seto/888mirror.pm/widget-test.php |
<?php
require_once __DIR__ . '/includes/db.php';
require_once __DIR__ . '/includes/helpers.php';
$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';
$embed = !empty($_GET['embed']);
$force_theme = in_array($_GET['theme'] ?? '', ['dark', 'light']) ? $_GET['theme'] : '';
$force_layout = in_array($_GET['layout'] ?? '', ['table', 'cards', 'ranked']) ? $_GET['layout'] : '';
$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));
}
$db = db();
$geo_brands = [];
if ($country) {
$stmt = $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
");
$stmt->execute([$country]);
$geo_brands = $stmt->fetchAll();
}
$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);
$translations = [];
if ($brands) {
$ids = implode(',', array_map(fn($b) => (int)$b['id'], $brands));
$rows = $db->query("SELECT * FROM brand_translations WHERE brand_id IN ($ids) AND language_code IN ('$lang','en')")->fetchAll();
foreach ($rows as $row) {
$bid = $row['brand_id']; $lc = $row['language_code'];
if (!isset($translations[$bid]) || $lc === $lang) $translations[$bid] = $row;
}
}
$brand_country_counts = [];
$brand_country_codes = [];
if ($brands) {
$ids = implode(',', array_map(fn($b) => (int)$b['id'], $brands));
$rows = $db->query("
SELECT brand_id, COUNT(*) as cnt FROM brand_countries
WHERE brand_id IN ($ids) AND country_code NOT IN ('en','crypto')
GROUP BY brand_id
")->fetchAll();
foreach ($rows as $row) $brand_country_counts[$row['brand_id']] = (int)$row['cnt'];
$rows2 = $db->query("
SELECT brand_id, country_code FROM brand_countries
WHERE brand_id IN ($ids) AND country_code NOT IN ('en','crypto')
ORDER BY brand_id
")->fetchAll();
foreach ($rows2 as $row) $brand_country_codes[$row['brand_id']][] = $row['country_code'];
}
$cta_map = [
'ru'=>'Получить бонус','de'=>'Bonus holen','fr'=>'Obtenir le bonus','es'=>'Obtener bono',
'pt'=>'Obter bônus','pl'=>'Odbierz bonus','tr'=>'Bonus al','uk'=>'Отримати бонус',
'it'=>'Ottieni bonus','ro'=>'Obține bonus','cs'=>'Získat bonus','fi'=>'Hae bonus',
'sv'=>'Hämta bonus','nb'=>'Få bonus','da'=>'Få bonus',
];
$cta_text = $cta_map[$lang] ?? 'Get Bonus';
$avail_map = [
'ru'=>'Доступно в','de'=>'Verfügbar in','fr'=>'Disponible en','es'=>'Disponible en',
'pt'=>'Disponível em','pl'=>'Dostępne w','tr'=>'Şurada mevcut','uk'=>'Доступно в',
'it'=>'Disponibile in','ro'=>'Disponibil în','cs'=>'Dostupné v','fi'=>'Saatavilla',
'sv'=>'Tillgänglig i','nb'=>'Tilgjengelig i','da'=>'Tilgängelig i',
];
$avail_label = $avail_map[$lang] ?? 'Available in';
function weight_stars(int $w): string {
$n = min(5, max(1, (int)ceil($w / 20)));
return str_repeat('★', $n) . str_repeat('☆', 5 - $n);
}
function geo_flag(string $cc): string {
if (!$cc) return '';
return '<img src="https://flagicons.lipis.dev/flags/4x3/' . h($cc) . '.svg"'
. ' width="18" height="13" style="border-radius:2px;vertical-align:middle"'
. ' title="' . h(country_name($cc)) . '">';
}
function logo_bg_gradient(int $id, string $custom = ''): string {
if ($custom) return $custom;
static $palette = [
'rgba(59,130,246,.85)', 'rgba(139,92,246,.85)', 'rgba(236,72,153,.85)', 'rgba(239,68,68,.85)',
'rgba(249,115,22,.85)', 'rgba(234,179,8,.85)', 'rgba(34,197,94,.85)', 'rgba(6,182,212,.85)',
'rgba(99,102,241,.85)', 'rgba(168,85,247,.85)', 'rgba(20,184,166,.85)', 'rgba(244,63,94,.85)',
'rgba(16,185,129,.85)', 'rgba(132,204,22,.85)', 'rgba(14,165,233,.85)', 'rgba(217,70,239,.85)',
];
return $palette[$id % count($palette)];
}
$brand_data = [];
foreach ($brands as $idx => $b) {
$tr = $translations[$b['id']] ?? [];
$adv = json_decode_safe($tr['advantages'] ?? '[]');
$country_count = $brand_country_counts[$b['id']] ?? 0;
$more_countries = max(0, $country_count - ($country ? 1 : 0));
$brand_data[] = [
'b' => $b,
'bonus' => $tr['bonus'] ?? '',
'free_spins' => $tr['free_spins'] ?? '',
'games_count' => $tr['games_count'] ?? '',
'license' => $tr['license'] ?? '',
'currencies' => $tr['currencies'] ?? '',
'adv' => $adv,
'stars' => weight_stars((int)$b['weight']),
'star_count' => min(5, max(1, (int)ceil((int)$b['weight'] / 20))),
'click' => '/click.php?id=' . (int)$b['id'],
'year_founded' => $b['year_founded'] ? (int)$b['year_founded'] : null,
'more_countries' => $more_countries,
'country_codes' => $brand_country_codes[$b['id']] ?? [],
'idx' => $idx,
];
}
?>
<!DOCTYPE html>
<html lang="<?= h($lang) ?>">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Widget Test</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
body { font-family: 'Inter', -apple-system, sans-serif; }
/* ── CSS Variables ──────────────────────────────────────── */
.ww {
--bg: #0e0e1a;
--surface: #181828;
--surface2: #1f1f35;
--border: rgba(255,255,255,0.08);
--border2: rgba(255,255,255,0.05);
--text: #e8e8f0;
--text2: rgba(255,255,255,0.5);
--text3: rgba(255,255,255,0.28);
--gold: #ffd700;
--gold-dim: rgba(255,215,0,0.15);
--gold-border: rgba(255,215,0,0.3);
--gold-text: #ffe566;
--green: #4ade80;
--accent: #ff2d55;
--logo-bg: #ffffff;
--hover: rgba(255,45,85,0.1);
--shadow: 0 8px 32px rgba(0,0,0,0.4);
}
.ww.light {
--bg: #f0f2f8;
--surface: #ffffff;
--surface2: #f7f8fc;
--border: rgba(0,0,0,0.08);
--border2: rgba(0,0,0,0.05);
--text: #1a1a2e;
--text2: rgba(0,0,0,0.5);
--text3: rgba(0,0,0,0.28);
--gold: #d4900a;
--gold-dim: rgba(212,144,10,0.08);
--gold-border: rgba(212,144,10,0.25);
--gold-text: #8a5c00;
--green: #16a34a;
--accent: #ff2d55;
--logo-bg: #f0f2f8;
--hover: rgba(255,45,85,0.04);
--shadow: 0 4px 20px rgba(0,0,0,0.1);
}
/* ── Wrapper ───────────────────────────────────────────── */
.ww { background: var(--bg); color: var(--text); padding: 32px 20px; min-height: 100vh; transition: background .3s, color .3s; }
.ww.embed { min-height: 0; padding: 20px; }
.ww-inner { max-width: 1160px; margin: 0 auto; }
/* ── Dev bar ───────────────────────────────────────────── */
#dev-bar {
position: sticky; top: 0; z-index: 9999;
background: #0a0a0a; border-bottom: 1px solid #222;
padding: 8px 16px; display: flex; align-items: center; gap: 12px; flex-wrap: wrap;
}
#dev-bar .dg { display: flex; align-items: center; gap: 5px; }
#dev-bar .dl { color: #555; font-size: 10px; text-transform: uppercase; letter-spacing: .6px; font-family: 'Inter', sans-serif; }
.db {
padding: 4px 11px; border-radius: 5px; border: 1px solid #333;
background: transparent; color: #888; cursor: pointer; font-size: 11px;
font-family: 'Inter', sans-serif; transition: .15s; text-decoration: none; display: inline-block;
}
.db:hover { border-color: #666; color: #ccc; }
.db.on { background: #ff2d55; border-color: #ff2d55; color: #fff; }
.db-sep { width: 1px; height: 18px; background: #222; flex-shrink: 0; }
.di { margin-left: auto; color: #333; font-size: 10px; font-family: 'Inter', sans-serif; }
/* ── Shared: button ────────────────────────────────────── */
.btn-cta {
display: inline-flex; align-items: center; justify-content: center; gap: 6px;
padding: 11px 22px; border-radius: 8px;
background: linear-gradient(135deg, #ff2d55 0%, #c026d3 100%);
color: #fff !important; font-size: 13px; font-weight: 700; letter-spacing: .3px;
text-decoration: none !important; border: none; cursor: pointer;
box-shadow: 0 3px 12px rgba(255,45,85,.35);
transition: transform .15s, box-shadow .15s;
position: relative; overflow: hidden; white-space: nowrap;
}
.btn-cta:hover { transform: translateY(-2px); box-shadow: 0 6px 20px rgba(255,45,85,.45); }
.btn-cta::after {
content: ''; position: absolute; inset: 0;
background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,.15) 50%, transparent 100%);
transform: translateX(-100%); transition: transform .4s;
}
.btn-cta:hover::after { transform: translateX(100%); }
/* ── Shared: logo pill ──────────────────────────────────── */
.logo-pill {
background: var(--logo-bg); border-radius: 8px;
display: flex; align-items: center; justify-content: center;
overflow: hidden; flex-shrink: 0;
}
.logo-pill img { object-fit: contain; display: block; }
.logo-pill-text { font-weight: 800; color: #1a1a2e; }
/* ── Shared: stars ──────────────────────────────────────── */
.stars { color: var(--gold); letter-spacing: 1px; font-size: 13px; }
/* ── Shared: badge ──────────────────────────────────────── */
.badge {
display: inline-flex; align-items: center; gap: 3px;
font-size: 9px; font-weight: 800; text-transform: uppercase; letter-spacing: .9px;
padding: 3px 9px; border-radius: 20px; vertical-align: middle; white-space: nowrap;
}
.badge-best {
background: linear-gradient(135deg, #f59e0b, #f97316);
color: #fff;
box-shadow: 0 2px 10px rgba(249,115,22,.45);
}
.badge-new {
background: linear-gradient(135deg, #6366f1, #8b5cf6);
color: #fff;
box-shadow: 0 2px 10px rgba(139,92,246,.45);
}
.badge-free {
background: linear-gradient(135deg, #10b981, #06b6d4);
color: #fff;
box-shadow: 0 2px 10px rgba(16,185,129,.4);
}
/* ── Shared: pro item ───────────────────────────────────── */
.pro { font-size: 12px; color: var(--text2); display: flex; align-items: flex-start; gap: 5px; line-height: 1.4; }
.pro::before { content: '✓'; color: var(--green); font-weight: 700; flex-shrink: 0; font-size: 11px; margin-top: 1px; }
/* ── Layout sections ────────────────────────────────────── */
.layout-section { display: none; }
.layout-section.active { display: block; }
/* ════════════════════════════════════════════════════════
LAYOUT 1 — TABLE
════════════════════════════════════════════════════════ */
.t-table { display: flex; flex-direction: column; gap: 8px; }
@keyframes rowFadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.t-row {
display: grid;
grid-template-columns: 180px 1fr 200px 150px 160px;
align-items: center;
background: var(--surface);
border: 1px solid var(--border);
border-radius: 12px;
overflow: hidden;
transition: transform .15s, box-shadow .15s, background .15s, opacity .1s;
cursor: pointer;
animation: rowFadeIn .35s ease both;
animation-delay: calc(var(--row-idx, 0) * 55ms);
}
.t-row:hover { transform: translateY(-2px); box-shadow: var(--shadow); background: var(--surface2); }
.t-row:active { opacity: .75; transform: scale(0.995); transition: opacity .05s, transform .05s; }
/* Top-3 */
.t-row.rank-1 { border-left: 3px solid #fbbf24; }
.t-row.rank-2 { border-left: 3px solid #94a3b8; }
.t-row.rank-3 { border-left: 3px solid #cd7f32; }
/* Featured */
.t-row.t-featured {
border-color: rgba(99,102,241,.4);
background: linear-gradient(to right, rgba(99,102,241,.06), var(--surface));
}
.t-row.t-featured:hover { background: linear-gradient(to right, rgba(99,102,241,.1), var(--surface2)); }
/* Mobile GEO flag */
.t-brand-geo-mobile { display: none; }
.t-num { display: none; }
.t-logo {
padding: 16px 12px;
display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
border-right: 1px solid var(--border2);
}
.t-logo-meta { font-size: 10px; color: var(--text3); letter-spacing: .3px; }
.t-logo .logo-pill { width: 164px; height: 84px; }
.t-logo .logo-pill img { width: 164px; height: 64px; }
.t-logo .logo-pill-text { font-size: 16px; }
.t-brand { padding: 16px 16px; display: flex; flex-direction: column; gap: 5px; }
.t-brand-year { font-size: 10px; font-weight: 400; color: var(--text3); vertical-align: middle; }
.t-brand-name { font-size: 15px; font-weight: 700; }
.t-brand-row { display: flex; align-items: center; gap: 6px; }
.t-bonus { padding: 16px; display: flex; flex-direction: column; justify-content: center; gap: 6px;
border-left: 1px solid var(--border2); border-right: 1px solid var(--border2); }
.t-bonus-inner { background: var(--surface2); border: 1px solid var(--border); border-radius: 10px; padding: 10px 14px; }
.t-bonus-label { font-size: 9px; font-weight: 600; text-transform: uppercase; color: var(--green); letter-spacing: 1px; margin-bottom: 3px; }
.t-bonus-spins { font-size: 12px; color: var(--green); margin-top: 2px; }
.t-bonus-text { font-size: 15px; font-weight: 800; color: var(--accent); line-height: 1.2; }
.t-geo { padding: 14px 16px; display: flex; flex-direction: column; justify-content: center; gap: 8px;
border-right: 1px solid var(--border2); }
.t-geo-label { font-size: 9px; font-weight: 600; text-transform: uppercase; letter-spacing: .7px; color: var(--text3); }
.t-geo-flags { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.t-geo-flags img { border-radius: 2px; }
.t-geo-country { font-size: 12px; font-weight: 500; }
.t-geo-more { font-size: 11px; color: var(--text3); }
.t-pros { padding: 16px 14px; display: flex; flex-direction: column; gap: 5px; border-right: 1px solid var(--border2); }
.t-action {
padding: 16px; display: flex; flex-direction: column;
align-items: center; gap: 8px;
}
.t-avail { display: flex; align-items: center; gap: 5px; font-size: 11px; color: var(--text3); }
.t-action .btn-cta { width: 100%; justify-content: center; }
/* ── Tablet ≤900px: лого | бренд | бонус | geo | кнопка (один ряд) ── */
@media (max-width: 900px) {
.t-row {
grid-template-columns: 136px 1fr 170px 120px 120px;
grid-template-rows: auto;
min-height: 88px;
}
.t-num { display: none; }
.t-logo { grid-column: 1; grid-row: 1; border-right: 1px solid var(--border2); padding: 12px 10px; justify-content: center; }
.t-logo .logo-pill { width: 112px !important; height: 80px !important; }
.t-logo .logo-pill img { width: 112px !important; height: 64px !important; object-fit: contain; }
.t-brand { grid-column: 2; grid-row: 1; padding: 14px 14px; border: none; justify-content: center; }
.t-brand-name { font-size: 14px; }
.t-brand .pro { display: none; }
.t-bonus { grid-column: 3; grid-row: 1; padding: 14px 12px; border-left: 1px solid var(--border2); border-right: none; align-items: flex-start; justify-content: center; }
.t-bonus-text { font-size: 13px; }
.t-stats, .t-pros { display: none; }
.t-geo { grid-column: 4; grid-row: 1; display: flex; padding: 14px 10px; border-left: 1px solid var(--border2); }
.t-geo-label { font-size: 8px; }
.t-geo-flags img { width: 20px !important; height: 15px !important; }
.t-geo-country { font-size: 11px; }
.t-action { grid-column: 5; grid-row: 1; border-left: 1px solid var(--border2); padding: 14px 12px; gap: 8px; }
.t-avail { font-size: 10px; }
.t-action .btn-cta { font-size: 12px; padding: 11px 14px; width: 100%; }
}
/* ── Mobile ≤480px: лого сверху на всю ширину, контент стопкой ── */
@media (max-width: 480px) {
.t-row {
display: flex; flex-direction: column;
min-height: 0;
border-radius: 10px;
}
.t-num { display: none; }
.t-logo {
width: 100%; border-right: none; border-bottom: 1px solid var(--border2);
padding: 0; justify-content: center; align-items: stretch;
}
.t-logo .logo-pill { width: 100% !important; height: 90px !important; border-radius: 0 !important; }
.t-logo .logo-pill img { width: auto !important; max-width: 70% !important; height: 64px !important; object-fit: contain; }
.t-brand { padding: 14px 16px 6px; border: none; align-items: center; text-align: center; }
.t-brand-name { font-size: 16px; }
.t-brand-geo-mobile { display: flex; align-items: center; justify-content: center; gap: 5px; font-size: 11px; color: var(--text2); margin-top: 4px; }
.t-brand .pro { display: none; }
.t-brand-row { justify-content: center; }
.t-brand-row .stars { font-size: 14px; }
.t-bonus { padding: 8px 16px 12px; border: none; align-items: center; }
.t-bonus-inner { padding: 10px 16px; text-align: center; width: 100%; }
.t-bonus-label { text-align: center; }
.t-bonus-text { font-size: 16px; text-align: center; }
.t-bonus-spins { text-align: center; }
.t-stats, .t-pros, .t-geo { display: none; }
.t-action {
border-top: 1px solid var(--border2);
padding: 12px 16px 16px;
flex-direction: column; align-items: center; gap: 8px;
}
.t-avail { font-size: 11px; flex-direction: row; gap: 4px; justify-content: center; }
.t-action .btn-cta { font-size: 14px; padding: 13px 24px; width: 100%; }
}
/* ════════════════════════════════════════════════════════
LAYOUT 2 — CARDS
════════════════════════════════════════════════════════ */
.c-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
gap: 20px;
}
.c-card {
background: var(--surface);
border: 1px solid var(--border);
border-radius: 16px; overflow: hidden;
display: flex; flex-direction: column;
transition: transform .2s, box-shadow .2s;
}
.c-card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.c-head {
padding: 24px 20px 18px;
display: flex; flex-direction: column; align-items: center; gap: 10px;
position: relative;
}
.c-head-badge { position: absolute; top: 14px; right: 14px; }
.c-logo.logo-pill { width: 200px; height: 72px; }
.c-logo.logo-pill img { width: 200px; height: 72px; }
.c-logo.logo-pill-text { width: 200px; height: 72px; font-size: 22px; }
.c-name { font-size: 13px; font-weight: 600; color: var(--text2); letter-spacing: .2px; }
.c-stars { font-size: 16px; letter-spacing: 2px; }
.c-bonus {
margin: 0 16px 16px;
background: var(--gold-dim);
border: 1px solid var(--gold-border);
border-radius: 10px; padding: 12px 16px; text-align: center;
}
.c-bonus-label { font-size: 10px; text-transform: uppercase; letter-spacing: .8px; color: var(--text3); margin-bottom: 4px; }
.c-bonus-text { font-size: 14px; font-weight: 700; color: var(--gold-text); line-height: 1.4; }
.c-stats {
margin: 0 16px 14px;
display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
border: 1px solid var(--border); border-radius: 10px; overflow: hidden;
}
.c-stat {
background: var(--surface2);
padding: 10px 12px; display: flex; flex-direction: column; gap: 2px;
}
.c-stat-val { font-size: 12px; font-weight: 700; }
.c-stat-label { font-size: 10px; color: var(--text3); text-transform: uppercase; letter-spacing: .4px; }
.c-stat.full { grid-column: 1/-1; }
.c-pros {
margin: 0 16px; flex: 1;
display: flex; flex-direction: column; gap: 6px;
padding-bottom: 16px;
border-bottom: 1px solid var(--border2);
}
.c-foot {
padding: 14px 16px 18px;
display: flex; flex-direction: column; gap: 10px; align-items: center;
}
.c-avail { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--text3); }
.c-foot .btn-cta { width: 100%; justify-content: center; font-size: 14px; padding: 13px 20px; }
/* ════════════════════════════════════════════════════════
LAYOUT 3 — RANKED LIST
════════════════════════════════════════════════════════ */
.r-list { display: flex; flex-direction: column; gap: 10px; }
.r-row {
display: flex; align-items: center; gap: 0;
background: var(--surface); border: 1px solid var(--border);
border-radius: 14px; overflow: hidden;
transition: transform .15s, box-shadow .15s;
}
.r-row:hover { transform: translateX(4px); box-shadow: var(--shadow); }
.r-num {
width: 52px; flex-shrink: 0;
display: flex; align-items: center; justify-content: center;
font-size: 24px; font-weight: 900; color: var(--text3);
border-right: 1px solid var(--border2); align-self: stretch;
}
.r-num.top { color: var(--gold); }
.r-logo {
padding: 14px 16px; flex-shrink: 0;
border-right: 1px solid var(--border2);
}
.r-logo .logo-pill { width: 160px; height: 56px; }
.r-logo .logo-pill img { width: 160px; height: 56px; }
.r-logo .logo-pill-text { width: 160px; height: 56px; font-size: 14px; }
.r-main {
flex: 1; padding: 14px 18px; min-width: 0;
display: flex; flex-direction: column; gap: 5px;
border-right: 1px solid var(--border2);
}
.r-name { font-size: 15px; font-weight: 700; display: flex; align-items: center; gap: 6px; }
.r-bonus { font-size: 13px; color: var(--gold-text); font-weight: 500;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.r-row2 { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.r-chip {
font-size: 11px; color: var(--text2); background: var(--surface2);
padding: 2px 8px; border-radius: 20px; border: 1px solid var(--border2);
white-space: nowrap;
}
.r-stars { padding: 14px 16px; flex-shrink: 0; border-right: 1px solid var(--border2); }
.r-stars .stars { font-size: 14px; letter-spacing: 2px; }
.r-geo { padding: 14px 16px; flex-shrink: 0; border-right: 1px solid var(--border2);
display: flex; flex-direction: column; align-items: center; gap: 4px; }
.r-geo-label { font-size: 10px; color: var(--text3); text-transform: uppercase; letter-spacing: .4px; }
.r-action { padding: 14px 16px; flex-shrink: 0; }
@media (max-width: 700px) {
.r-row { flex-wrap: wrap; }
.r-num { width: 44px; border-right: none; align-self: auto; }
.r-logo { border-right: none; padding: 12px; }
.r-logo .logo-pill { width: 120px; height: 44px; }
.r-logo .logo-pill img { width: 120px; height: 44px; }
.r-main { flex: 100%; border-right: none; border-top: 1px solid var(--border2); padding: 10px 14px; }
.r-stars, .r-geo { display: none; }
.r-action { flex: 100%; padding: 0 14px 14px; }
.r-action .btn-cta { width: 100%; justify-content: center; }
}
</style>
</head>
<body>
<!-- Dev bar -->
<div id="dev-bar" <?= !empty($_GET['embed']) ? 'style="display:none"' : '' ?>>
<div class="dg">
<span class="dl">Layout:</span>
<button class="db on" data-layout="table">⊞ Table</button>
<button class="db" data-layout="cards">▦ Cards</button>
<button class="db" data-layout="ranked">☰ Ranked</button>
</div>
<div class="db-sep"></div>
<div class="dg">
<span class="dl">Theme:</span>
<button class="db on" data-theme="auto">Auto</button>
<button class="db" data-theme="dark">Dark</button>
<button class="db" data-theme="light">Light</button>
</div>
<div class="db-sep"></div>
<div class="dg">
<span class="dl">GEO:</span>
<?php foreach (['de'=>'🇩🇪','ru'=>'🇷🇺','pl'=>'🇵🇱','tr'=>'🇹🇷','ua'=>'🇺🇦','fr'=>'🇫🇷'] as $cc=>$flag): ?>
<a href="?country=<?= $cc ?>&lang=<?= $cc==='ua'?'uk':$cc ?>"
class="db <?= $country===$cc?'on':'' ?>"><?= $flag ?> <?= strtoupper($cc) ?></a>
<?php endforeach ?>
<a href="?" class="db <?= !$country?'on':'' ?>">Auto</a>
</div>
<div class="di"><?= count($brands) ?> brands · <?= h($country?:'auto') ?> · <?= h($lang) ?></div>
</div>
<div class="ww <?= $embed ? 'embed' : '' ?>" id="ww">
<div class="ww-inner">
<?php if (empty($brand_data)): ?>
<div style="text-align:center;padding:80px 20px;opacity:.3;font-size:15px">No brands for this GEO</div>
<?php endif ?>
<!-- ══════════════════════════════════════════
LAYOUT 1: TABLE
══════════════════════════════════════════ -->
<div data-layout="table" class="layout-section active">
<div class="t-table">
<?php foreach ($brand_data as $d):
$is_top = $d['idx'] < 3;
$row_cls = 't-row';
if ($d['idx'] === 0) $row_cls .= ' rank-1';
elseif ($d['idx'] === 1) $row_cls .= ' rank-2';
elseif ($d['idx'] === 2) $row_cls .= ' rank-3';
if (!empty($d['b']['is_featured'])) $row_cls .= ' t-featured';
?>
<div class="<?= $row_cls ?>" style="--row-idx:<?= $d['idx'] ?>" onclick="window.open('<?= h($d['click']) ?>','_blank')">
<!-- # -->
<div class="t-num <?= $is_top ? 'top' : '' ?>"><?= $d['idx']+1 ?></div>
<!-- Logo -->
<div class="t-logo">
<div class="logo-pill" style="width:164px;height:84px;background:<?= logo_bg_gradient((int)$d['b']['id'], $d['b']['logo_bg'] ?? '') ?>">
<?php if ($d['b']['logo']): ?>
<img src="<?= h($d['b']['logo']) ?>" alt="<?= h($d['b']['name']) ?>" style="width:164px;height:64px;object-fit:contain">
<?php else: ?>
<span class="logo-pill-text" style="font-size:15px;padding:8px"><?= h($d['b']['name']) ?></span>
<?php endif ?>
</div>
</div>
<!-- Brand -->
<div class="t-brand">
<div class="t-brand-name">
<?= h($d['b']['name']) ?>
<?php if ($d['b']['badge']): ?>
<span class="badge badge-<?= h($d['b']['badge']) ?>"><?= badge_label($d['b']['badge']) ?></span>
<?php endif ?>
</div>
<div class="t-brand-row">
<span class="stars"><?= $d['stars'] ?></span>
</div>
<?php if ($d['adv']): ?>
<?php foreach (array_slice($d['adv'], 0, 2) as $item): ?>
<div class="pro"><?= h($item) ?></div>
<?php endforeach ?>
<?php endif ?>
<?php if ($country): ?>
<div class="t-brand-geo-mobile">
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($country) ?>.svg" width="16" height="12" style="border-radius:2px">
<span><?= h(country_name($country)) ?></span>
</div>
<?php endif ?>
</div>
<!-- Bonus -->
<div class="t-bonus">
<?php if ($d['bonus']): ?>
<div class="t-bonus-inner">
<div class="t-bonus-label">Welcome Bonus</div>
<div class="t-bonus-text"><?= h($d['bonus']) ?></div>
<?php if ($d['free_spins']): ?>
<div class="t-bonus-spins">+ <?= h($d['free_spins']) ?></div>
<?php endif ?>
</div>
<?php else: ?>
<span style="color:var(--text3);font-size:12px">—</span>
<?php endif ?>
</div>
<!-- Geo -->
<div class="t-geo">
<div class="t-geo-label">Accepts players from</div>
<div class="t-geo-flags">
<?php if ($country): ?>
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($country) ?>.svg" width="28" height="21" title="<?= h(country_name($country)) ?>">
<span class="t-geo-country"><?= h(country_name($country)) ?></span>
<?php else:
$show = array_slice($d['country_codes'], 0, 4);
$rest = count($d['country_codes']) - count($show);
foreach ($show as $cc): ?>
<img src="https://flagicons.lipis.dev/flags/4x3/<?= h($cc) ?>.svg" width="22" height="16" title="<?= h(country_name($cc)) ?>">
<?php endforeach;
if ($rest > 0): ?><span class="t-geo-more">+<?= $rest ?></span><?php endif ?>
<?php endif ?>
</div>
</div>
<!-- Action -->
<div class="t-action" onclick="event.stopPropagation()">
<a href="<?= h($d['click']) ?>" class="btn-cta" target="_blank" rel="noopener">
<?= h($cta_text) ?>
</a>
</div>
</div>
<?php endforeach ?>
</div>
</div>
<!-- ══════════════════════════════════════════
LAYOUT 2: CARDS
══════════════════════════════════════════ -->
<div data-layout="cards" class="layout-section">
<div class="c-grid">
<?php foreach ($brand_data as $d): ?>
<div class="c-card">
<div class="c-head">
<?php if ($d['b']['badge']): ?>
<div class="c-head-badge">
<span class="badge badge-<?= h($d['b']['badge']) ?>"><?= badge_label($d['b']['badge']) ?></span>
</div>
<?php endif ?>
<div class="logo-pill c-logo" style="width:200px;height:72px;background:<?= logo_bg_gradient((int)$d['b']['id'], $d['b']['logo_bg'] ?? '') ?>">
<?php if ($d['b']['logo']): ?>
<img src="<?= h($d['b']['logo']) ?>" alt="<?= h($d['b']['name']) ?>" style="width:200px;height:72px;object-fit:contain">
<?php else: ?>
<span class="logo-pill-text" style="font-size:18px;padding:10px"><?= h($d['b']['name']) ?></span>
<?php endif ?>
</div>
<div class="c-stars stars"><?= $d['stars'] ?></div>
<div class="c-name"><?= h($d['b']['name']) ?></div>
</div>
<?php if ($d['bonus']): ?>
<div class="c-bonus">
<div class="c-bonus-label">Welcome Bonus</div>
<div class="c-bonus-text"><?= h($d['bonus']) ?></div>
</div>
<?php endif ?>
<?php
$stats = [];
if ($d['year_founded']) $stats[] = ['Est.', $d['year_founded'], false];
if ($d['games_count']) $stats[] = ['Games', $d['games_count'], false];
if ($d['license']) $stats[] = ['License', $d['license'], false];
if ($d['currencies']) $stats[] = ['Currency', $d['currencies'], false];
if ($d['more_countries']>0) $stats[] = ['+Countries', '+' . $d['more_countries'] . ' more', true];
?>
<?php if ($stats): ?>
<div class="c-stats">
<?php foreach ($stats as [$label, $val, $full]): ?>
<div class="c-stat <?= $full ? 'full' : '' ?>">
<span class="c-stat-val"><?= h($val) ?></span>
<span class="c-stat-label"><?= h($label) ?></span>
</div>
<?php endforeach ?>
</div>
<?php endif ?>
<?php if ($d['adv']): ?>
<div class="c-pros">
<?php foreach (array_slice($d['adv'], 0, 3) as $item): ?>
<div class="pro"><?= h($item) ?></div>
<?php endforeach ?>
</div>
<?php endif ?>
<div class="c-foot">
<?php if ($country): ?>
<div class="c-avail">
<?= geo_flag($country) ?>
<span><?= h($avail_label) ?> <?= h(country_name($country)) ?></span>
</div>
<?php endif ?>
<a href="<?= h($d['click']) ?>" class="btn-cta" target="_blank" rel="noopener">
<?= h($cta_text) ?>
</a>
</div>
</div>
<?php endforeach ?>
</div>
</div>
<!-- ══════════════════════════════════════════
LAYOUT 3: RANKED LIST
══════════════════════════════════════════ -->
<div data-layout="ranked" class="layout-section">
<div class="r-list">
<?php foreach ($brand_data as $d):
$is_top = $d['idx'] < 3;
?>
<div class="r-row">
<div class="r-num <?= $is_top ? 'top' : '' ?>"><?= $d['idx']+1 ?></div>
<div class="r-logo">
<div class="logo-pill" style="width:160px;height:56px;background:<?= logo_bg_gradient((int)$d['b']['id'], $d['b']['logo_bg'] ?? '') ?>">
<?php if ($d['b']['logo']): ?>
<img src="<?= h($d['b']['logo']) ?>" alt="<?= h($d['b']['name']) ?>" style="width:160px;height:56px;object-fit:contain">
<?php else: ?>
<span class="logo-pill-text" style="font-size:13px;padding:6px"><?= h($d['b']['name']) ?></span>
<?php endif ?>
</div>
</div>
<div class="r-main">
<div class="r-name">
<?= h($d['b']['name']) ?>
<?php if ($d['b']['badge']): ?>
<span class="badge badge-<?= h($d['b']['badge']) ?>"><?= badge_label($d['b']['badge']) ?></span>
<?php endif ?>
</div>
<?php if ($d['bonus']): ?>
<div class="r-bonus"><?= h($d['bonus']) ?></div>
<?php endif ?>
<div class="r-row2">
<?php if ($d['games_count']): ?>
<span class="r-chip">🎮 <?= h($d['games_count']) ?></span>
<?php endif ?>
<?php if ($d['license']): ?>
<span class="r-chip">🪪 <?= h($d['license']) ?></span>
<?php endif ?>
<?php if ($d['year_founded']): ?>
<span class="r-chip">📅 <?= $d['year_founded'] ?></span>
<?php endif ?>
<?php if ($d['more_countries'] > 0): ?>
<span class="r-chip">🌍 +<?= $d['more_countries'] ?> countries</span>
<?php endif ?>
</div>
</div>
<div class="r-stars"><span class="stars"><?= $d['stars'] ?></span></div>
<?php if ($country): ?>
<div class="r-geo">
<span class="r-geo-label"><?= h($avail_label) ?></span>
<?= geo_flag($country) ?>
<span style="font-size:11px;color:var(--text2)"><?= h(strtoupper($country)) ?></span>
</div>
<?php endif ?>
<div class="r-action">
<a href="<?= h($d['click']) ?>" class="btn-cta" target="_blank" rel="noopener">
<?= h($cta_text) ?>
</a>
</div>
</div>
<?php endforeach ?>
</div>
</div>
</div><!-- /ww-inner -->
</div><!-- /ww -->
<script>
(function () {
function detectTheme() {
var el = document.body, bg = getComputedStyle(el).backgroundColor;
while ((bg==='rgba(0, 0, 0, 0)'||bg==='transparent') && el.parentElement) {
el = el.parentElement; bg = getComputedStyle(el).backgroundColor;
}
var m = bg.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
if (m) return (parseInt(m[1])*299+parseInt(m[2])*587+parseInt(m[3])*114)/1000 < 128 ? 'dark' : 'light';
return 'dark';
}
var ww = document.getElementById('ww');
var forcedTheme = <?= $force_theme ? '"' . $force_theme . '"' : 'null' ?>;
var forcedLayout = <?= $force_layout ? '"' . $force_layout . '"' : 'null' ?>;
var cur = {
layout: forcedLayout || localStorage.getItem('wt_layout') || 'table',
theme: localStorage.getItem('wt_theme') || 'auto'
};
function applyLayout(l) {
document.querySelectorAll('.layout-section').forEach(function(el) {
el.classList.toggle('active', el.dataset.layout === l);
});
document.querySelectorAll('[data-layout].db').forEach(function(b) {
b.classList.toggle('on', b.dataset.layout === l);
});
}
function applyTheme(t) {
ww.classList.remove('light');
if (t === 'light') ww.classList.add('light');
else if (t === 'auto' && detectTheme() === 'light') ww.classList.add('light');
document.querySelectorAll('[data-theme].db').forEach(function(b) {
b.classList.toggle('on', b.dataset.theme === t);
});
}
document.querySelectorAll('[data-layout].db').forEach(function(btn) {
btn.addEventListener('click', function() {
cur.layout = btn.dataset.layout;
applyLayout(cur.layout);
localStorage.setItem('wt_layout', cur.layout);
});
});
document.querySelectorAll('[data-theme].db').forEach(function(btn) {
btn.addEventListener('click', function() {
cur.theme = btn.dataset.theme;
applyTheme(cur.theme);
localStorage.setItem('wt_theme', cur.theme);
});
});
applyLayout(cur.layout);
applyTheme(forcedTheme || cur.theme);
})();
</script>
</body>
</html>