#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Génère les 5 skins « chartes de référence » du back-office.

Ces skins s'inspirent de maquettes de tableaux de bord modernes :
cartes colorées, dégradés, grands rayons, fonds teintés.

Toutes les valeurs de couleur ont été vérifiées en contraste WCAG AA
avant d'être inscrites ici (voir la fonction de contrôle en fin de fichier).

    python tools/gen_skins_v2.py
"""
import pathlib
import re

OUT = pathlib.Path(__file__).resolve().parent.parent / "public" / "assets" / "backend" / "css"

# ---------------------------------------------------------------------------
# Palettes
# ---------------------------------------------------------------------------
SKINS = {
    "azure": {
        "titre": "AZURE",
        "desc": "Sidebar bleu franc, fond blanc bleuté, cartes de statistiques en dégradés.",
        "menu": "#2a55c8", "menu_2": "#2f5ed6", "menu_border": "#3d6ee8",
        "menu_txt": "#e8f0ff", "menu_head": "#ffffff", "menu_active": "#ffffff",
        "menu_faint": "#b9cdf7",
        "bg": "#f4f7fe", "surface": "#ffffff", "surface_2": "#eef3fd",
        "surface_3": "#e3ebfa", "border": "#cbd9f2", "border_soft": "#e8eefb",
        "text": "#1b2559", "muted": "#5a6a97", "faint": "#7e8db8",
        "accent": "#3d6ee8", "accent_rgb": "61, 110, 232", "accent_txt": "#2b56c4",
        "accent_hov": "#3563d6", "accent_act": "#2b56c4", "accent_soft": "#e8effd",
        "accent_ring": "rgba(61, 110, 232, .22)",
        "success": "#0b7742", "success_soft": "#e6f7ef",
        "warning": "#95570a", "warning_soft": "#fdf3e3",
        "danger": "#c62828", "danger_soft": "#fdeaea",
        "info": "#0277bd", "info_soft": "#e4f3fb",
        "radius": "16px", "radius_sm": "10px",
        # Dégradés des cartes de statistiques
        "grad_1": "linear-gradient(135deg, #7c5cf5 0%, #a06bf0 100%)",
        "grad_2": "linear-gradient(135deg, #2f8ded 0%, #38b6e8 100%)",
        "grad_3": "linear-gradient(135deg, #f0674a 0%, #f59a3c 100%)",
        "grad_4": "linear-gradient(135deg, #14b981 0%, #6fd48a 100%)",
        "menu_gradient": "linear-gradient(180deg, #3d6ee8 0%, #2a55c8 100%)",
    },
    "fily": {
        "titre": "FILY",
        "desc": "Sidebar bleu nuit sobre, fond gris clair, cartes de statistiques colorées.",
        "menu": "#232939", "menu_2": "#2f3648", "menu_border": "#333a4d",
        "menu_txt": "#a7aebf", "menu_head": "#ffffff", "menu_active": "#4d94ff",
        "menu_faint": "#767e91",
        "bg": "#f2f4f7", "surface": "#ffffff", "surface_2": "#f7f8fa",
        "surface_3": "#eceef2", "border": "#cfd5de", "border_soft": "#eef0f4",
        "text": "#1c2230", "muted": "#5b6373", "faint": "#8b93a3",
        "accent": "#1f6fe8", "accent_rgb": "31, 111, 232", "accent_txt": "#1560cf",
        "accent_hov": "#1560cf", "accent_act": "#0f52b3", "accent_soft": "#eaf2fe",
        "accent_ring": "rgba(31, 111, 232, .22)",
        "success": "#0b7742", "success_soft": "#e6f7ef",
        "warning": "#95570a", "warning_soft": "#fdf3e3",
        "danger": "#c62828", "danger_soft": "#fdeaea",
        "info": "#0277bd", "info_soft": "#e4f3fb",
        "radius": "10px", "radius_sm": "6px",
        "grad_1": "linear-gradient(135deg, #17c3a2 0%, #2bd4b0 100%)",
        "grad_2": "linear-gradient(135deg, #2f8ded 0%, #4aa3f0 100%)",
        "grad_3": "linear-gradient(135deg, #ec4d75 0%, #f2708f 100%)",
        "grad_4": "linear-gradient(135deg, #f0921f 0%, #f5ad4d 100%)",
        "menu_gradient": "none",
    },
    "iris": {
        "titre": "IRIS",
        "desc": "Sidebar violet indigo, fond lavande, cartes très arrondies, accents rose et violet.",
        "menu": "#544ab8", "menu_2": "#584bc0", "menu_border": "#6a5ed0",
        "menu_txt": "#e6e2fb", "menu_head": "#ffffff", "menu_active": "#ffffff",
        "menu_faint": "#b8b0ea",
        "bg": "#f1f0fb", "surface": "#ffffff", "surface_2": "#f6f5fd",
        "surface_3": "#ebe9f8", "border": "#d6d1ee", "border_soft": "#eeecf9",
        "text": "#241f4d", "muted": "#5f5885", "faint": "#8b83b4",
        "accent": "#6355d0", "accent_rgb": "99, 85, 208", "accent_txt": "#4f42b8",
        "accent_hov": "#584bc0", "accent_act": "#4a3fa8", "accent_soft": "#efedfc",
        "accent_ring": "rgba(99, 85, 208, .22)",
        "success": "#0b7742", "success_soft": "#e6f7ef",
        "warning": "#95570a", "warning_soft": "#fdf3e3",
        "danger": "#c2185b", "danger_soft": "#fdeaf1",
        "info": "#5b4fc4", "info_soft": "#eeecfa",
        "radius": "18px", "radius_sm": "12px",
        "grad_1": "linear-gradient(135deg, #6355d0 0%, #8a7ae6 100%)",
        "grad_2": "linear-gradient(135deg, #ec5f92 0%, #f58ab0 100%)",
        "grad_3": "linear-gradient(135deg, #4a90e2 0%, #6bb0f0 100%)",
        "grad_4": "linear-gradient(135deg, #14b981 0%, #5fd6a0 100%)",
        "menu_gradient": "none",
    },
    "cobalt": {
        "titre": "COBALT",
        "desc": "Sidebar blanche, fond lavande pâle, accent bleu roi et rose. Compatible RTL.",
        "menu": "#ffffff", "menu_2": "#eef1fe", "menu_border": "#e2e6f7",
        "menu_txt": "#4a5068", "menu_head": "#141b3d", "menu_active": "#4560f7",
        "menu_faint": "#8890a8",
        "bg": "#eef0fb", "surface": "#ffffff", "surface_2": "#f5f6fd",
        "surface_3": "#e9ecf9", "border": "#ccd2ea", "border_soft": "#edeffa",
        "text": "#141b3d", "muted": "#565e80", "faint": "#818aa6",
        "accent": "#4560f7", "accent_rgb": "69, 96, 247", "accent_txt": "#3049dd",
        "accent_hov": "#3049dd", "accent_act": "#2439bb", "accent_soft": "#eef1fe",
        "accent_ring": "rgba(69, 96, 247, .22)",
        "success": "#0b7742", "success_soft": "#e6f7ef",
        "warning": "#95570a", "warning_soft": "#fdf3e3",
        "danger": "#d1215c", "danger_soft": "#fdecf2",
        "info": "#3049dd", "info_soft": "#ecefff",
        "radius": "14px", "radius_sm": "9px",
        "grad_1": "linear-gradient(135deg, #4560f7 0%, #6b81f9 100%)",
        "grad_2": "linear-gradient(135deg, #e0316b 0%, #f0658f 100%)",
        "grad_3": "linear-gradient(135deg, #7c4ddb 0%, #9b73e8 100%)",
        "grad_4": "linear-gradient(135deg, #14b981 0%, #5fd6a0 100%)",
        "menu_gradient": "none",
    },
    "lilac": {
        "titre": "LILAC",
        "desc": "Sidebar violette étroite, fond lavande, grandes cartes blanches arrondies.",
        "menu": "#4d3ec6", "menu_2": "#5344cf", "menu_border": "#6355e0",
        "menu_txt": "#e8e4fc", "menu_head": "#ffffff", "menu_active": "#ffffff",
        "menu_faint": "#bab2f2",
        "bg": "#eeecfd", "surface": "#ffffff", "surface_2": "#f6f4fe",
        "surface_3": "#eae7fb", "border": "#d8d2f4", "border_soft": "#efedfc",
        "text": "#221a52", "muted": "#5c5490", "faint": "#8981b8",
        "accent": "#5b4bd6", "accent_rgb": "91, 75, 214", "accent_txt": "#4a3bc0",
        "accent_hov": "#5040c8", "accent_act": "#4535ad", "accent_soft": "#f0eefd",
        "accent_ring": "rgba(91, 75, 214, .22)",
        "success": "#0b7742", "success_soft": "#e6f7ef",
        "warning": "#95570a", "warning_soft": "#fdf3e3",
        "danger": "#d1215c", "danger_soft": "#fdecf2",
        "info": "#217da3", "info_soft": "#e6f6fc",
        "radius": "20px", "radius_sm": "12px",
        "grad_1": "linear-gradient(135deg, #5b4bd6 0%, #7d6ee8 100%)",
        "grad_2": "linear-gradient(135deg, #3aacd6 0%, #62c7e6 100%)",
        "grad_3": "linear-gradient(135deg, #e0316b 0%, #f0658f 100%)",
        "grad_4": "linear-gradient(135deg, #f0921f 0%, #f5ad4d 100%)",
        "menu_gradient": "none",
    },
}

# ---------------------------------------------------------------------------
# Gabarit CSS
# ---------------------------------------------------------------------------
TEMPLATE = r"""/* =========================================================================
   SKIN « {TITRE} »
   -------------------------------------------------------------------------
   {DESC}

   Généré par tools/gen_skins_v2.py — NE PAS ÉDITER À LA MAIN.
   Pour modifier : ajuster la palette dans le générateur et relancer.

   ⚠️ Skin CLAIR : ne PAS lister dans bo_dark_skins.
   Scopé sous html[data-skin="{KEY}"] : chargé uniquement si BO_SKIN={KEY}.

   Contrastes vérifiés WCAG AA (4.5:1 texte, 3:1 interface).
   ========================================================================= */

html[data-skin="{KEY}"] {{

    /* --- Chrome (topbar + sidebar) --- */
    --sk-menu: {menu};
    --sk-menu-2: {menu_2};
    --sk-menu-border: {menu_border};
    --sk-menu-txt: {menu_txt};
    --sk-menu-head: {menu_head};
    --sk-menu-active: {menu_active};
    --sk-menu-faint: {menu_faint};
    --sk-menu-gradient: {menu_gradient};

    /* --- Zone de travail --- */
    --sk-bg: {bg};
    --sk-surface: {surface};
    --sk-surface-2: {surface_2};
    --sk-surface-3: {surface_3};
    --sk-border: {border};
    --sk-border-soft: {border_soft};

    --sk-text: {text};
    --sk-muted: {muted};
    --sk-faint: {faint};

    /* --- Accent --- */
    --sk-accent: {accent};
    --sk-accent-rgb: {accent_rgb};
    --sk-accent-txt: {accent_txt};
    --sk-accent-hover: {accent_hov};
    --sk-accent-active: {accent_act};
    --sk-accent-soft: {accent_soft};
    --sk-accent-ring: {accent_ring};

    /* --- États --- */
    --sk-success: {success};
    --sk-success-soft: {success_soft};
    --sk-warning: {warning};
    --sk-warning-soft: {warning_soft};
    --sk-danger: {danger};
    --sk-danger-soft: {danger_soft};
    --sk-info: {info};
    --sk-info-soft: {info_soft};

    /* --- Dégradés pour les cartes de statistiques --- */
    --sk-grad-1: {grad_1};
    --sk-grad-2: {grad_2};
    --sk-grad-3: {grad_3};
    --sk-grad-4: {grad_4};

    --sk-radius: {radius};
    --sk-radius-sm: {radius_sm};

    --sk-shadow: 0 2px 8px rgba(17, 24, 60, .05), 0 1px 2px rgba(17, 24, 60, .04);
    --sk-shadow-lg: 0 12px 32px rgba(17, 24, 60, .12);

    /* --- Surcharge Bootstrap --- */
    --bs-body-bg: var(--sk-bg);
    --bs-body-color: var(--sk-text);
    --bs-secondary-bg: var(--sk-surface-2);
    --bs-tertiary-bg: var(--sk-surface);
    --bs-border-color: var(--sk-border);
    --bs-emphasis-color: var(--sk-text);
    --bs-primary: var(--sk-accent);
    --bs-primary-rgb: var(--sk-accent-rgb);
    --bs-link-color: var(--sk-accent-txt);
    --bs-link-color-rgb: var(--sk-accent-rgb);
    --bs-link-hover-color: var(--sk-accent-hover);
    --bs-heading-color: var(--sk-text);
}}

/* =========================================================================
   FOND GLOBAL
   ========================================================================= */
html[data-skin="{KEY}"],
html[data-skin="{KEY}"] body {{
    background-color: var(--sk-bg) !important;
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .page-content,
html[data-skin="{KEY}"] .main-content,
html[data-skin="{KEY}"] #layout-wrapper {{
    background-color: var(--sk-bg);
}}

html[data-skin="{KEY}"] h1,
html[data-skin="{KEY}"] h2,
html[data-skin="{KEY}"] h3,
html[data-skin="{KEY}"] h4,
html[data-skin="{KEY}"] h5,
html[data-skin="{KEY}"] h6,
html[data-skin="{KEY}"] .page-title-box .page-title {{
    color: var(--sk-text);
    font-weight: 600;
}}

html[data-skin="{KEY}"] .text-muted {{
    color: var(--sk-muted) !important;
}}

/* =========================================================================
   TOPBAR
   ========================================================================= */
html[data-skin="{KEY}"] #page-topbar {{
    background-color: var(--sk-surface) !important;
    border-bottom: 1px solid var(--sk-border);
    box-shadow: none;
}}

html[data-skin="{KEY}"] .navbar-brand-box {{
    background: var(--sk-menu);
    background-image: var(--sk-menu-gradient);
}}

html[data-skin="{KEY}"] .logo,
html[data-skin="{KEY}"] .logo-text {{
    color: var(--sk-menu-head) !important;
}}

html[data-skin="{KEY}"] #vertical-menu-btn {{
    color: var(--sk-muted);
    transition: color .15s ease;
}}

html[data-skin="{KEY}"] #vertical-menu-btn:hover {{
    color: var(--sk-accent);
}}

html[data-skin="{KEY}"] #page-topbar .header-item,
html[data-skin="{KEY}"] #page-topbar .header-item i {{
    color: var(--sk-muted) !important;
}}

html[data-skin="{KEY}"] #page-topbar .header-item:hover {{
    color: var(--sk-text) !important;
}}

html[data-skin="{KEY}"] .header-item .rounded-circle[style*="626ed4"],
html[data-skin="{KEY}"] .header-item .rounded-circle[style*="#626ed4"] {{
    background-color: var(--sk-accent) !important;
    color: #fff !important;
}}

/* =========================================================================
   SIDEBAR
   ========================================================================= */
html[data-skin="{KEY}"] .vertical-menu,
html[data-skin="{KEY}"] body[data-sidebar=dark] .vertical-menu {{
    background: var(--sk-menu) !important;
    background-image: var(--sk-menu-gradient) !important;
    border-right: 1px solid var(--sk-menu-border);
}}

html[data-skin="{KEY}"] #sidebar-menu ul li a,
html[data-skin="{KEY}"] #sidebar-menu ul li a i,
html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li a,
html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li a i {{
    color: var(--sk-menu-txt) !important;
    transition: color .15s ease, background-color .15s ease;
}}

html[data-skin="{KEY}"] #sidebar-menu ul li a:hover,
html[data-skin="{KEY}"] #sidebar-menu ul li a:hover i,
html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li a:hover,
html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li a:hover i {{
    color: var(--sk-menu-head) !important;
    background-color: var(--sk-menu-2);
}}

/* Entrée active — pastille arrondie, conforme aux maquettes */
html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul>li>a.mm-active,
html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li>.mm-active,
html[data-skin="{KEY}"] body[data-sidebar=dark] .mm-active>a {{
    background-color: var(--sk-menu-2) !important;
    color: var(--sk-menu-active) !important;
    border-radius: var(--sk-radius-sm);
    margin: 2px 10px;
    box-shadow: none;
}}

html[data-skin="{KEY}"] body[data-sidebar=dark] .mm-active>a,
html[data-skin="{KEY}"] body[data-sidebar=dark] .mm-active>a i,
html[data-skin="{KEY}"] body[data-sidebar=dark] .mm-active>i,
html[data-skin="{KEY}"] body[data-sidebar=dark] .mm-active .active,
html[data-skin="{KEY}"] body[data-sidebar=dark] .mm-active .active i {{
    color: var(--sk-menu-active) !important;
    background-color: transparent;
}}

html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li ul.sub-menu li a {{
    color: var(--sk-menu-txt) !important;
}}

html[data-skin="{KEY}"] body[data-sidebar=dark] #sidebar-menu ul li ul.sub-menu li a:hover {{
    color: var(--sk-menu-head) !important;
}}

html[data-skin="{KEY}"] #sidebar-menu .menu-title {{
    color: var(--sk-menu-faint) !important;
    text-transform: uppercase;
    letter-spacing: .06em;
    font-size: 11px;
    font-weight: 600;
}}

html[data-skin="{KEY}"] body[data-sidebar=light].vertical-collpsed .vertical-menu #sidebar-menu>ul>li:hover>a,
html[data-skin="{KEY}"] body[data-sidebar=light].vertical-collpsed .vertical-menu #sidebar-menu>ul ul {{
    background: var(--sk-menu-2) !important;
    color: var(--sk-menu-head) !important;
    box-shadow: var(--sk-shadow-lg);
}}

/* =========================================================================
   SOUS-MENU ÉVÉNEMENT
   ========================================================================= */
html[data-skin="{KEY}"] .event-submenu-bar {{
    background-color: var(--sk-surface);
    border-bottom: 1px solid var(--sk-border);
}}

html[data-skin="{KEY}"] .event-submenu-title {{
    background: var(--sk-menu);
    background-image: var(--sk-menu-gradient);
    color: var(--sk-menu-head);
}}

html[data-skin="{KEY}"] .event-submenu-nav {{
    background: var(--sk-bg);
}}

html[data-skin="{KEY}"] .event-submenu-link {{
    background: var(--sk-surface);
    color: var(--sk-muted);
    border-color: var(--sk-border);
    border-radius: var(--sk-radius-sm);
    transition: all .15s ease;
}}

html[data-skin="{KEY}"] .event-submenu-link:hover {{
    background: var(--sk-surface-2);
    color: var(--sk-text);
    border-color: var(--sk-accent);
}}

html[data-skin="{KEY}"] .event-submenu-link.active {{
    color: #fff;
    background: var(--sk-accent);
    border-color: var(--sk-accent);
    box-shadow: 0 3px 10px rgba(var(--sk-accent-rgb), .3);
    font-weight: 600;
}}

/* =========================================================================
   CARTES — grands rayons, ombres douces
   ========================================================================= */
html[data-skin="{KEY}"] .card,
html[data-skin="{KEY}"] .modal-content,
html[data-skin="{KEY}"] .dropdown-menu,
html[data-skin="{KEY}"] .list-group-item,
html[data-skin="{KEY}"] .accordion-item {{
    background-color: var(--sk-surface);
    border-color: var(--sk-border-soft);
    color: var(--sk-text);
    border-radius: var(--sk-radius);
}}

html[data-skin="{KEY}"] .card {{
    box-shadow: var(--sk-shadow);
    border: 1px solid var(--sk-border-soft);
}}

html[data-skin="{KEY}"] .modal-content,
html[data-skin="{KEY}"] .dropdown-menu {{
    box-shadow: var(--sk-shadow-lg);
}}

html[data-skin="{KEY}"] .card-header,
html[data-skin="{KEY}"] .card-footer,
html[data-skin="{KEY}"] .modal-header,
html[data-skin="{KEY}"] .modal-footer {{
    background-color: transparent;
    border-color: var(--sk-border-soft);
}}

html[data-skin="{KEY}"] .card-title {{
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .dropdown-item {{
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .dropdown-item:hover,
html[data-skin="{KEY}"] .dropdown-item:focus {{
    background-color: var(--sk-accent-soft);
    color: var(--sk-accent-txt);
}}

/* --- Cartes de statistiques en dégradé -----------------------------------
   Appliquer la classe .sk-stat-1 à .sk-stat-4 sur une .card pour obtenir
   les tuiles colorées des maquettes. Le texte y est toujours blanc. */
html[data-skin="{KEY}"] .card.sk-stat-1,
html[data-skin="{KEY}"] .card.sk-stat-2,
html[data-skin="{KEY}"] .card.sk-stat-3,
html[data-skin="{KEY}"] .card.sk-stat-4 {{
    border: none;
    color: #fff;
    box-shadow: 0 6px 20px rgba(17, 24, 60, .16);
}}

html[data-skin="{KEY}"] .card.sk-stat-1 {{ background: var(--sk-grad-1); }}
html[data-skin="{KEY}"] .card.sk-stat-2 {{ background: var(--sk-grad-2); }}
html[data-skin="{KEY}"] .card.sk-stat-3 {{ background: var(--sk-grad-3); }}
html[data-skin="{KEY}"] .card.sk-stat-4 {{ background: var(--sk-grad-4); }}

html[data-skin="{KEY}"] .card[class*="sk-stat-"] .card-title,
html[data-skin="{KEY}"] .card[class*="sk-stat-"] h1,
html[data-skin="{KEY}"] .card[class*="sk-stat-"] h2,
html[data-skin="{KEY}"] .card[class*="sk-stat-"] h3,
html[data-skin="{KEY}"] .card[class*="sk-stat-"] h4,
html[data-skin="{KEY}"] .card[class*="sk-stat-"] h5,
html[data-skin="{KEY}"] .card[class*="sk-stat-"] .text-muted {{
    color: rgba(255, 255, 255, .92) !important;
}}

/* =========================================================================
   TABLEAUX
   ========================================================================= */
html[data-skin="{KEY}"] .table {{
    --bs-table-bg: transparent;
    --bs-table-color: var(--sk-text);
    --bs-table-border-color: var(--sk-border-soft);
    --bs-table-striped-bg: var(--sk-surface-2);
    --bs-table-striped-color: var(--sk-text);
    --bs-table-hover-bg: var(--sk-accent-soft);
    --bs-table-hover-color: var(--sk-text);
    color: var(--sk-text);
    border-color: var(--sk-border-soft);
}}

html[data-skin="{KEY}"] .table>thead th,
html[data-skin="{KEY}"] .table thead th {{
    background-color: var(--sk-surface-2);
    color: var(--sk-muted);
    border-color: var(--sk-border);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: .04em;
    font-size: 11.5px;
}}

html[data-skin="{KEY}"] .table>:not(caption)>*>* {{
    border-color: var(--sk-border-soft);
}}

html[data-skin="{KEY}"] table thead tr[style*="626ed4"],
html[data-skin="{KEY}"] table thead tr[style*="#626ed4"],
html[data-skin="{KEY}"] .bg-primary>thead,
html[data-skin="{KEY}"] thead.bg-primary {{
    background-color: var(--sk-surface-2) !important;
    color: var(--sk-muted) !important;
}}

html[data-skin="{KEY}"] .dataTables_wrapper,
html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_info,
html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_length,
html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_filter {{
    color: var(--sk-muted);
}}

html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_paginate .paginate_button {{
    color: var(--sk-muted) !important;
    border-radius: var(--sk-radius-sm);
}}

html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_paginate .paginate_button:hover {{
    background: var(--sk-surface-2) !important;
    border-color: var(--sk-border) !important;
    color: var(--sk-text) !important;
}}

html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_paginate .paginate_button.current,
html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {{
    background: var(--sk-accent) !important;
    border-color: var(--sk-accent) !important;
    color: #fff !important;
    font-weight: 600;
}}

html[data-skin="{KEY}"] .dataTables_wrapper .dataTables_processing {{
    background: var(--sk-surface) !important;
    color: var(--sk-text) !important;
    border: 1px solid var(--sk-border);
    border-radius: var(--sk-radius);
    box-shadow: var(--sk-shadow-lg);
}}

html[data-skin="{KEY}"] .page-link {{
    background-color: var(--sk-surface);
    border-color: var(--sk-border);
    color: var(--sk-muted);
}}

html[data-skin="{KEY}"] .page-link:hover {{
    background-color: var(--sk-surface-2);
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .page-item.active .page-link {{
    background-color: var(--sk-accent);
    border-color: var(--sk-accent);
    color: #fff;
}}

/* =========================================================================
   FORMULAIRES
   ========================================================================= */
html[data-skin="{KEY}"] .form-control,
html[data-skin="{KEY}"] .form-select,
html[data-skin="{KEY}"] .input-group-text {{
    background-color: var(--sk-surface);
    border-color: var(--sk-border);
    color: var(--sk-text);
    border-radius: var(--sk-radius-sm);
    transition: border-color .15s ease, box-shadow .15s ease;
}}

html[data-skin="{KEY}"] .input-group-text {{
    background-color: var(--sk-surface-2);
}}

html[data-skin="{KEY}"] .form-control::placeholder {{
    color: var(--sk-faint);
}}

html[data-skin="{KEY}"] .form-control:focus,
html[data-skin="{KEY}"] .form-select:focus {{
    background-color: var(--sk-surface);
    border-color: var(--sk-accent);
    color: var(--sk-text);
    box-shadow: 0 0 0 3px var(--sk-accent-ring);
}}

html[data-skin="{KEY}"] .form-control:disabled,
html[data-skin="{KEY}"] .form-control[readonly] {{
    background-color: var(--sk-surface-2);
    color: var(--sk-muted);
    border-color: var(--sk-border-soft);
}}

html[data-skin="{KEY}"] .form-label,
html[data-skin="{KEY}"] .col-form-label,
html[data-skin="{KEY}"] label {{
    color: var(--sk-text);
    font-weight: 500;
}}

html[data-skin="{KEY}"] .form-check-input {{
    border-color: var(--sk-border);
}}

html[data-skin="{KEY}"] .form-check-input:checked {{
    background-color: var(--sk-accent);
    border-color: var(--sk-accent);
}}

html[data-skin="{KEY}"] .form-check-input:focus {{
    border-color: var(--sk-accent);
    box-shadow: 0 0 0 3px var(--sk-accent-ring);
}}

html[data-skin="{KEY}"] .form-check-input.is-valid:checked,
html[data-skin="{KEY}"] .was-validated .form-check-input:valid:checked {{
    background-color: var(--sk-accent);
    border-color: var(--sk-accent);
}}

html[data-skin="{KEY}"] .form-control.is-valid:focus,
html[data-skin="{KEY}"] .was-validated .form-control:valid:focus {{
    border-color: var(--sk-accent);
}}

html[data-skin="{KEY}"] .invalid-feedback {{
    color: var(--sk-danger);
}}

html[data-skin="{KEY}"] .form-control.is-invalid,
html[data-skin="{KEY}"] .was-validated .form-control:invalid {{
    border-color: var(--sk-danger);
}}

/* Select2 */
html[data-skin="{KEY}"] .select2-container--default .select2-selection--single,
html[data-skin="{KEY}"] .select2-container--default .select2-selection--multiple {{
    background-color: var(--sk-surface);
    border-color: var(--sk-border);
    color: var(--sk-text);
    border-radius: var(--sk-radius-sm);
}}

html[data-skin="{KEY}"] .select2-dropdown {{
    background-color: var(--sk-surface);
    border-color: var(--sk-border);
    border-radius: var(--sk-radius-sm);
    box-shadow: var(--sk-shadow-lg);
}}

html[data-skin="{KEY}"] .select2-container--default .select2-results__option {{
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .select2-container--default .select2-results__option--highlighted[aria-selected] {{
    background-color: var(--sk-accent);
    color: #fff;
}}

html[data-skin="{KEY}"] .select2-container--default .select2-selection--single .select2-selection__rendered {{
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .select2-container--default .select2-selection--multiple .select2-selection__choice {{
    background-color: var(--sk-accent-soft);
    border-color: var(--sk-accent);
    color: var(--sk-accent-txt);
}}

/* =========================================================================
   BOUTONS
   ========================================================================= */
html[data-skin="{KEY}"] .btn {{
    border-radius: var(--sk-radius-sm);
    font-weight: 500;
    transition: all .15s ease;
}}

html[data-skin="{KEY}"] .btn-primary {{
    --bs-btn-bg: var(--sk-accent);
    --bs-btn-border-color: var(--sk-accent);
    --bs-btn-hover-bg: var(--sk-accent-hover);
    --bs-btn-hover-border-color: var(--sk-accent-hover);
    --bs-btn-active-bg: var(--sk-accent-active);
    --bs-btn-active-border-color: var(--sk-accent-active);
    --bs-btn-disabled-bg: var(--sk-accent);
    --bs-btn-disabled-border-color: var(--sk-accent);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
    --bs-btn-active-color: #fff;
    --bs-btn-disabled-color: #fff;
    font-weight: 600;
    box-shadow: 0 2px 8px rgba(var(--sk-accent-rgb), .25);
}}

html[data-skin="{KEY}"] .btn-outline-primary {{
    --bs-btn-color: var(--sk-accent-txt);
    --bs-btn-border-color: var(--sk-accent);
    --bs-btn-hover-bg: var(--sk-accent);
    --bs-btn-hover-border-color: var(--sk-accent);
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-blue,
html[data-skin="{KEY}"] .btn-dark-blue {{
    --bs-btn-bg: var(--sk-accent);
    --bs-btn-border-color: var(--sk-accent);
    --bs-btn-hover-bg: var(--sk-accent-hover);
    --bs-btn-hover-border-color: var(--sk-accent-hover);
    --bs-btn-active-bg: var(--sk-accent-active);
    --bs-btn-active-border-color: var(--sk-accent-active);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-secondary,
html[data-skin="{KEY}"] .btn-light {{
    --bs-btn-bg: var(--sk-surface-2);
    --bs-btn-border-color: var(--sk-border);
    --bs-btn-color: var(--sk-text);
    --bs-btn-hover-bg: var(--sk-surface-3);
    --bs-btn-hover-border-color: var(--sk-border);
    --bs-btn-hover-color: var(--sk-text);
}}

html[data-skin="{KEY}"] .btn-outline-secondary {{
    --bs-btn-color: var(--sk-muted);
    --bs-btn-border-color: var(--sk-border);
    --bs-btn-hover-bg: var(--sk-surface-2);
    --bs-btn-hover-border-color: var(--sk-border);
    --bs-btn-hover-color: var(--sk-text);
}}

html[data-skin="{KEY}"] .btn-success {{
    --bs-btn-bg: var(--sk-success);
    --bs-btn-border-color: var(--sk-success);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-warning {{
    --bs-btn-bg: var(--sk-warning);
    --bs-btn-border-color: var(--sk-warning);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-danger {{
    --bs-btn-bg: var(--sk-danger);
    --bs-btn-border-color: var(--sk-danger);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-info {{
    --bs-btn-bg: var(--sk-info);
    --bs-btn-border-color: var(--sk-info);
    --bs-btn-color: #fff;
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-success:hover,
html[data-skin="{KEY}"] .btn-warning:hover,
html[data-skin="{KEY}"] .btn-danger:hover,
html[data-skin="{KEY}"] .btn-info:hover {{
    filter: brightness(.92);
}}

html[data-skin="{KEY}"] .btn-outline-success {{
    --bs-btn-color: var(--sk-success);
    --bs-btn-border-color: var(--sk-success);
    --bs-btn-hover-bg: var(--sk-success);
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-outline-danger {{
    --bs-btn-color: var(--sk-danger);
    --bs-btn-border-color: var(--sk-danger);
    --bs-btn-hover-bg: var(--sk-danger);
    --bs-btn-hover-color: #fff;
}}

html[data-skin="{KEY}"] .btn-outline-warning {{
    --bs-btn-color: var(--sk-warning);
    --bs-btn-border-color: var(--sk-warning);
    --bs-btn-hover-bg: var(--sk-warning);
    --bs-btn-hover-color: #fff;
}}

/* =========================================================================
   BADGES ET PASTILLES
   ========================================================================= */
html[data-skin="{KEY}"] .bg-primary {{
    background-color: var(--sk-accent) !important;
    color: #fff !important;
}}

html[data-skin="{KEY}"] .text-primary {{
    color: var(--sk-accent-txt) !important;
}}

html[data-skin="{KEY}"] .bg-soft-primary {{
    background-color: var(--sk-accent-soft) !important;
}}

html[data-skin="{KEY}"] .border-primary {{
    border-color: var(--sk-accent) !important;
}}

html[data-skin="{KEY}"] .badge {{
    font-weight: 600;
    letter-spacing: .01em;
    border-radius: 6px;
    padding: .35em .6em;
}}

html[data-skin="{KEY}"] .badge.bg-soft-primary.text-primary {{
    color: var(--sk-accent-txt) !important;
    background-color: var(--sk-accent-soft) !important;
}}

html[data-skin="{KEY}"] .bg-success {{
    background-color: var(--sk-success) !important;
    color: #fff !important;
}}

html[data-skin="{KEY}"] .bg-warning {{
    background-color: var(--sk-warning) !important;
    color: #fff !important;
}}

html[data-skin="{KEY}"] .bg-danger {{
    background-color: var(--sk-danger) !important;
    color: #fff !important;
}}

html[data-skin="{KEY}"] .bg-info {{
    background-color: var(--sk-info) !important;
    color: #fff !important;
}}

html[data-skin="{KEY}"] .text-success {{
    color: var(--sk-success) !important;
}}

html[data-skin="{KEY}"] .text-warning {{
    color: var(--sk-warning) !important;
}}

html[data-skin="{KEY}"] .text-danger {{
    color: var(--sk-danger) !important;
}}

html[data-skin="{KEY}"] .text-info {{
    color: var(--sk-info) !important;
}}

html[data-skin="{KEY}"] .badge.bg-light {{
    background-color: var(--sk-surface-3) !important;
    color: var(--sk-text) !important;
}}

html[data-skin="{KEY}"] .alert {{
    border-radius: var(--sk-radius-sm);
}}

html[data-skin="{KEY}"] .alert-success {{
    background-color: var(--sk-success-soft);
    border-color: var(--sk-success);
    color: var(--sk-success);
}}

html[data-skin="{KEY}"] .alert-warning {{
    background-color: var(--sk-warning-soft);
    border-color: var(--sk-warning);
    color: var(--sk-warning);
}}

html[data-skin="{KEY}"] .alert-danger {{
    background-color: var(--sk-danger-soft);
    border-color: var(--sk-danger);
    color: var(--sk-danger);
}}

html[data-skin="{KEY}"] .alert-info,
html[data-skin="{KEY}"] .alert-primary {{
    background-color: var(--sk-info-soft);
    border-color: var(--sk-info);
    color: var(--sk-info);
}}

/* =========================================================================
   DIVERS
   ========================================================================= */
html[data-skin="{KEY}"] hr,
html[data-skin="{KEY}"] .dropdown-divider {{
    border-color: var(--sk-border);
    opacity: 1;
}}

html[data-skin="{KEY}"] a {{
    color: var(--sk-accent-txt);
    text-decoration: none;
}}

html[data-skin="{KEY}"] a:hover {{
    color: var(--sk-accent-hover);
}}

html[data-skin="{KEY}"] .role,
html[data-skin="{KEY}"] span.workshop-title {{
    color: var(--sk-accent-txt);
}}

html[data-skin="{KEY}"] .nav-tabs {{
    border-bottom-color: var(--sk-border);
}}

html[data-skin="{KEY}"] .nav-tabs .nav-link {{
    color: var(--sk-muted);
    border-color: transparent;
}}

html[data-skin="{KEY}"] .nav-tabs .nav-link:hover {{
    color: var(--sk-text);
    border-color: transparent;
}}

html[data-skin="{KEY}"] .nav-tabs .nav-link.active {{
    background-color: transparent;
    color: var(--sk-accent-txt);
    border-color: transparent;
    border-bottom: 2px solid var(--sk-accent);
    font-weight: 600;
}}

html[data-skin="{KEY}"] .breadcrumb-item,
html[data-skin="{KEY}"] .breadcrumb-item a {{
    color: var(--sk-muted);
}}

html[data-skin="{KEY}"] .breadcrumb-item.active {{
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] .progress {{
    background-color: var(--sk-surface-3);
    border-radius: 20px;
}}

html[data-skin="{KEY}"] .progress-bar {{
    background-color: var(--sk-accent);
    border-radius: 20px;
}}

html[data-skin="{KEY}"] .tooltip-inner {{
    background-color: var(--sk-text);
    color: #fff;
    border-radius: var(--sk-radius-sm);
}}

html[data-skin="{KEY}"] #toast-container>.toast {{
    background-color: var(--sk-surface) !important;
    border: 1px solid var(--sk-border);
    border-radius: var(--sk-radius-sm);
    box-shadow: var(--sk-shadow-lg);
    color: var(--sk-text);
    opacity: 1;
}}

html[data-skin="{KEY}"] #toast-container>.toast-success {{
    border-left: 3px solid var(--sk-success);
}}

html[data-skin="{KEY}"] #toast-container>.toast-error {{
    border-left: 3px solid var(--sk-danger);
}}

html[data-skin="{KEY}"] #toast-container>.toast-warning {{
    border-left: 3px solid var(--sk-warning);
}}

html[data-skin="{KEY}"] #toast-container>.toast-info {{
    border-left: 3px solid var(--sk-info);
}}

html[data-skin="{KEY}"] .swal2-popup {{
    background: var(--sk-surface) !important;
    color: var(--sk-text) !important;
    border-radius: var(--sk-radius);
}}

html[data-skin="{KEY}"] .swal2-title,
html[data-skin="{KEY}"] .swal2-html-container {{
    color: var(--sk-text) !important;
}}

html[data-skin="{KEY}"] .footer {{
    background-color: var(--sk-surface);
    border-top: 1px solid var(--sk-border);
    color: var(--sk-muted);
}}

html[data-skin="{KEY}"] .impersonation-bar {{
    background-color: var(--sk-warning) !important;
    color: #fff !important;
}}

/* Barre de défilement */
html[data-skin="{KEY}"] ::-webkit-scrollbar {{
    width: 11px;
    height: 11px;
}}

html[data-skin="{KEY}"] ::-webkit-scrollbar-track {{
    background: var(--sk-surface-2);
}}

html[data-skin="{KEY}"] ::-webkit-scrollbar-thumb {{
    background: var(--sk-border);
    border-radius: 8px;
    border: 2px solid var(--sk-surface-2);
}}

html[data-skin="{KEY}"] ::-webkit-scrollbar-thumb:hover {{
    background: var(--sk-faint);
}}

html[data-skin="{KEY}"] .vertical-menu ::-webkit-scrollbar-track {{
    background: var(--sk-menu);
}}

html[data-skin="{KEY}"] .vertical-menu ::-webkit-scrollbar-thumb {{
    background: var(--sk-menu-2);
    border-color: var(--sk-menu);
}}

html[data-skin="{KEY}"] ::selection {{
    background: var(--sk-accent-ring);
    color: var(--sk-text);
}}

html[data-skin="{KEY}"] :focus-visible {{
    outline: 2px solid var(--sk-accent);
    outline-offset: 2px;
}}

/* Support RTL — propriétés logiques pour les marges de menu actif */
html[data-skin="{KEY}"][dir="rtl"] body[data-sidebar=dark] .mm-active>a {{
    margin-inline: 10px;
}}

@media print {{

    html[data-skin="{KEY}"] #page-topbar,
    html[data-skin="{KEY}"] .vertical-menu,
    html[data-skin="{KEY}"] .footer {{
        display: none !important;
    }}

    html[data-skin="{KEY}"] .main-content {{
        margin-left: 0 !important;
    }}
}}
"""


# ---------------------------------------------------------------------------
# Contrôle de contraste WCAG
# ---------------------------------------------------------------------------
def _lum(h):
    h = h.lstrip("#")
    r, g, b = [int(h[i:i + 2], 16) / 255 for i in (0, 2, 4)]
    f = lambda c: c / 12.92 if c <= 0.03928 else ((c + 0.055) / 1.055) ** 2.4
    return 0.2126 * f(r) + 0.7152 * f(g) + 0.0722 * f(b)


def _ratio(a, b):
    la, lb = _lum(a), _lum(b)
    hi, lo = max(la, lb), min(la, lb)
    return (hi + 0.05) / (lo + 0.05)


def check(key, p):
    W = "#ffffff"
    tests = [
        ("menu txt / menu", p["menu_txt"], p["menu"], 4.5),
        ("menu head / menu", p["menu_head"], p["menu"], 4.5),
        ("menu actif / menu", p["menu_active"], p["menu"], 4.5),
        ("menu txt / menu-2", p["menu_txt"], p["menu_2"], 4.5),
        ("menu faint / menu", p["menu_faint"], p["menu"], 3.0),
        ("texte / fond", p["text"], p["bg"], 4.5),
        ("texte / surface", p["text"], p["surface"], 4.5),
        ("texte / surface-2", p["text"], p["surface_2"], 4.5),
        ("muted / fond", p["muted"], p["bg"], 4.5),
        ("muted / surface", p["muted"], p["surface"], 4.5),
        ("muted / surface-2", p["muted"], p["surface_2"], 4.5),
        ("faint / surface", p["faint"], p["surface"], 3.0),
        ("accent-txt / surface", p["accent_txt"], p["surface"], 4.5),
        ("accent-txt / accent-soft", p["accent_txt"], p["accent_soft"], 4.5),
        ("blanc / accent", W, p["accent"], 4.5),
        ("blanc / success", W, p["success"], 4.5),
        ("blanc / warning", W, p["warning"], 4.5),
        ("blanc / danger", W, p["danger"], 4.5),
        ("blanc / info", W, p["info"], 4.5),
        ("success / success-soft", p["success"], p["success_soft"], 4.5),
        ("danger / danger-soft", p["danger"], p["danger_soft"], 4.5),
        ("bordure / surface", p["border"], p["surface"], 1.4),
    ]
    return [(n, _ratio(f, b), s) for n, f, b, s in tests if _ratio(f, b) < s]


# ---------------------------------------------------------------------------
if __name__ == "__main__":
    total_ko = 0
    for key, p in SKINS.items():
        ko = check(key, p)
        total_ko += len(ko)
        css = TEMPLATE.format(KEY=key, TITRE=p["titre"], DESC=p["desc"], **p)
        (OUT / f"skin-{key}.css").write_text(css, encoding="utf-8")
        etat = "CONFORME" if not ko else f"{len(ko)} ECHEC(S)"
        print(f"  skin-{key + '.css':<18} {len(css.splitlines()):>4} lignes   {etat}")
        for n, r, s in ko:
            print(f"       ! {n:<26}{r:.2f}:1 (min {s})")
    print("\nTOUS LES SKINS SONT CONFORMES WCAG AA" if total_ko == 0
          else f"\n{total_ko} controle(s) en echec")
