using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Collections;
using System.Collections.Generic;

/// <summary>
/// Données d'un joueur dans le classement
/// </summary>
[System.Serializable]
public class ScoreboardPlayer
{
    public int user_id;
    public string first_name;
    public string last_name;
    public string email;
    public string company;
    public string position;
    public int score;
    public int completion;
    public int completed_quests;
    public string badge_type;
    public string badge_url;
    public string visibility;
    public int rank;
}

/// <summary>
/// Données de l'utilisateur depuis /api/ujsa/user
/// </summary>
[System.Serializable]
public class UserApiResponse
{
    public string status;
    public string message;
    public UserData data;
}

[System.Serializable]
public class UserData
{
    public string first_name;
    public string last_name;
    public string email;
    public string position;
    public string company;
    public bool has_membership;
    public int time_used;
    public string leaderboard_visibility;
    public List<SuperBadge> super_badges;
    public int total_trainings;
    public List<ProjectInfo> projects;
}

[System.Serializable]
public class ProjectInfo
{
    public string project_slug;
    public string project_title;
    public string rank;
    public int completed_quests;
}

[System.Serializable]
public class SuperBadge
{
    public int project_id;
    public string project_slug;
    public string project_title;
    public int score;
    public string badge_url;
    public string badge_type;
}

/// <summary>
/// Données du projet dans le classement
/// </summary>
[System.Serializable]
public class ScoreboardProject
{
    public int id;
    public string title;
    public string slug;
}

/// <summary>
/// Données du scoreboard depuis l'API
/// </summary>
[System.Serializable]
public class ScoreboardData
{
    public ScoreboardProject project;
    public List<ScoreboardPlayer> company;
    public List<ScoreboardPlayer> global;
}

/// <summary>
/// Réponse de l'API scoreboard
/// </summary>
[System.Serializable]
public class ScoreboardApiResponse
{
    public string status;
    public string message;
    public ScoreboardData data;
}

public class ClassementTab : SettingsTab
{
    // Anciennes variables (à conserver pour compatibilité)
    private GameObject topSection;
    private GameObject tabsSection;
    
    // Nouvelles variables pour les sous-onglets
    private GameObject detailsTabsMenu; // Menu des sous-onglets horizontal
    private GameObject detailsContent; // Contenu qui change selon le sous-onglet actif
    private List<Button> detailTabButtons = new List<Button>();
    private int activeDetailTab = 0; // 0=MON SUPERBADGE, 1=GLOBAL, 2=ENTREPRISE, 3=TOP 10
    
    // Références aux images à charger
    private List<(Image image, string url)> pendingImageLoads = new List<(Image, string)>();
    private bool imagesLoaded = false;
    private GameObject rankingListSection;
    
    private Button companyTabButton;
    private Button globalTabButton;
    
    private GameObject companyRankingList;
    private GameObject globalRankingList;
    
    private ScoreboardData scoreboardData;
    private UserData userData;
    private bool isLoadingData = false;
    private bool isLoadingUserData = false;
    
    // Navigation horizontale
    private List<ScoreboardPlayer> currentPlayers = new List<ScoreboardPlayer>();
    private int visibleStartIndex = 0;
    private const int maxVisiblePlayers = 4; // 4 joueurs visibles au lieu de 3
    private GameObject leftArrow;
    private GameObject rightArrow;
    private GameObject playersContainer;
    
    // Checkboxes cliquables
    private Image checkboxPrive;
    private Image checkboxEntreprise;
    private Image checkboxPublic;
    private string currentVisibility = "public"; // Par défaut
    
    // Badge utilisateur
    private Image userBadgeImage;
    private TextMeshProUGUI userScoreText;
    
    // Lignes d'information MON SUPERBADGE
    private TextMeshProUGUI scoreInfoText;
    private TextMeshProUGUI stateInfoText;
    private TextMeshProUGUI rankInfoText;
    private TextMeshProUGUI questsInfoText;
    private TextMeshProUGUI trainingsInfoText;
    
    // Couleurs depuis l'image
    private Color purpleColor = new Color(0.64f, 0.25f, 1f, 1f); // #a95bfb
    private Color beigeLightColor = new Color(0.96f, 0.93f, 0.90f, 1f); // #f5ece5
    private Color beigeDarkColor = new Color(0.86f, 0.76f, 0.72f, 1f); // #dbc3b7
    private Color textDarkColor = new Color(0.47f, 0.40f, 0.37f, 1f); // #78675f
    
    // Tracking des ressources dynamiques pour éviter les fuites mémoire (WebGL)
    private readonly RuntimeResourceTracker resourceTracker = new RuntimeResourceTracker();
    
    // Configuration
    private ClassementTabConfig config;
    
    protected override void Awake()
    {
        base.Awake();
        tabName = "CLASSEMENT";
        tabOrder = 1;
        
        // Charger la configuration
        LoadConfig();
        
        // Créer le contenu de l'onglet
        CreateContent();
    }
    
    /// <summary>
    /// Charge la configuration depuis GeneralConfigManager
    /// </summary>
    private void LoadConfig()
    {
        if (GeneralConfigManager.Instance != null)
        {
            config = GeneralConfigManager.Instance.GetConfig()?.classementTabConfig;
            
            if (config != null)
            {
                Debug.Log("[ClassementTab] ✅ Configuration chargée depuis general-config.json");
            }
            else
            {
                Debug.LogWarning("[ClassementTab] ⚠️ Configuration non trouvée, utilisation des valeurs par défaut");
                // Créer une config par défaut
                config = new ClassementTabConfig
                {
                    topSection = new ClassementTopSectionConfig { height = 160 },
                    tabsSection = new ClassementTabsSectionConfig { height = 80 },
                    rankingSection = new ClassementRankingSectionConfig { height = 240, maxVisiblePlayers = 4 }
                };
            }
        }
    }
    
    protected override void OnEnable()
    {
        base.OnEnable();
        
        // Charger les données quand l'onglet est activé
        // MAIS pas pendant la création initiale (le panneau est désactivé juste après)
        if (scoreboardData == null && !isLoadingData && gameObject.activeInHierarchy)
        {
            // Attendre une frame pour s'assurer que tout est bien activé
            StartCoroutine(LoadDataAfterFrame());
        }
    }
    
    /// <summary>
    /// Nettoyage des ressources dynamiques pour éviter les fuites mémoire (CRITIQUE en WebGL)
    /// </summary>
    private void OnDestroy()
    {
        Debug.Log("[ClassementTab] 🧹 Nettoyage des ressources dynamiques");
        int count = resourceTracker.Count;
        resourceTracker.Cleanup();
        Debug.Log($"[ClassementTab] ✅ Nettoyage terminé: {count} ressources libérées");
    }
    
    protected override void OnDisable()
    {
        base.OnDisable();
        // Pas de cleanup ici, on le fait seulement dans OnDestroy
    }
    
    /// <summary>
    /// Enregistre une texture et un sprite pour nettoyage ultérieur
    /// </summary>
    private void TrackDynamic(Texture2D tex, Sprite sp)
    {
        resourceTracker.Track(tex, sp);
    }
    
    /// <summary>
    /// Attend une frame avant de charger les données pour s'assurer que l'onglet est bien actif
    /// </summary>
    private IEnumerator LoadDataAfterFrame()
    {
        yield return null; // Attendre 1 frame
        
        // Charger les données utilisateur ET le scoreboard en parallèle
        if (userData == null)
        {
            Debug.Log("[ClassementTab] 👤 Lancement du chargement des données utilisateur depuis LoadDataAfterFrame");
            LoadUserData();
        }
        
        // Vérifier qu'on est toujours actif
        if (gameObject.activeInHierarchy && scoreboardData == null && !isLoadingData)
        {
            Debug.Log("[ClassementTab] 🚀 Lancement du chargement du scoreboard");
            LoadScoreboardData();
        }
        
        // Charger toutes les images en attente (flèches, checkboxes, etc.)
        if (!imagesLoaded && pendingImageLoads.Count > 0)
        {
            Debug.Log($"[ClassementTab] 🖼️ Chargement de {pendingImageLoads.Count} images en attente");
            StartCoroutine(LoadAllPendingImages());
            imagesLoaded = true;
        }
    }
    
    /// <summary>
    /// Charge toutes les images en attente
    /// </summary>
    private IEnumerator LoadAllPendingImages()
    {
        foreach (var (image, url) in pendingImageLoads)
        {
            if (image != null && !string.IsNullOrEmpty(url))
            {
                yield return StartCoroutine(LoadImageSprite(url, image));
            }
        }
        pendingImageLoads.Clear();
        Debug.Log("[ClassementTab] ✅ Toutes les images chargées");
    }
    
    /// <summary>
    /// Charge un sprite depuis une URL (méthode universelle)
    /// </summary>
    private IEnumerator LoadImageSprite(string url, Image targetImage)
    {
        Debug.Log($"[ClassementTab] 🔄 Chargement image: {url}");
        
        using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(url))
        {
            yield return request.SendWebRequest();
            
            if (request.result == UnityWebRequest.Result.Success)
            {
                Texture2D texture = DownloadHandlerTexture.GetContent(request);
                Sprite sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), 
                    new Vector2(0.5f, 0.5f), 100f);
                
                // Tracker pour nettoyage (WebGL)
                TrackDynamic(texture, sprite);
                
                if (targetImage != null)
                {
                    targetImage.sprite = sprite;
                    Debug.Log($"[ClassementTab] ✅ Image chargée: {texture.width}x{texture.height}");
                }
            }
            else
            {
                Debug.LogError($"[ClassementTab] ❌ Erreur chargement: {url} - {request.error}");
            }
        }
    }
    
    private void CreateContent()
    {
        // Layout vertical principal
        VerticalLayoutGroup mainLayout = gameObject.AddComponent<VerticalLayoutGroup>();
        
        // Récupérer les valeurs de padding depuis la config
        int padLeft = 40, padRight = 40, padTop = 5, padBottom = 40;
        float spacing = 20;
        
        if (config?.mainLayout != null)
        {
            padLeft = (int)config.mainLayout.paddingLeft;
            padRight = (int)config.mainLayout.paddingRight;
            padTop = (int)config.mainLayout.paddingTop;
            padBottom = (int)config.mainLayout.paddingBottom;
            spacing = config.mainLayout.spacing;
        }
        
        mainLayout.padding = new RectOffset(padLeft, padRight, padTop, padBottom);
        mainLayout.spacing = spacing;
        mainLayout.childAlignment = TextAnchor.UpperCenter;
        mainLayout.childControlWidth = true;
        mainLayout.childControlHeight = false;
        mainLayout.childForceExpandWidth = true;
        mainLayout.childForceExpandHeight = false;
        
        // Menu des sous-onglets horizontal
        CreateDetailsTabsMenu();
        
        // Zone de contenu qui change selon le sous-onglet
        CreateDetailsContent();
        
        // Afficher le premier sous-onglet par défaut
        ShowDetailTab(0);
    }
    
    /// <summary>
    /// Crée le menu des sous-onglets horizontal (MON SUPERBADGE, GLOBAL, {ENTREPRISE}, TOP 10)
    /// </summary>
    private void CreateDetailsTabsMenu()
    {
        detailsTabsMenu = new GameObject("DetailsTabsMenu");
        detailsTabsMenu.transform.SetParent(transform, false);
        
        // Récupérer la config des sous-onglets
        float height = config?.detailsTabsMenu?.height ?? 80;
        float paddingH = config?.detailsTabsMenu?.paddingHorizontal ?? 20;
        float paddingV = config?.detailsTabsMenu?.paddingVertical ?? 15;
        float tabSpacing = config?.detailsTabsMenu?.tabSpacing ?? 15;
        
        RectTransform menuRect = detailsTabsMenu.AddComponent<RectTransform>();
        menuRect.sizeDelta = new Vector2(0, height);
        
        LayoutElement menuLayout = detailsTabsMenu.AddComponent<LayoutElement>();
        menuLayout.preferredHeight = height;
        menuLayout.minHeight = height;
        
        // Layout horizontal pour les onglets
        HorizontalLayoutGroup hLayout = detailsTabsMenu.AddComponent<HorizontalLayoutGroup>();
        hLayout.childAlignment = TextAnchor.MiddleCenter;
        hLayout.spacing = tabSpacing;
        hLayout.padding = new RectOffset((int)paddingH, (int)paddingH, (int)paddingV, (int)paddingV);
        hLayout.childControlWidth = true;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = true;
        hLayout.childForceExpandHeight = false;
        
        // Créer les 4 boutons d'onglets
        string companyName = userData?.company ?? "SERONI";
        CreateDetailTabButton(detailsTabsMenu.transform, "MON SUPERBADGE", 0);
        CreateDetailTabButton(detailsTabsMenu.transform, "GLOBAL", 1);
        CreateDetailTabButton(detailsTabsMenu.transform, companyName.ToUpper(), 2);
        CreateDetailTabButton(detailsTabsMenu.transform, "TOP 10", 3);
    }
    
    /// <summary>
    /// Crée un bouton de sous-onglet
    /// </summary>
    private void CreateDetailTabButton(Transform parent, string label, int index)
    {
        GameObject buttonObj = new GameObject($"Tab_{label}");
        buttonObj.transform.SetParent(parent, false);
        
        // Récupérer la config du style des sous-onglets
        float height = config?.detailsTabsMenu?.tabStyle?.height ?? 50;
        
        RectTransform buttonRect = buttonObj.AddComponent<RectTransform>();
        buttonRect.sizeDelta = new Vector2(0, height);
        
        LayoutElement buttonLayoutElement = buttonObj.AddComponent<LayoutElement>();
        buttonLayoutElement.preferredHeight = height;
        buttonLayoutElement.preferredWidth = 0;
        buttonLayoutElement.minWidth = 0;
        buttonLayoutElement.flexibleWidth = 1;
        
        // Image de fond (toujours transparente, pas de gélule comme dans QUÊTES)
        Image bgImage = buttonObj.AddComponent<Image>();
        bgImage.color = Color.clear;
        bgImage.raycastTarget = true;
        
        // Texte
        GameObject textObj = new GameObject("Text");
        textObj.transform.SetParent(buttonObj.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.sizeDelta = Vector2.zero;
        
        TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
        text.text = label;
        text.fontSize = 32; // Même taille que QUÊTES
        // Couleur initiale : premier onglet sélectionné (#64477D violet foncé), les autres gris (#ac99b1)
        text.color = (index == 0) ? HexToColor("#64477D") : HexToColor("#ac99b1");
        text.alignment = TextAlignmentOptions.Center;
        text.fontStyle = FontStyles.Normal;
        
        // Charger la police Anton
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        if (antonFont != null)
        {
            text.font = antonFont;
        }
        
        text.raycastTarget = false;
        
        // Bouton
        Button button = buttonObj.AddComponent<Button>();
        button.targetGraphic = bgImage;
        button.transition = Selectable.Transition.None;
        
        int capturedIndex = index;
        button.onClick.AddListener(() => ShowDetailTab(capturedIndex));
        
        detailTabButtons.Add(button);
    }
    
    /// <summary>
    /// Crée la zone de contenu des sous-onglets
    /// </summary>
    private void CreateDetailsContent()
    {
        detailsContent = new GameObject("DetailsContent");
        detailsContent.transform.SetParent(transform, false);
        
        RectTransform contentRect = detailsContent.AddComponent<RectTransform>();
        
        // Le contenu prend tout l'espace restant
        LayoutElement contentLayout = detailsContent.AddComponent<LayoutElement>();
        contentLayout.flexibleHeight = 1;
        contentLayout.minHeight = 500;
        
        // Récupérer la config
        float cornerRadius = config?.detailsContent?.cornerRadius ?? 20;
        float padding = config?.detailsContent?.padding ?? 20;
        
        Color bgColor = new Color(0.91f, 0.85f, 0.81f, 1f); // #e9d9cf par défaut
        if (config?.detailsContent != null && !string.IsNullOrEmpty(config.detailsContent.backgroundColor))
        {
            bgColor = HexToColor(config.detailsContent.backgroundColor);
        }
        
        // Fond avec coins arrondis
        Image bgImage = detailsContent.AddComponent<Image>();
        bgImage.sprite = CreateRoundedSprite(1300, 500, (int)cornerRadius, bgColor);
        bgImage.color = Color.white;
        bgImage.raycastTarget = false;
        
        // Ombre si activée
        if (config?.detailsContent?.shadowEnabled == true)
        {
            Shadow shadow = detailsContent.AddComponent<Shadow>();
            Color shadowColor = new Color(0.85f, 0.76f, 0.7f, 1f);
            if (!string.IsNullOrEmpty(config.detailsContent.shadowColor))
            {
                shadowColor = HexToColor(config.detailsContent.shadowColor);
            }
            shadow.effectColor = shadowColor;
            shadow.effectDistance = new Vector2(0, config?.detailsContent?.shadowOffsetY ?? 8);
        }
        
        // Layout vertical pour empiler les éléments
        VerticalLayoutGroup vLayout = detailsContent.AddComponent<VerticalLayoutGroup>();
        vLayout.childAlignment = TextAnchor.UpperCenter;
        vLayout.spacing = 20;
        vLayout.padding = new RectOffset((int)padding, (int)padding, (int)padding, (int)padding);
        vLayout.childControlWidth = true;
        vLayout.childControlHeight = false;
        vLayout.childForceExpandWidth = true;
        vLayout.childForceExpandHeight = false;
    }
    
    /// <summary>
    /// Affiche un sous-onglet spécifique
    /// </summary>
    private void ShowDetailTab(int tabIndex)
    {
        activeDetailTab = tabIndex;
        
        // Mettre à jour les couleurs des boutons (comme QUÊTES : pas de fond, juste couleur du texte)
        for (int i = 0; i < detailTabButtons.Count; i++)
        {
            Button button = detailTabButtons[i];
            Image bgImage = button.GetComponent<Image>();
            TextMeshProUGUI text = button.GetComponentInChildren<TextMeshProUGUI>();
            
            // Pas de fond (toujours transparent)
            bgImage.color = Color.clear;
            
            if (i == tabIndex)
            {
                // Onglet sélectionné : texte en violet foncé
                if (text != null)
                    text.color = HexToColor("#64477D");
            }
            else
            {
                // Onglet non sélectionné : texte en gris violet clair
                if (text != null)
                    text.color = HexToColor("#ac99b1");
            }
        }
        
        // Nettoyer le contenu actuel
        foreach (Transform child in detailsContent.transform)
        {
            Destroy(child.gameObject);
        }
        
        // Afficher le contenu approprié
        switch (tabIndex)
        {
            case 0: // MON SUPERBADGE
                ShowMonSuperBadgeContent();
                break;
            case 1: // GLOBAL
                ShowGlobalContent();
                break;
            case 2: // ENTREPRISE
                ShowEntrepriseContent();
                break;
            case 3: // TOP 10
                ShowTop10Content();
                break;
        }
    }
    
    /// <summary>
    /// Met à jour le label du bouton de l'onglet entreprise avec le nom de l'entreprise
    /// </summary>
    private void UpdateCompanyTabLabel()
    {
        if (detailTabButtons.Count > 2 && userData != null && !string.IsNullOrEmpty(userData.company))
        {
            Button companyButton = detailTabButtons[2]; // Index 2 = onglet entreprise
            TextMeshProUGUI text = companyButton.GetComponentInChildren<TextMeshProUGUI>();
            if (text != null)
            {
                text.text = userData.company.ToUpper();
                Debug.Log($"[ClassementTab] ✅ Label de l'onglet entreprise mis à jour: {userData.company}");
            }
        }
    }
    
    /// <summary>
    /// Affiche le contenu du sous-onglet MON SUPERBADGE
    /// </summary>
    private void ShowMonSuperBadgeContent()
    {
        Debug.Log("[ClassementTab] 🏆 Affichage MON SUPERBADGE");
        
        CreateTopSection();
        CreateExportButton();
        
        if (userData != null)
        {
            Debug.Log("[ClassementTab] 🏆 userData présent, mise à jour du badge et du bloc d'infos");
            UpdateUserBadge();
            UpdateInfoBlock();
            UpdateCheckboxes();
        }
    }
    
    /// <summary>
    /// Affiche le contenu du sous-onglet GLOBAL
    /// </summary>
    private void ShowGlobalContent()
    {
        Debug.Log("[ClassementTab] 🌍 Affichage GLOBAL");
        
        // Bannière d'information en haut
        CreateInfoBanner("Pour débloquer le super-badge, il faut réaliser un minimum de 5 quêtes. À toi de jouer !");
        
        // Vérifier si on a des données
        if (scoreboardData == null || scoreboardData.global == null || scoreboardData.global.Count == 0)
        {
            CreateEmptyMessage("Aucun joueur dans le classement global");
            return;
        }
        
        // Créer la section de classement avec la liste globale
        currentPlayers = scoreboardData.global;
        visibleStartIndex = 0;
        CreateRankingSection("Classement Global");
    }
    
    /// <summary>
    /// Affiche le contenu du sous-onglet ENTREPRISE
    /// </summary>
    private void ShowEntrepriseContent()
    {
        Debug.Log("[ClassementTab] 🏢 Affichage ENTREPRISE");
        
        string companyName = userData?.company ?? "votre entreprise";
        
        // Bannière d'information en haut
        CreateInfoBanner($"Classement des joueurs de {companyName}");
        
        // Vérifier si on a des données
        if (scoreboardData == null || scoreboardData.company == null || scoreboardData.company.Count == 0)
        {
            CreateEmptyMessage($"Aucun joueur de {companyName} dans le classement");
            return;
        }
        
        // Créer la section de classement avec la liste entreprise
        currentPlayers = scoreboardData.company;
        visibleStartIndex = 0;
        CreateRankingSection($"Classement {companyName}");
    }
    
    /// <summary>
    /// Affiche le contenu du sous-onglet TOP 10
    /// </summary>
    private void ShowTop10Content()
    {
        Debug.Log("[ClassementTab] 🏅 Affichage TOP 10");
        
        // Bannière d'information en haut
        CreateInfoBanner("Les 10 meilleurs joueurs du classement général");
        
        // Vérifier si on a des données
        if (scoreboardData == null || scoreboardData.global == null || scoreboardData.global.Count == 0)
        {
            CreateEmptyMessage("Aucun joueur dans le TOP 10");
            return;
        }
        
        // Prendre les 10 premiers de la liste globale
        currentPlayers = new List<ScoreboardPlayer>();
        int count = Mathf.Min(10, scoreboardData.global.Count);
        for (int i = 0; i < count; i++)
        {
            currentPlayers.Add(scoreboardData.global[i]);
        }
        
        visibleStartIndex = 0;
        CreateRankingSection("TOP 10");
    }
    
    /// <summary>
    /// Crée une bannière d'information en haut du contenu
    /// </summary>
    private void CreateInfoBanner(string message)
    {
        GameObject banner = new GameObject("InfoBanner");
        banner.transform.SetParent(detailsContent.transform, false);
        
        RectTransform bannerRect = banner.AddComponent<RectTransform>();
        bannerRect.sizeDelta = new Vector2(0, 70);
        
        LayoutElement bannerLayout = banner.AddComponent<LayoutElement>();
        bannerLayout.preferredHeight = 70;
        bannerLayout.minHeight = 70;
        bannerLayout.flexibleWidth = 1;
        
        // Layout pour gérer le padding et l'alignement
        VerticalLayoutGroup vLayout = banner.AddComponent<VerticalLayoutGroup>();
        vLayout.childAlignment = TextAnchor.MiddleCenter;
        vLayout.padding = new RectOffset(40, 40, 15, 15);
        vLayout.childControlWidth = true;
        vLayout.childControlHeight = true;
        vLayout.childForceExpandWidth = true;
        vLayout.childForceExpandHeight = true;
        
        // Fond violet avec coins arrondis
        Image bgImage = banner.AddComponent<Image>();
        bgImage.sprite = CreateRoundedSprite(1200, 70, 20, purpleColor);
        bgImage.type = Image.Type.Sliced;
        
        // Texte du message
        GameObject textObj = new GameObject("Text");
        textObj.transform.SetParent(banner.transform, false);
        
        TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
        text.text = message;
        text.fontSize = 18;
        text.color = Color.white;
        text.alignment = TextAlignmentOptions.Center;
        text.fontStyle = FontStyles.Bold;
        text.raycastTarget = false;
    }
    
    /// <summary>
    /// Crée la section de classement avec liste verticale scrollable
    /// </summary>
    private void CreateRankingSection(string title)
    {
        GameObject rankingSection = new GameObject("RankingSection");
        rankingSection.transform.SetParent(detailsContent.transform, false);
        
        RectTransform rankingRect = rankingSection.AddComponent<RectTransform>();
        
        LayoutElement rankingLayout = rankingSection.AddComponent<LayoutElement>();
        rankingLayout.flexibleHeight = 1;
        rankingLayout.minHeight = 400;
        rankingLayout.preferredHeight = 500;
        
        // ScrollRect pour la liste
        ScrollRect scrollRect = rankingSection.AddComponent<ScrollRect>();
        scrollRect.horizontal = false;
        scrollRect.vertical = true;
        scrollRect.movementType = ScrollRect.MovementType.Clamped;
        
        // Viewport
        GameObject viewport = new GameObject("Viewport");
        viewport.transform.SetParent(rankingSection.transform, false);
        
        RectTransform viewportRect = viewport.AddComponent<RectTransform>();
        viewportRect.anchorMin = Vector2.zero;
        viewportRect.anchorMax = Vector2.one;
        viewportRect.sizeDelta = Vector2.zero;
        viewportRect.pivot = new Vector2(0.5f, 0.5f);
        
        Image viewportMask = viewport.AddComponent<Image>();
        viewportMask.color = Color.clear;
        
        Mask mask = viewport.AddComponent<Mask>();
        mask.showMaskGraphic = false;
        
        scrollRect.viewport = viewportRect;
        
        // Content (liste des joueurs)
        GameObject content = new GameObject("Content");
        content.transform.SetParent(viewport.transform, false);
        
        RectTransform contentRect = content.AddComponent<RectTransform>();
        contentRect.anchorMin = new Vector2(0, 1);
        contentRect.anchorMax = new Vector2(1, 1);
        contentRect.pivot = new Vector2(0.5f, 1);
        contentRect.anchoredPosition = Vector2.zero;
        
        scrollRect.content = contentRect;
        
        // Layout vertical pour la liste
        VerticalLayoutGroup vLayout = content.AddComponent<VerticalLayoutGroup>();
        vLayout.childAlignment = TextAnchor.UpperCenter;
        vLayout.spacing = 0;
        vLayout.padding = new RectOffset(20, 20, 10, 10);
        vLayout.childControlWidth = true;
        vLayout.childControlHeight = false;
        vLayout.childForceExpandWidth = true;
        vLayout.childForceExpandHeight = false;
        
        ContentSizeFitter contentSizeFitter = content.AddComponent<ContentSizeFitter>();
        contentSizeFitter.verticalFit = ContentSizeFitter.FitMode.PreferredSize;
        
        // Créer les lignes de joueurs
        for (int i = 0; i < currentPlayers.Count; i++)
        {
            CreatePlayerRow(content.transform, currentPlayers[i], i);
        }
    }
    
    /// <summary>
    /// Crée une ligne de joueur dans le classement
    /// </summary>
    private void CreatePlayerRow(Transform parent, ScoreboardPlayer player, int index)
    {
        // Vérifier si c'est le joueur actuel
        bool isCurrentUser = userData != null && 
            player.first_name == userData.first_name && 
            player.last_name == userData.last_name;
        
        GameObject row = new GameObject($"PlayerRow_{player.user_id}");
        row.transform.SetParent(parent, false);
        
        RectTransform rowRect = row.AddComponent<RectTransform>();
        rowRect.sizeDelta = new Vector2(0, 50);
        
        LayoutElement rowLayout = row.AddComponent<LayoutElement>();
        rowLayout.preferredHeight = 50;
        rowLayout.minHeight = 50;
        
        // Fond de la ligne (violet si joueur actuel, beige sinon)
        Image bgImage = row.AddComponent<Image>();
        Color bgColor = isCurrentUser ? purpleColor : new Color(0.93f, 0.87f, 0.82f, 1f); // #ede7d1
        bgImage.sprite = CreateRoundedSprite(1200, 50, 8f, bgColor);
        bgImage.raycastTarget = false;
        
        // Layout horizontal : Rang | Avatar | Nom | Entreprise | Score
        HorizontalLayoutGroup hLayout = row.AddComponent<HorizontalLayoutGroup>();
        hLayout.childAlignment = TextAnchor.MiddleLeft;
        hLayout.spacing = 15;
        hLayout.padding = new RectOffset(15, 15, 5, 5);
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = false;
        hLayout.childForceExpandHeight = false;
        
        Color textColor = isCurrentUser ? Color.white : textDarkColor;
        
        // 1. Rang (ex: "1 269e")
        GameObject rankObj = new GameObject("Rank");
        rankObj.transform.SetParent(row.transform, false);
        
        RectTransform rankRect = rankObj.AddComponent<RectTransform>();
        rankRect.sizeDelta = new Vector2(80, 40);
        
        LayoutElement rankLayoutElement = rankObj.AddComponent<LayoutElement>();
        rankLayoutElement.preferredWidth = 80;
        
        TextMeshProUGUI rankText = rankObj.AddComponent<TextMeshProUGUI>();
        rankText.text = $"{player.rank:N0}e".Replace(",", " "); // Format français avec espace
        rankText.fontSize = 16;
        rankText.color = textColor;
        rankText.alignment = TextAlignmentOptions.Left;
        rankText.raycastTarget = false;
        
        // 2. Avatar/Badge rond
        GameObject avatarObj = new GameObject("Avatar");
        avatarObj.transform.SetParent(row.transform, false);
        
        RectTransform avatarRect = avatarObj.AddComponent<RectTransform>();
        avatarRect.sizeDelta = new Vector2(40, 40);
        
        LayoutElement avatarLayoutElement = avatarObj.AddComponent<LayoutElement>();
        avatarLayoutElement.preferredWidth = 40;
        avatarLayoutElement.preferredHeight = 40;
        
        Image avatarImage = avatarObj.AddComponent<Image>();
        avatarImage.preserveAspect = true;
        avatarImage.raycastTarget = false;
        
        // Charger le badge du joueur (arrondi)
        if (!string.IsNullOrEmpty(player.badge_url))
        {
            pendingImageLoads.Add((avatarImage, player.badge_url));
        }
        else
        {
            // Badge placeholder circulaire
            avatarImage.sprite = CreateRoundedSprite(40, 40, 20f, beigeDarkColor);
        }
        
        // 3. Nom du joueur
        GameObject nameObj = new GameObject("Name");
        nameObj.transform.SetParent(row.transform, false);
        
        RectTransform nameRect = nameObj.AddComponent<RectTransform>();
        nameRect.sizeDelta = new Vector2(250, 40);
        
        LayoutElement nameLayoutElement = nameObj.AddComponent<LayoutElement>();
        nameLayoutElement.preferredWidth = 250;
        
        TextMeshProUGUI nameText = nameObj.AddComponent<TextMeshProUGUI>();
        nameText.text = $"{player.first_name} {player.last_name}";
        nameText.fontSize = 16;
        nameText.color = textColor;
        nameText.alignment = TextAlignmentOptions.Left;
        nameText.raycastTarget = false;
        nameText.overflowMode = TextOverflowModes.Ellipsis;
        
        // 4. Badge entreprise (pill)
        GameObject companyBadgeObj = new GameObject("CompanyBadge");
        companyBadgeObj.transform.SetParent(row.transform, false);
        
        RectTransform companyBadgeRect = companyBadgeObj.AddComponent<RectTransform>();
        companyBadgeRect.sizeDelta = new Vector2(100, 30);
        
        LayoutElement companyBadgeLayoutElement = companyBadgeObj.AddComponent<LayoutElement>();
        companyBadgeLayoutElement.preferredWidth = 100;
        companyBadgeLayoutElement.preferredHeight = 30;
        
        // Fond du badge pill
        Image companyBg = companyBadgeObj.AddComponent<Image>();
        Color companyBgColor = isCurrentUser ? new Color(1f, 1f, 1f, 0.3f) : new Color(0.5f, 0.5f, 0.5f, 0.3f);
        companyBg.sprite = CreateRoundedSprite(100, 30, 15f, companyBgColor);
        companyBg.raycastTarget = false;
        
        // Texte de l'entreprise
        GameObject companyTextObj = new GameObject("CompanyText");
        companyTextObj.transform.SetParent(companyBadgeObj.transform, false);
        
        RectTransform companyTextRect = companyTextObj.AddComponent<RectTransform>();
        companyTextRect.anchorMin = Vector2.zero;
        companyTextRect.anchorMax = Vector2.one;
        companyTextRect.sizeDelta = Vector2.zero;
        
        TextMeshProUGUI companyText = companyTextObj.AddComponent<TextMeshProUGUI>();
        companyText.text = player.company ?? "N/A";
        companyText.fontSize = 14;
        companyText.color = textColor;
        companyText.alignment = TextAlignmentOptions.Center;
        companyText.raycastTarget = false;
        companyText.overflowMode = TextOverflowModes.Ellipsis;
        
        // 5. Spacer flexible pour pousser le score à droite
        GameObject spacer = new GameObject("Spacer");
        spacer.transform.SetParent(row.transform, false);
        
        LayoutElement spacerLayout = spacer.AddComponent<LayoutElement>();
        spacerLayout.flexibleWidth = 1;
        
        // 6. Point coloré + Score
        GameObject scoreContainer = new GameObject("ScoreContainer");
        scoreContainer.transform.SetParent(row.transform, false);
        
        RectTransform scoreContainerRect = scoreContainer.AddComponent<RectTransform>();
        scoreContainerRect.sizeDelta = new Vector2(80, 40);
        
        LayoutElement scoreContainerLayout = scoreContainer.AddComponent<LayoutElement>();
        scoreContainerLayout.preferredWidth = 80;
        
        HorizontalLayoutGroup scoreHLayout = scoreContainer.AddComponent<HorizontalLayoutGroup>();
        scoreHLayout.childAlignment = TextAnchor.MiddleRight;
        scoreHLayout.spacing = 8;
        scoreHLayout.childControlWidth = false;
        scoreHLayout.childControlHeight = false;
        
        // Point coloré
        GameObject dotObj = new GameObject("Dot");
        dotObj.transform.SetParent(scoreContainer.transform, false);
        
        RectTransform dotRect = dotObj.AddComponent<RectTransform>();
        dotRect.sizeDelta = new Vector2(12, 12);
        
        LayoutElement dotLayout = dotObj.AddComponent<LayoutElement>();
        dotLayout.preferredWidth = 12;
        dotLayout.preferredHeight = 12;
        
        Image dotImage = dotObj.AddComponent<Image>();
        // Couleur aléatoire pour le point (ou basée sur le rang/score)
        Color dotColor = GetDotColorForRank(player.rank);
        dotImage.sprite = CreateRoundedSprite(12, 12, 6f, dotColor);
        dotImage.raycastTarget = false;
        
        // Score en pourcentage
        GameObject scoreObj = new GameObject("Score");
        scoreObj.transform.SetParent(scoreContainer.transform, false);
        
        TextMeshProUGUI scoreText = scoreObj.AddComponent<TextMeshProUGUI>();
        scoreText.text = $"{player.score}%";
        scoreText.fontSize = 16;
        scoreText.color = textColor;
        scoreText.alignment = TextAlignmentOptions.Right;
        scoreText.fontStyle = FontStyles.Bold;
        scoreText.raycastTarget = false;
    }
    
    /// <summary>
    /// Retourne une couleur pour le point en fonction du rang
    /// </summary>
    private Color GetDotColorForRank(int rank)
    {
        // Palette de couleurs pour les points
        Color[] colors = new Color[]
        {
            new Color(1f, 0.75f, 0f, 1f),     // Orange doré (#ffc000)
            new Color(0.4f, 0.6f, 1f, 1f),    // Bleu clair (#6699ff)
            new Color(0.4f, 0.6f, 1f, 1f),    // Bleu clair
            new Color(0.85f, 0.4f, 1f, 1f),   // Violet/Rose (#d966ff)
            new Color(0.6f, 0.3f, 0.2f, 1f),  // Marron (#994d33)
            new Color(0.5f, 0.3f, 0.8f, 1f),  // Violet (#8050cc)
            new Color(0.5f, 0.3f, 0.8f, 1f),  // Violet
        };
        
        // Utiliser le rang pour choisir une couleur de façon cyclique
        int colorIndex = (rank - 1) % colors.Length;
        return colors[colorIndex];
    }
    
    /// <summary>
    /// Crée un message vide (temporaire)
    /// </summary>
    private void CreateEmptyMessage(string message)
    {
        GameObject messageObj = new GameObject("EmptyMessage");
        messageObj.transform.SetParent(detailsContent.transform, false);
        
        RectTransform messageRect = messageObj.AddComponent<RectTransform>();
        messageRect.anchorMin = new Vector2(0.5f, 0.5f);
        messageRect.anchorMax = new Vector2(0.5f, 0.5f);
        messageRect.pivot = new Vector2(0.5f, 0.5f);
        messageRect.sizeDelta = new Vector2(600, 100);
        
        TextMeshProUGUI text = messageObj.AddComponent<TextMeshProUGUI>();
        text.text = message;
        text.fontSize = 24;
        text.color = textDarkColor;
        text.alignment = TextAlignmentOptions.Center;
        text.raycastTarget = false;
    }
    
    /// <summary>
    /// Crée le bouton "EXPORTER MON SUPER BADGE"
    /// </summary>
    private void CreateExportButton()
    {
        float containerHeight = config?.monSuperBadgeSection?.exportButton?.containerHeight ?? 120;
        string buttonText = config?.monSuperBadgeSection?.exportButton?.buttonText ?? "EXPORTER MON SUPER BADGE";
        string buttonStyle = config?.monSuperBadgeSection?.exportButton?.buttonStyle ?? "validationDefault";
        
        GameObject buttonContainer = new GameObject("ExportButtonContainer");
        buttonContainer.transform.SetParent(detailsContent.transform, false);
        
        RectTransform containerRect = buttonContainer.AddComponent<RectTransform>();
        containerRect.sizeDelta = new Vector2(0, containerHeight);
        
        LayoutElement containerLayout = buttonContainer.AddComponent<LayoutElement>();
        containerLayout.preferredHeight = containerHeight;
        containerLayout.minHeight = containerHeight;
        
        // Centrer le bouton
        HorizontalLayoutGroup hLayout = buttonContainer.AddComponent<HorizontalLayoutGroup>();
        hLayout.childAlignment = TextAnchor.MiddleLeft;
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = false;
        hLayout.childForceExpandHeight = false;
        
        // Créer le bouton avec le style de la config
        GameObject buttonObj = CreateStyledButton(buttonContainer.transform, buttonText, buttonStyle, OnExportBadgeClicked);
    }
    
    private void OnExportBadgeClicked()
    {
        Debug.Log("[ClassementTab] Export du super badge demandé");
        // TODO: Implémenter l'export du badge
    }
    
    private GameObject CreateStyledButton(Transform parent, string text, string styleName, System.Action onClick)
    {
        GameObject button = new GameObject("StyledButton");
        button.transform.SetParent(parent, false);
        
        ButtonStyleConfig buttonStyle = null;
        float buttonWidth = 300f;
        float buttonHeight = 80f;
        float borderRadius = 35f;
        float borderWidth = 4f;
        Color startColor = HexToColor("#CE9BFD");
        Color endColor = HexToColor("#9A2DFF");
        Color borderColor = HexToColor("#f5ece5");
        Color textColor = Color.white;
        float textFontSize = 28f;
        string fontName = "Anton-Regular SDF";
        FontStyles fontStyle = FontStyles.Bold;
        
        if (GeneralConfigManager.Instance != null)
        {
            buttonStyle = GeneralConfigManager.Instance.GetButtonStyle(styleName);
            if (buttonStyle != null)
            {
                Debug.Log($"[ClassementTab] Style '{styleName}' trouvé - width:{buttonStyle.width}, height:{buttonStyle.height}");
                buttonWidth = buttonStyle.width;
                buttonHeight = buttonStyle.height;
                borderRadius = buttonStyle.borderRadius;
                borderWidth = buttonStyle.borderWidth;
                if (buttonStyle.gradient != null && buttonStyle.gradient.enabled)
                {
                    startColor = HexToColor(buttonStyle.gradient.startColor ?? "#CE9BFD");
                    endColor = HexToColor(buttonStyle.gradient.endColor ?? "#9A2DFF");
                }
                borderColor = HexToColor(buttonStyle.borderColor ?? "#f5ece5");
                if (buttonStyle.text != null)
                {
                    textColor = HexToColor(buttonStyle.text.color ?? "#FFFFFF");
                    textFontSize = buttonStyle.text.fontSize;
                    fontName = buttonStyle.text.fontFamily ?? "Anton-Regular SDF";
                    fontStyle = buttonStyle.text.GetFontStyle();
                    Debug.Log($"[ClassementTab] Text style - fontSize:{textFontSize}, fontFamily:{fontName}, fontStyle:{fontStyle}");
                }
                else
                {
                    Debug.LogWarning($"[ClassementTab] buttonStyle.text est null pour le style '{styleName}'");
                }
            }
            else
            {
                Debug.LogWarning($"[ClassementTab] Style '{styleName}' non trouvé");
            }
        }
        
        RectTransform rect = button.AddComponent<RectTransform>();
        rect.sizeDelta = new Vector2(buttonWidth, buttonHeight);
        
        LayoutElement layoutElement = button.AddComponent<LayoutElement>();
        layoutElement.preferredWidth = buttonWidth;
        layoutElement.preferredHeight = buttonHeight;
        layoutElement.minWidth = buttonWidth;
        layoutElement.minHeight = buttonHeight;
        layoutElement.flexibleWidth = 0;
        layoutElement.flexibleHeight = 0;
        
        Image image = button.AddComponent<Image>();
        image.sprite = CreateGradientSpriteWithBorder((int)buttonWidth, (int)buttonHeight, borderRadius, 
            startColor, endColor, borderColor, borderWidth);
        image.color = Color.white;
        image.raycastTarget = true;
        
        if (buttonStyle?.shadow != null && buttonStyle.shadow.enabled)
        {
            Shadow shadow = button.GetComponent<Shadow>();
            if (shadow == null) shadow = button.AddComponent<Shadow>();
            shadow.effectColor = HexToColor(buttonStyle.shadow.color ?? "#00000040");
            shadow.effectDistance = new Vector2(buttonStyle.shadow.offsetX, -buttonStyle.shadow.offsetY);
        }
        
        Button btn = button.AddComponent<Button>();
        btn.targetGraphic = image;
        btn.interactable = true;
        
        ColorBlock colors = btn.colors;
        colors.normalColor = Color.white;
        colors.highlightedColor = new Color(1.1f, 1.1f, 1.1f, 1f);
        colors.pressedColor = new Color(0.9f, 0.9f, 0.9f, 1f);
        btn.colors = colors;
        
        if (onClick != null)
        {
            btn.onClick.AddListener(() => onClick());
        }
        
        GameObject textObj = new GameObject("Text");
        textObj.transform.SetParent(button.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.sizeDelta = Vector2.zero;
        textRect.anchoredPosition = Vector2.zero;
        
        TextMeshProUGUI buttonText = textObj.AddComponent<TextMeshProUGUI>();
        buttonText.text = text;
        buttonText.fontSize = textFontSize;
        buttonText.color = textColor;
        buttonText.alignment = TextAlignmentOptions.Center;
        buttonText.fontStyle = fontStyle;
        buttonText.raycastTarget = false;
        
        TMP_FontAsset font = Resources.Load<TMP_FontAsset>($"Fonts/{fontName}");
        if (font != null) buttonText.font = font;
        
        return button;
    }
    
    /// <summary>
    /// Crée la section supérieure avec badge à gauche et options de confidentialité à droite
    /// (Réutilisée pour MON SUPERBADGE)
    /// </summary>
    private void CreateTopSection()
    {
        GameObject topSection = new GameObject("TopSection");
        topSection.transform.SetParent(detailsContent.transform, false);
        
        // Récupérer la config de monSuperBadgeSection
        float height = config?.monSuperBadgeSection?.height ?? 280;
        float columnSpacing = config?.monSuperBadgeSection?.columnSpacing ?? 30;
        
        Color bgColor = new Color(0.93f, 0.91f, 0.88f, 1f); // #ede7e1 par défaut
        if (config?.monSuperBadgeSection != null && !string.IsNullOrEmpty(config.monSuperBadgeSection.backgroundColor))
        {
            bgColor = HexToColor(config.monSuperBadgeSection.backgroundColor);
        }
        
        RectTransform topRect = topSection.AddComponent<RectTransform>();
        topRect.sizeDelta = new Vector2(0, height);
        
        LayoutElement topLayout = topSection.AddComponent<LayoutElement>();
        topLayout.preferredHeight = height;
        topLayout.minHeight = height;
        
        // Fond
        Image bgImage = topSection.AddComponent<Image>();
        bgImage.color = bgColor;
        bgImage.raycastTarget = false;
        
        // Récupérer le padding depuis la config
        int padLeft = 40, padRight = 40, padTop = 30, padBottom = 30;
        if (config?.monSuperBadgeSection?.padding != null)
        {
            padLeft = (int)(config.monSuperBadgeSection.padding.left);
            padRight = (int)(config.monSuperBadgeSection.padding.right);
            padTop = (int)(config.monSuperBadgeSection.padding.top);
            padBottom = (int)(config.monSuperBadgeSection.padding.bottom);
        }
        
        // Layout horizontal : Badge (gauche) | Infos (milieu) | Options (droite)
        HorizontalLayoutGroup hLayout = topSection.AddComponent<HorizontalLayoutGroup>();
        hLayout.childAlignment = TextAnchor.UpperCenter;
        hLayout.spacing = columnSpacing;
        hLayout.padding = new RectOffset(padLeft, padRight, padTop, padBottom);
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = false;
        hLayout.childForceExpandHeight = false;
        
        // 1. Badge à gauche
        CreateBadgeVisual(topSection.transform);
        
        // 2. Bloc d'informations au milieu
        CreateInfoBlock(topSection.transform);
        
        // 3. Options de confidentialité à droite
        CreateConfidentialityOptions(topSection.transform);
    }
    
    /// <summary>
    /// Crée le bloc d'informations au milieu (Classement, Score, etc.)
    /// </summary>
    private void CreateInfoBlock(Transform parent)
    {
        GameObject infoBlock = new GameObject("InfoBlock");
        infoBlock.transform.SetParent(parent, false);
        
        float width = config?.monSuperBadgeSection?.infoColumn?.width ?? 350;
        float height = config?.monSuperBadgeSection?.infoColumn?.height ?? 200;
        float cornerRadius = config?.monSuperBadgeSection?.infoColumn?.cornerRadius ?? 20;
        Color bgColor = HexToColor(config?.monSuperBadgeSection?.infoColumn?.backgroundColor ?? "#ede1d2");
        
        RectTransform infoRect = infoBlock.AddComponent<RectTransform>();
        infoRect.sizeDelta = new Vector2(width, height);
        
        LayoutElement infoLayout = infoBlock.AddComponent<LayoutElement>();
        infoLayout.preferredWidth = width;
        infoLayout.preferredHeight = height;
        
        // Fond beige clair avec coins arrondis
        Image bgImage = infoBlock.AddComponent<Image>();
        bgImage.sprite = CreateRoundedSprite((int)width, (int)height, cornerRadius, bgColor);
        bgImage.raycastTarget = false;
        
        // Layout vertical pour les lignes d'info
        int padLeft = (int)(config?.monSuperBadgeSection?.infoColumn?.padding?.left ?? 20);
        int padRight = (int)(config?.monSuperBadgeSection?.infoColumn?.padding?.right ?? 20);
        int padTop = (int)(config?.monSuperBadgeSection?.infoColumn?.padding?.top ?? 20);
        int padBottom = (int)(config?.monSuperBadgeSection?.infoColumn?.padding?.bottom ?? 20);
        float lineSpacing = config?.monSuperBadgeSection?.infoColumn?.lineSpacing ?? 12;
        
        VerticalLayoutGroup vLayout = infoBlock.AddComponent<VerticalLayoutGroup>();
        vLayout.childAlignment = TextAnchor.UpperLeft;
        vLayout.spacing = lineSpacing;
        vLayout.padding = new RectOffset(padLeft, padRight, padTop, padBottom);
        vLayout.childControlWidth = false;
        vLayout.childControlHeight = false;
        vLayout.childForceExpandWidth = false;
        vLayout.childForceExpandHeight = false;
        
        // Titre "Classement"
        string titleText = config?.monSuperBadgeSection?.infoColumn?.title?.text ?? "Classement";
        float titleFontSize = config?.monSuperBadgeSection?.infoColumn?.title?.fontSize ?? 24;
        string titleFontName = config?.monSuperBadgeSection?.infoColumn?.title?.fontName ?? "Anton-Regular SDF";
        Color titleColor = HexToColor(config?.monSuperBadgeSection?.infoColumn?.title?.color ?? "#59504a");
        float titleTopMargin = config?.monSuperBadgeSection?.infoColumn?.title?.topMargin ?? 0;
        
        if (titleTopMargin > 0)
        {
            GameObject spacer = new GameObject("TitleSpacer");
            spacer.transform.SetParent(infoBlock.transform, false);
            LayoutElement spacerLayout = spacer.AddComponent<LayoutElement>();
            spacerLayout.preferredHeight = titleTopMargin;
        }
        
        GameObject titleObj = new GameObject("Title");
        titleObj.transform.SetParent(infoBlock.transform, false);
        
        TextMeshProUGUI titleTextComp = titleObj.AddComponent<TextMeshProUGUI>();
        titleTextComp.text = titleText;
        titleTextComp.fontSize = titleFontSize;
        titleTextComp.color = titleColor;
        titleTextComp.fontStyle = FontStyles.Bold;
        titleTextComp.alignment = TextAlignmentOptions.Left;
        titleTextComp.raycastTarget = false;
        
        // Charger la police
        TMP_FontAsset font = Resources.Load<TMP_FontAsset>($"Fonts/{titleFontName}");
        if (font != null) titleTextComp.font = font;
        
        // Ligne 1 : Score
        scoreInfoText = CreateInfoLine(infoBlock.transform, "", "Score :", "0");
        
        // Ligne 2 : État
        stateInfoText = CreateInfoLine(infoBlock.transform, "", "État :", "vide");
        
        // Ligne 3 : Positionnement
        rankInfoText = CreateInfoLine(infoBlock.transform, "", "Positionnement :", "Inconnu");
        
        // Ligne 4 : Nombre de quêtes complétées
        questsInfoText = CreateInfoLine(infoBlock.transform, "", "Nombre de quêtes complétées :", "0");
        
        // Ligne 5 : Nombre de formations réalisées
        trainingsInfoText = CreateInfoLine(infoBlock.transform, "", "Nombre de formations réalisées :", "0");
        
        // Si les données utilisateur sont déjà chargées, les afficher immédiatement
        if (userData != null)
        {
            Debug.Log("[ClassementTab] 📊 userData déjà présent dans CreateInfoBlock, mise à jour immédiate");
            UpdateInfoBlock();
        }
        else
        {
            Debug.LogWarning("[ClassementTab] ⚠️ userData null dans CreateInfoBlock, utilisation de UserDataManager en attendant");
            // Fallback: utiliser UserDataManager si l'API ne répond pas
            UpdateInfoBlockFromUserDataManager();
        }
    }
    
    /// <summary>
    /// Met à jour le bloc d'informations avec les données de UserDataManager (fallback)
    /// </summary>
    private void UpdateInfoBlockFromUserDataManager()
    {
        if (UserDataManager.Instance == null)
        {
            Debug.LogWarning("[ClassementTab] ⚠️ UserDataManager pas disponible");
            return;
        }
        
        Debug.Log("[ClassementTab] 📊 Utilisation des données de UserDataManager comme fallback");
        
        // On ne peut pas afficher le score et l'état du badge car ces infos ne sont pas dans UserDataManager
        // Mais on peut afficher les autres informations si disponibles
        
        if (trainingsInfoText != null)
        {
            trainingsInfoText.text = "N/A";
            Debug.Log("[ClassementTab] ✅ Formations: N/A (non disponible dans UserDataManager)");
        }
    }
    
    /// <summary>
    /// Crée une ligne de séparation
    /// </summary>
    private void CreateSeparatorLine(Transform parent, float width)
    {
        GameObject separator = new GameObject("Separator");
        separator.transform.SetParent(parent, false);
        
        float height = config?.monSuperBadgeSection?.infoColumn?.separator?.height ?? 2;
        Color separatorColor = HexToColor(config?.monSuperBadgeSection?.infoColumn?.separator?.color ?? "#b0a090");
        
        RectTransform sepRect = separator.AddComponent<RectTransform>();
        sepRect.sizeDelta = new Vector2(width, height);
        
        LayoutElement sepLayout = separator.AddComponent<LayoutElement>();
        sepLayout.preferredWidth = width;
        sepLayout.preferredHeight = height;
        
        Image sepImage = separator.AddComponent<Image>();
        sepImage.color = separatorColor;
        sepImage.raycastTarget = false;
    }
    
    /// <summary>
    /// Crée une ligne d'information avec icône, label et valeur
    /// </summary>
    private TextMeshProUGUI CreateInfoLine(Transform parent, string icon, string label, string value)
    {
        GameObject line = new GameObject($"InfoLine_{label}");
        line.transform.SetParent(parent, false);
        
        float labelFontSize = config?.monSuperBadgeSection?.infoColumn?.lineStyle?.labelFontSize ?? 14;
        Color labelColor = HexToColor(config?.monSuperBadgeSection?.infoColumn?.lineStyle?.labelColor ?? "#59504a");
        float lineHeight = config?.monSuperBadgeSection?.infoColumn?.lineStyle?.lineHeight ?? 20;
        float infoWidth = config?.monSuperBadgeSection?.infoColumn?.width ?? 350;
        float padLeft = config?.monSuperBadgeSection?.infoColumn?.padding?.left ?? 20;
        float padRight = config?.monSuperBadgeSection?.infoColumn?.padding?.right ?? 20;
        float lineWidth = Mathf.Max(0, infoWidth - padLeft - padRight);
        
        RectTransform lineRect = line.AddComponent<RectTransform>();
        lineRect.sizeDelta = new Vector2(lineWidth, lineHeight);
        lineRect.anchorMin = new Vector2(0, 1);
        lineRect.anchorMax = new Vector2(0, 1);
        lineRect.pivot = new Vector2(0, 1);
        
        LayoutElement lineLayout = line.AddComponent<LayoutElement>();
        lineLayout.preferredHeight = lineHeight;
        lineLayout.preferredWidth = lineWidth;
        
        // Un seul TextMeshProUGUI pour toute la ligne
        TextMeshProUGUI lineText = line.AddComponent<TextMeshProUGUI>();
        lineText.text = $"{label} <b>{value}</b>";
        lineText.fontSize = labelFontSize;
        lineText.color = labelColor;
        lineText.alignment = TextAlignmentOptions.Left;
        lineText.raycastTarget = false;
        lineText.richText = true;
        lineText.overflowMode = TextOverflowModes.Overflow;
        lineText.enableWordWrapping = false;
        
        RectTransform textRect = lineText.GetComponent<RectTransform>();
        textRect.anchorMin = new Vector2(0, 0);
        textRect.anchorMax = new Vector2(1, 1);
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;
        
        return lineText;
    }
    
    /// <summary>
    /// Crée le visuel du badge à gauche (avec fond arrondi beige + score)
    /// </summary>
    private void CreateBadgeVisual(Transform parent)
    {
        GameObject badgeContainer = new GameObject("BadgeContainer");
        badgeContainer.transform.SetParent(parent, false);
        
        // Lire les dimensions depuis la config
        float badgeWidth = config?.monSuperBadgeSection?.badgeColumn?.width ?? 200;
        float badgeHeight = config?.monSuperBadgeSection?.badgeColumn?.height ?? 220;
        float imageWidth = config?.monSuperBadgeSection?.badgeColumn?.imageWidth ?? 182;
        float imageHeight = config?.monSuperBadgeSection?.badgeColumn?.imageHeight ?? 210;
        float scoreFontSize = config?.monSuperBadgeSection?.badgeColumn?.scoreFontSize ?? 32;
        
        // Récupérer la position du score
        string scoreMode = config?.monSuperBadgeSection?.badgeColumn?.scorePosition?.mode ?? config?.topSection?.badge?.scorePosition?.mode ?? "overlay";
        float scoreOffsetX = config?.monSuperBadgeSection?.badgeColumn?.scorePosition?.offsetX ?? config?.topSection?.badge?.scorePosition?.offsetX ?? 0;
        float scoreOffsetY = config?.monSuperBadgeSection?.badgeColumn?.scorePosition?.offsetY ?? config?.topSection?.badge?.scorePosition?.offsetY ?? 10;
        
        // Couleur du score
        Color scoreColor = purpleColor;
        if (config?.monSuperBadgeSection?.badgeColumn != null && !string.IsNullOrEmpty(config.monSuperBadgeSection.badgeColumn.scoreColor))
        {
            scoreColor = HexToColor(config.monSuperBadgeSection.badgeColumn.scoreColor);
        }
        else if (config?.topSection?.badge != null && !string.IsNullOrEmpty(config.topSection.badge.scoreColor))
        {
            scoreColor = HexToColor(config.topSection.badge.scoreColor);
        }
        
        RectTransform badgeRect = badgeContainer.AddComponent<RectTransform>();
        badgeRect.sizeDelta = new Vector2(badgeWidth, badgeHeight);
        
        LayoutElement badgeLayout = badgeContainer.AddComponent<LayoutElement>();
        badgeLayout.preferredWidth = badgeWidth;
        badgeLayout.preferredHeight = badgeHeight;

        // Cadre de fond configurable sous le visuel
        float frameWidth = config?.monSuperBadgeSection?.badgeColumn?.frame?.width ?? badgeWidth;
        float frameHeight = config?.monSuperBadgeSection?.badgeColumn?.frame?.height ?? badgeHeight;
        float frameOffsetX = config?.monSuperBadgeSection?.badgeColumn?.frame?.offsetX ?? 0;
        float frameOffsetY = config?.monSuperBadgeSection?.badgeColumn?.frame?.offsetY ?? 0;
        float frameCornerRadius = config?.monSuperBadgeSection?.badgeColumn?.frame?.cornerRadius ?? 20;
        Color frameColor = HexToColor(config?.monSuperBadgeSection?.badgeColumn?.frame?.backgroundColor ?? "#ede1d2");
        
        GameObject frameObj = new GameObject("BadgeFrame");
        frameObj.transform.SetParent(badgeContainer.transform, false);
        frameObj.transform.SetAsFirstSibling();
        
        RectTransform frameRect = frameObj.AddComponent<RectTransform>();
        frameRect.anchorMin = new Vector2(0.5f, 0.5f);
        frameRect.anchorMax = new Vector2(0.5f, 0.5f);
        frameRect.pivot = new Vector2(0.5f, 0.5f);
        frameRect.anchoredPosition = new Vector2(frameOffsetX, frameOffsetY);
        frameRect.sizeDelta = new Vector2(frameWidth, frameHeight);
        
        Image frameImage = frameObj.AddComponent<Image>();
        frameImage.sprite = CreateRoundedSprite((int)frameWidth, (int)frameHeight, frameCornerRadius, frameColor);
        frameImage.raycastTarget = false;
        
        bool useOverlay = scoreMode == "overlay";
        
        if (!useOverlay)
        {
            // Mode "below" : Layout vertical classique (badge + score)
            VerticalLayoutGroup vLayout = badgeContainer.AddComponent<VerticalLayoutGroup>();
            vLayout.padding = new RectOffset(10, 10, 15, 10);
            vLayout.spacing = 10;
            vLayout.childAlignment = TextAnchor.UpperCenter;
            vLayout.childControlWidth = false;
            vLayout.childControlHeight = false;
        }
        
        // Image du badge (PNG)
        GameObject badgeImage = new GameObject("BadgeImage");
        badgeImage.transform.SetParent(badgeContainer.transform, false);
        
        RectTransform imgRect = badgeImage.AddComponent<RectTransform>();
        
        if (useOverlay)
        {
            // Mode overlay : badge centré dans le conteneur
            imgRect.anchorMin = new Vector2(0.5f, 0.5f);
            imgRect.anchorMax = new Vector2(0.5f, 0.5f);
            imgRect.pivot = new Vector2(0.5f, 0.5f);
            imgRect.anchoredPosition = Vector2.zero;
        }
        
        imgRect.sizeDelta = new Vector2(imageWidth, imageHeight);
        
        userBadgeImage = badgeImage.AddComponent<Image>();
        userBadgeImage.color = Color.white;
        userBadgeImage.sprite = CreateCircleSprite();
        
        if (!useOverlay)
        {
            LayoutElement imgLayout = badgeImage.AddComponent<LayoutElement>();
            imgLayout.preferredWidth = imageWidth;
            imgLayout.preferredHeight = imageHeight;
        }
        
        // Score
        GameObject scoreObj = new GameObject("ScoreText");
        scoreObj.transform.SetParent(badgeContainer.transform, false);
        
        RectTransform scoreRect = scoreObj.AddComponent<RectTransform>();
        
        if (useOverlay)
        {
            // Mode overlay : score centré sur le badge avec offset
            scoreRect.anchorMin = new Vector2(0.5f, 0.5f);
            scoreRect.anchorMax = new Vector2(0.5f, 0.5f);
            scoreRect.pivot = new Vector2(0.5f, 0.5f);
            scoreRect.anchoredPosition = new Vector2(scoreOffsetX, scoreOffsetY);
            scoreRect.sizeDelta = new Vector2(badgeWidth, 40);
        }
        else
        {
            // Mode below : score positionné normalement sous le badge
            scoreRect.sizeDelta = new Vector2(badgeWidth, 30);
        }
        
        userScoreText = scoreObj.AddComponent<TextMeshProUGUI>();
        userScoreText.text = "0"; // Sera mis à jour
        userScoreText.fontSize = scoreFontSize;
        userScoreText.fontStyle = FontStyles.Bold;
        userScoreText.color = scoreColor;
        userScoreText.alignment = TextAlignmentOptions.Center;
    }
    
    /// <summary>
    /// Crée la section des options de confidentialité à droite
    /// </summary>
    private void CreateConfidentialityOptions(Transform parent)
    {
        GameObject optionsContainer = new GameObject("ConfidentialityOptions");
        optionsContainer.transform.SetParent(parent, false);
        
        // Lire les configurations
        float width = config?.monSuperBadgeSection?.confidentialityColumn?.width ?? 300;
        float height = config?.monSuperBadgeSection?.confidentialityColumn?.height ?? 220;
        float cornerRadius = config?.monSuperBadgeSection?.confidentialityColumn?.cornerRadius ?? 20;
        Color bgColor = HexToColor(config?.monSuperBadgeSection?.confidentialityColumn?.backgroundColor ?? "#ede1d2");
        float spacing = config?.monSuperBadgeSection?.confidentialityColumn?.spacing ?? 15;
        
        int padLeft = (int)(config?.monSuperBadgeSection?.confidentialityColumn?.padding?.left ?? 15);
        int padRight = (int)(config?.monSuperBadgeSection?.confidentialityColumn?.padding?.right ?? 15);
        int padTop = (int)(config?.monSuperBadgeSection?.confidentialityColumn?.padding?.top ?? 15);
        int padBottom = (int)(config?.monSuperBadgeSection?.confidentialityColumn?.padding?.bottom ?? 15);
        
        RectTransform optionsRect = optionsContainer.AddComponent<RectTransform>();
        optionsRect.sizeDelta = new Vector2(width, height);
        
        LayoutElement optionsLayout = optionsContainer.AddComponent<LayoutElement>();
        optionsLayout.preferredWidth = width;
        optionsLayout.preferredHeight = height;
        
        // Fond beige avec coins arrondis
        Image bgImage = optionsContainer.AddComponent<Image>();
        bgImage.sprite = CreateRoundedSprite((int)width, (int)height, cornerRadius, bgColor);
        bgImage.raycastTarget = false;
        
        // Layout vertical pour organiser : Titre | Question | Confidentialité
        VerticalLayoutGroup vLayout = optionsContainer.AddComponent<VerticalLayoutGroup>();
        vLayout.spacing = spacing;
        vLayout.padding = new RectOffset(padLeft, padRight, padTop, padBottom);
        vLayout.childAlignment = TextAnchor.UpperCenter;
        vLayout.childControlWidth = false;
        vLayout.childControlHeight = false;
        vLayout.childForceExpandWidth = false;
        vLayout.childForceExpandHeight = false;
        
        // Titre "Confidentialité"
        string titleTextStr = config?.monSuperBadgeSection?.confidentialityColumn?.title?.text ?? "Confidentialité";
        float titleFontSize = config?.monSuperBadgeSection?.confidentialityColumn?.title?.fontSize ?? 20;
        string titleFontName = config?.monSuperBadgeSection?.confidentialityColumn?.title?.fontName ?? "Anton-Regular SDF";
        Color titleColor = HexToColor(config?.monSuperBadgeSection?.confidentialityColumn?.title?.color ?? "#59504a");
        float titleTopMargin = config?.monSuperBadgeSection?.confidentialityColumn?.title?.topMargin ?? 0;
        
        if (titleTopMargin > 0)
        {
            GameObject spacer = new GameObject("TitleSpacer");
            spacer.transform.SetParent(optionsContainer.transform, false);
            LayoutElement spacerLayout = spacer.AddComponent<LayoutElement>();
            spacerLayout.preferredHeight = titleTopMargin;
        }
        
        GameObject titleObj = new GameObject("Title");
        titleObj.transform.SetParent(optionsContainer.transform, false);
        
        RectTransform titleRect = titleObj.AddComponent<RectTransform>();
        titleRect.sizeDelta = new Vector2(width - padLeft - padRight, 25);
        
        TextMeshProUGUI titleText = titleObj.AddComponent<TextMeshProUGUI>();
        titleText.text = titleTextStr;
        titleText.fontSize = titleFontSize;
        titleText.color = titleColor;
        titleText.fontStyle = FontStyles.Bold;
        titleText.alignment = TextAlignmentOptions.Left;
        titleText.raycastTarget = false;
        
        // Charger la police
        TMP_FontAsset font = Resources.Load<TMP_FontAsset>($"Fonts/{titleFontName}");
        if (font != null) titleText.font = font;
        
        // Question (prend toute la largeur)
        GameObject questionObj = new GameObject("QuestionText");
        questionObj.transform.SetParent(optionsContainer.transform, false);
        
        string questionTextStr = config?.monSuperBadgeSection?.confidentialityColumn?.question?.text ?? "Souhaites-tu rendre ton super-badge public pour pouvoir te comparer aux autres joueurs ?";
        float questionFontSize = config?.monSuperBadgeSection?.confidentialityColumn?.question?.fontSize ?? 14;
        float questionHeight = config?.monSuperBadgeSection?.confidentialityColumn?.question?.height ?? 60;
        Color questionColor = HexToColor(config?.monSuperBadgeSection?.confidentialityColumn?.question?.color ?? "#59504a");
        
        RectTransform questionRect = questionObj.AddComponent<RectTransform>();
        questionRect.sizeDelta = new Vector2(width - padLeft - padRight, questionHeight);
        
        LayoutElement questionLayoutElem = questionObj.AddComponent<LayoutElement>();
        questionLayoutElem.preferredWidth = width - padLeft - padRight;
        questionLayoutElem.preferredHeight = questionHeight;
        
        TextMeshProUGUI questionText = questionObj.AddComponent<TextMeshProUGUI>();
        questionText.text = questionTextStr;
        questionText.fontSize = questionFontSize;
        questionText.fontStyle = FontStyles.Normal;
        questionText.color = questionColor;
        questionText.alignment = TextAlignmentOptions.Center;
        questionText.textWrappingMode = TextWrappingModes.Normal;
        questionText.raycastTarget = false;
        
        // Section Confidentialité
        CreateConfidentialityRadioButtons(optionsContainer.transform);
    }
    
    /// <summary>
    /// Crée les boutons radio pour la confidentialité
    /// </summary>
    private void CreateConfidentialityRadioButtons(Transform parent)
    {
        GameObject radioContainer = new GameObject("RadioButtonsContainer");
        radioContainer.transform.SetParent(parent, false);
        
        float labelFontSize = config?.monSuperBadgeSection?.confidentialityColumn?.radioButtons?.labelFontSize ?? 14;
        float spacing = config?.monSuperBadgeSection?.confidentialityColumn?.radioButtons?.spacing ?? 8;
        float totalWidth = config?.monSuperBadgeSection?.confidentialityColumn?.width ?? 300;
        float padLeft = config?.monSuperBadgeSection?.confidentialityColumn?.padding?.left ?? 15;
        float padRight = config?.monSuperBadgeSection?.confidentialityColumn?.padding?.right ?? 15;
        float availableWidth = Mathf.Max(0, totalWidth - padLeft - padRight);
        float weightPrive = config?.monSuperBadgeSection?.confidentialityColumn?.radioButtons?.optionWeights?.prive ?? 1;
        float weightEntreprise = config?.monSuperBadgeSection?.confidentialityColumn?.radioButtons?.optionWeights?.entreprise ?? 1;
        float weightPublic = config?.monSuperBadgeSection?.confidentialityColumn?.radioButtons?.optionWeights?.publicOpt ?? 1;
        float totalWeight = Mathf.Max(0.001f, weightPrive + weightEntreprise + weightPublic);
        float gapTotal = spacing * 2;
        float usableWidth = Mathf.Max(0, availableWidth - gapTotal);
        float optionWidthPrive = usableWidth * (weightPrive / totalWeight);
        float optionWidthEntreprise = usableWidth * (weightEntreprise / totalWeight);
        float optionWidthPublic = usableWidth * (weightPublic / totalWeight);
        float optionHeight = 30;
        
        RectTransform radioRect = radioContainer.AddComponent<RectTransform>();
        radioRect.sizeDelta = new Vector2(availableWidth, optionHeight);
        
        LayoutElement radioLayoutElem = radioContainer.AddComponent<LayoutElement>();
        radioLayoutElem.preferredWidth = availableWidth;
        radioLayoutElem.preferredHeight = optionHeight;
        
        // Layout horizontal pour les 3 options sur la même ligne
        HorizontalLayoutGroup hLayout = radioContainer.AddComponent<HorizontalLayoutGroup>();
        hLayout.spacing = spacing;
        hLayout.childAlignment = TextAnchor.MiddleCenter;
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = true;
        hLayout.childForceExpandHeight = false;
        
        // 3 options radio (cliquables)
        checkboxPrive = CreateRadioOption(radioContainer.transform, "Privé", "private", false, labelFontSize, optionWidthPrive, optionHeight);
        checkboxEntreprise = CreateRadioOption(radioContainer.transform, "Mon entreprise", "company", false, labelFontSize, optionWidthEntreprise, optionHeight);
        checkboxPublic = CreateRadioOption(radioContainer.transform, "Public", "public", true, labelFontSize, optionWidthPublic, optionHeight); // Coché par défaut
    }
    
    /// <summary>
    /// Crée une option radio avec case à cocher (cliquable)
    /// </summary>
    private Image CreateRadioOption(Transform parent, string label, string visibilityValue, bool isChecked, float fontSize, float optionWidth, float optionHeight)
    {
        GameObject optionContainer = new GameObject($"RadioOption_{label}");
        optionContainer.transform.SetParent(parent, false);
        
        // Récupérer la taille de la checkbox depuis la config
        float checkboxSize = config?.monSuperBadgeSection?.confidentialityColumn?.radioButtons?.checkboxSize ?? 24;
        
        RectTransform optionRect = optionContainer.AddComponent<RectTransform>();
        optionRect.sizeDelta = new Vector2(optionWidth, optionHeight);
        
        LayoutElement optionLayout = optionContainer.AddComponent<LayoutElement>();
        optionLayout.preferredWidth = optionWidth;
        optionLayout.preferredHeight = optionHeight;
        optionLayout.minWidth = optionWidth;
        optionLayout.flexibleWidth = 1;
        
        // Layout horizontal pour : case + label
        HorizontalLayoutGroup hLayout = optionContainer.AddComponent<HorizontalLayoutGroup>();
        hLayout.spacing = 5;
        hLayout.childAlignment = TextAnchor.MiddleCenter;
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        
        // Case à cocher (PNG depuis uiPath)
        GameObject checkboxObj = new GameObject("Checkbox");
        checkboxObj.transform.SetParent(optionContainer.transform, false);
        
        RectTransform checkRect = checkboxObj.AddComponent<RectTransform>();
        checkRect.sizeDelta = new Vector2(checkboxSize, checkboxSize);
        
        Image checkBg = checkboxObj.AddComponent<Image>();
        checkBg.color = Color.white; // Blanc pour que le PNG s'affiche correctement
        
        LayoutElement checkLayout = checkboxObj.AddComponent<LayoutElement>();
        checkLayout.preferredWidth = checkboxSize;
        checkLayout.preferredHeight = checkboxSize;
        
        // Ajouter à la liste des images à charger (sera chargé quand l'onglet est actif)
        string imageName = isChecked ? "check_box_checked.png" : "check_box_unchecked.png";
        string imageUrl = GeneralConfigManager.Instance?.GetUIUrl(imageName) ?? "";
        if (!string.IsNullOrEmpty(imageUrl))
        {
            pendingImageLoads.Add((checkBg, imageUrl));
        }
        
        // Rendre la checkbox cliquable
        Button checkboxButton = checkboxObj.AddComponent<Button>();
        checkboxButton.targetGraphic = checkBg;
        checkboxButton.transition = Selectable.Transition.None;
        checkboxButton.onClick.AddListener(() => OnVisibilityChanged(visibilityValue));
        
        // Label
        GameObject labelObj = new GameObject("Label");
        labelObj.transform.SetParent(optionContainer.transform, false);
        
        TextMeshProUGUI labelText = labelObj.AddComponent<TextMeshProUGUI>();
        labelText.text = label;
        labelText.fontSize = fontSize;
        labelText.color = textDarkColor;
        labelText.alignment = TextAlignmentOptions.Left;
        
        return checkBg; // Retourner l'Image pour pouvoir la mettre à jour
    }
    
    /// <summary>
    /// Appelé quand l'utilisateur change la visibilité (boutons radios)
    /// </summary>
    private void OnVisibilityChanged(string newVisibility)
    {
        if (currentVisibility == newVisibility)
        {
            return; // Déjà sélectionné, ne rien faire
        }
        
        currentVisibility = newVisibility;
        Debug.Log($"[ClassementTab] 🔒 Visibilité changée: {newVisibility}");
        
        // Mettre à jour les checkboxes (comportement radio: une seule cochée)
        UpdateCheckboxes();
        
        // Envoyer à l'API pour sauvegarder la préférence
        StartCoroutine(SaveVisibilityToApi(newVisibility));
    }
    
    /// <summary>
    /// Envoie la nouvelle visibilité à l'API
    /// </summary>
    private IEnumerator SaveVisibilityToApi(string visibility)
    {
        string baseUrl = GeneralConfigManager.Instance?.GetApiBaseUrl();
        if (string.IsNullOrEmpty(baseUrl))
        {
            Debug.LogError("[ClassementTab] ❌ BaseUrl non définie");
            yield break;
        }
        
        string url = $"{baseUrl}/api/ujsa/user/leaderboard-visibility";
        
        // Créer le JSON
        string jsonData = $"{{\"visibility\": \"{visibility}\"}}";
        
        Debug.Log($"[ClassementTab] 📤 POST vers {url} avec données: {jsonData}");
        
        using (UnityWebRequest www = UnityWebRequest.Post(url, jsonData, "application/json"))
        {
            // Ajouter le token d'authentification
            string token = UserDataManager.Instance?.token;
            if (!string.IsNullOrEmpty(token))
            {
                www.SetRequestHeader("Authorization", $"Bearer {token}");
            }
            
            yield return www.SendWebRequest();
            
            if (www.result == UnityWebRequest.Result.Success)
            {
                Debug.Log($"[ClassementTab] ✅ Visibilité sauvegardée: {visibility}");
                
                // Attendre 0.2 secondes puis recharger les données
                yield return new WaitForSeconds(0.2f);
                
                Debug.Log("[ClassementTab] 🔄 Rechargement des données après changement de visibilité");
                
                // Recharger les données utilisateur
                LoadUserData();
                
                // Recharger le classement
                isLoadingData = false; // Réinitialiser le flag
                LoadScoreboardData();
            }
            else
            {
                Debug.LogError($"[ClassementTab] ❌ Erreur sauvegarde visibilité: {www.error}");
                Debug.LogError($"[ClassementTab] ❌ Response: {www.downloadHandler?.text}");
            }
        }
    }
    
    /// <summary>
    /// Met à jour l'affichage des checkboxes
    /// </summary>
    private void UpdateCheckboxes()
    {
        if (checkboxPrive != null)
        {
            string url = GeneralConfigManager.Instance?.GetUIUrl(
                currentVisibility == "private" ? "check_box_checked.png" : "check_box_unchecked.png") ?? "";
            if (!string.IsNullOrEmpty(url))
            {
                StartCoroutine(LoadImageSprite(url, checkboxPrive));
            }
        }
        
        if (checkboxEntreprise != null)
        {
            string url = GeneralConfigManager.Instance?.GetUIUrl(
                currentVisibility == "company" ? "check_box_checked.png" : "check_box_unchecked.png") ?? "";
            if (!string.IsNullOrEmpty(url))
            {
                StartCoroutine(LoadImageSprite(url, checkboxEntreprise));
            }
        }
        
        if (checkboxPublic != null)
        {
            string url = GeneralConfigManager.Instance?.GetUIUrl(
                currentVisibility == "public" ? "check_box_checked.png" : "check_box_unchecked.png") ?? "";
            if (!string.IsNullOrEmpty(url))
            {
                StartCoroutine(LoadImageSprite(url, checkboxPublic));
            }
        }
    }
    
    /// <summary>
    /// Crée le bouton "Exporter mon super-badge" avec le style validationDefault (PAS DE VALEURS EN DUR)
    /// </summary>
    private void CreateExportButton(Transform parent)
    {
        // Récupérer le style depuis la config
        ButtonStyleConfig buttonStyle = null;
        float buttonWidth = 300f; // Valeur par défaut si config échoue
        float buttonHeight = 80f;
        float borderRadius = 35f;
        float borderWidth = 4f;
        Color startColor = HexToColor("#CE9BFD");
        Color endColor = HexToColor("#9A2DFF");
        Color borderColor = HexToColor("#ffffff");
        Color textColor = Color.white;
        float textFontSize = 28f;
        string fontFamily = "Anton-Regular SDF";
        
        if (GeneralConfigManager.Instance != null)
        {
            buttonStyle = GeneralConfigManager.Instance.GetButtonStyle("exportBadgeButton");
            if (buttonStyle != null)
            {
                // Lire TOUTES les valeurs depuis le config
                buttonWidth = buttonStyle.width;
                buttonHeight = buttonStyle.height;
                borderRadius = buttonStyle.borderRadius;
                borderWidth = buttonStyle.borderWidth;
                
                if (buttonStyle.gradient != null && buttonStyle.gradient.enabled)
                {
                    startColor = HexToColor(buttonStyle.gradient.startColor ?? "#CE9BFD");
                    endColor = HexToColor(buttonStyle.gradient.endColor ?? "#9A2DFF");
                }
                
                borderColor = HexToColor(buttonStyle.borderColor ?? "#ffffff");
                
                if (buttonStyle.text != null)
                {
                    textColor = HexToColor(buttonStyle.text.color ?? "#FFFFFF");
                    textFontSize = buttonStyle.text.fontSize;
                    if (!string.IsNullOrEmpty(buttonStyle.text.fontFamily))
                    {
                        fontFamily = buttonStyle.text.fontFamily;
                    }
                }
                
                Debug.Log($"[ClassementTab] ✅ Style exportBadgeButton chargé: {buttonWidth}x{buttonHeight}");
            }
            else
            {
                Debug.LogWarning("[ClassementTab] ⚠️ Style exportBadgeButton introuvable, utilisation des valeurs par défaut");
            }
        }
        
        GameObject buttonObj = new GameObject("ExportButton");
        buttonObj.transform.SetParent(parent, false);
        
        RectTransform buttonRect = buttonObj.AddComponent<RectTransform>();
        buttonRect.sizeDelta = new Vector2(buttonWidth, buttonHeight);
        
        LayoutElement buttonLayout = buttonObj.AddComponent<LayoutElement>();
        buttonLayout.preferredWidth = buttonWidth;
        buttonLayout.preferredHeight = buttonHeight;
        buttonLayout.minWidth = buttonWidth;
        buttonLayout.minHeight = buttonHeight;
        buttonLayout.flexibleWidth = 0;
        buttonLayout.flexibleHeight = 0;
        
        // Image du bouton avec gradient
        Image buttonBg = buttonObj.AddComponent<Image>();
        buttonBg.sprite = CreateGradientSpriteWithBorder((int)buttonWidth, (int)buttonHeight, borderRadius, 
            startColor, endColor, borderColor, borderWidth);
        buttonBg.color = Color.white;
        buttonBg.raycastTarget = true;
        
        // Ombre depuis le style
        if (buttonStyle?.shadow != null && buttonStyle.shadow.enabled)
        {
            Shadow shadow = buttonObj.GetComponent<Shadow>();
            if (shadow == null) shadow = buttonObj.AddComponent<Shadow>();
            shadow.effectColor = HexToColor(buttonStyle.shadow.color ?? "#00000040");
            shadow.effectDistance = new Vector2(buttonStyle.shadow.offsetX, -buttonStyle.shadow.offsetY);
        }
        
        // Ajouter le composant Button
        Button button = buttonObj.AddComponent<Button>();
        button.targetGraphic = buttonBg;
        button.interactable = true;
        
        // Configurer les couleurs du bouton (effets hover/pressed)
        ColorBlock colors = button.colors;
        colors.normalColor = Color.white;
        colors.highlightedColor = new Color(1.1f, 1.1f, 1.1f, 1f);
        colors.pressedColor = new Color(0.9f, 0.9f, 0.9f, 1f);
        button.colors = colors;
        
        // Texte du bouton
        GameObject textObj = new GameObject("ButtonText");
        textObj.transform.SetParent(buttonObj.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.sizeDelta = Vector2.zero;
        textRect.anchoredPosition = Vector2.zero;
        
        TextMeshProUGUI buttonText = textObj.AddComponent<TextMeshProUGUI>();
        buttonText.text = "EXPORTER MON SUPER-BADGE";
        buttonText.fontSize = textFontSize;
        buttonText.fontStyle = FontStyles.Bold;
        buttonText.alignment = TextAlignmentOptions.Center;
        buttonText.verticalAlignment = VerticalAlignmentOptions.Middle;
        buttonText.color = textColor;
        buttonText.enableAutoSizing = false;
        buttonText.raycastTarget = false;
        
        // Charger la police
        TMP_FontAsset customFont = Resources.Load<TMP_FontAsset>($"Fonts/{fontFamily}");
        if (customFont != null)
        {
            buttonText.font = customFont;
        }
        
        // Action du bouton (placeholder pour l'instant)
        button.onClick.AddListener(() => {
            Debug.Log("[ClassementTab] 📤 Export du super-badge demandé");
        });
    }
    
    /// <summary>
    /// Crée la section des onglets (CLASSEMENT CHEZ {COMPANY} / CLASSEMENT GLOBAL)
    /// </summary>
    private void CreateTabsSection()
    {
        tabsSection = new GameObject("TabsSection");
        tabsSection.transform.SetParent(transform, false);
        
        float height = config?.tabsSection?.height ?? 80;
        
        RectTransform tabsRect = tabsSection.AddComponent<RectTransform>();
        tabsRect.sizeDelta = new Vector2(0, height);
        
        LayoutElement tabsLayout = tabsSection.AddComponent<LayoutElement>();
        tabsLayout.preferredHeight = height;
        tabsLayout.minHeight = height;
        
        // Layout horizontal pour les onglets
        HorizontalLayoutGroup hLayout = tabsSection.AddComponent<HorizontalLayoutGroup>();
        
        float spacing = config?.tabsSection?.spacing ?? 20;
        
        hLayout.spacing = spacing;
        hLayout.childAlignment = TextAnchor.MiddleCenter;
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = false;
        hLayout.childForceExpandHeight = false;
        
        // Récupérer le nom de la compagnie de l'utilisateur
        string companyName = "VOTRE ENTREPRISE"; // Valeur par défaut
        
        if (UserDataManager.Instance != null && !string.IsNullOrEmpty(UserDataManager.Instance.companyName))
        {
            companyName = UserDataManager.Instance.companyName.ToUpper();
        }
        else if (scoreboardData != null && scoreboardData.company != null && scoreboardData.company.Count > 0)
        {
            // Fallback : utiliser le nom de la compagnie du premier joueur
            companyName = scoreboardData.company[0].company.ToUpper();
        }
        
        Debug.Log($"[ClassementTab] 🏢 Nom de la compagnie pour l'onglet: {companyName}");
        
        // Onglet "CLASSEMENT CHEZ {COMPANY}"
        string companyTabLabel = $"CLASSEMENT CHEZ {companyName}";
        companyTabButton = CreateRankingTabButton(companyTabLabel, true);
        companyTabButton.transform.SetParent(tabsSection.transform, false);
        companyTabButton.onClick.AddListener(() => ShowCompanyRanking());
        
        // Onglet "CLASSEMENT GLOBAL"
        globalTabButton = CreateRankingTabButton("CLASSEMENT GLOBAL", false);
        globalTabButton.transform.SetParent(tabsSection.transform, false);
        globalTabButton.onClick.AddListener(() => ShowGlobalRanking());
    }
    
    /// <summary>
    /// Crée un bouton d'onglet pour le classement
    /// </summary>
    private Button CreateRankingTabButton(string label, bool isActive)
    {
        GameObject buttonObj = new GameObject($"Tab_{label}");
        
        RectTransform buttonRect = buttonObj.AddComponent<RectTransform>();
        buttonRect.sizeDelta = new Vector2(340, 70);
        
        LayoutElement buttonLayout = buttonObj.AddComponent<LayoutElement>();
        buttonLayout.preferredWidth = 340;
        buttonLayout.preferredHeight = 70;
        
        // Image du bouton
        Image buttonImage = buttonObj.AddComponent<Image>();
        buttonImage.sprite = CreateRoundedSprite(340, 70, 35f, isActive ? beigeDarkColor : Color.clear);
        buttonImage.type = Image.Type.Simple;
        buttonImage.raycastTarget = true;
        
        Button button = buttonObj.AddComponent<Button>();
        button.targetGraphic = buttonImage;
        button.transition = Selectable.Transition.None;
        
        // Texte du bouton
        GameObject textObj = new GameObject("Text");
        textObj.transform.SetParent(buttonObj.transform, false);
        
        RectTransform textRect = textObj.AddComponent<RectTransform>();
        textRect.anchorMin = Vector2.zero;
        textRect.anchorMax = Vector2.one;
        textRect.offsetMin = Vector2.zero;
        textRect.offsetMax = Vector2.zero;
        
        TextMeshProUGUI text = textObj.AddComponent<TextMeshProUGUI>();
        text.text = label;
        text.fontSize = 26;
        text.fontStyle = FontStyles.Bold;
        text.color = isActive ? Color.white : textDarkColor;
        text.alignment = TextAlignmentOptions.Center;
        
        // Charger la police Anton
        TMP_FontAsset antonFont = Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
        if (antonFont != null)
        {
            text.font = antonFont;
        }
        
        return button;
    }
    
    /// <summary>
    /// Crée la section de la liste de classement scrollable (HORIZONTALE avec navigation - PLUS HAUTE)
    /// </summary>
    private void CreateRankingListSection()
    {
        rankingListSection = new GameObject("RankingListSection");
        rankingListSection.transform.SetParent(transform, false);
        
        float height = config?.rankingSection?.height ?? 240;
        
        RectTransform listRect = rankingListSection.AddComponent<RectTransform>();
        listRect.sizeDelta = new Vector2(0, height);
        
        LayoutElement listLayout = rankingListSection.AddComponent<LayoutElement>();
        listLayout.preferredHeight = height;
        listLayout.minHeight = height;
        listLayout.flexibleHeight = 1f; // Prendre tout l'espace restant
        
        // Fond semi-transparent
        Image sectionBg = rankingListSection.AddComponent<Image>();
        sectionBg.color = new Color(0.9f, 0.9f, 0.85f, 0.3f);
        sectionBg.raycastTarget = false;
        
        // Layout horizontal pour: Flèche gauche | Container joueurs | Flèche droite
        HorizontalLayoutGroup hLayout = rankingListSection.AddComponent<HorizontalLayoutGroup>();
        hLayout.childAlignment = TextAnchor.MiddleCenter;
        
        float arrowSpacing = config?.rankingSection?.arrowSpacing ?? 10;
        
        // Padding depuis le config ou valeur par défaut
        int padLeft = 20, padRight = 20, padTop = 20, padBottom = 20;
        if (config?.rankingSection?.padding != null)
        {
            padLeft = (int)config.rankingSection.padding.left;
            padRight = (int)config.rankingSection.padding.right;
            padTop = (int)config.rankingSection.padding.top;
            padBottom = (int)config.rankingSection.padding.bottom;
        }
        
        hLayout.spacing = arrowSpacing;
        hLayout.childControlWidth = false;
        hLayout.childControlHeight = false;
        hLayout.childForceExpandWidth = false;
        hLayout.childForceExpandHeight = false;
        hLayout.padding = new RectOffset(padLeft, padRight, padTop, padBottom);
        
        // Flèche gauche
        leftArrow = CreateNavigationArrow(rankingListSection.transform, true);
        
        // Container pour les joueurs
        playersContainer = new GameObject("PlayersContainer");
        playersContainer.transform.SetParent(rankingListSection.transform, false);
        
        int maxPlayers = config?.rankingSection?.maxVisiblePlayers ?? maxVisiblePlayers;
        float containerWidth = maxPlayers * 220 + (maxPlayers - 1) * 25 + 80; // 4×220 + 3×25 + marge
        
        RectTransform containerRect = playersContainer.AddComponent<RectTransform>();
        containerRect.sizeDelta = new Vector2(containerWidth, 200);
        
        LayoutElement containerLayout = playersContainer.AddComponent<LayoutElement>();
        containerLayout.preferredWidth = containerWidth;
        containerLayout.preferredHeight = 200;
        containerLayout.flexibleWidth = 0;
        
        // Layout horizontal pour les joueurs
        HorizontalLayoutGroup playersLayout = playersContainer.AddComponent<HorizontalLayoutGroup>();
        playersLayout.spacing = 25;
        playersLayout.childAlignment = TextAnchor.MiddleCenter;
        playersLayout.childControlWidth = false;
        playersLayout.childControlHeight = false;
        playersLayout.childForceExpandWidth = false;
        playersLayout.childForceExpandHeight = false;
        
        // Flèche droite
        rightArrow = CreateNavigationArrow(rankingListSection.transform, false);
        
        Debug.Log($"[ClassementTab] 📊 RankingListSection créée (horizontale avec navigation - hauteur: {height})");
    }
    
    /// <summary>
    /// Crée une flèche de navigation (gauche ou droite) - COPIE EXACTE de QuetesTab
    /// </summary>
    private GameObject CreateNavigationArrow(Transform parent, bool isLeft)
    {
        GameObject arrow = new GameObject(isLeft ? "LeftArrow" : "RightArrow");
        arrow.transform.SetParent(parent, false);
        
        RectTransform arrowRect = arrow.AddComponent<RectTransform>();
        arrowRect.sizeDelta = new Vector2(60, 60);
        
        LayoutElement arrowLayout = arrow.AddComponent<LayoutElement>();
        arrowLayout.preferredWidth = 60;
        arrowLayout.preferredHeight = 60;
        arrowLayout.flexibleWidth = 0;
        
        // Image de la flèche
        Image arrowImage = arrow.AddComponent<Image>();
        arrowImage.color = Color.white;
        arrowImage.raycastTarget = true;
        
        // Ajouter à la liste des images à charger (sera chargé quand l'onglet est actif)
        string imageName = isLeft ? "nav_gauche.png" : "nav_droite.png";
        string imageUrl = GeneralConfigManager.Instance?.GetUIUrl(imageName) ?? "";
        if (!string.IsNullOrEmpty(imageUrl))
        {
            pendingImageLoads.Add((arrowImage, imageUrl));
        }
        
        // Bouton
        Button button = arrow.AddComponent<Button>();
        button.transition = Selectable.Transition.ColorTint;
        button.targetGraphic = arrowImage;
        
        ColorBlock colors = button.colors;
        colors.normalColor = Color.white;
        colors.highlightedColor = new Color(1.2f, 1.2f, 1.2f, 1f);
        colors.pressedColor = new Color(0.8f, 0.8f, 0.8f, 1f);
        button.colors = colors;
        
        int direction = isLeft ? -1 : 1;
        button.onClick.AddListener(() => NavigatePlayers(direction));
        
        return arrow;
    }
    
    /// <summary>
    /// Navigue dans la liste des joueurs (gauche/droite)
    /// </summary>
    private void NavigatePlayers(int direction)
    {
        int maxPlayers = config?.rankingSection?.maxVisiblePlayers ?? maxVisiblePlayers;
        visibleStartIndex += direction;
        visibleStartIndex = Mathf.Clamp(visibleStartIndex, 0, Mathf.Max(0, currentPlayers.Count - maxPlayers));
        
        RefreshVisiblePlayers();
        UpdateArrowsVisibility();
    }
    
    /// <summary>
    /// Rafraîchit l'affichage des joueurs visibles
    /// </summary>
    private void RefreshVisiblePlayers()
    {
        int maxPlayers = config?.rankingSection?.maxVisiblePlayers ?? maxVisiblePlayers;
        
        // Nettoyer le container
        foreach (Transform child in playersContainer.transform)
        {
            Destroy(child.gameObject);
        }
        
        // Afficher les joueurs visibles
        int endIndex = Mathf.Min(visibleStartIndex + maxPlayers, currentPlayers.Count);
        
        for (int i = visibleStartIndex; i < endIndex; i++)
        {
            CreatePlayerCard(currentPlayers[i], playersContainer.transform);
        }
        
        Debug.Log($"[ClassementTab] 🔄 Affichage de {endIndex - visibleStartIndex} joueurs ({visibleStartIndex} à {endIndex - 1})");
    }
    
    /// <summary>
    /// Met à jour la visibilité des flèches de navigation
    /// </summary>
    private void UpdateArrowsVisibility()
    {
        int maxPlayers = config?.rankingSection?.maxVisiblePlayers ?? maxVisiblePlayers;
        
        if (leftArrow != null)
        {
            leftArrow.SetActive(visibleStartIndex > 0);
        }
        
        if (rightArrow != null)
        {
            int maxStartIndex = Mathf.Max(0, currentPlayers.Count - maxPlayers);
            rightArrow.SetActive(visibleStartIndex < maxStartIndex);
        }
    }
    
    /// <summary>
    /// Charge les données utilisateur depuis l'API
    /// </summary>
    private void LoadUserData()
    {
        if (isLoadingUserData)
        {
            Debug.LogWarning("[ClassementTab] 👤 Chargement utilisateur déjà en cours, skip");
            return;
        }
        
        Debug.Log("[ClassementTab] 👤 LoadUserData appelé");
        
        if (GeneralConfigManager.Instance == null)
        {
            Debug.LogError("[ClassementTab] GeneralConfigManager n'est pas initialisé");
            return;
        }
        
        StartCoroutine(LoadUserDataCoroutine());
    }
    
    private IEnumerator LoadUserDataCoroutine()
    {
        Debug.Log("[ClassementTab] 🔄 LoadUserDataCoroutine démarré");
        isLoadingUserData = true;
        
        string apiBaseUrl = GeneralConfigManager.Instance?.GetApiBaseUrl() ?? "";
        
        if (string.IsNullOrEmpty(apiBaseUrl))
        {
            Debug.LogError("[ClassementTab] ❌ URL de base de l'API non définie");
            isLoadingUserData = false;
            yield break;
        }
        
        string url = $"{apiBaseUrl}/api/ujsa/user";
        Debug.Log($"[ClassementTab] 📡 URL: {url}");
        
        using (UnityWebRequest www = UnityWebRequest.Get(url))
        {
            string token = UserDataManager.Instance?.token ?? "";
            if (!string.IsNullOrEmpty(token))
            {
                www.SetRequestHeader("Authorization", $"Bearer {token}");
                Debug.Log("[ClassementTab] 🔑 Token ajouté");
            }
            
            Debug.Log("[ClassementTab] 📤 Envoi requête...");
            yield return www.SendWebRequest();
            Debug.Log($"[ClassementTab] 📥 Réponse reçue: {www.result}");
            
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[ClassementTab] ❌ Erreur: {www.error}");
                isLoadingUserData = false;
                yield break;
            }
            
            string jsonResponse = www.downloadHandler.text;
            Debug.Log($"[ClassementTab] ✅ JSON reçu: {jsonResponse.Length} chars");
            
            try
            {
                UserApiResponse response = JsonUtility.FromJson<UserApiResponse>(jsonResponse);
                
                if (response != null && response.status == "success" && response.data != null)
                {
                    userData = response.data;
                    Debug.Log($"[ClassementTab] ✅ Utilisateur: {userData.first_name} {userData.last_name}");
                    
                    UpdateCompanyTabLabel();
                    UpdateUserBadge();
                    UpdateInfoBlock();
                    
                    if (!string.IsNullOrEmpty(userData.leaderboard_visibility))
                    {
                        currentVisibility = userData.leaderboard_visibility;
                        UpdateCheckboxes();
                    }
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[ClassementTab] ❌ Erreur parsing: {e.Message}");
            }
        }
        
        isLoadingUserData = false;
        Debug.Log("[ClassementTab] 🏁 LoadUserDataCoroutine terminé");
    }
    
    /// <summary>
    /// Met à jour le badge et le score de l'utilisateur
    /// </summary>
    private void UpdateUserBadge()
    {
        if (userData == null || userData.super_badges == null || userData.super_badges.Count == 0)
        {
            Debug.LogWarning("[ClassementTab] ⚠️ Pas de super badge pour l'utilisateur");
            return;
        }
        
        // Trouver le badge du projet actuel
        string projectSlug = GeneralConfigManager.Instance.GetConfig()?.slug;
        SuperBadge badge = userData.super_badges.Find(b => b.project_slug == projectSlug);
        
        if (badge == null)
        {
            badge = userData.super_badges[0]; // Prendre le premier si pas trouvé
        }
        
        // Mettre à jour le score
        if (userScoreText != null)
        {
            userScoreText.text = badge.score.ToString();
        }
        
        // Charger l'image du badge
        if (userBadgeImage != null && !string.IsNullOrEmpty(badge.badge_url))
        {
            StartCoroutine(LoadImageSprite(badge.badge_url, userBadgeImage));
        }
        
        Debug.Log($"[ClassementTab] 🏅 Badge mis à jour: {badge.badge_type}, Score: {badge.score}");
        
        // Mettre à jour le bloc d'informations
        UpdateInfoBlock();
    }
    
    /// <summary>
    /// Met à jour le bloc d'informations avec les données utilisateur
    /// </summary>
    private void UpdateInfoBlock()
    {
        if (userData == null)
        {
            Debug.LogWarning("[ClassementTab] ⚠️ Pas de données utilisateur pour UpdateInfoBlock");
            return;
        }
        
        Debug.Log($"[ClassementTab] 📊 UpdateInfoBlock - userData présent, super_badges count: {userData.super_badges?.Count ?? 0}, projects count: {userData.projects?.Count ?? 0}, total_trainings: {userData.total_trainings}");
        
        // Trouver le badge du projet actuel
        string projectSlug = GeneralConfigManager.Instance.GetConfig()?.slug;
        SuperBadge badge = userData.super_badges?.Find(b => b.project_slug == projectSlug);
        
        if (badge == null && userData.super_badges != null && userData.super_badges.Count > 0)
        {
            badge = userData.super_badges[0]; // Prendre le premier si pas trouvé
        }
        
        // Trouver les infos du projet actuel
        ProjectInfo projectInfo = userData.projects?.Find(p => p.project_slug == projectSlug);
        
        if (projectInfo == null && userData.projects != null && userData.projects.Count > 0)
        {
            projectInfo = userData.projects[0]; // Prendre le premier si pas trouvé
        }
        
        Debug.Log($"[ClassementTab] 📊 References UI - scoreInfoText: {scoreInfoText != null}, stateInfoText: {stateInfoText != null}, rankInfoText: {rankInfoText != null}, questsInfoText: {questsInfoText != null}, trainingsInfoText: {trainingsInfoText != null}");
        Debug.Log($"[ClassementTab] 📊 Données - badge: {badge != null}, projectInfo: {projectInfo != null}");
        
        // Mettre à jour Score
        if (scoreInfoText != null && badge != null)
        {
            scoreInfoText.text = $"Score : <b>{badge.score}</b>";
        }
        
        // Mettre à jour État
        if (stateInfoText != null && badge != null)
        {
            stateInfoText.text = $"État : <b>{badge.badge_type ?? "vide"}</b>";
        }
        
        // Mettre à jour Positionnement (rank)
        if (rankInfoText != null && projectInfo != null)
        {
            rankInfoText.text = $"Positionnement : <b>{projectInfo.rank ?? "Inconnu"}</b>";
        }
        
        // Mettre à jour Nombre de quêtes complétées
        if (questsInfoText != null && projectInfo != null)
        {
            questsInfoText.text = $"Nombre de quêtes complétées : <b>{projectInfo.completed_quests}</b>";
        }
        
        // Mettre à jour Nombre de formations réalisées
        if (trainingsInfoText != null)
        {
            trainingsInfoText.text = $"Nombre de formations réalisées : <b>{userData.total_trainings}</b>";
        }
        
        Debug.Log($"[ClassementTab] 📊 Bloc d'informations mis à jour");
    }
    
    /// <summary>
    /// Charge les données du scoreboard depuis l'API
    /// </summary>
    private void LoadScoreboardData()
    {
        if (GeneralConfigManager.Instance == null)
        {
            Debug.LogError("[ClassementTab] GeneralConfigManager n'est pas initialisé");
            return;
        }
        
        StartCoroutine(LoadScoreboardDataCoroutine());
    }
    
    private IEnumerator LoadScoreboardDataCoroutine()
    {
        isLoadingData = true;
        
        // Construire l'URL de l'API
        string baseUrl = GeneralConfigManager.Instance.GetApiBaseUrl();
        var config = GeneralConfigManager.Instance.GetConfig();
        string projectSlug = config?.slug ?? "ujsa-default";
        
        string apiUrl = $"{baseUrl}/api/ujsa/projects/{projectSlug}/scoreboard";
        
        Debug.Log($"[ClassementTab] 📊 Chargement du scoreboard depuis: {apiUrl}");
        
        // Récupérer le token d'authentification (comme dans UserDataManager et GameDataManager)
        string token = UserDataManager.Instance?.token;
        
        if (!string.IsNullOrEmpty(token))
        {
            Debug.Log($"[ClassementTab] 🔑 Token présent, ajout à la requête");
        }
        else
        {
            Debug.LogWarning("[ClassementTab] ⚠️ Pas de token - requête sans authentification");
        }
        
        using (UnityWebRequest www = UnityWebRequest.Get(apiUrl))
        {
            // Ajouter l'authentification Bearer Token (comme dans UserDataManager)
            if (!string.IsNullOrEmpty(token))
            {
                www.SetRequestHeader("Authorization", $"Bearer {token}");
            }
            
            www.SetRequestHeader("Content-Type", "application/json");
            
            yield return www.SendWebRequest();
            
            if (www.result != UnityWebRequest.Result.Success)
            {
                Debug.LogError($"[ClassementTab] ❌ Erreur chargement scoreboard: {www.error}");
                Debug.LogError($"[ClassementTab] ❌ Code HTTP: {www.responseCode}");
                if (!string.IsNullOrEmpty(www.downloadHandler?.text))
                {
                    Debug.LogError($"[ClassementTab] ❌ Réponse serveur: {www.downloadHandler.text}");
                }
                // Afficher un message d'erreur basique
                currentPlayers = new List<ScoreboardPlayer>();
                RefreshVisiblePlayers();
                isLoadingData = false;
                yield break;
            }
            
            string jsonData = www.downloadHandler.text;
            Debug.Log($"[ClassementTab] ✅ Données brutes reçues ({jsonData.Length} caractères)");
            Debug.Log($"[ClassementTab] 📋 JSON complet: {jsonData}");
            
            try
            {
                ScoreboardApiResponse response = JsonUtility.FromJson<ScoreboardApiResponse>(jsonData);
                
                Debug.Log($"[ClassementTab] 🔍 Parsing terminé - response null? {response == null}");
                if (response != null)
                {
                    Debug.Log($"[ClassementTab] 🔍 response.status = {response.status}");
                    Debug.Log($"[ClassementTab] 🔍 response.data null? {response.data == null}");
                    if (response.data != null)
                    {
                        Debug.Log($"[ClassementTab] 🔍 response.data.company null? {response.data.company == null}");
                        Debug.Log($"[ClassementTab] 🔍 response.data.global null? {response.data.global == null}");
                        if (response.data.company != null)
                        {
                            Debug.Log($"[ClassementTab] 🔍 response.data.company.Count = {response.data.company.Count}");
                        }
                        if (response.data.global != null)
                        {
                            Debug.Log($"[ClassementTab] 🔍 response.data.global.Count = {response.data.global.Count}");
                        }
                    }
                }
                
                if (response != null && response.status == "success" && response.data != null)
                {
                    scoreboardData = response.data;
                    Debug.Log($"[ClassementTab] ✅ Scoreboard chargé: {scoreboardData.company?.Count ?? 0} joueurs (compagnie), {scoreboardData.global?.Count ?? 0} joueurs (global)");
                    
                    // Les données sont chargées, elles seront utilisées quand l'utilisateur cliquera sur les sous-onglets
                    // Pas besoin d'appeler PopulateRankingLists() ici
                }
                else
                {
                    Debug.LogError($"[ClassementTab] ❌ Réponse API invalide: status={response?.status}, data null? {response?.data == null}");
                }
            }
            catch (System.Exception e)
            {
                Debug.LogError($"[ClassementTab] ❌ Erreur parsing JSON: {e.Message}");
                Debug.LogError($"[ClassementTab] ❌ Stack trace: {e.StackTrace}");
            }
        }
        
        isLoadingData = false;
    }
    
    /// <summary>
    /// Remplit les listes de classement avec les données de l'API
    /// </summary>
    private void PopulateRankingLists()
    {
        Debug.Log("[ClassementTab] 🎯 PopulateRankingLists appelé");
        
        if (scoreboardData == null)
        {
            Debug.LogWarning("[ClassementTab] ⚠️ scoreboardData est null");
            return;
        }
        
        Debug.Log($"[ClassementTab] 📊 scoreboardData.company: {scoreboardData.company?.Count ?? -1} joueurs");
        Debug.Log($"[ClassementTab] 🌍 scoreboardData.global: {scoreboardData.global?.Count ?? -1} joueurs");
        
        // Déterminer quelle liste afficher
        bool showCompany = companyTabButton != null && companyTabButton.GetComponent<Image>().color != Color.clear;
        
        if (showCompany && scoreboardData.company != null && scoreboardData.company.Count > 0)
        {
            currentPlayers = new List<ScoreboardPlayer>(scoreboardData.company);
            Debug.Log($"[ClassementTab] 📊 Affichage classement compagnie: {currentPlayers.Count} joueurs");
        }
        else if (scoreboardData.global != null && scoreboardData.global.Count > 0)
        {
            currentPlayers = new List<ScoreboardPlayer>(scoreboardData.global);
            Debug.Log($"[ClassementTab] 🌍 Affichage classement global: {currentPlayers.Count} joueurs");
        }
        else
        {
            currentPlayers = new List<ScoreboardPlayer>();
            Debug.LogWarning("[ClassementTab] ⚠️ Aucune donnée à afficher");
        }
        
        // Réinitialiser l'index de navigation
        visibleStartIndex = 0;
        
        // Afficher les joueurs
        RefreshVisiblePlayers();
        UpdateArrowsVisibility();
        
        Debug.Log("[ClassementTab] ✅ PopulateRankingLists terminé");
    }
    
    
    /// <summary>
    /// Crée une card pour un joueur dans le classement (COMME LE VISUEL FOURNI)
    /// </summary>
    private void CreatePlayerCard(ScoreboardPlayer player, Transform parent)
    {
        GameObject card = new GameObject($"PlayerCard_{player.user_id}");
        card.transform.SetParent(parent, false);
        
        RectTransform cardRect = card.AddComponent<RectTransform>();
        cardRect.sizeDelta = new Vector2(220, 190); // Même taille que le visuel
        
        LayoutElement cardLayout = card.AddComponent<LayoutElement>();
        cardLayout.preferredWidth = 220;
        cardLayout.preferredHeight = 190;
        cardLayout.flexibleWidth = 0;
        
        // Fond beige clair avec coins arrondis (EXACTEMENT comme le visuel)
        Image cardBg = card.AddComponent<Image>();
        cardBg.sprite = CreateRoundedSprite(220, 190, 15f, beigeLightColor);
        cardBg.type = Image.Type.Simple;
        cardBg.raycastTarget = false;
        
        // Layout vertical pour organiser: Badge | Rang | Nom | Entreprise
        VerticalLayoutGroup vLayout = card.AddComponent<VerticalLayoutGroup>();
        vLayout.padding = new RectOffset(15, 15, 15, 10);
        vLayout.spacing = 8;
        vLayout.childAlignment = TextAnchor.UpperCenter;
        vLayout.childControlWidth = false;
        vLayout.childControlHeight = false;
        vLayout.childForceExpandWidth = false;
        vLayout.childForceExpandHeight = false;
        
        // Badge du joueur (en haut, centré)
        GameObject badgeObj = new GameObject("BadgeImage");
        badgeObj.transform.SetParent(card.transform, false);
        
        // Récupérer les dimensions depuis la config
        float badgeWidth = config?.rankingSection?.badge?.width ?? 80;
        float badgeHeight = config?.rankingSection?.badge?.height ?? 80;
        
        RectTransform badgeRect = badgeObj.AddComponent<RectTransform>();
        badgeRect.sizeDelta = new Vector2(badgeWidth, badgeHeight);
        
        Image badgeImage = badgeObj.AddComponent<Image>();
        badgeImage.sprite = CreateCircleSprite();
        badgeImage.color = GetBadgeColor(player.badge_type);
        
        LayoutElement badgeLayout = badgeObj.AddComponent<LayoutElement>();
        badgeLayout.preferredWidth = badgeWidth;
        badgeLayout.preferredHeight = badgeHeight;
        
        // Charger l'image du badge depuis l'URL
        if (!string.IsNullOrEmpty(player.badge_url))
        {
            StartCoroutine(LoadBadgeImage(player.badge_url, badgeImage));
        }
        
        // RANG juste en dessous du badge (GROS et VIOLET comme demandé)
        string rankSuffix = player.rank == 1 ? "er" : "ème";
        CreatePlayerInfoTextCompact(card.transform, $"{player.rank}{rankSuffix}", 28, FontStyles.Bold, purpleColor);
        
        // Nom du joueur (plus petit)
        CreatePlayerInfoTextCompact(card.transform, $"{player.first_name} {player.last_name}", 16, FontStyles.Bold, textDarkColor);
        
        // Entreprise (encore plus petit, style "Entreprise" gris comme le visuel)
        CreatePlayerInfoTextCompact(card.transform, player.company, 14, FontStyles.Normal, new Color(0.5f, 0.45f, 0.42f, 1f));
    }
    
    /// <summary>
    /// Crée un texte d'information pour un joueur (VERSION COMPACTE)
    /// </summary>
    private GameObject CreatePlayerInfoTextCompact(Transform parent, string text, float fontSize, FontStyles fontStyle, Color textColor)
    {
        GameObject textObj = new GameObject("InfoText");
        textObj.transform.SetParent(parent, false);
        
        TextMeshProUGUI textComponent = textObj.AddComponent<TextMeshProUGUI>();
        textComponent.text = text;
        textComponent.fontSize = fontSize;
        textComponent.fontStyle = fontStyle;
        textComponent.color = textColor;
        textComponent.alignment = TextAlignmentOptions.Center;
        textComponent.raycastTarget = false;
        textComponent.textWrappingMode = TextWrappingModes.NoWrap;
        textComponent.overflowMode = TextOverflowModes.Ellipsis; // Tronquer si trop long
        
        LayoutElement textLayout = textObj.AddComponent<LayoutElement>();
        textLayout.preferredHeight = fontSize + 2;
        
        return textObj;
    }
    
    /// <summary>
    /// Retourne une couleur selon le type de badge
    /// </summary>
    private Color GetBadgeColor(string badgeType)
    {
        switch (badgeType?.ToLower())
        {
            case "gold":
            case "or":
                return new Color(1f, 0.84f, 0f, 1f); // Or
            case "silver":
            case "argent":
                return new Color(0.75f, 0.75f, 0.75f, 1f); // Argent
            case "bronze":
                return new Color(0.8f, 0.5f, 0.2f, 1f); // Bronze
            case "unlocked":
            default:
                return new Color(0.64f, 0.25f, 1f, 1f); // Violet par défaut
        }
    }
    
    /// <summary>
    /// Charge l'image du badge depuis une URL (utilise LoadImageSprite)
    /// </summary>
    private IEnumerator LoadBadgeImage(string url, Image targetImage)
    {
        using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(url))
        {
            yield return request.SendWebRequest();
            
            if (request.result == UnityWebRequest.Result.Success)
            {
                Texture2D texture = DownloadHandlerTexture.GetContent(request);
                Sprite sprite = Sprite.Create(
                    texture,
                    new Rect(0, 0, texture.width, texture.height),
                    new Vector2(0.5f, 0.5f),
                    100f
                );
                
                // Tracker pour nettoyage (WebGL)
                TrackDynamic(texture, sprite);
                
                targetImage.sprite = sprite;
                targetImage.color = Color.white; // Enlever la teinte de couleur
            }
            else
            {
                Debug.LogWarning($"[ClassementTab] ⚠️ Impossible de charger l'image du badge: {url}");
            }
        }
    }
    
    /// <summary>
    /// Affiche le classement de la compagnie
    /// </summary>
    private void ShowCompanyRanking()
    {
        // Mettre à jour les styles des onglets
        UpdateTabButtonStyle(companyTabButton, true);
        UpdateTabButtonStyle(globalTabButton, false);
        
        // Recharger les joueurs
        if (scoreboardData != null && scoreboardData.company != null)
        {
            currentPlayers = new List<ScoreboardPlayer>(scoreboardData.company);
            visibleStartIndex = 0;
            RefreshVisiblePlayers();
            UpdateArrowsVisibility();
        }
    }
    
    /// <summary>
    /// Affiche le classement global
    /// </summary>
    private void ShowGlobalRanking()
    {
        // Mettre à jour les styles des onglets
        UpdateTabButtonStyle(companyTabButton, false);
        UpdateTabButtonStyle(globalTabButton, true);
        
        // Recharger les joueurs
        if (scoreboardData != null && scoreboardData.global != null)
        {
            currentPlayers = new List<ScoreboardPlayer>(scoreboardData.global);
            visibleStartIndex = 0;
            RefreshVisiblePlayers();
            UpdateArrowsVisibility();
        }
    }
    
    /// <summary>
    /// Met à jour le style d'un bouton d'onglet
    /// </summary>
    private void UpdateTabButtonStyle(Button button, bool isActive)
    {
        if (button == null) return;
        
        Image buttonImage = button.GetComponent<Image>();
        TextMeshProUGUI buttonText = button.GetComponentInChildren<TextMeshProUGUI>();
        
        if (buttonImage != null)
        {
            buttonImage.color = isActive ? beigeDarkColor : Color.clear;
        }
        
        if (buttonText != null)
        {
            buttonText.color = isActive ? Color.white : textDarkColor;
        }
    }
    
    // Helper methods pour créer des sprites
    
    private Sprite CreateRoundedSprite(int width, int height, float radius, Color fillColor)
    {
        Texture2D texture = new Texture2D(width, height);
        Color[] pixels = new Color[width * height];
        
        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float alpha = 1f;
                
                // Coins arrondis (simplifié)
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius) alpha = 0f;
                }
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius) alpha = 0f;
                }
                else if (x < radius && y < radius)
                {
                    float dx = radius - x;
                    float dy = radius - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius) alpha = 0f;
                }
                else if (x > width - radius && y < radius)
                {
                    float dx = x - (width - radius);
                    float dy = radius - y;
                    float distance = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distance > radius) alpha = 0f;
                }
                
                pixels[y * width + x] = new Color(fillColor.r, fillColor.g, fillColor.b, fillColor.a * alpha);
            }
        }
        
        texture.SetPixels(pixels);
        texture.Apply();
        
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
        TrackDynamic(texture, sprite);
        return sprite;
    }
    
    private Sprite CreateCircleSprite()
    {
        int size = 128;
        Texture2D texture = new Texture2D(size, size);
        Color[] pixels = new Color[size * size];
        
        float center = size / 2f;
        float radius = size / 2f;
        
        for (int y = 0; y < size; y++)
        {
            for (int x = 0; x < size; x++)
            {
                float distance = Vector2.Distance(new Vector2(x, y), new Vector2(center, center));
                pixels[y * size + x] = distance <= radius ? Color.white : Color.clear;
            }
        }
        
        texture.SetPixels(pixels);
        texture.Apply();
        
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, size, size), new Vector2(0.5f, 0.5f));
        TrackDynamic(texture, sprite);
        return sprite;
    }
    
    /// <summary>
    /// Crée un sprite avec dégradé vertical et bordure
    /// </summary>
    private Sprite CreateGradientSpriteWithBorder(int width, int height, float radius, Color startColor, Color endColor, Color borderColor, float borderWidth)
    {
        Texture2D texture = new Texture2D(width, height);
        Color[] pixels = new Color[width * height];

        for (int y = 0; y < height; y++)
        {
            for (int x = 0; x < width; x++)
            {
                float alpha = 1f;
                bool isBorder = false;
                
                // Vérifier si on est dans la bordure
                if (x < borderWidth || x >= width - borderWidth || y < borderWidth || y >= height - borderWidth)
                {
                    isBorder = true;
                }

                // Coins arrondis
                float distanceFromCorner = float.MaxValue;
                
                // Coin supérieur gauche
                if (x < radius && y > height - radius)
                {
                    float dx = radius - x;
                    float dy = (height - radius) - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin supérieur droit
                else if (x > width - radius && y > height - radius)
                {
                    float dx = x - (width - radius);
                    float dy = (height - radius) - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin inférieur gauche
                else if (x < radius && y < radius)
                {
                    float dx = radius - x;
                    float dy = radius - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }
                // Coin inférieur droit
                else if (x > width - radius && y < radius)
                {
                    float dx = x - (width - radius);
                    float dy = radius - y;
                    distanceFromCorner = Mathf.Sqrt(dx * dx + dy * dy);
                    if (distanceFromCorner > radius) alpha = 0f;
                    else if (distanceFromCorner > radius - borderWidth) isBorder = true;
                }

                Color pixelColor;
                if (isBorder && alpha > 0)
                {
                    pixelColor = borderColor;
                }
                else
                {
                    // Dégradé vertical
                    float t = (float)y / height;
                    pixelColor = Color.Lerp(endColor, startColor, t);
                }
                
                pixels[y * width + x] = new Color(pixelColor.r, pixelColor.g, pixelColor.b, pixelColor.a * alpha);
            }
        }

        texture.SetPixels(pixels);
        texture.Apply();
        
        Sprite sprite = Sprite.Create(texture, new Rect(0, 0, width, height), new Vector2(0.5f, 0.5f), 100f);
        TrackDynamic(texture, sprite);
        return sprite;
    }
    
    /// <summary>
    /// Convertit une couleur hexadécimale en Color Unity
    /// </summary>
    private Color HexToColor(string hex)
    {
        hex = hex.TrimStart('#');
        
        if (hex.Length == 6)
            hex += "FF"; // Ajouter l'alpha si absent
        
        if (hex.Length != 8)
            return Color.white;
        
        byte r = System.Convert.ToByte(hex.Substring(0, 2), 16);
        byte g = System.Convert.ToByte(hex.Substring(2, 2), 16);
        byte b = System.Convert.ToByte(hex.Substring(4, 2), 16);
        byte a = System.Convert.ToByte(hex.Substring(6, 2), 16);
        
        return new Color32(r, g, b, a);
    }
    
    /// <summary>
    /// Récupère la police Anton depuis les resources
    /// </summary>
    private TMP_FontAsset GetAntonFont()
    {
        return Resources.Load<TMP_FontAsset>("Fonts/Anton-Regular SDF");
    }
}