<?php
define('_MN_USER', 'bfde858980d61eb8ef06475ca1df225c6ff6f324');
require_once($_SERVER['DOCUMENT_ROOT'] . '/' . _MN_USER . '/' . 'magenet.php');
// NOTE: new Magenet() est instancié APRÈS la vérification du cache HTML (voir plus bas).
// Cela évite un appel HTTP externe bloquant (~5-10s) sur chaque requête,
// même quand la page peut être servie directement depuis le cache.

include_once('Mobile-Detect-master/Mobile_Detect.php');
require_once('includes/fonctions.php');
require_once('administration/inc.includes/inc.configuration.php');
require_once('administration/inc.includes/inc.connexion.php');
require_once('administration/inc.includes/class.rubrique.php');
require_once('administration/inc.includes/class.jeu.php');

/**
 * ------------------------------------------------------------
 * CACHE GLOBAL
 * ------------------------------------------------------------
 */
$canCache = ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'GET';

if (isset($_GET['nocache']) && $_GET['nocache'] == '1') {
    $canCache = false;
}

/**
 * WARM-UP CACHE (appelé uniquement par le cron serveur, jamais par un vrai visiteur).
 * Contrairement à ?nocache=1, ce mode force une régénération complète mais
 * ECRIT bien le résultat dans le cache (c'est tout le but du warm-up).
 * Le secret évite que n'importe qui puisse déclencher des régénérations
 * à répétition depuis l'extérieur (ce qui annulerait le bénéfice du cache).
 * REMPLACE 'CHANGE_MOI_PAR_UN_TOKEN_LONG_ET_ALEATOIRE' par une vraie valeur secrète.
 */
define('UF_CACHE_WARM_SECRET', '92ecce1e13424390e84bd8dd5073451edf6f6a5d');
$forceRefresh = isset($_GET['warmcache']) && hash_equals(UF_CACHE_WARM_SECRET, (string)$_GET['warmcache']);

/**
 * Si un visiteur a déjà un historique de jeux joués,
 * on ne sert pas une home HTML mise en cache,
 * sinon la section "Reprendre une partie" devient fausse.
 */
if (!empty($_COOKIE['activity_recent'])) {
    $canCache = false;
}

$uri = $_SERVER['REQUEST_URI'] ?? '/';

$detect = new Mobile_Detect();
$isTablet = $detect->isTablet();
$isMobile = $detect->isMobile() && !$isTablet;
$isMobileOrTablet = $detect->isMobile();
$deviceKey = $isMobile ? 'm' : ($isTablet ? 't' : 'd');

$globalCacheKey = 'page:index:responsive:v7-mosaic-inline-video:' . $deviceKey . ':' . $uri;

function cache_get($key, $ttl = 60)
{
    $file = __DIR__ . '/cache/' . md5($key) . '.cache';
    if (is_file($file) && (time() - filemtime($file)) < $ttl) {
        return file_get_contents($file);
    }
    return false;
}

// Variante "stale" : renvoie le contenu même s'il est périmé, et indique
// via $isStale si on est dans ce cas (utilisé pour le stale-while-revalidate).
function cache_get_stale($key, $ttl = 60, &$isStale = false)
{
    $file = __DIR__ . '/cache/' . md5($key) . '.cache';
    if (!is_file($file)) {
        $isStale = false;
        return false;
    }
    $isStale = (time() - filemtime($file)) >= $ttl;
    return file_get_contents($file);
}

function cache_set($key, $content)
{
    $dir = __DIR__ . '/cache';
    if (!is_dir($dir)) {
        @mkdir($dir, 0775, true);
    }
    $file = $dir . '/' . md5($key) . '.cache';
    file_put_contents($file, $content, LOCK_EX);
}

/**
 * Cache HTML complet court : sert uniquement les visiteurs sans cookie de reprise.
 * Cela réduit fortement le TTFB sans casser la section personnalisée "Reprendre une partie".
 *
 * STALE-WHILE-REVALIDATE + verrou anti-stampede :
 * - Si le cache est frais -> on le sert direct.
 * - Si le cache est périmé mais existant -> on le sert quand même instantanément
 *   (au lieu de faire attendre le visiteur pendant la régénération), et UN SEUL
 *   process PHP se charge de régénérer en arrière-plan (flock non bloquant).
 *   Les autres visiteurs qui arrivent pendant la régénération reçoivent aussi
 *   la version périmée, le temps que la nouvelle soit prête.
 * - Si aucun cache n'existe du tout (premier déploiement, cache vidé) -> on
 *   tombe dans le rendu normal ci-dessous, seul cas qui paie le coût plein.
 */
if ($canCache && !$forceRefresh) {
    $isStale = false;
    $cachedHtml = cache_get_stale($globalCacheKey, 60, $isStale);

    if ($cachedHtml !== false && !$isStale) {
        echo $cachedHtml;
        exit; // Magenet n'est jamais appelé ici -> 0 requete HTTP externe
    }

    if ($cachedHtml !== false && $isStale) {
        $lockFile = __DIR__ . '/cache/' . md5($globalCacheKey) . '.lock';
        $lockDir = __DIR__ . '/cache';
        if (!is_dir($lockDir)) {
            @mkdir($lockDir, 0775, true);
        }
        $lockHandle = @fopen($lockFile, 'c');

        if ($lockHandle && flock($lockHandle, LOCK_EX | LOCK_NB)) {
            // On devient le régénérateur : on "rafraîchit" tout de suite la
            // date du fichier cache pour que les requêtes concurrentes le
            // voient comme frais pendant qu'on régénère (évite le stampede).
            $cacheFile = $lockDir . '/' . md5($globalCacheKey) . '.cache';
            @touch($cacheFile);
            register_shutdown_function(function () use ($lockHandle) {
                flock($lockHandle, LOCK_UN);
                fclose($lockHandle);
            });
            // On continue l'exécution normale plus bas pour régénérer le HTML.
        } else {
            // Un autre process régénère déjà : on sert le stale, pas d'attente.
            echo $cachedHtml;
            exit;
        }
    }
}

/**
 * Magenet est instancie ICI, apres le cache HTML.
 * Son constructeur fait une requete HTTP externe vers les serveurs Magenet.
 * Quand leur serveur est lent (timeout, surcharge CDN), cela pouvait bloquer PHP
 * pendant 5 a 10 secondes, meme pour une page deja en cache.
 * En le placant ici, seules les regenerations reelles paient ce cout.
 */
$magenet = new Magenet();

ob_start();

/**
 * ------------------------------------------------------------
 * REDIRECTS
 * ------------------------------------------------------------
 */
$UrlActuel = "https://" . ($_SERVER['HTTP_HOST'] ?? '');
if ($UrlActuel === 'https://universflash.com') {
    header("Status: 301 Moved Permanently", false, 301);
    header("Location: " . WEB_RACINE);
    exit();
}

if (($_SERVER['REQUEST_URI'] ?? '') === '/index.php') {
    header('Location: /', true, 301);
    exit();
}

/**
 * ------------------------------------------------------------
 * COOKIE JEUX RÉCENTS
 * ------------------------------------------------------------
 */
$listeJeuxJoues = [];
if (!empty($_COOKIE['activity_recent'])) {
    $tmp = @unserialize($_COOKIE['activity_recent'], ['allowed_classes' => false]);
    if (is_array($tmp)) {
        $listeJeuxJoues = $tmp;
    }
}
$nombreJeuxJoues = count($listeJeuxJoues);

/**
 * ------------------------------------------------------------
 * HELPERS
 * ------------------------------------------------------------
 */
if (!function_exists('uf_h')) {
    function uf_h($value)
    {
        return htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
    }
}

if (!function_exists('uf_object_get')) {
    function uf_object_get($obj, array $keys, $default = '')
    {
        if (!is_object($obj) || !method_exists($obj, 'get')) {
            return $default;
        }

        foreach ($keys as $key) {
            try {
                // Certains vieux objets Jeu echo un message du type
                // "propriété non existante" quand la propriété est absente.
                // On bufferise donc l'appel pour éviter que ces warnings maison
                // s'affichent en haut de page avant que le rendu ne soit terminé.
                $level = ob_get_level();
                ob_start();
                $value = $obj->get($key);
                ob_end_clean();

                if ($value !== null && $value !== '') {
                    return $value;
                }
            } catch (Throwable $e) {
                while (ob_get_level() > $level) {
                    ob_end_clean();
                }
                // ignore
            } catch (Exception $e) {
                while (ob_get_level() > $level) {
                    ob_end_clean();
                }
                // compat vieux PHP
            }
        }

        return $default;
    }
}

if (!function_exists('uf_slugify')) {
    function uf_slugify($text)
    {
        $text = trim((string)$text);
        $map = [
            'à'=>'a','á'=>'a','â'=>'a','ã'=>'a','ä'=>'a','å'=>'a',
            'ç'=>'c',
            'è'=>'e','é'=>'e','ê'=>'e','ë'=>'e',
            'ì'=>'i','í'=>'i','î'=>'i','ï'=>'i',
            'ñ'=>'n',
            'ò'=>'o','ó'=>'o','ô'=>'o','õ'=>'o','ö'=>'o',
            'ù'=>'u','ú'=>'u','û'=>'u','ü'=>'u',
            'ý'=>'y','ÿ'=>'y',
            'À'=>'a','Á'=>'a','Â'=>'a','Ã'=>'a','Ä'=>'a','Å'=>'a',
            'Ç'=>'c',
            'È'=>'e','É'=>'e','Ê'=>'e','Ë'=>'e',
            'Ì'=>'i','Í'=>'i','Î'=>'i','Ï'=>'i',
            'Ñ'=>'n',
            'Ò'=>'o','Ó'=>'o','Ô'=>'o','Õ'=>'o','Ö'=>'o',
            'Ù'=>'u','Ú'=>'u','Û'=>'u','Ü'=>'u',
            'Ý'=>'y'
        ];
        $text = strtr($text, $map);
        $text = strtolower($text);
        $text = preg_replace('~[^a-z0-9]+~', '-', $text);
        $text = trim($text, '-');
        return $text ?: 'rubrique';
    }
}


if (!function_exists('uf_mb_ucfirst')) {
    function uf_mb_ucfirst($text)
    {
        $text = trim((string)$text);
        if ($text === '') {
            return '';
        }

        if (function_exists('mb_substr')) {
            return mb_strtoupper(mb_substr($text, 0, 1, 'UTF-8'), 'UTF-8') . mb_substr($text, 1, null, 'UTF-8');
        }

        return ucfirst($text);
    }
}

if (!function_exists('uf_local_image_path')) {
    function uf_local_image_path($url)
    {
        $url = trim((string)$url);
        if ($url === '' || strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
            return '';
        }
        $path = strtok($url, '?') ?: $url;
        if (strpos($path, '/') !== 0) {
            $path = '/' . ltrim($path, '/');
        }
        return $path;
    }
}

if (!function_exists('uf_image_candidate_url')) {
    function uf_image_candidate_url($url, $ext)
    {
        $url = trim((string)$url);
        if ($url === '' || strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
            return '';
        }
        $path = strtok($url, '?') ?: $url;
        $query = strpos($url, '?') !== false ? '?' . substr($url, strpos($url, '?') + 1) : '';
        if (!preg_match('~\.(jpe?g|png|webp|avif)$~i', $path)) {
            return '';
        }
        return preg_replace('~\.(jpe?g|png|webp|avif)$~i', '.' . ltrim($ext, '.'), $path) . $query;
    }
}

if (!function_exists('uf_file_is_real_avif')) {
    function uf_file_is_real_avif($url)
    {
        static $cache = [];
        $path = uf_local_image_path($url);
        if ($path === '' || !preg_match('~\.avif(?:\?.*)?$~i', $url)) {
            return false;
        }
        if (isset($cache[$path])) {
            return $cache[$path];
        }
        $abs = rtrim($_SERVER['DOCUMENT_ROOT'], '/') . $path;
        if (!is_file($abs) || !is_readable($abs)) {
            $cache[$path] = false;
            return false;
        }
        $fh = @fopen($abs, 'rb');
        if (!$fh) {
            $cache[$path] = false;
            return false;
        }
        $head = fread($fh, 64);
        fclose($fh);
        // Vrai AVIF = marque ftypavif/ftypavis. Évite les HEIF/HEVC renommés en .avif.
        $ok = (strpos($head, 'ftypavif') !== false || strpos($head, 'ftypavis') !== false);
        $cache[$path] = $ok;
        return $ok;
    }
}

if (!function_exists('uf_image_avif_url')) {
    function uf_image_avif_url($url)
    {
        $candidate = uf_image_candidate_url($url, 'avif');
        if ($candidate !== '' && uf_file_is_real_avif($candidate)) {
            return $candidate;
        }
        return '';
    }
}

if (!function_exists('uf_image_fallback_url')) {
    function uf_image_fallback_url($url)
    {
        // Fallback demandé : JPEG en priorité, puis WebP/original pour éviter toute image cassée.
        static $cache = [];
        $url = trim((string)$url);
        if ($url === '' || strpos($url, 'http://') === 0 || strpos($url, 'https://') === 0) {
            return $url;
        }
        if (isset($cache[$url])) {
            return $cache[$url];
        }
        $path = strtok($url, '?') ?: $url;
        $query = strpos($url, '?') !== false ? '?' . substr($url, strpos($url, '?') + 1) : '';
        if (!preg_match('~\.(jpe?g|png|webp|avif)$~i', $path)) {
            $cache[$url] = $url;
            return $url;
        }
        foreach (['jpg', 'jpeg', 'webp'] as $ext) {
            $candidate = preg_replace('~\.(jpe?g|png|webp|avif)$~i', '.' . $ext, $path);
            if ($candidate && file_exists($_SERVER['DOCUMENT_ROOT'] . $candidate)) {
                $cache[$url] = $candidate . $query;
                return $cache[$url];
            }
        }
        if (file_exists($_SERVER['DOCUMENT_ROOT'] . $path)) {
            $cache[$url] = $url;
            return $url;
        }
        $cache[$url] = '/jeu/images/200x170UF.jpg';
        return $cache[$url];
    }
}

if (!function_exists('uf_optimized_image_url')) {
    function uf_optimized_image_url($url)
    {
        // Ne retourne pas AVIF directement : l'AVIF doit être servi via <picture> avec fallback.
        return uf_image_fallback_url($url);
    }
}


if (!function_exists('uf_preview_image_url')) {
    function uf_preview_image_url($url)
    {
        // La fiche hover utilise un simple <img> : on donne directement le vrai AVIF s'il existe, sinon le fallback JPEG/WebP.
        $avif = uf_image_avif_url($url);
        return $avif !== '' ? $avif : uf_image_fallback_url($url);
    }
}

if (!function_exists('uf_picture_html')) {
    function uf_picture_html($url, $class, $alt, $attrs = '')
    {
        $fallback = uf_image_fallback_url($url);
        $avif = uf_image_avif_url($url);
        $html = '<picture>';
        if ($avif !== '') {
            $html .= '<source srcset="' . uf_h($avif) . '" type="image/avif">';
        }
        $html .= '<img';
        if ($class !== '') {
            $html .= ' class="' . uf_h($class) . '"';
        }
        $html .= ' src="' . uf_h($fallback) . '" alt="' . uf_h($alt) . '"' . $attrs . '>';
        $html .= '</picture>';
        return $html;
    }
}

if (!function_exists('uf_img_attrs')) {
    function uf_img_attrs($isPriority = false, $width = 200, $height = 170, $isAboveFold = false)
    {
        $attrs = ' width="' . (int)$width . '" height="' . (int)$height . '" decoding="async"';
        if ($isPriority) {
            $attrs .= ' loading="eager" fetchpriority="high"';
        } elseif ($isAboveFold) {
            // Les premières vignettes visibles sur mobile ne doivent pas attendre le lazy-load.
            $attrs .= ' loading="eager" fetchpriority="auto"';
        } else {
            $attrs .= ' loading="lazy" fetchpriority="low"';
        }
        return $attrs;
    }
}

if (!function_exists('uf_game_image')) {
    function uf_game_image($jeu)
    {
        $img = trim((string)uf_object_get($jeu, ['FichierIMG', 'nomptimage', 'NomPtImage'], ''));

        if ($img === '') {
            return uf_optimized_image_url('/jeu/images/200x170UF.jpg');
        }

        if (strpos($img, 'http://') === 0 || strpos($img, 'https://') === 0) {
            return $img;
        }

        if (strpos($img, '/') === 0) {
            $absPath = $_SERVER['DOCUMENT_ROOT'] . $img;
            if (file_exists($absPath)) {
                return uf_optimized_image_url($img);
            }
            return uf_optimized_image_url('/jeu/images/200x170UF.jpg');
        }

        $img = ltrim($img, '/');
        $base = '/jeu/images/' . $img;
        $abs  = $_SERVER['DOCUMENT_ROOT'] . $base;

        if (file_exists($abs)) {
            return uf_optimized_image_url($base);
        }

        return uf_optimized_image_url('/jeu/images/200x170UF.jpg');
    }
}


if (!function_exists('uf_game_video_url')) {
    function uf_game_video_url($jeu)
    {
        $video = trim((string)uf_object_get($jeu, ['FichierVID', 'nomfichiervideo', 'NomFichierVideo'], ''));
        if ($video === '') {
            return '';
        }

        // Sécurité : on ne sert que les fichiers réellement présents dans /videos/
        $filename = basename($video);
        if ($filename === '' || !preg_match('~\.mp4$~i', $filename)) {
            return '';
        }

        $abs = '/www/universflash.com/videos/' . $filename;
        if (!is_file($abs) || !is_readable($abs)) {
            return '';
        }

        return '/videos/' . rawurlencode($filename);
    }
}

if (!function_exists('uf_game_title')) {
    function uf_game_title($jeu)
    {
        return uf_object_get($jeu, ['nom', 'NomJeu', 'nomjeu'], 'Jeu');
    }
}

if (!function_exists('uf_game_url')) {
    function uf_game_url($jeu)
    {
        $url = uf_object_get($jeu, ['url', 'Url'], '');
        if ($url !== '') {
            return $url;
        }

        $id = (int)uf_object_get($jeu, ['id', 'Id'], 0);
        if ($id > 0) {
            return '/jeu-' . $id . '.html';
        }

        return '#';
    }
}


if (!function_exists('uf_game_preview_description')) {
    function uf_game_preview_description($jeu, $wordLimit = 25)
    {
        $raw = uf_object_get($jeu, ['description', 'Description', 'ds', 'Ds', 'DS', 'instruction', 'Instruction'], '');
        $raw = (string)$raw;

        // Pour les descriptions générées avec un premier <h2>, on extrait le texte qui suit ce titre.
        if (preg_match('~</h2\s*>\s*(.*)$~is', $raw, $m)) {
            $raw = $m[1];
        }

        $text = html_entity_decode(strip_tags($raw), ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $text = preg_replace('/\s+/u', ' ', trim($text));

        if ($text === '') {
            return '';
        }

        $words = preg_split('/\s+/u', $text, -1, PREG_SPLIT_NO_EMPTY);
        if (!$words) {
            return '';
        }

        if (count($words) > $wordLimit) {
            return implode(' ', array_slice($words, 0, $wordLimit)) . '...';
        }

        return implode(' ', $words);
    }
}


if (!function_exists('uf_preview_meta_key')) {
    function uf_preview_meta_key($name)
    {
        $name = html_entity_decode(strip_tags((string)$name), ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $name = trim($name);

        if ($name === '') {
            return '';
        }

        if (function_exists('iconv')) {
            $converted = @iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $name);
            if ($converted !== false) {
                $name = $converted;
            }
        }

        $name = strtolower($name);
        $name = preg_replace('~\bjeux?\b~', ' ', $name);
        $name = preg_replace('~\b(de|du|des|d|la|le|les)\b~', ' ', $name);
        $name = preg_replace('~[^a-z0-9]+~', ' ', $name);
        $name = trim(preg_replace('~\s+~', ' ', $name));

        return $name;
    }
}

if (!function_exists('uf_game_preview_meta')) {
    function uf_game_preview_meta($cnx, $jeu, $maxItems = 5)
    {
        // Cache statique : cette fonction est appelée pour chaque jeu affiché.
        // Sans cache, elle déclenche jusqu'à 6 new Rubrique() + 1 SQL par jeu,
        // soit plusieurs centaines de requêtes sur la HP complète.
        static $metaCache = [];

        $gameId = (int)uf_object_get($jeu, ['id', 'Id', 'ID'], 0);
        $cacheKey = $gameId . ':' . $maxItems;
        if ($gameId > 0 && isset($metaCache[$cacheKey])) {
            return $metaCache[$cacheKey];
        }

        $items = [];
        $seen = [];

        for ($i = 1; $i <= 6; $i++) {
            $keys = $i === 1 ? ['RubriqueId', 'rubrique_id'] : ['RubriqueId' . $i, 'rubrique_id' . $i];
            $rid = (int)uf_object_get($jeu, $keys, 0);
            if ($rid <= 0) {
                continue;
            }
            try {
                $Rubrique = new Rubrique($rid);
                $name = trim(strip_tags((string)$Rubrique->get('nom')));
                $key = uf_preview_meta_key($name);
                if ($name !== '' && $key !== '' && empty($seen[$key])) {
                    $items[] = $name;
                    $seen[$key] = true;
                }
            } catch (Throwable $e) {
            } catch (Exception $e) {
            }
            if (count($items) >= $maxItems) {
                $result = implode(' • ', $items);
                if ($gameId > 0) $metaCache[$cacheKey] = $result;
                return $result;
            }
        }

        if ($gameId > 0 && $cnx) {
            $sql = '
                SELECT c.nom
                FROM liaison_categorie_flash lcf
                INNER JOIN categorie c ON c.id = lcf.categorie_id
                WHERE lcf.flash_id = ' . $gameId . '
                  AND c.etat = "active"
                  AND (
                    SELECT COUNT(*)
                    FROM liaison_categorie_flash lcf_count
                    INNER JOIN flash f_count ON f_count.id = lcf_count.flash_id
                    WHERE lcf_count.categorie_id = c.id
                      AND f_count.etat = "actif"
                  ) >= 4
                ORDER BY c.nom ASC
                LIMIT ' . (int)$maxItems;
            $cnx->Executer($sql);
            while ($row = $cnx->Extraire()) {
                $name = trim(strip_tags((string)($row['nom'] ?? '')));
                $key = uf_preview_meta_key($name);
                if ($name !== '' && $key !== '' && empty($seen[$key])) {
                    $items[] = $name;
                    $seen[$key] = true;
                }
                if (count($items) >= $maxItems) {
                    break;
                }
            }
        }

        $result = !empty($items) ? implode(' • ', array_slice($items, 0, $maxItems)) : 'Jeu gratuit';
        if ($gameId > 0) $metaCache[$cacheKey] = $result;
        return $result;
    }
}

if (!function_exists('uf_rubrique_name')) {
    function uf_rubrique_name($rubrique)
    {
        if (!is_object($rubrique) || !method_exists($rubrique, 'get')) {
            return 'Rubrique';
        }
        return $rubrique->get('nom');
    }
}

if (!function_exists('uf_rubrique_url')) {
    function uf_rubrique_url($rubrique)
    {
        if (!is_object($rubrique) || !method_exists($rubrique, 'get')) {
            return '#';
        }

        $url = $rubrique->get('url');
        if ($url) {
            return $url;
        }

        $nom = $rubrique->get('nom');
        return '/games/' . uf_slugify($nom) . '/';
    }
}

if (!function_exists('uf_rubrique_icon')) {
    function uf_rubrique_icon($nom)
    {
        $key = uf_slugify($nom);

        $map = [
            'voiture'     => '🚗',
            'sport'       => '⚽',
            'moto'        => '🏍️',
            'fille'       => '👧',
            'action'      => '🎯',
            'reflexion'   => '🧠',
            'mahjong'     => '🀄',
            'io'          => '🌐',
            'aventure'    => '🗺️',
            'arcade'      => '🕹️',
            'course'      => '🏁',
            'puzzle'      => '🧩',
            'combat'      => '🥊',
            'tir'         => '🎯',
            'strategie'   => '♟️',
            'multijoueur' => '🌍',
            'plateforme'  => '🪜',
            'zombie'      => '🧟',
            'animaux'     => '🐼',
            'enfant'      => '🧒',
            'classique'   => '🎲',
            'agilite'     => '⚡',
            'serie'       => '📚',
            'vol'         => '✈️',
            'guerre'      => '💥',
            'foot'        => '⚽',
        ];

        return isset($map[$key]) ? $map[$key] : '🎮';
    }
}

if (!function_exists('uf_rubrique_class')) {
    function uf_rubrique_class($slug)
    {
        $slug = uf_slugify($slug);

        $map = [
            'voiture' => 'uf-accent-cyan',
            'moto'    => 'uf-accent-violet',
            'foot'    => 'uf-accent-green',
            'mahjong' => 'uf-accent-orange',
            'fille'   => 'uf-accent-violet',
            'io'      => 'uf-accent-cyan',
            'action'  => 'uf-accent-green',
            'guerre'  => 'uf-accent-orange',
        ];

        return isset($map[$slug]) ? $map[$slug] : 'uf-accent-cyan';
    }
}

if (!function_exists('uf_rubrique_image')) {
    function uf_rubrique_image($nom)
    {
        $slug = uf_slugify($nom);

        $map = [
            'moto'         => '/images/rubriques/rub-moto.jpg',
            'motocross'    => '/images/rubriques/rub-motocross.jpg',
            'moto-trial'   => '/images/rubriques/rub-moto-trial.jpg',
            'zombie'       => '/images/rubriques/rub-zombie.jpg',
            'serie'        => '/images/rubriques/rub-serie.jpg',
            'populaire'    => '/images/rubriques/rub-populaire.jpg',
            'multijoueur'  => '/images/rubriques/rub-multijoueur.jpg',
            'papa-louis'   => '/images/rubriques/rub-papa-louis.jpg',
            'plateau'      => '/images/rubriques/rub-plateau.jpg',
            'arcade'       => '/images/rubriques/rub-arcade.jpg',
        ];

        if (isset($map[$slug])) {
            return $map[$slug];
        }

        return '/jeu/images/200x170UF.jpg';
    }
}

if (!function_exists('uf_count_games_in_rubrique')) {
    function uf_count_games_in_rubrique($cnx, $rubriqueId)
    {
        // Cache statique : évite une requête COUNT par rubrique (jusqu'à 24 appels sur la HP)
        static $countCache = [];

        $rubriqueId = (int)$rubriqueId;
        if ($rubriqueId <= 0) {
            return 0;
        }
        if (isset($countCache[$rubriqueId])) {
            return $countCache[$rubriqueId];
        }

        $sql = '
            SELECT COUNT(*) AS nb
            FROM flash
            WHERE etat = "actif"
              AND (
                rubrique_id = ' . $rubriqueId . '
                OR rubrique_id2 = ' . $rubriqueId . '
                OR rubrique_id3 = ' . $rubriqueId . '
                OR rubrique_id4 = ' . $rubriqueId . '
                OR rubrique_id5 = ' . $rubriqueId . '
                OR rubrique_id6 = ' . $rubriqueId . '
              )
        ';
        $cnx->Executer($sql);
        $row = $cnx->Extraire();

        $count = (int)($row['nb'] ?? 0);
        $countCache[$rubriqueId] = $count;
        return $count;
    }
}

if (!function_exists('uf_get_games_by_rubrique')) {
    function uf_get_games_by_rubrique($cnx, $rubriqueId, $limit = 5)
    {
        $rubriqueId = (int)$rubriqueId;
        $limit = (int)$limit;

        $sql = Jeu::getRequeteSQL() . '
            WHERE etat = "actif"
              AND (
                rubrique_id = ' . $rubriqueId . '
                OR rubrique_id2 = ' . $rubriqueId . '
                OR rubrique_id3 = ' . $rubriqueId . '
                OR rubrique_id4 = ' . $rubriqueId . '
                OR rubrique_id5 = ' . $rubriqueId . '
                OR rubrique_id6 = ' . $rubriqueId . '
              )
            ORDER BY id DESC
            LIMIT ' . $limit;

        $cnx->Executer($sql);

        $liste = [];
        while ($row = $cnx->Extraire()) {
            $liste[] = new Jeu($row);
        }

        return $liste;
    }
}

if (!function_exists('uf_build_game_card')) {
    function uf_build_game_card($jeu)
    {
        global $cnx;

        return [
            'title'       => uf_game_title($jeu),
            'url'         => uf_game_url($jeu),
            'image'       => uf_game_image($jeu),
            'video'       => uf_game_video_url($jeu),
            'meta'        => uf_game_preview_meta($cnx ?? null, $jeu, 5),
            'description' => uf_game_preview_description($jeu, 25),
        ];
    }
}



if (!function_exists('uf_get_category_meta')) {
    function uf_get_category_meta($cnx, $categoryId)
    {
        $categoryId = (int)$categoryId;
        if ($categoryId <= 0) {
            return null;
        }

        $cnx->Executer('SELECT id, nom FROM categorie WHERE id = ' . $categoryId . ' AND etat = "active" LIMIT 1');
        if ($row = $cnx->Extraire()) {
            return [
                'id'  => (int)($row['id'] ?? 0),
                'nom' => trim((string)($row['nom'] ?? '')),
            ];
        }

        return null;
    }
}

if (!function_exists('uf_get_games_by_category')) {
    function uf_get_games_by_category($cnx, $categoryId, $limit = 6)
    {
        $categoryId = (int)$categoryId;
        $limit = (int)$limit;

        if ($categoryId <= 0 || $limit <= 0) {
            return [];
        }

        $ids = [];
        $sqlIds = '
            SELECT flash.id
            FROM flash
            INNER JOIN liaison_categorie_flash
                ON liaison_categorie_flash.flash_id = flash.id
            WHERE liaison_categorie_flash.categorie_id = ' . $categoryId . '
              AND flash.etat = "actif"
            ORDER BY flash.id DESC
            LIMIT ' . $limit;

        $cnx->Executer($sqlIds);
        while ($row = $cnx->Extraire()) {
            $id = (int)($row['id'] ?? 0);
            if ($id > 0) {
                $ids[] = $id;
            }
        }

        if (empty($ids)) {
            return [];
        }

        // Une seule requête IN() au lieu de N requêtes individuelles
        $inClause = implode(',', $ids);
        $sqlGames = Jeu::getRequeteSQL() . ' WHERE id IN (' . $inClause . ') AND etat = "actif" ORDER BY id DESC';
        $cnx->Executer($sqlGames);

        $map = [];
        while ($row = $cnx->Extraire()) {
            $map[(int)$row['id']] = new Jeu($row);
        }

        // On restitue dans l'ordre d'origine (ORDER BY id DESC de la requête IDs)
        $liste = [];
        foreach ($ids as $id) {
            if (isset($map[$id])) {
                $liste[] = $map[$id];
            }
        }

        return $liste;
    }
}


if (!function_exists('uf_get_top_games_from_latest')) {
    /**
     * Retourne les meilleurs jeux parmi les derniers jeux ajoutés.
     * Ici, "meilleurs" = les plus ouverts/populaires parmi les 180 derniers jeux actifs.
     */
    function uf_get_top_games_from_latest($cnx, $recentLimit = 180, $limit = 10)
    {
        $recentLimit = max(1, (int)$recentLimit);
        $limit = max(1, (int)$limit);

        $ids = [];
        $sqlIds = '
            SELECT recent.id
            FROM (
                SELECT id, ouvertures, vote_up, total_votes
                FROM flash
                WHERE etat = "actif"
                  AND (
                    nomfichierswf IS NULL
                    OR nomfichierswf = ""
                    OR nomfichierswf NOT LIKE "%.swf%"
                  )
                ORDER BY id DESC
                LIMIT ' . $recentLimit . '
            ) AS recent
            ORDER BY recent.ouvertures DESC, recent.vote_up DESC, recent.total_votes DESC, recent.id DESC
            LIMIT ' . $limit;

        $cnx->Executer($sqlIds);
        while ($row = $cnx->Extraire()) {
            $id = (int)($row['id'] ?? 0);
            if ($id > 0) {
                $ids[] = $id;
            }
        }

        if (empty($ids)) {
            return [];
        }

        // Une seule requête IN() au lieu de N requêtes individuelles
        $inClause = implode(',', $ids);
        $sqlGames = Jeu::getRequeteSQL() . ' WHERE id IN (' . $inClause . ') AND etat="actif"';
        $cnx->Executer($sqlGames);

        $map = [];
        while ($row = $cnx->Extraire()) {
            $map[(int)$row['id']] = new Jeu($row);
        }

        // On restitue dans l'ordre trié par popularité (ordre d'origine des IDs)
        $liste = [];
        foreach ($ids as $id) {
            if (isset($map[$id])) {
                $liste[] = $map[$id];
            }
        }

        return $liste;
    }
}

/**
 * ------------------------------------------------------------
 * DONNÉES HOMEPAGE
 * ------------------------------------------------------------
 */
$ufDataCacheKey = 'uf:homepage:data:v17_mosaic_inline_video:' . $deviceKey;
$ufData = cache_get($ufDataCacheKey, 600); // Augmenté de 120s → 600s : le contenu HP ne change pas toutes les 2 minutes

if ($ufData !== false) {
    $ufData = @unserialize($ufData, ['allowed_classes' => false]);
}

if (!is_array($ufData)) {
    $ufData = [];

    /**
     * 1) Navigation haute
     */
    $ufTopNav = [];
    $ListeRubriquesTop = Rubrique::getAllRubrique($cnx, 'prio = "1" AND etat="active"');

    if (is_array($ListeRubriquesTop)) {
        foreach ($ListeRubriquesTop as $RubriqueTop) {
            $ufTopNav[] = [
                'label' => uf_rubrique_name($RubriqueTop),
                'url'   => uf_rubrique_url($RubriqueTop),
            ];
            if (count($ufTopNav) >= 7) {
                break;
            }
        }
    }

    $ufTopNav[] = ['label' => 'Nouveaux', 'url' => '/tous-les-jeux/'];
    $ufTopNav[] = ['label' => 'Populaires', 'url' => '/games/populaire/'];

    /**
     * 2) Hero = dernier jeu actif
     */
    $heroJeu = null;
    $sql = Jeu::getRequeteSQL() . ' WHERE etat="actif" ORDER BY id DESC LIMIT 1';
    $cnx->Executer($sql);
    if ($row = $cnx->Extraire()) {
        $heroJeu = new Jeu($row);
    }

    $ufHeroGame = [
        'title'       => $heroJeu ? uf_game_title($heroJeu) : 'Universflash',
        'url'         => $heroJeu ? uf_game_url($heroJeu) : '/',
        'image'       => $heroJeu ? uf_game_image($heroJeu) : '/jeu/images/200x170UF.jpg',
        'subtitle'    => 'Jeu du moment',
        'description' => $heroJeu
            ? 'Découvre ' . uf_game_title($heroJeu) . ', le dernier jeu ajouté sur Universflash.'
            : 'Retrouve les meilleurs jeux gratuits en ligne sur Universflash.',
    ];

    /**
     * 3) Tendances = ouvertures DESC
     */
    $ufTrendingGames = [];
    $sql = Jeu::getRequeteSQL() . '
    WHERE etat="actif"
    AND (
        nomfichierswf IS NULL 
        OR nomfichierswf = "" 
        OR nomfichierswf NOT LIKE "%.swf%"
    )
    ORDER BY ouvertures DESC, id DESC
    LIMIT 10
';
    $cnx->Executer($sql);
    $ufTrendingJeux = [];
    while ($row = $cnx->Extraire()) {
        $ufTrendingJeux[] = new Jeu($row);
    }

    foreach ($ufTrendingJeux as $jeu) {
        $ufTrendingGames[] = uf_build_game_card($jeu);
    }

/**
 * 4) Nouveaux jeux
 * Important : on ne fait PAS de requêtes annexes dans le while SQL principal.
 */
$ufLatestGames = [];
$listeDerniersJeux = [];

$latestLimit = $isMobile ? 12 : 18;
$sql = Jeu::getRequeteSQL() . ' WHERE etat="actif" ORDER BY id DESC LIMIT ' . $latestLimit;
$cnx->Executer($sql);

while ($row = $cnx->Extraire()) {
    $listeDerniersJeux[] = new Jeu($row);
}

foreach ($listeDerniersJeux as $jeu) {
    $ufLatestGames[] = uf_build_game_card($jeu);
}

    /**
     * 5) Catégories
     */
   $ufCategories = [];
$ListeRubriques = Rubrique::getAllRubrique($cnx, 'prio = "1" AND etat="active"');

if (is_array($ListeRubriques)) {
    foreach ($ListeRubriques as $RubriqueCat) {
        $rubriqueId = (int)$RubriqueCat->get('id');
        $rubriqueNom = uf_rubrique_name($RubriqueCat);
        $rubriqueSlug = uf_slugify($rubriqueNom);

        // Catégories à masquer dans "Explorer par catégorie"
        if (in_array($rubriqueSlug, ['serie', 'cinema', 'mario'])) {
            continue;
        }

        $ufCategories[] = [
            'id'    => $rubriqueId,
            'name'  => $rubriqueNom,
            'url'   => uf_rubrique_url($RubriqueCat),
            'count' => uf_count_games_in_rubrique($cnx, $rubriqueId),
            'icon'  => uf_rubrique_icon($rubriqueNom),
            'image' => uf_rubrique_image($rubriqueNom),
        ];
    }
}

    /**
     * Si trop peu de rubriques prio 1, on complète avec prio 3
     */
    if (count($ufCategories) < 12) {
        $existingIds = [];
        foreach ($ufCategories as $cat) {
            $existingIds[(int)$cat['id']] = true;
        }

        $ListeRubriquesMore = Rubrique::getAllRubrique($cnx, 'prio = "3" AND etat="active"');
        if (is_array($ListeRubriquesMore)) {
            foreach ($ListeRubriquesMore as $RubriqueCat) {
                $rubriqueId = (int)$RubriqueCat->get('id');
                if (isset($existingIds[$rubriqueId])) {
                    continue;
                }

                $ufCategories[] = [
                    'id'    => $rubriqueId,
                    'name'  => uf_rubrique_name($RubriqueCat),
                    'url'   => uf_rubrique_url($RubriqueCat),
                    'count' => uf_count_games_in_rubrique($cnx, $rubriqueId),
                    'icon'  => uf_rubrique_icon(uf_rubrique_name($RubriqueCat)),
                    'image' => uf_rubrique_image(uf_rubrique_name($RubriqueCat)),
                ];

                $existingIds[$rubriqueId] = true;

                if (count($ufCategories) >= 24) {
                    break;
                }
            }
        }
    }

    /**
     * 6) Sections thématiques
     * rubriques déjà présentes dans l'ancien index
     */
    $ufSectionDefs = [
        ['title' => 'Jeux de voiture', 'slug' => 'voiture', 'rubrique_id' => 26],
        ['title' => 'Jeux de moto', 'slug' => 'moto', 'rubrique_id' => 84],
        ['title' => 'Jeux de foot', 'slug' => 'foot', 'rubrique_id' => 32],
        ['title' => 'Jeux de mahjong', 'slug' => 'mahjong', 'rubrique_id' => 45],
        ['title' => 'Jeux IO', 'slug' => 'io', 'rubrique_id' => 92],
        ['title' => 'Jeux de fille', 'slug' => 'fille', 'rubrique_id' => 8],
    ];

    $ufSections = [];
    foreach ($ufSectionDefs as $sectionDef) {
        $items = [];
        $sectionLimit = $isMobileOrTablet ? 9 : 10;
        $listeSection = uf_get_games_by_rubrique($cnx, $sectionDef['rubrique_id'], $sectionLimit);

        foreach ($listeSection as $jeu) {
            $items[] = uf_build_game_card($jeu);
        }

        if (!empty($items)) {
            $ufSections[] = [
                'title' => $sectionDef['title'],
                'url'   => '/games/' . $sectionDef['slug'] . '/',
                'class' => uf_rubrique_class($sectionDef['slug']),
                'items' => $items,
            ];
        }
    }


    /**
     * 7) Section Coupe du monde 2026 (rubrique Foot)
     * Source : table rubrique, id 32.
     */
    $ufWorldCupSection = [];
    $worldCupItems = [];
    $worldCupLimit = 10;
    $listeWorldCup = uf_get_games_by_rubrique($cnx, 32, $worldCupLimit);

    foreach ($listeWorldCup as $jeu) {
        $worldCupItems[] = uf_build_game_card($jeu);
    }

    if (!empty($worldCupItems)) {
        $ufWorldCupSection = [
            'title' => 'Coupe du monde 2026',
            'url'   => '/t/coupe-du-monde/',
            'items' => $worldCupItems,
        ];
    }

    /**
     * 8) Top 10 des derniers jeux ajoutés
     * Sélection : les 10 jeux les plus populaires parmi les 180 derniers jeux actifs.
     */
    $ufTopRecentSection = [];
    $topRecentItems = [];
    $listeTopRecent = uf_get_top_games_from_latest($cnx, 180, 10);

    foreach ($listeTopRecent as $jeu) {
        $topRecentItems[] = uf_build_game_card($jeu);
    }

    if (!empty($topRecentItems)) {
        $ufTopRecentSection = [
            'title' => 'Top 10 populaires',
            'url'   => '/tous-les-jeux/',
            'items' => $topRecentItems,
        ];
    }

    /**
     * 8) Section Obby (catégorie/tag)
     */
    $ufObbySection = [];
    $ufObbyCategory = uf_get_category_meta($cnx, 27581);

    if (is_array($ufObbyCategory) && !empty($ufObbyCategory['nom'])) {
        $obbyItems = [];
        $obbyLimit = 10;
        $listeObby = uf_get_games_by_category($cnx, 27581, $obbyLimit);

        foreach ($listeObby as $jeu) {
            $obbyItems[] = uf_build_game_card($jeu);
        }

        if (!empty($obbyItems)) {
            $ufObbySection = [
                'title' => 'Jeux ' . uf_mb_ucfirst($ufObbyCategory['nom']),
                'url'   => '/jeux-flash/obby/0/',
                'items' => $obbyItems,
            ];
        }
    }

    /**
     * 8) Reprendre une partie
     */
$ufData = [

    'ufTopNav'        => $ufTopNav,
    'ufHeroGame'      => $ufHeroGame,
    'ufTrendingGames' => $ufTrendingGames,
    'ufLatestGames'   => $ufLatestGames,
    'ufCategories'    => $ufCategories,
    'ufSections'          => $ufSections,
    'ufWorldCupSection'   => $ufWorldCupSection,
    'ufTopRecentSection'  => $ufTopRecentSection,
    'ufObbySection'       => $ufObbySection,
];

cache_set($ufDataCacheKey, serialize($ufData));
}

$ufTopNav        = $ufData['ufTopNav'] ?? [];
$ufHeroGame      = $ufData['ufHeroGame'] ?? [];
$ufTrendingGames = $ufData['ufTrendingGames'] ?? [];
$ufLatestGames   = $ufData['ufLatestGames'] ?? [];
$ufCategories    = $ufData['ufCategories'] ?? [];
$ufSections          = $ufData['ufSections'] ?? [];
$ufWorldCupSection   = $ufData['ufWorldCupSection'] ?? [];
$ufTopRecentSection  = $ufData['ufTopRecentSection'] ?? [];
$ufObbySection       = $ufData['ufObbySection'] ?? [];

/**
 * Reprendre une partie = toujours calculé hors cache
 * car dépend du cookie utilisateur.
 */
$ufResumeGames = [];
if (!empty($listeJeuxJoues)) {
    $recentIds = array_reverse(array_slice($listeJeuxJoues, -3));

    foreach ($recentIds as $jeuId) {
        $jeuId = (int)$jeuId;
        if ($jeuId <= 0) {
            continue;
        }

        $sql = Jeu::getRequeteSQL() . ' WHERE id = ' . $jeuId . ' AND etat="actif" LIMIT 1';
        $cnx->Executer($sql);
        if ($row = $cnx->Extraire()) {
            $jeu = new Jeu($row);
            $ufResumeGames[] = [
                'title' => uf_game_title($jeu),
                'url'   => uf_game_url($jeu),
                'image' => uf_game_image($jeu),
            ];
        }
    }
}

/**
 * fallback si aucun jeu récent
 */
if (empty($ufResumeGames) && !empty($ufLatestGames)) {
    foreach (array_slice($ufLatestGames, 0, 3) as $g) {
        $ufResumeGames[] = [
            'title' => $g['title'],
            'url'   => $g['url'],
            'image' => $g['image'],
        ];
    }
}
?>
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Jeux gratuits en ligne | Universflash</title>
<meta name="description" content="Universflash vous propose une large sélection de jeux en ligne gratuits, pour tous les âges et tous les goûts. Que vous soyez fan de jeux d'action, de réflexion, de stratégie ou de sport, vous trouverez forcément votre bonheur sur notre site !">
<meta name="robots" content="index,follow">
<meta name="author" content="Priazu">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<link rel="shortcut icon" href="favicon.ico">
<link rel="alternate" href="https://www.universflash.com/" hreflang="fr"/>
<link rel="canonical" href="<?php echo WEB_RACINE; ?>" title="jeux gratuits">
<link rel="image_src" href="<?php echo WEB_RACINE; ?>images/logouniversflash.gif">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<?php /* PageSpeed mobile: pas de preload du background header, on garde le preload pour la vraie image LCP. */ ?>
<meta property="og:locale" content="fr_FR">
<meta property="og:type" content="website">
<meta property="og:title" content="Jeux gratuits en ligne | Universflash">
<meta property="og:description" content="Universflash vous propose une large sélection de jeux en ligne gratuits, pour tous les âges et tous les goûts. Que vous soyez fan de jeux d'action, de réflexion, de stratégie ou de sport, vous trouverez forcément votre bonheur sur notre site !">
<meta property="og:url" content="https://www.universflash.com/">
<meta property="og:site_name" content="Universflash.com">
<meta property="og:image" content="https://www.universflash.com/images/og-universflash.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@universflash">
<meta name="twitter:domain" content="universflash.com">
<meta name="twitter:creator" content="@universflash">
<meta name="twitter:title" content="Jeux gratuits en ligne | Universflash">
<meta name="twitter:description" content="Plus de 8000 jeux gratuits en ligne sans téléchargement. Action, voiture, moto, sport, réflexion et bien plus sur Universflash.">
<meta name="twitter:image" content="https://www.universflash.com/images/og-universflash.jpg">
<meta name="google-site-verification" content="QbhdwEs2abLya1s_gIvlNcbNa5K1Tc9dY6ad0wqPYDk" />
<meta name="google-site-verification" content="YTJgD8ruejA-IXmsx2oyIhxeUnLEFSHVpgcLRlfOTtg" />
<meta name="msvalidate.01" content="1D7AA7169BAF631DD8329290184DE91D" />
<?php
$ufPreloadImage = '';
if (!empty($ufLatestGames[0]['image'])) {
    $ufPreloadImage = uf_image_avif_url($ufLatestGames[0]['image']) ?: uf_image_fallback_url($ufLatestGames[0]['image']);
} elseif (!empty($ufHeroGame['image'])) {
    $ufPreloadImage = uf_image_avif_url($ufHeroGame['image']) ?: uf_image_fallback_url($ufHeroGame['image']);
}
if ($ufPreloadImage !== ''):
?>
<link rel="preload" as="image" href="<?= uf_h($ufPreloadImage) ?>" fetchpriority="high">
<?php endif; ?>




<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('consent', 'default', {
  ad_storage: 'denied',
  analytics_storage: 'denied',
  ad_user_data: 'denied',
  ad_personalization: 'denied',
  wait_for_update: 500
});
</script>
<script src="https://cache.consentframework.com/js/pa/25151/c/d6tod/stub"
        data-cfasync="false"
        referrerpolicy="unsafe-url"></script>
<script src="https://choices.consentframework.com/js/pa/25151/c/d6tod/cmp"
        data-cfasync="false"
        referrerpolicy="unsafe-url"
        async></script>

<style>

:root {
  --uf-bg-1: #d7efff;
  --uf-bg-2: #bfe4ff;
  --uf-bg-3: #daf1ff;
  --uf-primary: #0b72b9;
  --uf-primary-dark: #075587;
  --uf-surface: #ffffff;
  --uf-surface-2: #f6fbff;
  --uf-border: #d7ebf7;
  --uf-text: #18364a;
  --uf-muted: #5b7990;
  --uf-shadow: 0 14px 36px rgba(55, 143, 201, 0.15);
  --uf-radius-xl: 14px !important;
  --uf-radius-lg: 10px !important;
  --uf-radius-md: 6px !important;
  --uf-max: 2000px;
}
* { box-sizing: border-box; }
body {
  margin: 0;
  color: var(--uf-text);
  font-family: Arial, Helvetica, sans-serif;
  background:linear-gradient(180deg,var(--uf-bg-1),var(--uf-bg-2));
  background-color: #bfe4ff;
}
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; border: 0; }

.uf-shell {
  width: min(var(--uf-max), calc(100% - 24px));
  margin: 0 auto;
}

.uf-topbar {
  background: rgba(26,83,164);
  position: sticky;
  top: 0;
  z-index: 80;
  /* On garde le flou et les bordures sur le conteneur principal */
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.18);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.08);
  
  /* Important : on enlève l'opacity d'ici pour que le contenu reste net */
  overflow: visible; 
}

/* On crée la couche d'image de fond séparée */
.uf-topbar::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0; bottom: 0;
  z-index: -1; /* On le place derrière le contenu */
  
  /* Tes réglages d'image et de couleur */
  background: rgba(11, 114, 185, 0.8); /* Fond bleu semi-transparent */
  background-image: url('/images/header_background.avif');
  background-position: center;
  background-size: cover;
  
  /* ICI on gère la transparence de l'image uniquement */
  opacity: 0.5; 
}

.uf-topbar-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 4px 0; /* avant 14px → réduit fortement */
}
.uf-brand {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}
.uf-brand-badge {
  width: 50px;
  height: 50px;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 8px 24px rgba(0,0,0,0.14);
  font-size: 28px;
}
.uf-brand-title {
  color: #7fd3ff;
  font-size: 24px;
  line-height: 1;
  font-weight: 800;
}
.uf-brand-sub {
  display: block;
  color: #cfeefe;
  font-size: 12px;
  margin-top: 4px;
}

.uf-search input {
  width: 100%;
  height: 48px;
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.16);
  padding: 0 46px 0 16px;
  outline: none;
  color: var(--uf-text);
  background: rgba(255,255,255,0.97);
  box-shadow: 0 8px 24px rgba(0,0,0,0.08);
}
.uf-search-icon {
  position: absolute;
  right: 16px;
  top: 50%;
  transform: translateY(-50%);
  color: #547086;
  font-size: 18px;
}
.uf-nav {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding: 0 0 16px;
}
.uf-pill {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(26,83,164);
  color: #7fd3ff;
  font-size: 14px;
  font-weight: 700;
  transition: 0.2s ease;
}
.uf-pill:hover { background: rgba(255,255,255,0.22); }

.uf-ad-strip {
  padding: 10px 0 0;
}
.uf-ad-inline {
  display: flex;
  justify-content: center;
  gap: 12px;
  flex-wrap: wrap;
  min-height: 50px;
}

.uf-main { padding: 0px 0px; }

.uf-grid-hero {
  display: grid;
  grid-template-columns: minmax(0, 1.35fr) minmax(300px, .65fr);
  gap: 20px;
}

.uf-plays-games-panel {
  min-width: 0;
  overflow: hidden;
  border-radius: var(--uf-radius-xl);
  background: #07111f;
  border: 1px solid var(--uf-border);
  box-shadow: var(--uf-shadow);
}

.uf-plays-games-frame {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 620px;
  border: 0;
  background: #07111f;
}

@media (max-width: 1024px) {
  .uf-plays-games-frame {
    min-height: 720px;
  }
}

@media (max-width: 768px) {
  .uf-plays-games-panel {
    display: none;
  }
}
.uf-card {
  background: var(--uf-surface);
  border: 1px solid var(--uf-border);
  border-radius: var(--uf-radius-xl);
  box-shadow: var(--uf-shadow);
}
.uf-hero { overflow: hidden; }
.uf-hero-inner {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(280px, .9fr);
}
.uf-hero-copy {
  padding: 28px;
  color: #fff;
  background:
    radial-gradient(circle at top left, #39bdf8, transparent 45%),
    linear-gradient(135deg, #0369a1, #0f172a);
}
.uf-badge {
  display: inline-flex;
  padding: 7px 12px;
  border-radius: 999px;
  background: rgba(255,255,255,0.14);
  font-size: 11px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .18em;
  color: #d9f3ff;
}
.uf-hero-copy h1 {
  margin: 18px 0 0;
  font-size: 46px;
  line-height: 1.02;
}
.uf-hero-headline {
  margin: 18px 0 0;
  font-size: 46px;
  line-height: 1.02;
  font-weight: 800;
  color: inherit;
}
.uf-hero-copy p {
  margin: 18px 0 0;
  max-width: 680px;
  font-size: 16px;
  line-height: 1.7;
  color: #d4ecf8;
}
.uf-hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 24px;
}
.uf-btn,
.uf-btn-outline {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 46px;
  border-radius: 16px;
  padding: 10px 18px;
  font-size: 14px;
  font-weight: 800;
}
.uf-btn {
  background: #fff;
  color: #0c67a3;
  box-shadow: 0 10px 24px rgba(0,0,0,0.15);
}
.uf-btn-outline {
  border: 1px solid rgba(255,255,255,0.28);
  color: #fff;
  background: rgba(255,255,255,0.08);
}
.uf-hero-media {
  min-height: 320px;
  padding: 28px;
  background: linear-gradient(180deg,#7dd3fc,#38bdf8);
  position: relative;
}
.uf-hero-media::before {
  content: '';
  position: absolute;
  inset: 0;
  opacity: .22;
  background:
    radial-gradient(circle at 20% 20%, white 0, transparent 18%),
    radial-gradient(circle at 70% 35%, white 0, transparent 12%),
    radial-gradient(circle at 50% 70%, white 0, transparent 13%);
}
.uf-hero-frame {
  position: relative;
  margin: 10px auto 0;
  max-width: 370px;
  min-height: 260px;
  padding: 16px;
  border-radius: 26px;
  border: 1px solid rgba(255,255,255,0.32);
  background: rgba(255,255,255,0.28);
  backdrop-filter: blur(5px);
  box-shadow: 0 18px 42px rgba(0,0,0,0.18);
}
.uf-hero-poster {
  height: 100%;
  min-height: 228px;
  border-radius: 20px;
  overflow: hidden;
  background: #0f172a;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  color: #fff;
  padding: 16px;
}
.uf-hero-poster img {
  width: 100%;
  height: 180px;
  object-fit: cover;
  border-radius: 14px;
  margin-bottom: 14px;
}

.uf-section {
  margin-bottom: 8px;
  margin-top: 8px;
  padding: 0;
}

.uf-section-plain {
  padding-left: 0;
  padding-right: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}
.uf-section:first-of-type {
  margin-top: 0;
}

.uf-section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 18px;
}
.uf-section-title {
  margin: 0;
  font-size: 32px;
  line-height: 1.1;
}
.uf-section-desc {
  margin: 6px 0 0;
  color: var(--uf-muted);
  font-size: 14px;
}
.uf-light-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 42px;
  border-radius: 14px;
  padding: 10px 16px;
  background: #e5f5ff;
  color: #1170b1;
  font-size: 14px;
  font-weight: 800;
}

.uf-light-btn-nouveaux{
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: #1170b1;
  font-size: 14px;
  font-weight: 800;
}

.uf-trending-list,
.uf-resume-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.uf-trending-item,
.uf-resume-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: 18px;
  border: 1px solid #edf4f9;
  background: #f8fbfe;
}
.uf-rank {
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: linear-gradient(135deg, #38bdf8, #1d4ed8);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 14px;
  font-weight: 800;
}
.uf-item-title {
  display: block;
  font-weight: 800;
  font-size: 14px;
  color: var(--uf-text);
}
.uf-item-sub {
  display: block;
  margin-top: 4px;
  font-size: 12px;
  color: var(--uf-muted);
}
.uf-arrow {
  margin-left: auto;
  color: var(--uf-primary-dark);
  font-size: 18px;
}

.uf-games-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 8px;
}
.uf-games-slider {
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
  cursor: grab;
  padding-bottom: 4px;
}
.uf-games-slider::-webkit-scrollbar {
  display: none;
}
.uf-games-slider.is-dragging {
  cursor: grabbing;
}
.uf-games-slider-track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: calc((100% - 40px) / 6);
  gap: 8px;
}
.uf-games-slider-wrap {
  position: relative;
}
.uf-slider-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 999px;
  /* Flèches sliders : rond bleu ciel + chevron bleu foncé */
  background: var(--uf-bg-2);
  color: var(--uf-primary-dark);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: 0 10px 24px rgba(7, 85, 135, 0.18);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity .18s ease, visibility .18s ease, transform .18s ease, background .18s ease;
  z-index: 5;
  font-size: 24px;
  line-height: 1;
}

.uf-slider-arrow:hover {
  background: var(--uf-bg-1);
  color: var(--uf-primary-dark);
}
.uf-slider-arrow-left { left: 12px; }
.uf-slider-arrow-right { right: 12px; }
.uf-games-slider-wrap.has-left-arrow .uf-slider-arrow-left,
.uf-games-slider-wrap.has-right-arrow .uf-slider-arrow-right {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}
.uf-slider-arrow[disabled] {
  opacity: 0 !important;
  visibility: hidden !important;
  pointer-events: none !important;
}
.uf-game-card,
.uf-mini-game {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--uf-radius-lg);
  border: 1px solid #edf4f9;
  background: #f8fbfe;
  transition: transform .22s ease, box-shadow .22s ease;
}
.uf-game-card:hover,
.uf-mini-game:hover,
.uf-cat-card:hover,
.uf-all-link:hover {
  transform: translateY(-2px);
  box-shadow: 0 14px 28px rgba(55, 143, 201, 0.16);
}

.uf-game-card.uf-new-card {
  isolation: isolate;
}
.uf-game-card.uf-new-card::before,
.uf-game-card.uf-new-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
}
.uf-game-card.uf-new-card::before {
  inset: -1px;
  padding: 5px;
  border-radius: calc(var(--uf-radius-lg) + 1px);
  background:
    linear-gradient(110deg,
      rgba(255,255,255,0) 0%,
      rgba(255,255,255,calc(var(--uf-new-strength, 1) * .12)) 30%,
      rgba(255,255,255,calc(var(--uf-new-strength, 1) * .95)) 50%,
      rgba(255,255,255,calc(var(--uf-new-strength, 1) * .22)) 70%,
      rgba(255,255,255,0) 100%);
  background-size: 300% 100%;
  background-position: -200% 0;
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  animation: ufNewSweep 6s linear infinite;
  z-index: 4;
}
.uf-game-card.uf-new-card::after {
  inset: -1px;
  border-radius: calc(var(--uf-radius-lg) + 1px);
  box-shadow:
    0 0 0 1px rgba(255,255,255,calc(var(--uf-new-strength, 1) * .18)),
    0 0 14px rgba(255,255,255,calc(var(--uf-new-strength, 1) * .16));
  opacity: .9;
  z-index: 3;
}
.uf-new-1 { --uf-new-strength: 1; }
.uf-new-2 { --uf-new-strength: .68; }
.uf-new-3 { --uf-new-strength: .4; }
@keyframes ufNewSweep {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}
@media (prefers-reduced-motion: reduce) {
  .uf-game-card.uf-new-card::before {
    animation: none;
    background-position: 50% 0;
  }
}
.uf-thumb,
.uf-mini-thumb {
  display: block;
  width: 100%;
  object-fit: cover;
  background: linear-gradient(135deg, #8bd8ff, #2f7dc3);
  transition: transform .3s ease, filter .3s ease;
}
.uf-thumb { height: 122px; }
.uf-mini-thumb { height: 112px; }
.uf-game-body,
.uf-mini-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  min-height: 22%;
  padding: 18px 10px 10px;
  background: linear-gradient(to top, rgba(191,228,255,0.97) 0%, rgba(191,228,255,0.86) 35%, rgba(191,228,255,0) 100%);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .24s ease, transform .24s ease;
  pointer-events: none;
}
.uf-game-card:hover .uf-game-body,
.uf-mini-game:hover .uf-mini-body,
.uf-game-card:focus-visible .uf-game-body,
.uf-mini-game:focus-visible .uf-mini-body {
  opacity: 1;
  transform: translateY(0);
}
.uf-game-card:hover .uf-thumb,
.uf-mini-game:hover .uf-mini-thumb,
.uf-game-card:focus-visible .uf-thumb,
.uf-mini-game:focus-visible .uf-mini-thumb {
  transform: scale(1.05);
  filter: brightness(.82) saturate(.96) blur(.3px);
}
.uf-game-name,
.uf-mini-name {
  display: block;
  width: 100%;
  font-size: 12px;
  font-weight: 800;
  line-height: 1.2;
  color: #163247;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin: 0;
}
.uf-game-meta {
  display: none;
}
@media (hover: none), (pointer: coarse) {
  .uf-game-body,
  .uf-mini-body {
    opacity: 1;
    transform: translateY(0);
  }

  .uf-thumb,
  .uf-mini-thumb {
    filter: brightness(.92);
  }
}

.uf-cat-grid {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 12px;
}
.uf-cat-card {
  display: block;
  position: relative;
  overflow: hidden;
  border-radius: var(--uf-radius-lg);
  border: 1px solid #edf4f9;
  background: #f8fbfe;
  box-shadow: var(--uf-shadow);
  transition: transform .22s ease, box-shadow .22s ease;
}
.uf-cat-thumb {
  display: block;
  width: 100%;
  height: 104px;
  object-fit: cover;
  background: linear-gradient(135deg, #8bd8ff, #2f7dc3);
  transition: transform .3s ease, filter .3s ease;
}
.uf-cat-body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  min-height: 30%;
  padding: 18px 10px 8px;
  background: linear-gradient(to top, rgba(191,228,255,0.98) 0%, rgba(191,228,255,0.88) 42%, rgba(191,228,255,0) 100%);
  opacity: 0;
  transform: translateY(12px);
  transition: opacity .24s ease, transform .24s ease;
  pointer-events: none;
}
.uf-cat-card:hover .uf-cat-body,
.uf-cat-card:focus-visible .uf-cat-body {
  opacity: 1;
  transform: translateY(0);
}
.uf-cat-card:hover .uf-cat-thumb,
.uf-cat-card:focus-visible .uf-cat-thumb {
  transform: scale(1.05);
  filter: brightness(.82) saturate(.96) blur(.3px);
}
.uf-cat-title {
  display: block;
  width: 100%;
  margin: 0;
  font-size: 11px;
  font-weight: 800;
  line-height: 1.2;
  color: #163247;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (hover: none), (pointer: coarse) {
  .uf-cat-body {
    opacity: 1;
    transform: translateY(0);
  }

  .uf-cat-thumb {
    filter: brightness(.92);
  }
}


.uf-all-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 12px 18px;
}
.uf-all-link {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 13px 14px;
  border-radius: 16px;
  background: #f8fbfe;
  border: 1px solid #edf4f9;
  font-size: 14px;
  font-weight: 700;
  color: #355267;
}
.uf-all-left {
  display: flex;
  align-items: center;
  gap: 10px;
}
.uf-all-count {
  color: #94a8b8;
  font-size: 12px;
  font-weight: 700;
}

.uf-sections-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px;
  margin-top: 0; /* correction : évite que les blocs rubriques soient rognés en haut */
}
.uf-block-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 18px;
  color: #fff;
}
.uf-block-title {
  margin: 0;
  font-size: 26px;
}
.uf-accent-cyan .uf-block-head { background: linear-gradient(90deg, #14b8a6, #0369a1); }
.uf-accent-violet .uf-block-head { background: linear-gradient(90deg, #d946ef, #6d28d9); }
.uf-accent-green .uf-block-head { background: linear-gradient(90deg, #10b981, #0f766e); }
.uf-accent-orange .uf-block-head { background: linear-gradient(90deg, #f59e0b, #ea580c); }
.uf-block-body {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 14px;
  padding: 8px;
}

.uf-two-cols {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(320px, .9fr);
  gap: 20px;
}
.uf-seo-box {
  padding: 26px;
  border-radius: var(--uf-radius-xl);
  color: #fff;
  background: linear-gradient(135deg, #0762a1, #0f2d56);
  box-shadow: var(--uf-shadow);
}
.uf-seo-box h2,
.uf-resume-box h2 {
  margin: 16px 0 0;
  font-size: 38px;
  line-height: 1.05;
}
.uf-seo-box p,
.uf-resume-box p {
  margin-top: 16px;
  font-size: 15px;
  line-height: 1.8;
}
.uf-tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 20px;
}
.uf-tag {
  display: inline-flex;
  padding: 10px 14px;
  border-radius: 999px;
  background: rgba(255,255,255,0.12);
  color: #fff;
  font-size: 13px;
  font-weight: 800;
}

.uf-resume-box { padding: 22px; }
.uf-resume-thumb {
  width: 48px;
  height: 48px;
  border-radius: 14px;
  overflow: hidden;
  flex: 0 0 auto;
  background: linear-gradient(135deg, #9ae6ff, #2563eb);
}
.uf-resume-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.uf-footer {
  margin-top: 34px;
  background: #0b2341;
  color: #cbe1ef;
  border-top: 1px solid rgba(255,255,255,0.15);
}
.uf-footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 28px;
  padding: 36px 0;
}
.uf-footer-title {
  color: #fff;
  font-size: 22px;
  font-weight: 800;
}
.uf-footer-head {
  color: #fff;
  font-weight: 800;
  margin-bottom: 12px;
}
.uf-footer-list a,
.uf-footer-list span {
  display: block;
  margin-bottom: 9px;
  font-size: 14px;
  color: #cbe1ef;
}
.uf-mobile-search { display: none; }

@media (max-width: 1024px) {
  /* Mobile/tablette : on garde les flèches visibles pour les sliders Top 10 + Jeux Obby */
  .uf-games-slider-wrap .uf-slider-arrow {
    display: flex;
    width: 32px;
    height: 32px;
    font-size: 22px;
  }

  .uf-games-slider-wrap .uf-slider-arrow-left { left: 6px; }
  .uf-games-slider-wrap .uf-slider-arrow-right { right: 6px; }
}

@media (max-width: 1279px) {
  .uf-cat-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .uf-games-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .uf-block-body { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
@media (max-width: 1024px) {
  .uf-grid-hero,
  .uf-sections-grid,
  .uf-two-cols,
  .uf-footer-grid,
  .uf-hero-inner {
    grid-template-columns: 1fr;
  }
  .uf-all-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .uf-cat-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .uf-games-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .uf-block-body { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .uf-hero-copy h1, .uf-hero-headline { font-size: 38px; }
}
@media (max-width: 1024px) {
  .uf-games-slider-track { grid-auto-columns: calc((100% - 16px) / 3); }
}
@media (max-width: 768px) {
  .uf-section:first-of-type {
  margin-top: 8px;
}
  .uf-shell { width: min(var(--uf-max), calc(100% - 16px)); }
  .uf-topbar-row { padding: 12px 0; }
  .uf-search { display: none; }
  .uf-mobile-search { display: block; padding: 0 0 14px; }
  .uf-mobile-search .uf-search { display: block; max-width: none; margin: 0; }
  .uf-nav {
    overflow-x: auto;
    flex-wrap: nowrap;
    padding-bottom: 14px;
    scrollbar-width: none;
  }
  .uf-nav::-webkit-scrollbar { display: none; }
  .uf-pill { white-space: nowrap; }
  .uf-main { padding-top: 16px; }
  .uf-section {}
  .uf-section-head { align-items: flex-start; flex-direction: column; }
  .uf-section-title { font-size: 26px; }
  .uf-hero-copy,
  .uf-hero-media,
  .uf-seo-box,
  .uf-resume-box { padding: 18px; }
  .uf-hero-copy h1, .uf-hero-headline { font-size: 30px; }
  .uf-hero-copy p { font-size: 14px; }
  .uf-hero-frame { max-width: 100%; min-height: 0; }
  .uf-games-grid,
  .uf-cat-grid,
  .uf-all-grid,
  .uf-block-body { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .uf-thumb { height: 110px; }
  .uf-seo-box h2,
  .uf-resume-box h2 { font-size: 28px; }
  .uf-footer-grid { grid-template-columns: 1fr; padding: 28px 0; }
}
@media (max-width: 520px) {
  .uf-brand-title { font-size: 20px; }
  .uf-brand-badge { width: 44px; height: 44px; font-size: 24px; }
  .uf-games-grid,
  .uf-cat-grid,
  .uf-all-grid,
  .uf-block-body { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .uf-thumb { height: 110px; }
  .uf-mini-thumb { height: 100px; }
  .uf-cat-thumb { height: 95px; }
}
.uf-home-seo{
font-size:15px;
line-height:1.8;
}
.uf-hero-seo {
  padding: 28px 30px 32px;
  background: #fff;
  color: #243f54;
  border-top: 1px solid #e7f0f7;
  border-bottom-left-radius: var(--uf-radius-xl);
  border-bottom-right-radius: var(--uf-radius-xl);
}

.uf-hero-seo h2 {
  margin: 0 0 16px;
  font-size: 28px;
  line-height: 1.15;
  color: #1f3d53;
}

.uf-hero-seo p {
  margin: 0 0 14px;
  font-size: 15px;
  line-height: 1.8;
  color: #355267;
}

.uf-hero-seo a {
  color: #0f78bc;
  text-decoration: none;
  font-weight: 700;
}

.uf-hero-seo a:hover {
  text-decoration: underline;
}

@media (max-width: 768px) {
  .uf-hero-seo {
    padding: 20px 18px 22px;
  }

  .uf-hero-seo h2 {
    font-size: 23px;
  }

  .uf-hero-seo p {
    font-size: 14px;
    line-height: 1.75;
  }
}
.uf-search {
  flex: 1;
  max-width: 260px;
  margin-left: auto;
  position: relative;
}


.uf-search input {
  width: 100%;
  height: 48px;
  border-radius: 16px;
  border: 1px solid rgba(255,255,255,0.16);
  padding: 0 52px 0 16px;
  outline: none;
  color: var(--uf-text);
  background: rgba(255,255,255,0.97);
  box-shadow: 0 8px 24px rgba(0,0,0,0.08);
}

.uf-search-submit {
  position: absolute;
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
  border: 0;
  background: transparent;
  cursor: pointer;
  font-size: 18px;
  color: #547086;
  width: 32px;
  height: 32px;
  padding: 0;
}

.uf-search-icon {
  display: none;
}

.uf-search-suggest {
  display: none;
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  right: 0;
  background: #fff;
  border-radius: 18px;
  box-shadow: 0 16px 40px rgba(0,0,0,.14);
  overflow: hidden;
  z-index: 120;
  border: 1px solid #e7f0f7;
}

.uf-search-suggest.is-open {
  display: block;
}

.uf-search-suggest a {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-bottom: 1px solid #eef4f8;
  text-decoration: none;
  color: #18364a;
  background: #fff;
}

.uf-search-suggest a:last-child {
  border-bottom: 0;
}

.uf-search-suggest a:hover {
  background: #f7fbff;
}

.uf-search-suggest img {
  width: 56px;
  height: 42px;
  object-fit: cover;
  border-radius: 10px;
  flex: 0 0 auto;
}

.uf-search-suggest strong {
  display: block;
  font-size: 14px;
  line-height: 1.3;
}

.uf-search-suggest span {
  display: block;
  font-size: 12px;
  color: #6b8397;
  margin-top: 3px;
}

@media (max-width: 768px) {
  .uf-search-suggest a {
    padding: 12px;
  }

  .uf-search-suggest img {
    width: 52px;
    height: 40px;
  }
}

@media (max-width: 768px) {
  .uf-topbar {
    position: static;
    top: auto;
  }
}

html, body {
  max-width: 100%;
  overflow-x: hidden;
}

.uf-shell,
.uf-main,
.uf-grid-hero,
.uf-sections-grid,
.uf-two-cols {
  max-width: 100%;
}

.uf-all-link,
.uf-all-left,
.uf-trending-item,
.uf-resume-item,
.uf-section-head,
.uf-block-head {
  min-width: 0;
}

.uf-all-left span:last-child,
.uf-item-title,
.uf-item-sub,
.uf-section-title,
.uf-block-title {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 768px) {
  .uf-shell {
    width: calc(100% - 16px);
    max-width: 100%;
  }
}

@media (max-width: 560px){
  .uf-games-grid,
  .uf-cat-grid,
  .uf-all-grid,
  .uf-trend-grid,
  .uf-mini-grid,
  .uf-grid-games{
    grid-template-columns:repeat(3, minmax(0,1fr)) !important;
    gap:8px !important;
  }

  .uf-game-card,
  .uf-cat-card,
  .uf-trend-card,
  .uf-mini-card,
  .uf-all-card,
  .uf-card-game,
  .uf-mini-game{
    display:flex !important;
    flex-direction:column !important;
    align-items:stretch !important;
    background:transparent !important;
    border:0 !important;
    box-shadow:none !important;
    border-radius:0 !important;
    padding:0 !important;
    margin:0 !important;
    min-height:auto !important;
    height:auto !important;
    overflow:visible !important;
    transform:none !important;
  }

  .uf-game-card::before,
  .uf-game-card::after,
  .uf-cat-card::before,
  .uf-cat-card::after,
  .uf-trend-card::before,
  .uf-trend-card::after,
  .uf-mini-card::before,
  .uf-mini-card::after,
  .uf-all-card::before,
  .uf-all-card::after,
  .uf-mini-game::before,
  .uf-mini-game::after,
  .uf-game-card.uf-new-card::before,
  .uf-game-card.uf-new-card::after,
  .uf-new-1::before,
  .uf-new-1::after,
  .uf-new-2::before,
  .uf-new-2::after,
  .uf-new-3::before,
  .uf-new-3::after{
    content:none !important;
    display:none !important;
    animation:none !important;
    background:none !important;
    box-shadow:none !important;
  }

  .uf-game-card:hover,
  .uf-cat-card:hover,
  .uf-trend-card:hover,
  .uf-mini-card:hover,
  .uf-all-card:hover,
  .uf-card-game:hover,
  .uf-mini-game:hover,
  .uf-all-link:hover{
    transform:none !important;
    box-shadow:none !important;
  }

  .uf-thumb,
  .uf-cat-thumb,
  .uf-trend-thumb,
  .uf-mini-thumb,
  .uf-all-thumb{
    display:block !important;
    width:100% !important;
    height:auto !important;
    aspect-ratio:1 / 1 !important;
    object-fit:cover !important;
    border-radius:16px !important;
    overflow:hidden !important;
    background:none !important;
    border:0 !important;
    box-shadow:none !important;
    transform:none !important;
    filter:none !important;
  }

  .uf-thumb img,
  .uf-cat-thumb img,
  .uf-trend-thumb img,
  .uf-mini-thumb img,
  .uf-all-thumb img{
    width:100% !important;
    height:100% !important;
    object-fit:cover !important;
    display:block !important;
    border-radius:16px !important;
  }

  .uf-game-card:hover .uf-thumb,
  .uf-cat-card:hover .uf-cat-thumb,
  .uf-trend-card:hover .uf-trend-thumb,
  .uf-mini-card:hover .uf-mini-thumb,
  .uf-mini-game:hover .uf-mini-thumb,
  .uf-game-card:focus-visible .uf-thumb,
  .uf-cat-card:focus-visible .uf-cat-thumb,
  .uf-trend-card:focus-visible .uf-trend-thumb,
  .uf-mini-card:focus-visible .uf-mini-thumb,
  .uf-mini-game:focus-visible .uf-mini-thumb{
    transform:none !important;
    filter:none !important;
  }

  .uf-game-body,
  .uf-cat-body,
  .uf-trend-body,
  .uf-mini-body,
  .uf-all-body{
    position:static !important;
    left:auto !important;
    right:auto !important;
    bottom:auto !important;
    z-index:auto !important;
    display:block !important;
    min-height:auto !important;
    height:auto !important;
    padding:6px 0 0 !important;
    margin:0 !important;
    background:transparent !important;
    border:0 !important;
    box-shadow:none !important;
    opacity:1 !important;
    transform:none !important;
    overflow:visible !important;
    pointer-events:auto !important;
  }

  .uf-game-name,
  .uf-cat-title,
  .uf-trend-name,
  .uf-mini-name,
  .uf-all-title{
    display:block !important;
    position:static !important;
    width:100% !important;
    min-height:18px !important;
    margin:0 !important;
    padding:0 2px !important;
    font-size:11px !important;
    font-weight:800 !important;
    line-height:1.3 !important;
    color:#163247 !important;
    text-align:center !important;
    white-space:nowrap !important;
    overflow:hidden !important;
    text-overflow:ellipsis !important;
    box-sizing:border-box !important;
    opacity:1 !important;
    transform:none !important;
    pointer-events:auto !important;
  }
}

/* Sliders mobile : flèches activées aussi sur Top 10 populaires et Jeux Obby */
@media (max-width: 1024px) {
  .uf-games-slider-wrap.has-left-arrow .uf-slider-arrow-left,
  .uf-games-slider-wrap.has-right-arrow .uf-slider-arrow-right {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }
}

/* Ajustement Universflash : espace uniforme autour des blocs Top récent / Jeux Obby */
.uf-obby-section-tight {
  position: relative;
}
@media (max-width: 720px) {
  .uf-obby-section-tight {
    margin-top: 8px !important;
  }
}


/* ============================================================
   Universflash - optimisation mobile PageSpeed V2
   Objectif : réduire le coût de rendu mobile sans toucher au consentement.
   ============================================================ */
.uf-defer-render {
  content-visibility: auto;
  contain-intrinsic-size: 1px 900px;
}

@media (max-width: 768px) {
  body {
    background: #bfe4ff;
  }

  .uf-topbar {
    background:
      linear-gradient(rgba(26,83,164,.62), rgba(26,83,164,.62)),
      url('/images/header_background.avif') center / cover no-repeat !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    box-shadow: none !important;
  }

  .uf-topbar::before {
    background-image: none !important;
    opacity: 0 !important;
  }

  .uf-card,
  .uf-cat-card,
  .uf-game-card,
  .uf-mini-game,
  .uf-all-link,
  .uf-trending-item,
  .uf-resume-item,
  .uf-seo-box,
  .uf-resume-box {
    box-shadow: none !important;
  }

  .uf-game-card,
  .uf-mini-game,
  .uf-cat-card,
  .uf-all-link,
  .uf-thumb,
  .uf-mini-thumb,
  .uf-cat-thumb,
  .uf-game-body,
  .uf-mini-body,
  .uf-cat-body,
  .uf-slider-arrow {
    transition: none !important;
    animation: none !important;
  }

  .uf-game-card:hover,
  .uf-mini-game:hover,
  .uf-cat-card:hover,
  .uf-all-link:hover,
  .uf-game-card:focus-visible,
  .uf-mini-game:focus-visible,
  .uf-cat-card:focus-visible {
    transform: none !important;
  }

  .uf-game-card:hover .uf-thumb,
  .uf-mini-game:hover .uf-mini-thumb,
  .uf-cat-card:hover .uf-cat-thumb,
  .uf-game-card:focus-visible .uf-thumb,
  .uf-mini-game:focus-visible .uf-mini-thumb,
  .uf-cat-card:focus-visible .uf-cat-thumb {
    transform: none !important;
    filter: none !important;
  }

  .uf-thumb,
  .uf-mini-thumb,
  .uf-cat-thumb {
    filter: none !important;
  }

  .uf-section {
    margin-top: 8px;
    margin-bottom: 8px;
  }

  .uf-defer-render {
    contain-intrinsic-size: 1px 760px;
  }
}

@media (max-width: 560px) {
  .uf-defer-render {
    contain-intrinsic-size: 1px 680px;
  }
}



/* Aperçu desktop façon Prime Video au survol des vignettes */
.uf-hover-preview {
  position: fixed;
  z-index: 99990;
  width: 336px;
  max-width: calc(100vw - 28px);
  border-radius: 18px;
  overflow: hidden;
  background: #050910;
  color: #fff;
  box-shadow: 0 24px 70px rgba(0,0,0,.55), 0 0 0 1px rgba(255,255,255,.08);
  opacity: 0;
  transform: translateY(16px) scale(.6);
  pointer-events: none;
  transition: opacity .65s ease, transform .85s cubic-bezier(.16, 1, .3, 1);
}

.uf-hover-preview.is-visible {
  opacity: 1;
  transform: translateY(0) scale(1);
  pointer-events: auto;
}

.uf-hover-preview-media {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 3 / 2;
  overflow: hidden;
  background: #101827;
  border-radius: 18px 18px 0 0;
}

.uf-hover-preview-media::after { display:none; }

.uf-hover-preview-img,
.uf-hover-preview-video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  background: #101827;
}

.uf-hover-preview-video {
  display: none;
  object-fit: cover;
  object-position: center center;
}

.uf-hover-preview.has-video .uf-hover-preview-img {
  display: none;
}

.uf-hover-preview.has-video .uf-hover-preview-video {
  display: block;
}

.uf-hover-preview-content {
  padding: 14px 16px 16px;
}

.uf-hover-preview-title {
  display: block;
  font-size: 22px;
  line-height: 1.12;
  font-weight: 900;
  letter-spacing: .01em;
  margin-bottom: 7px;
}

.uf-hover-preview-meta {
  display: block;
  color: #7fd3ff;
  font-size: 13px;
  line-height: 1.35;
  font-weight: 400;
  margin-bottom: 12px;
}

.uf-hover-preview-actions {
  display: flex;
  align-items: center;
  gap: 9px;
  margin-bottom: 12px;
}

.uf-hover-preview-action {
  width: 39px;
  height: 39px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,255,255,.16);
  border: 1px solid rgba(255,255,255,.18);
  font-size: 21px;
  font-weight: 800;
}

.uf-hover-preview-action.uf-play {
  width: auto;
  padding: 0 16px;
  background: linear-gradient(135deg,#2ea8ff,#6dd7ff);
  color: #fff;
  font-size: 14px;
}

.uf-hover-preview-desc {
  margin: 0;
  color: #fff;
  font-size: 13px;
  line-height: 1.35;
  font-weight: 400;
}

@media (max-width: 900px), (hover: none) {
  .uf-hover-preview { display: none !important; }
}


/* ============================================================
   Universflash - PageSpeed mobile LCP V4
   - moins d'images eager au-dessus de la ligne de flottaison
   - sections sous le premier écran différées
   - simplification mobile sans toucher au CMP
   ============================================================ */
@media (max-width: 768px) {
  .uf-page-home.uf-mobile-lite .uf-section:not(:first-of-type),
  .uf-page-home.uf-mobile-lite .uf-grid-hero,
  .uf-page-home.uf-mobile-lite .uf-sections-grid,
  .uf-page-home.uf-mobile-lite .uf-two-cols {
    content-visibility: auto;
    contain-intrinsic-size: 1px 620px;
  }

  .uf-page-home.uf-mobile-lite .uf-section:first-of-type {
    content-visibility: visible;
    contain: none;
  }

  .uf-page-home.uf-mobile-lite .uf-home-wide-slider,
  .uf-page-home.uf-mobile-lite .uf-explore-categories,
  .uf-page-home.uf-mobile-lite .uf-seo-box,
  .uf-page-home.uf-mobile-lite .uf-resume-box {
    contain: layout paint style;
  }

  .uf-page-home.uf-mobile-lite .uf-section {
    margin-top: 8px !important;
    margin-bottom: 12px !important;
  }
}

@media (max-width: 560px) {
  .uf-page-home.uf-mobile-lite .uf-section:not(:first-of-type),
  .uf-page-home.uf-mobile-lite .uf-grid-hero,
  .uf-page-home.uf-mobile-lite .uf-sections-grid,
  .uf-page-home.uf-mobile-lite .uf-two-cols {
    contain-intrinsic-size: 1px 560px;
  }
}

</style>
<script type="application/ld+json">
[
  {
    "@context": "https://schema.org",
    "@type": "WebSite",
    "name": "Universflash",
    "url": "https://www.universflash.com/",
    "description": "Portail de jeux en ligne gratuits depuis 2004. Plus de 8000 jeux sans téléchargement.",
    "inLanguage": "fr-FR",
    "potentialAction": {
      "@type": "SearchAction",
      "target": "https://www.universflash.com/recherche.php?q={search_term_string}",
      "query-input": "required name=search_term_string"
    }
  },
  {
    "@context": "https://schema.org",
    "@type": "Organization",
    "name": "Universflash",
    "url": "https://www.universflash.com/",
    "logo": {
      "@type": "ImageObject",
      "url": "https://www.universflash.com/images/logouniversflash.gif"
    },
    "foundingDate": "2004",
    "description": "Portail de jeux gratuits en ligne depuis 2004. Plus de 8000 jeux accessibles sans téléchargement sur ordinateur, tablette et mobile.",
    "sameAs": [
      "https://twitter.com/universflash"
    ]
  },
  {
    "@context": "https://schema.org",
    "@type": "ItemList",
    "name": "Nouveaux jeux gratuits en ligne",
    "description": "Les derniers jeux ajoutés sur Universflash",
    "url": "https://www.universflash.com/tous-les-jeux/",
    "numberOfItems": <?= count($ufLatestGames) ?>,
    "itemListElement": [
      <?php foreach (array_slice($ufLatestGames, 0, 10) as $i => $game): ?>
      {
        "@type": "ListItem",
        "position": <?= $i + 1 ?>,
        "name": <?= json_encode($game['title'], JSON_UNESCAPED_UNICODE) ?>,
        "url": "https://www.universflash.com<?= uf_h($game['url']) ?>"
      }<?= $i < min(9, count($ufLatestGames) - 1) ? ',' : '' ?>
      <?php endforeach; ?>
    ]
  }
]
</script>


<style id="uf-slider-vertical-bars-v24">
@media (min-width: 1025px){
  .uf-games-slider-wrap{position:relative!important;overflow:visible!important;z-index:40!important;}
  .uf-slider-arrow{
    top:0!important;transform:none!important;width:44px!important;min-height:122px!important;
    border-radius:0!important;border:0!important;background:rgba(191,228,255,.55)!important;color:#075587!important;box-shadow:none!important;
    opacity:0!important;visibility:hidden!important;pointer-events:none!important;z-index:10050!important;font-size:34px!important;line-height:1!important;
    backdrop-filter:blur(3px);-webkit-backdrop-filter:blur(3px);
  }
  .uf-slider-arrow:hover{background:rgba(191,228,255,.82)!important;color:#063f66!important;}
  .uf-games-slider-wrap.has-left-arrow .uf-slider-arrow-left,
  .uf-games-slider-wrap.has-right-arrow .uf-slider-arrow-right{opacity:1!important;visibility:visible!important;pointer-events:auto!important;}
  .uf-slider-arrow-left{left:0!important;border-top-left-radius:12px!important;border-bottom-left-radius:12px!important;}
  .uf-slider-arrow-right{right:0!important;border-top-right-radius:12px!important;border-bottom-right-radius:12px!important;}
  .uf-slider-arrow::before{content:"";position:absolute;inset:0;}
  .uf-game-preview,.uf-game-preview-card,.uf-prime-preview,.uf-hover-preview,[class*="preview"]{z-index:9000!important;}
}
@media (max-width: 1024px){
  .uf-slider-arrow{width:34px!important;height:34px!important;min-height:1px!important;border-radius:999px!important;}
}
</style>



<style id="uf-explore-categories-css-v34">
/* Style isolé uniquement pour le bloc “Explorer par catégorie”.
   Comportement aligné avec jeux.php : dégradé + titre masqués au repos,
   puis apparition au survol avec remontée depuis le bas. */
.uf-explore-categories .uf-cat-card{
  display:block;
  position:relative;
  overflow:hidden;
  border-radius:18px;
  border:1px solid #edf4f9;
  background:#f8fbfe;
  box-shadow:0 6px 14px rgba(15,40,70,.06);
  transition:transform .22s ease, box-shadow .22s ease;
}

.uf-explore-categories .uf-cat-thumb{
  display:block;
  width:100%;
  height:104px;
  object-fit:cover;
  background:linear-gradient(135deg,#8bd8ff,#2f7dc3);
  transition:transform .3s ease, filter .3s ease;
}

.uf-explore-categories .uf-cat-body{
  position:absolute !important;
  left:0 !important;
  right:0 !important;
  bottom:0 !important;
  z-index:2 !important;
  display:flex !important;
  align-items:flex-end !important;
  min-height:30% !important;
  height:auto !important;
  padding:18px 10px 8px !important;
  margin:0 !important;
  background:linear-gradient(to top, rgba(191,228,255,0.98) 0%, rgba(191,228,255,0.88) 42%, rgba(191,228,255,0) 100%) !important;
  border:0 !important;
  box-shadow:none !important;
  opacity:0 !important;
  visibility:visible !important;
  transform:translateY(12px) !important;
  transition:opacity .24s ease, transform .24s ease !important;
  pointer-events:none !important;
}

.uf-explore-categories .uf-cat-card:hover .uf-cat-body,
.uf-explore-categories .uf-cat-card:focus-visible .uf-cat-body{
  opacity:1 !important;
  transform:translateY(0) !important;
}

.uf-explore-categories .uf-cat-card:hover .uf-cat-thumb,
.uf-explore-categories .uf-cat-card:focus-visible .uf-cat-thumb{
  transform:scale(1.05);
  filter:brightness(.82) saturate(.96) blur(.3px);
}

.uf-explore-categories .uf-cat-title{
  display:block !important;
  width:100% !important;
  margin:0 !important;
  padding:0 !important;
  font-size:11px !important;
  font-weight:800 !important;
  line-height:1.2 !important;
  color:#163247 !important;
  text-align:left !important;
  white-space:nowrap !important;
  overflow:hidden !important;
  text-overflow:ellipsis !important;
  text-shadow:none !important;
  opacity:1 !important;
  transform:none !important;
}

@media (hover:none), (pointer:coarse){
  .uf-explore-categories .uf-cat-body{
    opacity:1 !important;
    transform:translateY(0) !important;
  }
}

@media (max-width:560px){
  .uf-explore-categories .uf-cat-body{
    padding:18px 8px 7px !important;
  }
}
</style>


<style id="uf-hover-preview-speed-v32">
.uf-hover-preview{
  transition:
    opacity .65s ease,
    transform .85s cubic-bezier(.16, 1, .3, 1) !important;
}
</style>


<style>
.uf-footer-tags,
.uf-bottom-categories,
.footer-categories,
.footer-rubriques{
    display:none !important;
}
</style>



<style id="uf-hover-preview-no-blue-overlay-v1">
.uf-game-card:hover .uf-game-body,
.uf-mini-game:hover .uf-mini-body{
  opacity:0 !important;
  transform:translateY(12px) !important;
}
</style>

<style id="uf-trending-slider-card-rank-v1">
.uf-trending-slider { min-width: 0; }
.uf-trending-slider .uf-game-card { position: relative; }
.uf-rank-on-card {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 3;
  width: 28px;
  height: 28px;
  border-radius: 999px;
  background: rgba(10, 37, 64, .82);
  color: #fff;
  font-size: 13px;
}
</style>



<style id="uf-slider-arrow-radius-fix-v25">
/* Correctif Universflash : alignement des voiles de flèche + coins arrondis stables après clic/scroll */
.uf-game-card,
.uf-mini-game {
  border-radius: var(--uf-radius-lg) !important;
  overflow: hidden !important;
  clip-path: inset(0 round var(--uf-radius-lg));
  -webkit-mask-image: -webkit-radial-gradient(white, black);
}

.uf-thumb,
.uf-mini-thumb {
  border-radius: inherit !important;
}

@media (min-width: 1025px) {
  .uf-games-slider-wrap {
    overflow: hidden !important;
    border-radius: var(--uf-radius-lg);
  }

  .uf-games-slider {
    overflow-x: auto !important;
    overflow-y: hidden !important;
    border-radius: var(--uf-radius-lg);
  }

  .uf-slider-arrow {
    top: 0 !important;
    bottom: auto !important;
    height: 122px !important;
    min-height: 122px !important;
    transform: none !important;
    overflow: hidden !important;
    background-clip: padding-box !important;
    -webkit-mask-image: -webkit-radial-gradient(white, black);
  }

  .uf-slider-arrow-left {
    left: 0 !important;
    border-radius: var(--uf-radius-lg) 0 0 var(--uf-radius-lg) !important;
  }

  .uf-slider-arrow-right {
    right: 0 !important;
    border-radius: 0 var(--uf-radius-lg) var(--uf-radius-lg) 0 !important;
  }

  .uf-slider-arrow:active,
  .uf-slider-arrow:focus,
  .uf-slider-arrow:focus-visible {
    transform: none !important;
    outline: none !important;
  }
}
</style>

<style id="uf-home-thumb-ratio-desktop-mobile-radius-v1">/* ============================================================
   Universflash - ratios vignettes HP desktop + arrondis mobile V1
   - Desktop uniquement : conserve le ratio rectangle des blocs
     Nouveaux jeux, Top 10 populaires, Jeux Obby et Tendances.
   - Mobile : force les 4 coins arrondis sur les vignettes des blocs
     jeux + rubriques HP.
   ============================================================ */
@media (min-width: 769px) {
  .uf-page-home .uf-home-wide-new .uf-game-card,
  .uf-page-home .uf-home-wide-slider .uf-game-card,
  .uf-page-home .uf-trending-slider .uf-game-card {
    aspect-ratio: auto !important;
    height: auto !important;
  }

  .uf-page-home .uf-home-wide-new .uf-thumb,
  .uf-page-home .uf-home-wide-slider .uf-thumb,
  .uf-page-home .uf-trending-slider .uf-thumb {
    width: 100% !important;
    height: auto !important;
    aspect-ratio: 1.69 / 1 !important;
    object-fit: cover !important;
    display: block !important;
  }

  .uf-page-home .uf-home-wide-slider .uf-slider-arrow,
  .uf-page-home .uf-trending-slider .uf-slider-arrow {
    top: 0 !important;
    bottom: 0 !important;
    height: auto !important;
    min-height: 0 !important;
  }
}

@media (max-width: 560px) {
  .uf-page-home .uf-home-wide-new .uf-game-card,
  .uf-page-home .uf-home-wide-slider .uf-game-card,
  .uf-page-home .uf-trending-slider .uf-game-card,
  .uf-page-home .uf-sections-grid .uf-mini-game,
  .uf-page-home .uf-block-body .uf-mini-game {
    overflow: visible !important;
    border-radius: 0 !important;
    clip-path: none !important;
    -webkit-mask-image: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-thumb,
  .uf-page-home .uf-home-wide-slider .uf-thumb,
  .uf-page-home .uf-trending-slider .uf-thumb,
  .uf-page-home .uf-sections-grid .uf-mini-thumb,
  .uf-page-home .uf-block-body .uf-mini-thumb {
    aspect-ratio: 1 / 1 !important;
    height: auto !important;
    width: 100% !important;
    object-fit: cover !important;
    border-radius: 16px !important;
    overflow: hidden !important;
    clip-path: inset(0 round 16px) !important;
    -webkit-mask-image: -webkit-radial-gradient(white, black) !important;
  }

  .uf-page-home .uf-home-wide-new .uf-thumb img,
  .uf-page-home .uf-home-wide-slider .uf-thumb img,
  .uf-page-home .uf-trending-slider .uf-thumb img,
  .uf-page-home .uf-sections-grid .uf-mini-thumb img,
  .uf-page-home .uf-block-body .uf-mini-thumb img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    border-radius: 16px !important;
  }
}
</style>


<style id="uf-home-thumb-radius-mobile-tablet-v1">/* Complément mobile/tablette : coins arrondis conservés jusqu'à 768px */
@media (max-width: 768px) {
  .uf-page-home .uf-home-wide-new .uf-thumb,
  .uf-page-home .uf-home-wide-slider .uf-thumb,
  .uf-page-home .uf-trending-slider .uf-thumb,
  .uf-page-home .uf-sections-grid .uf-mini-thumb,
  .uf-page-home .uf-block-body .uf-mini-thumb {
    border-radius: 16px !important;
    overflow: hidden !important;
    clip-path: inset(0 round 16px) !important;
    -webkit-mask-image: -webkit-radial-gradient(white, black) !important;
  }
}
</style>


<style id="uf-new-games-mosaic-v7">
/* ============================================================
   Universflash - mosaïque Nouveaux jeux V7
   Desktop : grosses vignettes sans Prime + vidéo inline + dégradé au survol.
   Mobile : ratio type Top 10, titres sous les images, + ligne de 3 petites.
   ============================================================ */
.uf-page-home .uf-home-wide-new .uf-new-games-mosaic {
  display: grid !important;
  gap: 8px !important;
  grid-auto-flow: row !important;
}

.uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-inline-video {
  display: none;
}

@media (min-width: 769px) {
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic {
    grid-template-columns: repeat(6, minmax(0, 1fr)) !important;
    grid-auto-rows: calc((min(2000px, calc(100vw - 24px)) - 40px) / 6 / 1.69) !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card {
    height: 100% !important;
    min-height: 0 !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-thumb {
    width: 100% !important;
    height: 100% !important;
    aspect-ratio: auto !important;
    object-fit: cover !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible {
    transform: none !important;
    box-shadow: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large.uf-new-card::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large.uf-new-card::after,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large::after {
    content: none !important;
    display: none !important;
    animation: none !important;
    box-shadow: none !important;
    background: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large .uf-mosaic-inline-video {
    position: absolute;
    inset: 0;
    z-index: 1;
    width: 100%;
    height: 100%;
    object-fit: cover;
    border: 0;
    border-radius: inherit;
    background: #0f172a;
    opacity: 0;
    pointer-events: none;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover .uf-mosaic-inline-video,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible .uf-mosaic-inline-video {
    display: block;
    opacity: 1;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large .uf-game-body {
    z-index: 2 !important;
    opacity: 0 !important;
    transform: translateY(10px) !important;
    background: linear-gradient(to top, rgba(191,228,255,.97) 0%, rgba(191,228,255,.82) 45%, rgba(191,228,255,0) 100%) !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover .uf-game-body,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible .uf-game-body {
    opacity: 1 !important;
    transform: translateY(0) !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-small .uf-game-body {
    display: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(1) { grid-column: 1 / span 2 !important; grid-row: 1 / span 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(2) { grid-column: 3 !important; grid-row: 1 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(3) { grid-column: 3 !important; grid-row: 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(4) { grid-column: 4 / span 2 !important; grid-row: 1 / span 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(5) { grid-column: 6 !important; grid-row: 1 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(6) { grid-column: 6 !important; grid-row: 2 !important; }
}

@media (max-width: 768px) {
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic {
    --uf-new-gap: 8px;
    --uf-new-title-h: 30px;
    --uf-new-cell-w: calc((100vw - 32px) / 3);
    --uf-new-small-h: calc((var(--uf-new-cell-w) / 1.69) + var(--uf-new-title-h));
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    grid-auto-rows: var(--uf-new-small-h) !important;
    gap: var(--uf-new-gap) !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card {
    display: flex !important;
    flex-direction: column !important;
    position: relative !important;
    height: 100% !important;
    min-height: 0 !important;
    overflow: visible !important;
    border: 0 !important;
    border-radius: 0 !important;
    background: transparent !important;
    box-shadow: none !important;
    transform: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-thumb {
    display: block !important;
    width: 100% !important;
    height: calc(100% - var(--uf-new-title-h)) !important;
    aspect-ratio: auto !important;
    object-fit: cover !important;
    border-radius: 16px !important;
    overflow: hidden !important;
    clip-path: inset(0 round 16px) !important;
    filter: none !important;
    transform: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-inline-video {
    display: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-body {
    position: static !important;
    display: block !important;
    min-height: 0 !important;
    height: var(--uf-new-title-h) !important;
    padding: 6px 2px 0 !important;
    margin: 0 !important;
    background: transparent !important;
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-name {
    display: block !important;
    width: 100% !important;
    color: #163247 !important;
    text-align: center !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
    font-size: 11px !important;
    font-weight: 800 !important;
    line-height: 1.25 !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(1) { grid-column: 1 / span 2 !important; grid-row: 1 / span 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(2) { grid-column: 3 !important; grid-row: 1 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(3) { grid-column: 3 !important; grid-row: 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(4) { grid-column: 1 !important; grid-row: 3 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(5) { grid-column: 1 !important; grid-row: 4 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(6) { grid-column: 2 / span 2 !important; grid-row: 3 / span 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(7) { grid-column: 1 !important; grid-row: 5 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(8) { grid-column: 2 !important; grid-row: 5 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(9) { grid-column: 3 !important; grid-row: 5 !important; }
}
</style>



<style id="uf-new-games-mosaic-v9-fixes">
/* ============================================================
   Universflash - corrections finales mosaïque Nouveaux jeux V9
   - Desktop : les grandes vignettes n'ont plus le hover Prime
   - Mobile : petites vignettes calées sur le rendu Top 10, images carrées
   - Mobile : grandes vignettes avec image au ratio 1:1
   ============================================================ */
@media (min-width: 769px) {
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible {
    transform: none !important;
    box-shadow: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large.uf-new-card::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large.uf-new-card::after,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large::after {
    content: none !important;
    display: none !important;
    animation: none !important;
    background: none !important;
    box-shadow: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover .uf-thumb,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible .uf-thumb {
    transform: none !important;
    filter: none !important;
  }
}

@media (max-width: 768px) {
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic {
    --uf-new-gap: 8px;
    --uf-new-title-h: 34px;
    --uf-new-cell-w: calc((100vw - 32px) / 3);
    display: grid !important;
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    grid-auto-rows: calc(var(--uf-new-cell-w) + var(--uf-new-title-h)) !important;
    gap: var(--uf-new-gap) !important;
    align-items: start !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    justify-content: flex-start !important;
    height: auto !important;
    min-height: 0 !important;
    overflow: visible !important;
    background: transparent !important;
    border: 0 !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 0 !important;
    margin: 0 !important;
    transform: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card::after,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card.uf-new-card::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card.uf-new-card::after {
    content: none !important;
    display: none !important;
    animation: none !important;
    background: none !important;
    box-shadow: none !important;
  }

  /* Petites vignettes Nouveaux jeux = rendu visuel Top 10 populaires mobile */
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-small .uf-thumb {
    display: block !important;
    width: 100% !important;
    height: auto !important;
    aspect-ratio: 1 / 1 !important;
    object-fit: cover !important;
    border-radius: 16px !important;
    overflow: hidden !important;
    clip-path: inset(0 round 16px) !important;
    -webkit-mask-image: -webkit-radial-gradient(white, black) !important;
    background: none !important;
    border: 0 !important;
    box-shadow: none !important;
    transform: none !important;
    filter: none !important;
  }

  /* Grandes vignettes mobile : image carrée, pas de dégradé mobile */
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large .uf-thumb {
    display: block !important;
    width: 100% !important;
    height: auto !important;
    aspect-ratio: 1 / 1 !important;
    object-fit: cover !important;
    border-radius: 16px !important;
    overflow: hidden !important;
    clip-path: inset(0 round 16px) !important;
    -webkit-mask-image: -webkit-radial-gradient(white, black) !important;
    background: none !important;
    border: 0 !important;
    box-shadow: none !important;
    transform: none !important;
    filter: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-inline-video {
    display: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-body {
    position: static !important;
    display: block !important;
    width: 100% !important;
    height: var(--uf-new-title-h) !important;
    min-height: 0 !important;
    padding: 6px 2px 0 !important;
    margin: 0 !important;
    background: transparent !important;
    opacity: 1 !important;
    transform: none !important;
    pointer-events: auto !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-name {
    display: block !important;
    width: 100% !important;
    min-height: 18px !important;
    margin: 0 !important;
    padding: 0 2px !important;
    font-size: 11px !important;
    font-weight: 800 !important;
    line-height: 1.3 !important;
    color: #163247 !important;
    text-align: center !important;
    white-space: nowrap !important;
    overflow: hidden !important;
    text-overflow: ellipsis !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(1) { grid-column: 1 / span 2 !important; grid-row: 1 / span 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(2) { grid-column: 3 !important; grid-row: 1 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(3) { grid-column: 3 !important; grid-row: 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(4) { grid-column: 1 !important; grid-row: 3 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(5) { grid-column: 1 !important; grid-row: 4 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(6) { grid-column: 2 / span 2 !important; grid-row: 3 / span 2 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(7) { grid-column: 1 !important; grid-row: 5 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(8) { grid-column: 2 !important; grid-row: 5 !important; }
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-card:nth-child(9) { grid-column: 3 !important; grid-row: 5 !important; }
}
</style>



<style id="uf-new-games-mobile-spacing-v12">
/* ============================================================
   Universflash - ajustement fin espacement mobile Nouveaux jeux V12
   Objectif : espace vignette -> titre = espace titre -> vignette suivante.
   Ne modifie pas le desktop ni les tailles/ratios des images.
   ============================================================ */
@media (max-width: 768px) {
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic {
    --uf-new-gap: 4px !important;
    --uf-new-title-h: 22px !important;
    row-gap: 4px !important;
    column-gap: 8px !important;
    grid-auto-rows: calc(var(--uf-new-cell-w) + var(--uf-new-title-h)) !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-body {
    height: var(--uf-new-title-h) !important;
    padding: 4px 2px 0 !important;
    margin: 0 !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-game-name {
    min-height: 14px !important;
    line-height: 1.2 !important;
  }
}
</style>


<style id="uf-new-games-large-no-prime-v14">
/* Suppression définitive du hover Prime sur les grandes vignettes desktop Nouveaux jeux */
@media (min-width: 769px) {
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible {
    transform: none !important;
    box-shadow: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large::after,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large.uf-new-card::before,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large.uf-new-card::after {
    content: none !important;
    display: none !important;
    animation: none !important;
    background: none !important;
    box-shadow: none !important;
  }

  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:hover .uf-thumb,
  .uf-page-home .uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large:focus-visible .uf-thumb {
    transform: none !important;
    filter: none !important;
  }
}

/* FIX Universflash : lien Voir tout juste à droite du titre */
.uf-page-home .uf-section-head{
  justify-content:flex-start !important;
  gap:8px !important;
}
.uf-page-home .uf-section-head > div{
  flex:0 0 auto !important;
}
.uf-page-home .uf-section-head .uf-light-btn,
.uf-page-home .uf-section-head .uf-light-btn-nouveaux{
  flex:0 0 auto !important;
}
.uf-page-home .uf-sections-grid .uf-block-head{
  justify-content:flex-start !important;
  gap:8px !important;
}
.uf-page-home .uf-sections-grid .uf-block-title{
  flex:0 0 auto !important;
}
.uf-page-home .uf-sections-grid .uf-block-head .uf-btn-outline{
  flex:0 0 auto !important;
}
@media (max-width:768px){
  .uf-page-home .uf-section-head{
    flex-direction:row !important;
    align-items:center !important;
    flex-wrap:wrap !important;
  }
}

</style>



<!-- UF HEADER + FREDOKA UNIFORME 2026-07-05 -->
<style id="uf-fredoka-light-final-override">
@font-face {
    font-family: 'Fredoka';
    src: url('/fonts/Fredoka-VariableFont_wdth.ttf') format('truetype');
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}

html, body, button, input, textarea, select, * {
    font-family: 'Fredoka', Arial, Helvetica, sans-serif !important;
    font-optical-sizing: auto;
}

h1, h2, h3, h4, h5, h6,
.uf-page-hero-main h1,
.uf-rub-hero-head h1,
.uf-cat-hero-head h1,
.uf-section-title,
.uf-side-title,
.uf-game-name,
.uf-trend-title,
.uf-cat-title,
.uf-badge,
.uf-chip,
strong, b {
    font-weight: 500 !important;
}

h1,
.uf-page-hero-main h1,
.uf-rub-hero-head h1,
.uf-cat-hero-head h1,
.uf-section-title {
    font-weight: 600 !important;
}

p, li, a, span, small, .uf-side-sub, .uf-section-desc, .uf-seo-box p {
    font-weight: 400 !important;
}
</style>


<style id="uf-header-fredoka-final-70">
@font-face {
    font-family: 'Fredoka';
    src: url('/fonts/Fredoka-VariableFont_wdth.ttf') format('truetype');
    font-weight: 300 700;
    font-style: normal;
    font-display: swap;
}

html,
body,
button,
input,
textarea,
select,
a,
span,
div,
p,
h1,
h2,
h3,
h4,
h5,
h6 {
    font-family: 'Fredoka', Arial, Helvetica, sans-serif !important;
    font-optical-sizing: auto;
}

/* Fredoka : graisses allégées */
h1,
.uf-title,
.uf-page-title,
.uf-section-title {
    font-weight: 600 !important;
}

h2,
h3,
.uf-game-title,
.uf-game-name,
.uf-card-title,
.uf-thumb-title,
.uf-nav a,
.uf-nav-mobile a,
.uf-cat-title,
.uf-rubrique-title,
.uf-brand,
.uf-brand-name {
    font-weight: 500 !important;
}

strong,
b,
.uf-btn,
.uf-button,
.uf-chip,
.uf-badge {
    font-weight: 600 !important;
}

/* Header Universflash : desktop 70px, mobile/tablette 5px */
:root{
    --uf-header-left-limit: 70px;
    --uf-header-right-gap: 12px;
}

.uf-topbar > .uf-shell,
.uf-topbar .uf-shell:first-child{
    width: calc(100% - var(--uf-header-left-limit) - var(--uf-header-right-gap)) !important;
    max-width: none !important;
    margin-left: var(--uf-header-left-limit) !important;
    margin-right: var(--uf-header-right-gap) !important;
}

.uf-topbar-row,
.uf-mobile-header-row{
    margin-left: 0 !important;
    margin-right: 0 !important;
    justify-content: flex-start !important;
}

.uf-brand{
    margin-left: 0 !important;
    transform: none !important;
}

.uf-nav,
.uf-nav-mobile,
.uf-menu-panel,
.uf-burger-panel,
.uf-mobile-menu,
.uf-mobile-dropdown,
.uf-mobile-nav-panel{
    margin-left: 0 !important;
    transform: none !important;
}

.uf-nav{
    justify-content: flex-start !important;
}

@media (max-width: 1024px){
    :root{
        --uf-header-left-limit: 5px;
        --uf-header-right-gap: 5px;
    }

    .uf-topbar > .uf-shell,
    .uf-topbar .uf-shell:first-child{
        width: calc(100% - var(--uf-header-left-limit) - var(--uf-header-right-gap)) !important;
        margin-left: var(--uf-header-left-limit) !important;
        margin-right: var(--uf-header-right-gap) !important;
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    .uf-topbar-row,
    .uf-mobile-header-row{
        padding-left: 0 !important;
        padding-right: 0 !important;
    }

    .uf-nav{
        padding-left: 0 !important;
    }
}
</style>

<!-- UF RÉGLAGE ÉPAISSEUR RUBRIQUES HEADER - NE TOUCHE PAS À LA DISPOSITION -->
<style id="uf-header-rubriques-weight-600-final">
/* Uniformisation uniquement de l'épaisseur des noms de rubriques du header.
   Aucune règle de position, marge, largeur ou flex n'est modifiée ici. */
.uf-topbar .uf-nav a,
.uf-topbar .uf-nav a *,
.uf-topbar .uf-nav-mobile a,
.uf-topbar .uf-nav-mobile a *,
.uf-topbar .uf-pill,
.uf-topbar .uf-pill *,
.uf-topbar .uf-menu-panel a,
.uf-topbar .uf-menu-panel a *,
.uf-topbar .uf-burger-panel a,
.uf-topbar .uf-burger-panel a *,
.uf-topbar .uf-mobile-menu a,
.uf-topbar .uf-mobile-menu a *,
.uf-topbar .uf-mobile-dropdown a,
.uf-topbar .uf-mobile-dropdown a *,
.uf-topbar .uf-mobile-nav-panel a,
.uf-topbar .uf-mobile-nav-panel a *,
.uf-topbar .uf-categories-scroll a,
.uf-topbar .uf-categories-scroll a *,
.uf-topbar .uf-rubriques-scroll a,
.uf-topbar .uf-rubriques-scroll a *,
.uf-topbar .uf-cat-link,
.uf-topbar .uf-cat-link *,
.uf-topbar .uf-rubrique-link,
.uf-topbar .uf-rubrique-link * {
    font-family: 'Fredoka', Arial, Helvetica, sans-serif !important;
    font-weight: 600 !important;
    font-variation-settings: 'wght' 600 !important;
    font-optical-sizing: auto;
}
</style>

<!-- UF CORRECTION FINALE POIDS RUBRIQUES - NE MODIFIE PAS LA DISPOSITION -->
<style id="uf-rubriques-font-weight-550-global-final">
/* Uniformisation de l'épaisseur des noms de rubriques uniquement.
   Aucune marge, position, largeur, flex ou hauteur n'est modifiée. */
.uf-pill,
.uf-pill *,
a.uf-pill,
a.uf-pill *,
.uf-nav a,
.uf-nav a *,
.uf-nav-mobile a,
.uf-nav-mobile a *,
.uf-horizontal-menu a,
.uf-horizontal-menu a *,
.uf-menu-panel a,
.uf-menu-panel a *,
.uf-mobile-menu a,
.uf-mobile-menu a *,
.uf-burger-panel a,
.uf-burger-panel a *,
.uf-mobile-dropdown a,
.uf-mobile-dropdown a *,
.uf-categories-scroll a,
.uf-categories-scroll a *,
.uf-rubriques-scroll a,
.uf-rubriques-scroll a *,
.uf-cat-link,
.uf-cat-link *,
.uf-rubrique-link,
.uf-rubrique-link *,
[class*="rubrique"] a,
[class*="rubrique"] a *,
[class*="categorie"] a,
[class*="categorie"] a * {
    font-family: 'Fredoka', Arial, Helvetica, sans-serif !important;
    font-weight: 550 !important;
    font-variation-settings: 'wght' 550 !important;
    font-optical-sizing: auto !important;
}
</style>



<!-- UF ALIGNEMENT TYPO MENUS SUR RUBRIQUE/CATEGORIE - NE TOUCHE PAS A LA DISPOSITION -->
<style id="uf-menu-rubrique-categorie-weight-550-final">
/* Même épaisseur que les pages rubrique.php et categorie.php.
   Modifie uniquement la typographie des menus rubriques, aucune position/marge/flex. */
.uf-pill,
.uf-pill *,
a.uf-pill,
a.uf-pill *,
.uf-nav a,
.uf-nav a *,
.uf-nav-mobile a,
.uf-nav-mobile a *,
.uf-horizontal-menu a,
.uf-horizontal-menu a *,
.uf-menu-panel a,
.uf-menu-panel a *,
.uf-mobile-menu a,
.uf-mobile-menu a *,
.uf-burger-panel a,
.uf-burger-panel a *,
.uf-mobile-dropdown a,
.uf-mobile-dropdown a *,
.uf-categories-scroll a,
.uf-categories-scroll a *,
.uf-rubriques-scroll a,
.uf-rubriques-scroll a *,
.uf-cat-link,
.uf-cat-link *,
.uf-rubrique-link,
.uf-rubrique-link *,
[class*="rubrique"] a,
[class*="rubrique"] a *,
[class*="categorie"] a,
[class*="categorie"] a * {
    font-family: 'Fredoka', Arial, Helvetica, sans-serif !important;
    font-weight: 550 !important;
    font-variation-settings: 'wght' 550 !important;
    font-optical-sizing: auto !important;
}
</style>

<!-- UF TYPO HEADER MENUS FINAL - 20260705
     Ne modifie aucune disposition : uniquement font-size/font-weight des textes du header/menu. -->
<style id="uf-header-menu-typo-400-final">
/* Logo Universflash */
.uf-brand-title,
.uf-brand-name,
.uf-logo,
.site-logo,
.logo-text{
    font-family:'Fredoka', Arial, Helvetica, sans-serif !important;
    font-size:24px !important;
    font-weight:600 !important;
    font-variation-settings:'wght' 600 !important;
    line-height:1.05 !important;
}

/* Sous-titre */
.uf-brand-sub,
.uf-tagline,
.site-tagline{
    font-family:'Fredoka', Arial, Helvetica, sans-serif !important;
    font-size:13px !important;
    font-weight:400 !important;
    font-variation-settings:'wght' 400 !important;
    line-height:1.15 !important;
}

/* Menu horizontal rubriques */
.uf-topbar .uf-nav a,
.uf-topbar .uf-nav a *,
.uf-topbar .uf-pill,
.uf-topbar .uf-pill *,
.uf-topbar a.uf-pill,
.uf-topbar a.uf-pill *,
.uf-topbar .uf-categories-scroll a,
.uf-topbar .uf-categories-scroll a *,
.uf-topbar .uf-rubriques-scroll a,
.uf-topbar .uf-rubriques-scroll a *,
.uf-topbar .uf-horizontal-menu a,
.uf-topbar .uf-horizontal-menu a *{
    font-family:'Fredoka', Arial, Helvetica, sans-serif !important;
    font-weight:400 !important;
    font-variation-settings:'wght' 400 !important;
    font-optical-sizing:auto !important;
}

/* Menu vertical ouvert par le burger */
.uf-topbar .uf-nav-mobile a,
.uf-topbar .uf-nav-mobile a *,
.uf-topbar .uf-menu-panel a,
.uf-topbar .uf-menu-panel a *,
.uf-topbar .uf-burger-panel a,
.uf-topbar .uf-burger-panel a *,
.uf-topbar .uf-mobile-menu a,
.uf-topbar .uf-mobile-menu a *,
.uf-topbar .uf-mobile-dropdown a,
.uf-topbar .uf-mobile-dropdown a *,
.uf-topbar .uf-mobile-nav-panel a,
.uf-topbar .uf-mobile-nav-panel a *,
.uf-nav-mobile a,
.uf-nav-mobile a *,
.uf-menu-panel a,
.uf-menu-panel a *,
.uf-burger-panel a,
.uf-burger-panel a *,
.uf-mobile-menu a,
.uf-mobile-menu a *,
.uf-mobile-dropdown a,
.uf-mobile-dropdown a *,
.uf-mobile-nav-panel a,
.uf-mobile-nav-panel a *,
.uf-drawer a,
.uf-drawer a *,
.uf-offcanvas a,
.uf-offcanvas a *,
.uf-vertical-menu a,
.uf-vertical-menu a *,
.uf-sidebar-menu a,
.uf-sidebar-menu a *{
    font-family:'Fredoka', Arial, Helvetica, sans-serif !important;
    font-weight:400 !important;
    font-variation-settings:'wght' 400 !important;
    font-optical-sizing:auto !important;
}

/* Sécurité : les boutons/liens de rubriques du header ne doivent plus hériter de 550/600 */
.uf-topbar [class*="rubrique"] a,
.uf-topbar [class*="rubrique"] a *,
.uf-topbar [class*="categorie"] a,
.uf-topbar [class*="categorie"] a *,
.uf-topbar .uf-cat-link,
.uf-topbar .uf-cat-link *,
.uf-topbar .uf-rubrique-link,
.uf-topbar .uf-rubrique-link *{
    font-family:'Fredoka', Arial, Helvetica, sans-serif !important;
    font-weight:400 !important;
    font-variation-settings:'wght' 400 !important;
    font-optical-sizing:auto !important;
}
</style>


<style id="uf-video-contain-full-frame-fix-20260720">
/* Vidéos : afficher l'image complète sans zoom ni recadrage.
   Les images restent en object-fit: cover. */
.uf-hover-preview-video,
.uf-page-home .uf-mosaic-inline-video {
  object-fit: contain !important;
  object-position: center center !important;
  background: #000 !important;
}

/* Sécurité pour l'aperçu Prime : cadre strictement 3/2. */
.uf-hover-preview-media {
  aspect-ratio: 3 / 2 !important;
}
</style>

</head>
<body class="uf-page-home<?= $isMobile ? ' uf-mobile-lite' : '' ?>">
<script>
window.addEventListener('load', function () {
  var loadAds = function () {
    var s = document.createElement('script');
    s.src = 'https://f.a2d.io/p/t/gadw.js';
    s.async = true;
    s.setAttribute('data-gad-token', 'F5BEF237');
    s.setAttribute('data-gad-params', "p:'b-r', 'b-l','m-b','m-m';rc:2;rd:5000;fc:3600");
    document.body.appendChild(s);
  };

  if ('requestIdleCallback' in window) {
    requestIdleCallback(loadAds, {timeout: 2500});
  } else {
    setTimeout(loadAds, 1200);
  }
});
</script>

<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php'; ?>



<main class="uf-main">
  <div class="uf-shell">
    <h1 class="uf-main-title" style="position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;">Jeux gratuits en ligne — Universflash</h1>
        <section class="uf-section uf-section-plain uf-home-wide-new">
      <div class="uf-section-head" style="justify-content:flex-end; margin-bottom:14px;">
        <a class="uf-light-btn-nouveaux" href="/tous-les-jeux/">Voir tout</a>
      </div>

      <?php $latestDisplayGames = $isMobile ? array_slice($ufLatestGames, 0, 9) : $ufLatestGames; ?>
      <div class="uf-games-grid uf-new-games-mosaic">
        <?php foreach ($latestDisplayGames as $i => $game): ?>
          <?php
            $newClass = ' uf-mosaic-small';
            if ($i === 0 || $i === 3) {
              $newClass = ' uf-mosaic-large';
            } elseif ($i === 1) {
              $newClass .= ' uf-new-card uf-new-1';
            } elseif ($i === 2) {
              $newClass .= ' uf-new-card uf-new-2';
            } elseif ($i === 4) {
              $newClass .= ' uf-new-card uf-new-3';
            }
          ?>
          <a class="uf-game-card<?= $newClass ?>" href="<?= uf_h($game['url']) ?>"<?php if ($newClass !== ' uf-mosaic-large'): ?> data-uf-preview-title="<?= uf_h($game['title'] ?? '') ?>" data-uf-preview-image="<?= uf_h(uf_preview_image_url($game['image'] ?? '')) ?>" data-uf-preview-meta="<?= uf_h($game['meta'] ?? 'Jeu gratuit') ?>" data-uf-preview-desc="<?= uf_h($game['description'] ?? '') ?>" data-uf-preview-video="<?= uf_h($game['video'] ?? '') ?>"<?php endif; ?>>
            <?= uf_picture_html($game['image'], 'uf-thumb', $game['title'], uf_img_attrs(($i ?? 99) === 0, 200, 170, ($i ?? 99) < ($isMobile ? 3 : 6))) ?>
            <?php if (!empty($game['video'])): ?>
              <video class="uf-mosaic-inline-video" muted loop playsinline preload="none" src="<?= uf_h($game['video']) ?>"></video>
            <?php endif; ?>
            <span class="uf-game-body">
              <span class="uf-game-name"><?= uf_h($game['title']) ?></span>
              <span class="uf-game-meta"><?= uf_h($game['meta']) ?></span>
            </span>
          </a>
        <?php endforeach; ?>
      </div>
    </section>


    <?php if (!empty($ufWorldCupSection) && !empty($ufWorldCupSection['items'])): ?>
      <section class="uf-section uf-section-plain uf-obby-section-tight uf-home-wide-slider uf-defer-render">
        <div class="uf-section-head" style="justify-content:flex-start; gap:8px; margin-bottom:8px;">
          <div>
            <h3 class="uf-section-title" style="font-size:24px;"><?= uf_h($ufWorldCupSection['title']) ?></h3>
          </div>
          <a class="uf-light-btn-nouveaux" href="<?= uf_h($ufWorldCupSection['url']) ?>">Voir tout</a>
        </div>

        <div class="uf-games-slider-wrap">
          <button class="uf-slider-arrow uf-slider-arrow-left" type="button" aria-label="Faire défiler vers la gauche" data-uf-slider-prev>‹</button>
          <div class="uf-games-slider" data-uf-slider>
            <div class="uf-games-slider-track">
              <?php foreach ($ufWorldCupSection['items'] as $game): ?>
                <a class="uf-game-card" href="<?= uf_h($game['url']) ?>" data-uf-preview-title="<?= uf_h($game['title'] ?? '') ?>" data-uf-preview-image="<?= uf_h(uf_preview_image_url($game['image'] ?? '')) ?>" data-uf-preview-meta="<?= uf_h($game['meta'] ?? 'Jeu gratuit') ?>" data-uf-preview-desc="<?= uf_h($game['description'] ?? '') ?>" data-uf-preview-video="<?= uf_h($game['video'] ?? '') ?>">
                  <?= uf_picture_html($game['image'], 'uf-thumb', $game['title'], uf_img_attrs(false, 200, 170)) ?>
                  <span class="uf-game-body">
                    <span class="uf-game-name"><?= uf_h($game['title']) ?></span>
                    <span class="uf-game-meta"><?= uf_h($game['meta']) ?></span>
                  </span>
                </a>
              <?php endforeach; ?>
            </div>
          </div>
          <button class="uf-slider-arrow uf-slider-arrow-right" type="button" aria-label="Faire défiler vers la droite" data-uf-slider-next>›</button>
        </div>
      </section>
    <?php endif; ?>

    <?php if (!empty($ufTopRecentSection) && !empty($ufTopRecentSection['items'])): ?>
      <section class="uf-section uf-section-plain uf-home-wide-slider uf-defer-render">
        <div class="uf-section-head" style="justify-content:flex-start; gap:8px; margin-bottom:8px;">
          <div>
            <h3 class="uf-section-title" style="font-size:24px;"><?= uf_h($ufTopRecentSection['title']) ?></h3>
          </div>
        </div>

        <div class="uf-games-slider-wrap">
          <button class="uf-slider-arrow uf-slider-arrow-left" type="button" aria-label="Faire défiler vers la gauche" data-uf-slider-prev>‹</button>
          <div class="uf-games-slider" data-uf-slider>
            <div class="uf-games-slider-track">
              <?php foreach ($ufTopRecentSection['items'] as $game): ?>
                <a class="uf-game-card" href="<?= uf_h($game['url']) ?>" data-uf-preview-title="<?= uf_h($game['title'] ?? '') ?>" data-uf-preview-image="<?= uf_h(uf_preview_image_url($game['image'] ?? '')) ?>" data-uf-preview-meta="<?= uf_h($game['meta'] ?? 'Jeu gratuit') ?>" data-uf-preview-desc="<?= uf_h($game['description'] ?? '') ?>" data-uf-preview-video="<?= uf_h($game['video'] ?? '') ?>">
                  <?= uf_picture_html($game['image'], 'uf-thumb', $game['title'], uf_img_attrs(false, 200, 170)) ?>
                  <span class="uf-game-body">
                    <span class="uf-game-name"><?= uf_h($game['title']) ?></span>
                    <span class="uf-game-meta"><?= uf_h($game['meta']) ?></span>
                  </span>
                </a>
              <?php endforeach; ?>
            </div>
          </div>
          <button class="uf-slider-arrow uf-slider-arrow-right" type="button" aria-label="Faire défiler vers la droite" data-uf-slider-next>›</button>
        </div>
      </section>
    <?php endif; ?>

    <?php if (!empty($ufObbySection) && !empty($ufObbySection['items'])): ?>
      <section class="uf-section uf-section-plain uf-obby-section-tight uf-home-wide-slider uf-defer-render">
        <div class="uf-section-head" style="justify-content:flex-start; gap:8px; margin-bottom:8px;">
          <div>
            <h3 class="uf-section-title" style="font-size:24px;"><?= uf_h($ufObbySection['title']) ?></h3>
          </div>
          <a class="uf-light-btn-nouveaux" href="<?= uf_h($ufObbySection['url']) ?>">Voir tout</a>
        </div>

        <div class="uf-games-slider-wrap">
          <button class="uf-slider-arrow uf-slider-arrow-left" type="button" aria-label="Faire défiler vers la gauche" data-uf-slider-prev>‹</button>
          <div class="uf-games-slider" data-uf-slider>
            <div class="uf-games-slider-track">
              <?php foreach ($ufObbySection['items'] as $game): ?>
                <a class="uf-game-card" href="<?= uf_h($game['url']) ?>" data-uf-preview-title="<?= uf_h($game['title'] ?? '') ?>" data-uf-preview-image="<?= uf_h(uf_preview_image_url($game['image'] ?? '')) ?>" data-uf-preview-meta="<?= uf_h($game['meta'] ?? 'Jeu gratuit') ?>" data-uf-preview-desc="<?= uf_h($game['description'] ?? '') ?>" data-uf-preview-video="<?= uf_h($game['video'] ?? '') ?>">
                  <?= uf_picture_html($game['image'], 'uf-thumb', $game['title'], uf_img_attrs(false, 200, 170)) ?>
                  <span class="uf-game-body">
                    <span class="uf-game-name"><?= uf_h($game['title']) ?></span>
                    <span class="uf-game-meta"><?= uf_h($game['meta']) ?></span>
                  </span>
                </a>
              <?php endforeach; ?>
            </div>
          </div>
          <button class="uf-slider-arrow uf-slider-arrow-right" type="button" aria-label="Faire défiler vers la droite" data-uf-slider-next>›</button>
        </div>
      </section>
    <?php endif; ?>

    <section class="uf-section uf-section-plain uf-home-wide-slider uf-trending-slider uf-defer-render">
        <div class="uf-section-head" style="justify-content:flex-start; gap:8px; margin-bottom:8px;">
          <div>
            <h3 class="uf-section-title" style="font-size:24px;">🔥 Tendances</h3>
          </div>
        </div>

        <div class="uf-games-slider-wrap">
          <button class="uf-slider-arrow uf-slider-arrow-left" type="button" aria-label="Faire défiler vers la gauche" data-uf-slider-prev>‹</button>
          <div class="uf-games-slider" data-uf-slider>
            <div class="uf-games-slider-track">
              <?php foreach ($ufTrendingGames as $i => $game): ?>
                <a class="uf-game-card" href="<?= uf_h($game['url']) ?>" data-uf-preview-title="<?= uf_h($game['title'] ?? '') ?>" data-uf-preview-image="<?= uf_h(uf_preview_image_url($game['image'] ?? '')) ?>" data-uf-preview-meta="<?= uf_h($game['meta'] ?? 'Jeu gratuit') ?>" data-uf-preview-desc="<?= uf_h($game['description'] ?? '') ?>" data-uf-preview-video="<?= uf_h($game['video'] ?? '') ?>">
                  <span class="uf-rank uf-rank-on-card"><?= (int)$i + 1 ?></span>
                  <?= uf_picture_html($game['image'], 'uf-thumb', $game['title'], uf_img_attrs(false, 200, 170)) ?>
                  <span class="uf-game-body">
                    <span class="uf-game-name"><?= uf_h($game['title']) ?></span>
                    <span class="uf-game-meta"><?= uf_h($game['meta'] ?? 'Jeu gratuit') ?></span>
                  </span>
                </a>
              <?php endforeach; ?>
            </div>
          </div>
          <button class="uf-slider-arrow uf-slider-arrow-right" type="button" aria-label="Faire défiler vers la droite" data-uf-slider-next>›</button>
        </div>
    </section>

    <?php if (!empty($ufSections)): ?>
      <section class="uf-section uf-section-plain uf-defer-render">
        <section class="uf-sections-grid">
          <?php foreach ($ufSections as $section): ?>
            <article class="uf-card <?= uf_h($section['class']) ?>">
              <div class="uf-block-head" style="justify-content:flex-start !important; gap:8px !important;">
                <h3 class="uf-block-title"><?= uf_h($section['title']) ?></h3>
                <a class="uf-btn-outline" style="min-height:34px; padding:7px 12px; border-radius:999px;" href="<?= uf_h($section['url']) ?>">Voir tout</a>
              </div>

              <?php $sectionItems = $isMobileOrTablet ? array_slice($section['items'], 0, 9) : $section['items']; ?>
              <div class="uf-block-body">
                <?php foreach ($sectionItems as $game): ?>
                  <a class="uf-mini-game" href="<?= uf_h($game['url']) ?>" data-uf-preview-title="<?= uf_h($game['title'] ?? '') ?>" data-uf-preview-image="<?= uf_h(uf_preview_image_url($game['image'] ?? '')) ?>" data-uf-preview-meta="<?= uf_h($game['meta'] ?? 'Jeu gratuit') ?>" data-uf-preview-desc="<?= uf_h($game['description'] ?? '') ?>" data-uf-preview-video="<?= uf_h($game['video'] ?? '') ?>">
                    <?= uf_picture_html($game['image'], 'uf-mini-thumb', $game['title'], uf_img_attrs(false, 200, 170)) ?>
                    <span class="uf-mini-body">
                      <span class="uf-mini-name"><?= uf_h($game['title']) ?></span>
                    </span>
                  </a>
                <?php endforeach; ?>
              </div>
            </article>
          <?php endforeach; ?>
        </section>
      </section>
    <?php endif; ?>

    <section class="uf-grid-hero uf-defer-render">
      <article class="uf-card uf-hero">
        <div class="uf-hero-inner">
          <div class="uf-hero-copy">
            <span class="uf-badge"><?= uf_h($ufHeroGame['subtitle']) ?></span>
            <p class="uf-hero-headline">Redécouvre les meilleurs jeux gratuits du web</p>
            <p><?= uf_h($ufHeroGame['description']) ?></p>
            <div class="uf-hero-actions">
              <a class="uf-btn" href="<?= uf_h($ufHeroGame['url']) ?>">▶ Jouer maintenant</a>
              <a class="uf-btn-outline" href="/games/populaire/">Voir les populaires</a>
            </div>
          </div>

          <div class="uf-hero-media">
            <div class="uf-hero-frame">
              <a class="uf-hero-poster" href="<?= uf_h($ufHeroGame['url']) ?>">
                <?= uf_picture_html($ufHeroGame['image'], '', 'Jouer à ' . $ufHeroGame['title'] . ' gratuitement en ligne', uf_img_attrs(false, 370, 180)) ?>
                <strong style="font-size:28px; line-height:1.1;"><?= uf_h($ufHeroGame['title']) ?></strong>
                <span style="margin-top:8px; color:#cdd7df; font-size:13px;">Dernier jeu ajouté sur Universflash</span>
              </a>
            </div>
          </div>
        </div>

        <div class="uf-hero-seo">
  <h2>Jeux gratuits en ligne sur Universflash</h2>

  <p>
    Vous cherchez un site de <strong>jeux gratuits en ligne</strong> pour jouer facilement depuis votre navigateur ?
    <strong>Universflash</strong> vous propose une large sélection de <strong>jeux en ligne gratuits</strong>
    accessibles instantanément sur ordinateur, tablette et smartphone.
  </p>

  <p>
    Retrouvez des <a href="/games/action/"><strong>jeux d’action</strong></a>,
    des <a href="/games/reflexion/"><strong>jeux de réflexion</strong></a>,
    des jeux d’aventure, de sport, de voiture, d’arcade et bien d’autres catégories
    pour tous les profils de joueurs.
  </p>

  <p>
    Que vous soyez joueur occasionnel ou passionné, vous trouverez sur Universflash
    des <strong>jeux gratuits</strong> variés, mis à jour régulièrement, pour découvrir
    chaque jour de nouveaux titres et profiter d’une expérience simple, rapide et amusante.
  </p>

  <p>
    Pour <strong>jouer gratuitement en ligne</strong> et explorer les meilleurs jeux du moment,
    Universflash est une destination idéale pour se divertir sans téléchargement.
  </p>
</div>
      </article>

      <aside class="uf-plays-games-panel" aria-label="Découvrir Plays Games">
        <iframe
          class="uf-plays-games-frame"
          src="https://www.plays-games.com/"
          title="Plays Games"
          loading="lazy"
          allow="autoplay; fullscreen"
          referrerpolicy="strict-origin-when-cross-origin">
        </iframe>
      </aside>

    </section>

    <section class="uf-section uf-defer-render uf-explore-categories" style="padding-left:0; padding-right:0;">
      <div class="uf-section-head" style="padding:0 2px;">
        <div>
          <h3 class="uf-section-title">🎮 Explorer par catégorie</h3>
        </div>
      </div>

      <div class="uf-cat-grid">
  <?php foreach ($ufCategories as $cat): ?>
    <?php
      $nom = $cat['name'] ?? '';
      $slug = uf_slugify($nom);

      // Images de rubriques : on reprend le chemin réellement utilisé sur le site.
      // Exemple : /images/rub-adresse.jpg, /images/rub-voiture.jpg, etc.
      $img = '/images/rub-' . $slug . '.jpg';

      // Fallback uniquement si le fichier n'existe pas sur le serveur.
      if (!file_exists($_SERVER['DOCUMENT_ROOT'] . $img)) {
          $img = '/jeu/images/200x170UF.jpg';
      }
    ?>
    <a class="uf-cat-card" href="<?= uf_h($cat['url']) ?>">
      <?= uf_picture_html($img, 'uf-cat-thumb', 'Jeux de ' . $nom, uf_img_attrs(false, 200, 170)) ?>
      <span class="uf-cat-body">
        <span class="uf-cat-title">Jeux de <?= uf_h($nom) ?></span>
      </span>
    </a>
  <?php endforeach; ?>
</div>
    </section>

    <section class="uf-card uf-section uf-defer-render" style="padding:22px;">
      <div class="uf-section-head">
        <div>
          <h3 class="uf-section-title">📚 Toutes les rubriques clés</h3>
        </div>
        <a class="uf-light-btn" href="/toutes-rubriques.php">Voir toutes les rubriques</a>
      </div>

      <div class="uf-all-grid">
        <?php foreach ($ufCategories as $cat): ?>
          <a class="uf-all-link" href="<?= uf_h($cat['url']) ?>">
            <span class="uf-all-left">
              <span style="font-size:18px;"><?= $cat['icon'] ?></span>
              <span><?= uf_h($cat['name']) ?></span>
            </span>
            <span class="uf-all-count"><?= (int)$cat['count'] ?></span>
          </a>
        <?php endforeach; ?>
      </div>
    </section>

    <section class="uf-two-cols uf-defer-render" style="margin-top:24px;">
      <div class="uf-seo-box">
        <span class="uf-badge">Universflash</span>
        <h2>Plus de 8000 jeux gratuits en ligne</h2>
        <p>
          Universflash propose des jeux gratuits pour tous les goûts : action, aventure, sport, voiture, moto,
          réflexion, mahjong et bien d’autres rubriques. Le site est accessible sur ordinateur, tablette et mobile
          avec une navigation plus claire vers les pages fortes.
        </p>
        <div class="uf-tag-list">
          <a class="uf-tag" href="/games/populaire/">Jeux populaires</a>
          <a class="uf-tag" href="/games/voiture/">Jeux de voiture</a>
          <a class="uf-tag" href="/games/sport/">Jeux de sport</a>
          <a class="uf-tag" href="/games/io/">Jeux IO</a>
          <a class="uf-tag" href="/tous-les-jeux/">Tous les jeux</a>
        </div>
      </div>

      <aside class="uf-card uf-resume-box">
        <h3>Reprendre une partie</h3>
        <p></p>
        <div class="uf-resume-list">
          <?php foreach ($ufResumeGames as $i => $game): ?>
            <a class="uf-resume-item" href="<?= uf_h($game['url']) ?>">
              <span class="uf-resume-thumb">
                <?= uf_picture_html($game['image'], '', $game['title'], uf_img_attrs(false, 96, 96)) ?>
              </span>
              <span>
                <span class="uf-item-title"><?= uf_h($game['title']) ?></span>
                <span class="uf-item-sub">Partie récente #<?= (int)$i + 1 ?></span>
              </span>
              <span class="uf-light-btn" style="min-height:36px; padding:8px 12px; margin-left:auto;">Rejouer</span>
            </a>
          <?php endforeach; ?>
        </div>
      </aside>
    </section>
  </div>
</main>

<?php include $_SERVER['DOCUMENT_ROOT'] . '/includes/footer.php'; ?>

<!-- Google tag (gtag.js) chargé après le rendu initial pour préserver le LCP mobile -->
<script>
window.addEventListener('load', function () {
  var loadGtag = function () {
    var s = document.createElement('script');
    s.src = 'https://www.googletagmanager.com/gtag/js?id=G-BY3FNS21EX';
    s.async = true;
    document.head.appendChild(s);
    gtag('js', new Date());
    gtag('config', 'G-BY3FNS21EX');
  };
  if ('requestIdleCallback' in window) {
    requestIdleCallback(loadGtag, {timeout: 3000});
  } else {
    setTimeout(loadGtag, 1500);
  }
});
</script>
<script src="/assets/js/uf-search.js" defer></script>
<script>
(function () {
  var sliders = document.querySelectorAll('[data-uf-slider]');

  function getStep(slider) {
    var firstCard = slider.querySelector('.uf-game-card');
    if (!firstCard) return Math.max(240, slider.clientWidth * 0.8);
    var styles = window.getComputedStyle(firstCard);
    var gap = 8;
    var track = slider.querySelector('.uf-games-slider-track');
    if (track) {
      var trackStyles = window.getComputedStyle(track);
      gap = parseFloat(trackStyles.columnGap || trackStyles.gap || 8) || 8;
    }
    return firstCard.getBoundingClientRect().width + gap;
  }

  function updateArrows(slider) {
    var wrap = slider.closest('.uf-games-slider-wrap');
    if (!wrap) return;
    var prev = wrap.querySelector('[data-uf-slider-prev]');
    var next = wrap.querySelector('[data-uf-slider-next]');
    if (!prev || !next) return;

    var maxScroll = Math.max(0, slider.scrollWidth - slider.clientWidth);
    var canGoLeft = slider.scrollLeft > 4;
    var canGoRight = slider.scrollLeft < (maxScroll - 4);

    prev.disabled = !canGoLeft;
    next.disabled = !canGoRight;

    wrap.classList.toggle('has-left-arrow', canGoLeft);
    wrap.classList.toggle('has-right-arrow', canGoRight);
  }

  sliders.forEach(function (slider) {
    var isDown = false;
    var startX = 0;
    var startScrollLeft = 0;
    var wrap = slider.closest('.uf-games-slider-wrap');
    var prev = wrap ? wrap.querySelector('[data-uf-slider-prev]') : null;
    var next = wrap ? wrap.querySelector('[data-uf-slider-next]') : null;

    slider.addEventListener('mousedown', function (e) {
      isDown = true;
      slider.classList.add('is-dragging');
      startX = e.pageX;
      startScrollLeft = slider.scrollLeft;
    });

    slider.addEventListener('mouseleave', function () {
      isDown = false;
      slider.classList.remove('is-dragging');
    });

    slider.addEventListener('mouseup', function () {
      isDown = false;
      slider.classList.remove('is-dragging');
    });

    slider.addEventListener('mousemove', function (e) {
      if (!isDown) return;
      e.preventDefault();
      var walk = e.pageX - startX;
      slider.scrollLeft = startScrollLeft - walk;
      updateArrows(slider);
    });

    slider.addEventListener('scroll', function () {
      updateArrows(slider);
    }, { passive: true });

    if (prev) {
      prev.addEventListener('click', function () {
        slider.scrollBy({ left: -getStep(slider) * 2, behavior: 'smooth' });
      });
    }

    if (next) {
      next.addEventListener('click', function () {
        slider.scrollBy({ left: getStep(slider) * 2, behavior: 'smooth' });
      });
    }

    updateArrows(slider);
    window.addEventListener('resize', function () { updateArrows(slider); });
  });
})();
</script>

<script>
(function () {
  if (!window.matchMedia || !window.matchMedia('(hover: hover) and (min-width: 901px)').matches) return;

  var cards = document.querySelectorAll('.uf-game-card[data-uf-preview-title]:not(.uf-mosaic-large), .uf-mini-game[data-uf-preview-title]');
  if (!cards.length) return;

  var preview = document.createElement('div');
  preview.className = 'uf-hover-preview';
  preview.setAttribute('aria-hidden', 'true');
  preview.innerHTML =
    '<div class="uf-hover-preview-media">' +
      '<img class="uf-hover-preview-img" alt="">' +
      '<video class="uf-hover-preview-video" muted loop playsinline preload="none"></video>' +
    '</div>' +
    '<div class="uf-hover-preview-content">' +
      '<strong class="uf-hover-preview-title"></strong>' +
      '<span class="uf-hover-preview-meta"></span>' +
      '<div class="uf-hover-preview-actions">' +
        '<span class="uf-hover-preview-action uf-play">▶ Jouer</span>' +
      '</div>' +
      '<p class="uf-hover-preview-desc"></p>' +
    '</div>';
  document.body.appendChild(preview);

  var img = preview.querySelector('.uf-hover-preview-img');
  var video = preview.querySelector('.uf-hover-preview-video');
  var title = preview.querySelector('.uf-hover-preview-title');
  var meta = preview.querySelector('.uf-hover-preview-meta');
  var desc = preview.querySelector('.uf-hover-preview-desc');
  var activeCard = null;
  var pendingCard = null;
  var showTimer = null;
  var hideTimer = null;
  var hideDisplayTimer = null;

  function clearShowTimer() {
    clearTimeout(showTimer);
  }

  function clearHideTimers() {
    clearTimeout(hideTimer);
    clearTimeout(hideDisplayTimer);
  }

  function clearAllTimers() {
    clearShowTimer();
    clearHideTimers();
  }

  function hidePreviewNow() {
    clearAllTimers();
    activeCard = null;
    pendingCard = null;
    preview.classList.remove('is-visible');
    preview.setAttribute('aria-hidden', 'true');
    preview.style.display = 'none';
    img.removeAttribute('src');
    if (video) {
      video.pause();
      video.removeAttribute('src');
      video.load();
    }
    preview.classList.remove('has-video');
  }

  function positionPreview(card) {
    var rect = card.getBoundingClientRect();
    var pw = preview.offsetWidth || 336;
    var ph = preview.offsetHeight || 270;
    var margin = 10;

    var left = rect.left + (rect.width / 2) - (pw / 2);
    left = Math.max(margin, Math.min(left, window.innerWidth - pw - margin));

    var top;

    /*
      Si la vignette touche ou dépasse le haut de la fenêtre,
      on colle l'encart au bord haut visible.
    */
    if (rect.top <= 0) {
      top = 0;
    } else if (rect.top <= margin) {
      top = 0;
    } else {
      top = rect.top - 12;
    }

    if (top + ph > window.innerHeight - margin) {
      top = Math.max(0, window.innerHeight - ph - margin);
    }

    preview.style.left = left + 'px';
    preview.style.top = top + 'px';
  }

  function showPreview(card) {
    clearAllTimers();
    pendingCard = null;
    activeCard = card;

    title.textContent = card.getAttribute('data-uf-preview-title') || '';
    meta.textContent = card.getAttribute('data-uf-preview-meta') || 'Jeu gratuit';
    desc.textContent = card.getAttribute('data-uf-preview-desc') || '';
    img.src = card.getAttribute('data-uf-preview-image') || '';
    img.alt = card.getAttribute('data-uf-preview-title') || '';

    var videoUrl = card.getAttribute('data-uf-preview-video') || '';
    preview.classList.remove('has-video');
    if (video) {
      video.pause();
      video.removeAttribute('src');
      video.load();
      if (videoUrl) {
        video.src = videoUrl;
        video.currentTime = 0;
        preview.classList.add('has-video');
      }
    }

    preview.classList.remove('is-visible');
    preview.setAttribute('aria-hidden', 'true');

    /* fermeture réelle avant nouvelle ouverture */
    preview.style.display = 'none';
    void preview.offsetWidth;

    preview.style.display = 'block';
    positionPreview(card);

    preview.style.transition = 'none';
    preview.style.opacity = '0';
    preview.style.transform = 'translateY(16px) scale(.6)';
    void preview.offsetWidth;
    preview.style.transition = '';

    requestAnimationFrame(function () {
      requestAnimationFrame(function () {

        if (activeCard === card) {

          /* reset total pour relancer le smooth entre toutes les vignettes */
          preview.classList.remove('is-visible');
          void preview.offsetWidth;

          preview.style.opacity = '';
          preview.style.transform = '';

          requestAnimationFrame(function () {
            preview.classList.add('is-visible');
            preview.setAttribute('aria-hidden', 'false');
            if (video && preview.classList.contains('has-video')) {
              video.playbackRate = 1.75;
              var playPromise = video.play();
              if (playPromise && typeof playPromise.catch === 'function') {
                playPromise.catch(function () {});
              }
            }
          });

        }
      });
    });
  }

  function showPreviewSoon(card, delay) {
    clearShowTimer();
    clearHideTimers();
    pendingCard = card;

    showTimer = setTimeout(function () {
      if (pendingCard === card) {
        showPreview(card);
      }
    }, typeof delay === 'number' ? delay : 45);
  }

  function hidePreviewSoon(delay) {
    clearTimeout(hideTimer);
    clearTimeout(hideDisplayTimer);

    hideTimer = setTimeout(function () {
      if (pendingCard) return;

      activeCard = null;
      preview.classList.remove('is-visible');
      preview.setAttribute('aria-hidden', 'true');

      hideDisplayTimer = setTimeout(function () {
        if (!activeCard && !pendingCard) {
          preview.style.display = 'none';
          img.removeAttribute('src');
          if (video) {
            video.pause();
            video.removeAttribute('src');
            video.load();
          }
          preview.classList.remove('has-video');
        }
      }, 80);
    }, typeof delay === 'number' ? delay : 30);
  }

  function closestPreviewCard(target) {
    if (!target || target === window || target === document) return null;
    if (target.closest) {
      return target.closest('[data-uf-preview-title]');
    }
    return null;
  }

  function isInsidePreviewOrCard(target) {
    return !!target && ((activeCard && activeCard.contains(target)) || preview.contains(target));
  }

  cards.forEach(function (card) {
    card.addEventListener('mouseenter', function () {
      showPreviewSoon(card, 0);
    });

    card.addEventListener('mousemove', function () {
      if (pendingCard === card) return;
      if (activeCard !== card) {
        showPreviewSoon(card, 600);
      }
    }, { passive: true });

    card.addEventListener('mouseleave', function (e) {
      var nextCard = closestPreviewCard(e.relatedTarget);

      if (nextCard && nextCard !== card) {
        showPreviewSoon(nextCard, 600);
        return;
      }

      if (e.relatedTarget && isInsidePreviewOrCard(e.relatedTarget)) return;

      pendingCard = null;
      hidePreviewSoon(25);
    });

    card.addEventListener('focus', function () { showPreview(card); });
    card.addEventListener('blur', function () { hidePreviewSoon(20); });
  });

  preview.addEventListener('mouseenter', function () {
    clearHideTimers();
    clearShowTimer();
    pendingCard = null;
  });

  preview.addEventListener('mouseleave', function (e) {
    var nextCard = closestPreviewCard(e.relatedTarget);

    if (nextCard) {
      showPreviewSoon(nextCard, 800);
      return;
    }

    if (e.relatedTarget && activeCard && activeCard.contains(e.relatedTarget)) return;

    pendingCard = null;
    hidePreviewSoon(20);
  });

  preview.addEventListener('click', function () {
    if (activeCard && activeCard.href) {
      window.location.href = activeCard.href;
    }
  });

  document.addEventListener('mousemove', function (e) {
    var hoveredCard = closestPreviewCard(e.target);

    if (hoveredCard) {
      if (activeCard !== hoveredCard && pendingCard !== hoveredCard) {
        showPreviewSoon(hoveredCard, 800);
      }
      return;
    }

    if (!activeCard || preview.contains(e.target)) return;

    var cardRect = activeCard.getBoundingClientRect();
    var previewRect = preview.getBoundingClientRect();
    var safe = 8;

    var insideCardBox =
      e.clientX >= cardRect.left - safe &&
      e.clientX <= cardRect.right + safe &&
      e.clientY >= cardRect.top - safe &&
      e.clientY <= cardRect.bottom + safe;

    var insidePreviewBox =
      e.clientX >= previewRect.left - safe &&
      e.clientX <= previewRect.right + safe &&
      e.clientY >= previewRect.top - safe &&
      e.clientY <= previewRect.bottom + safe;

    if (!insideCardBox && !insidePreviewBox) {
      pendingCard = null;
      hidePreviewSoon(10);
    }
  }, { passive: true });

  document.addEventListener('mouseleave', hidePreviewNow);
  window.addEventListener('blur', hidePreviewNow);
  window.addEventListener('pagehide', hidePreviewNow);

  window.addEventListener('scroll', function () {
    if (activeCard) hidePreviewNow();
  }, { passive: true });

  window.addEventListener('resize', function () {
    if (activeCard) positionPreview(activeCard);
  });
})();
</script>


<script>
(function () {
  if (!window.matchMedia || !window.matchMedia('(hover: hover) and (min-width: 769px)').matches) return;

  var largeCards = document.querySelectorAll('.uf-home-wide-new .uf-new-games-mosaic .uf-mosaic-large');
  if (!largeCards.length) return;

  largeCards.forEach(function (card) {
    var video = card.querySelector('.uf-mosaic-inline-video');
    if (!video) return;

    card.addEventListener('mouseenter', function () {
      try {
        video.currentTime = 0;
        video.playbackRate = 1.75;
        var playPromise = video.play();
        if (playPromise && typeof playPromise.catch === 'function') {
          playPromise.catch(function () {});
        }
      } catch (e) {}
    });

    card.addEventListener('mouseleave', function () {
      try {
        video.pause();
        video.currentTime = 0;
      } catch (e) {}
    });
  });
})();
</script>

</body>
</html>
<?php
$out = ob_get_clean();

if ($canCache) {
    cache_set($globalCacheKey, $out);
}

echo $out;
exit;
?>

/* V13 remove Prime hover on large desktop cards */
@media (min-width:769px){
.uf-big-card:hover,
.uf-big-card:focus-visible{
 transform:none !important;
 box-shadow:none !important;
}
.uf-big-card:hover .uf-thumb,
.uf-big-card:focus-visible .uf-thumb{
 transform:none !important;
 filter:none !important;
}
}
