// ECO-PANNEAU.FR - _react/ui/_ui_components.jsx

// 1. - DESIGN SYSTEM : COMPOSANTS UI ATOMIQUES

// 1.1 - Bouton unifié (Gestion des variantes, icônes et formes)
window.pano_Button = ({ children, onClick, disabled, variant = 'primary', icon: Icon, className = '', type = 'button', title = '', shape, ...props }) => {
    const hasPx = /(^|\s)(px-|p-)/.test(className);
    const hasPy = /(^|\s)(py-|p-)/.test(className);
    const hasH = /(^|\s)(h-|min-h-|max-h-)/.test(className);
    const hasW = /(^|\s)(w-|min-w-|max-w-)/.test(className);

    let baseClass = "text-xs font-bold transition flex items-center justify-center gap-2 shadow-sm border border-transparent select-none";
    
    if (shape === 'square') {
        baseClass += " rounded-xl shrink-0 aspect-square";
        if (!hasPx && !hasPy && !hasW && !hasH) baseClass += " p-2.5";
    } else if (shape === 'round') {
        baseClass += " rounded-full shrink-0 aspect-square";
        if (!hasPx && !hasPy && !hasW && !hasH) baseClass += " p-2.5";
    } else {
        baseClass += " rounded-xl";
        if (!hasPx) baseClass += " px-4";
        if (!hasPy && !hasH) baseClass += " py-2.5";
    }
    
    const variants = {
        primary: "bg-emerald-600 text-white hover:bg-emerald-700 shadow-md",
        success: "bg-emerald-50 text-emerald-600 hover:bg-emerald-100", 
        successSolid: "bg-emerald-600 text-white hover:bg-emerald-700 shadow-md",
        danger: "bg-red-50 text-red-600 hover:bg-red-100",
        dangerSolid: "bg-red-600 text-white hover:bg-red-700 shadow-md",
        warning: "bg-orange-50 text-orange-600 hover:bg-orange-100",
        warningSolid: "bg-orange-500 text-white hover:bg-orange-600 shadow-md",
        info: "bg-blue-50 text-blue-700 hover:bg-blue-100",
        infoSolid: "bg-blue-600 text-white hover:bg-blue-700 shadow-md",
        secondary: "bg-slate-100 text-slate-700 hover:bg-slate-200 border-slate-200",
        outline: "bg-white border-slate-200 text-slate-600 hover:bg-slate-50",
        purple: "bg-purple-50 text-purple-700 hover:bg-purple-100",
        dark: "bg-slate-900 text-white hover:bg-slate-800 shadow-md",
        ghost: "bg-transparent text-slate-500 hover:text-slate-800 hover:bg-slate-100 shadow-none border-transparent"
    };

    return (
        <button 
            type={type}
            disabled={disabled}
            onClick={(e) => { if (!disabled && onClick) onClick(e); }}
            title={title} 
            className={`${baseClass} ${variants[variant] || variants.primary} ${className} ${disabled ? 'opacity-50 cursor-not-allowed' : ''}`} 
            {...props}
        >
            {Icon && <Icon size={16} className="shrink-0" />}
            {children}
        </button>
    );
};

// 1.2 - Badge d'icône (Décoratif)
window.pano_IconBadge = ({ icon: Icon, variant = 'info', size = 'md', className = '' }) => {
    const variants = {
        primary: "bg-emerald-100 text-emerald-600",
        success: "bg-emerald-100 text-emerald-600",
        danger: "bg-red-100 text-red-600",
        warning: "bg-orange-100 text-orange-600",
        info: "bg-blue-100 text-blue-600",
        secondary: "bg-slate-100 text-slate-500",
        purple: "bg-purple-100 text-purple-600",
        dark: "bg-slate-800 text-slate-300"
    };
    const sizes = {
        sm: "w-8 h-8 rounded-lg",
        md: "w-10 h-10 rounded-xl",
        lg: "w-12 h-12 rounded-2xl",
        xl: "w-14 h-14 rounded-2xl"
    };
    const iconSizes = { sm: 14, md: 18, lg: 24, xl: 28 };
    return (
        <div className={`flex items-center justify-center shrink-0 ${variants[variant] || variants.info} ${sizes[size] || sizes.md} ${className}`}>
            {Icon && <Icon size={iconSizes[size] || 18} />}
        </div>
    );
};

// 1.3 - Badge de notification (Compteur)
window.pano_NotificationBadge = ({ count, className = '' }) => {
    if (!count || count <= 0) return null;
    const displayCount = count > 99 ? '99+' : count;
    return (
        <span className={`min-w-[20px] h-5 px-1.5 flex items-center justify-center rounded-full bg-red-600 text-white text-[10px] font-black shadow-sm leading-none select-none ${className}`}>
            {displayCount}
        </span>
    );
};

// 1.4 - Interrupteur (Toggle)
window.pano_Toggle = ({ checked, onChange, variant = 'success', disabled = false }) => {
    const variants = {
        success: 'bg-emerald-500',
        info: 'bg-blue-500',
        warning: 'bg-orange-500',
        danger: 'bg-red-500',
        purple: 'bg-purple-500'
    };
    const colorClass = variants[variant] || variants.success;
    return (
        <div 
            className={`w-10 h-5 rounded-full transition-colors flex items-center px-0.5 shrink-0 select-none ${disabled ? 'opacity-50 cursor-not-allowed' : (onChange ? 'cursor-pointer' : '')} ${checked ? colorClass : 'bg-slate-300'}`}
            onClick={(e) => { if(onChange && !disabled) { e.stopPropagation(); onChange(!checked); } }}
        >
            <div className={`bg-white w-4 h-4 rounded-full transition-transform shadow-sm ${checked ? 'translate-x-5' : 'translate-x-0'}`}></div>
        </div>
    );
};

// 1.5 - État vide (Empty State)
window.pano_EmptyState = ({ icon: Icon, text, subtext, className = "" }) => (
    <div className={`text-center p-6 bg-slate-50 border border-slate-200 border-dashed rounded-2xl ${className}`}>
        {Icon && <Icon size={32} className="mx-auto text-slate-300 mb-3" />}
        <h3 className="text-sm font-black text-slate-700">{text}</h3>
        {subtext && <p className="text-xs text-slate-500 mt-1">{subtext}</p>}
    </div>
);

// 1.6 - Boîte d'alerte (Informations critiques)
window.pano_AlertBox = ({ type = 'info', icon: Icon, title, children, className = "" }) => {
    const styles = {
        info: 'bg-blue-50 text-blue-800 border-blue-200',
        warning: 'bg-orange-50 text-orange-800 border-orange-200',
        error: 'bg-red-50 text-red-800 border-red-200',
        success: 'bg-emerald-50 text-emerald-800 border-emerald-200'
    };
    const iconColors = {
        info: 'text-blue-500',
        warning: 'text-orange-500',
        error: 'text-red-500',
        success: 'text-emerald-500'
    };
    return (
        <div className={`p-3 sm:p-4 rounded-xl border flex gap-3 items-start shadow-sm ${styles[type] || styles.info} ${className}`}>
            {Icon && <Icon size={20} className={`shrink-0 ${title ? ('mt-0.5 ' + iconColors[type]) : ''}`} />}
            <div className="flex-1 text-sm leading-relaxed">
                {title && <p className="font-bold mb-1">{title}</p>}
                {children}
            </div>
        </div>
    );
};

// 1.7 - Carte de statistique
window.pano_StatCard = ({ title, value, icon, variant = 'info', onClick }) => {
    const variants = {
        success: { bg: 'bg-emerald-100', text: 'text-emerald-600' },
        info: { bg: 'bg-blue-100', text: 'text-blue-600' },
        warning: { bg: 'bg-amber-100', text: 'text-amber-600' },
        danger: { bg: 'bg-red-100', text: 'text-red-600' },
        secondary: { bg: 'bg-slate-200', text: 'text-slate-600' },
        purple: { bg: 'bg-purple-100', text: 'text-purple-600' },
        indigo: { bg: 'bg-indigo-100', text: 'text-indigo-600' }
    };
    const v = variants[variant] || variants.info;
    return (
        <div onClick={onClick} className={`bg-white rounded-2xl p-4 shadow-sm border border-slate-100 flex items-center gap-3 ${onClick ? 'cursor-pointer hover:shadow-md transition hover:border-slate-300 select-none' : ''}`}>
            <div className={`w-12 h-12 rounded-xl flex items-center justify-center shrink-0 ${v.bg} ${v.text}`}>{icon}</div>
            <div className="min-w-0 flex-1">
                <p className="text-xs font-bold text-slate-500 uppercase tracking-widest break-words leading-snug">{title}</p>
                <p className="text-xl font-black text-slate-800 mt-1 break-words leading-tight">{value}</p>
            </div>
        </div>
    );
};

// 1.8 - Saisie de prix (HT)
// CORRECTION UX : Implémentation du pattern "Controlled Input" avec état local pour ne pas bloquer les virgules (décimales)
window.pano_PriceInput = ({ label, value, onChange, ...props }) => {
    const { useState, useEffect } = React;
    // On conserve la saisie exacte de l'utilisateur sous forme de chaîne (permet de taper "10.")
    const [localValue, setLocalValue] = useState(value === 0 ? '' : String(value));

    // Si la valeur externe change "de force" (ex: reset du formulaire), on met à jour
    useEffect(() => {
        const parsedLocal = parseFloat(localValue);
        if (parsedLocal !== value && !(localValue === '' && value === 0)) {
            setLocalValue(value === 0 ? '' : String(value));
        }
    }, [value]);

    const handleChange = (e) => {
        const val = e.target.value;
        setLocalValue(val);
        const parsed = parseFloat(val);
        onChange(isNaN(parsed) ? 0 : parsed);
    };

    return (
        <div className="p-3 bg-slate-50 border border-slate-100 rounded-xl">
            <label className="text-xs font-bold text-slate-700 uppercase block mb-2">{label}</label>
            <div className="relative">
                <input 
                    type="number" 
                    step="0.01" 
                    min="0" 
                    value={localValue} 
                    onChange={handleChange} 
                    className="w-full border-2 border-slate-200 rounded-xl p-2.5 pr-8 text-sm focus:border-emerald-500 outline-none transition font-bold text-slate-800" 
                    {...props} 
                />
                <span className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 font-bold select-none">€</span>
            </div>
        </div>
    );
};

// 1.9 - Badge de statut (Coloration intelligente)
window.pano_StatusBadge = ({ status, variant, className = '' }) => {
    let colorClass = 'bg-slate-100 text-slate-600 border-slate-200';
    let displayStatus = status;

    if (status === 'En attente de validation') displayStatus = 'Validation';
    else if (status === 'En attente de commande au fournisseur') displayStatus = 'Commande';
    else if (status === "En attente d'impression") displayStatus = 'Impression';
    else if (status === 'Réception confirmée') displayStatus = 'Livré';
    
    if (variant) {
        const variants = {
            success: 'bg-emerald-100 text-emerald-700 border-emerald-200',
            danger: 'bg-red-100 text-red-700 border-red-200',
            warning: 'bg-amber-100 text-amber-700 border-amber-200',
            info: 'bg-blue-100 text-blue-700 border-blue-200',
            secondary: 'bg-slate-100 text-slate-600 border-slate-200'
        };
        colorClass = variants[variant] || colorClass;
    } else {
        const s = (status || '').toLowerCase();
        if (s.includes('actif') || s.includes('livré') || s.includes('activé') || s.includes('accept') || s === 'réception confirmée') {
            colorClass = 'bg-emerald-100 text-emerald-700 border-emerald-200';
        } else if (s.includes('suspendu') || s.includes('erreur') || s.includes('hors ligne') || s.includes('refus') || s.includes('désactivé')) {
            colorClass = 'bg-red-100 text-red-700 border-red-200';
        } else if (s.includes('brouillon') || s.includes('attente') || s.includes('validation') || s.includes('programmé') || s.includes('commande') || s.includes('impression')) {
            colorClass = 'bg-amber-100 text-amber-700 border-amber-200';
        } else if (s.includes('expédié')) {
            colorClass = 'bg-blue-100 text-blue-700 border-blue-200';
        }
    }
    
    return (
        <span className={`px-2 py-0.5 rounded-md text-[10px] font-black uppercase tracking-widest text-center border select-none ${colorClass} ${className}`}>
            {displayStatus}
        </span>
    );
};

// 1.10 - Champ de saisie (FormInput)
window.pano_FormInput = ({ label, value, onChange, type = 'text', required = false, disabled = false, placeholder = '', className = '', inputClassName = '', hint = '', error = false, errorText = '', icon, ...props }) => {
    const [showPwd, setShowPwd] = React.useState(false);
    const { EyeIcon, EyeOffIcon } = window.pano_getIcons();
    const isPassword = type === 'password';
    const actualType = isPassword ? (showPwd ? 'text' : 'password') : type;

    return (
        <div className={`space-y-1 ${className}`}>
            {label && (
                <label className="text-xs font-bold text-slate-500 uppercase block">
                    {label} {required && <span className="text-red-500 font-black">*</span>}
                </label>
            )}
            <div className="relative">
                {icon && (
                    <div className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400">
                        {icon}
                    </div>
                )}
                <input 
                    type={actualType} 
                    value={value} 
                    onChange={onChange} 
                    required={required}
                    disabled={disabled}
                    placeholder={placeholder}
                    className={`w-full border-2 rounded-xl p-3 text-sm outline-none transition font-bold disabled:bg-slate-50 disabled:text-slate-500 disabled:cursor-not-allowed ${icon ? 'pl-10' : ''} ${isPassword ? 'pr-10' : ''} ${error ? 'border-red-400 focus:border-red-500 bg-red-50 text-red-900' : 'border-slate-200 focus:border-emerald-500 bg-white text-slate-800'} ${inputClassName}`} 
                    {...props}
                />
                {isPassword && (
                    <div 
                        role="button"
                        tabIndex={0}
                        className="absolute right-3 top-1/2 -translate-y-1/2 text-slate-400 hover:text-emerald-600 cursor-pointer select-none"
                        onClick={(e) => { e.preventDefault(); e.stopPropagation(); setShowPwd(!showPwd); }}
                        title={showPwd ? "Masquer" : "Afficher"}
                    >
                        {showPwd ? (EyeOffIcon && <EyeOffIcon size={18} />) : (EyeIcon && <EyeIcon size={18} />)}
                    </div>
                )}
            </div>
            {hint && !errorText && <p className="text-xs text-slate-400 mt-1">{hint}</p>}
            {errorText && <p className="text-xs text-red-500 font-bold mt-1">{errorText}</p>}
        </div>
    );
};

// 1.11 - Zone de texte (FormTextarea)
// CORRECTION CSS : Séparation propre de className (conteneur) et inputClassName (textarea)
window.pano_FormTextarea = ({ label, value, onChange, rows = 3, required = false, disabled = false, placeholder = '', className = '', inputClassName = '', hint = '', error = false, errorText = '', ...props }) => (
    <div className={`space-y-1 ${className}`}>
        <label className="text-xs font-bold text-slate-500 uppercase block">
            {label} {required && <span className="text-red-500 font-black">*</span>}
        </label>
        <textarea 
            rows={rows}
            value={value} 
            onChange={onChange} 
            required={required}
            disabled={disabled}
            placeholder={placeholder}
            className={`w-full border-2 rounded-xl p-3 text-sm outline-none transition font-bold disabled:bg-slate-50 disabled:text-slate-500 disabled:cursor-not-allowed resize-none custom-scrollbar ${error ? 'border-red-400 focus:border-red-500 bg-red-50 text-red-900' : 'border-slate-200 focus:border-emerald-500 bg-white text-slate-800'} ${inputClassName}`} 
            {...props}
        />
        {hint && !errorText && <p className="text-xs text-slate-400 mt-1">{hint}</p>}
        {errorText && <p className="text-xs text-red-500 font-bold mt-1">{errorText}</p>}
    </div>
);

// 2. - CONTAINERS ET GRILLES DE CARTES

// 2.1 - Grille responsive (CardGrid)
window.pano_CardGrid = ({ children, minWidth = "300px", className = "" }) => (
    <div 
        className={`grid gap-4 ${className}`} 
        style={{ gridTemplateColumns: `repeat(auto-fill, minmax(${minWidth}, 1fr))` }}
    >
        {children}
    </div>
);

// 2.2 - Carte de données stylisée (DataCard)
window.pano_DataCard = ({ children, variant = 'default', className = "", onClick, ...props }) => {
    const variants = {
        default: 'bg-white border-slate-200',
        warning: 'bg-amber-50/50 border-amber-300',
        danger: 'bg-red-50/30 border-red-400',
        success: 'bg-emerald-50 border-emerald-200',
        info: 'bg-blue-50 border-blue-200',
        slate: 'bg-slate-50 border-slate-200',
    };
    
    const vClass = variants[variant] || variants.default;
    
    return (
        <div 
            onClick={onClick}
            className={`rounded-2xl p-4 shadow-sm border flex flex-col gap-3 transition hover:shadow-md ${vClass} ${onClick ? 'cursor-pointer hover:border-emerald-300 select-none' : ''} ${className}`}
            {...props}
        >
            {children}
        </div>
    );
};

// 3. - COMPOSANTS DE RECHERCHE ET PAGINATION

// 3.1 - Barre de recherche (SearchBar)
window.pano_SearchBar = ({ searchQuery, setSearchQuery, placeholder = "Rechercher..." }) => {
    const { SearchIcon, XIcon } = window.pano_getIcons();
    return (
        <div className="relative w-full md:w-80 shrink-0">
            <div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
                {SearchIcon && <SearchIcon size={18} className="text-slate-400" />}
            </div>
            <input
                type="text"
                value={searchQuery}
                onChange={(e) => setSearchQuery(e.target.value)}
                onKeyDown={(e) => {
                    if (e.key === 'Escape') {
                        setSearchQuery('');
                    }
                }}
                placeholder={placeholder}
                className="w-full pl-10 pr-10 py-3 bg-white border-2 border-slate-200 rounded-xl text-sm font-bold text-slate-700 outline-none focus:border-blue-500 transition shadow-sm"
            />
            {searchQuery && (
                <button 
                    onClick={() => setSearchQuery('')}
                    className="absolute inset-y-0 right-0 pr-3 flex items-center text-slate-400 hover:text-slate-600 select-none"
                >
                    {XIcon && <XIcon size={16} />}
                </button>
            )}
        </div>
    );
};

// 3.2 - Résultat de recherche vide (EmptySearch)
window.pano_EmptySearch = ({ searchQuery }) => {
    const { SearchIcon } = window.pano_getIcons();
    return (
        <div className="text-center p-10 bg-white rounded-3xl border border-slate-200 border-dashed">
            <SearchIcon size={48} className="mx-auto text-slate-300 mb-4" />
            <p className="text-slate-500 font-bold">Aucun résultat pour "<span className="text-slate-800">{searchQuery}</span>".</p>
            <p className="text-sm text-slate-400 mt-1">Essayez d'autres mots-clés ou videz la recherche.</p>
        </div>
    );
};

// 3.3 - Pied de pagination
window.pano_PaginationFooter = ({ visibleCount, setVisibleCount, totalCount, step = 50 }) => {
    const { PlusIcon } = window.pano_getIcons();
    const { Button } = window.pano_getComponents();
    
    if (totalCount <= visibleCount) return null;
    
    const remaining = totalCount - visibleCount;
    const nextCount = Math.min(step, remaining);

    const labelText = nextCount > 1 
        ? `Afficher ${window.pano_formatPlural(nextCount, "résultat suivant", "résultats suivants")}` 
        : `Afficher le résultat suivant`;

    return (
        <div className="text-center pt-6 pb-12">
            <Button variant="outline" icon={PlusIcon} onClick={() => setVisibleCount(v => v + step)} className="mx-auto px-8 py-3 bg-white hover:bg-slate-50 shadow-sm">
                {labelText}
            </Button>
            <p className="text-xs text-slate-400 mt-3 font-bold">
                {visibleCount} affichés sur {totalCount}
            </p>
        </div>
    );
};

// 4. - LAYOUT PRINCIPAL (DASHBOARD SHELL)
window.pano_DashboardLayout = ({ role, user, theme = 'emerald', navItems, activeTab, setActiveTab, onLogout, customLogout, children, sidebarFooter }) => {
    const { LogOutIcon, XIcon, MenuIcon } = window.pano_getIcons();
    const { LogoSVG, NotificationBadge } = window.pano_getComponents();
    
    const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);
    
    const themeConfig = {
        emerald: { bg: 'bg-emerald-900', hover: 'hover:bg-emerald-800', active: 'bg-emerald-800 text-white border-emerald-400', text: 'text-emerald-100', border: 'border-emerald-800' },
        purple: { bg: 'bg-slate-900', hover: 'hover:bg-slate-800', active: 'bg-purple-600 text-white border-purple-400', text: 'text-slate-300', border: 'border-slate-800' },
        blue: { bg: 'bg-blue-900', hover: 'hover:bg-blue-800', active: 'bg-blue-800 text-white border-blue-400', text: 'text-blue-100', border: 'border-blue-800' }
    }[theme];

    return (
        <div className="absolute inset-0 flex bg-slate-50 overflow-x-hidden" style={{ '--sidebar-width': '18rem' }}>
            {/* 4.1 - Sidebar (Desktop) */}
            <aside className={`hidden lg:flex w-[var(--sidebar-width)] shrink-0 flex-col ${themeConfig.bg} text-white shadow-2xl z-20`}>
                <div className={`p-6 border-b ${themeConfig.border} flex items-center gap-4 shrink-0 select-none`}>
                    {LogoSVG && <LogoSVG size={40} className="shrink-0 drop-shadow-md" />}
                    <div className="min-w-0">
                        <h2 className="font-black text-lg break-words leading-tight uppercase tracking-widest">{role}</h2>
                        <p className={`text-xs ${themeConfig.text} break-words leading-tight`}>{user}</p>
                    </div>
                </div>
                
                <nav className="flex-1 min-h-0 p-4 space-y-2 overflow-y-auto custom-scrollbar">
                    {navItems.map(item => (
                        <div 
                            role="button"
                            tabIndex={0}
                            key={item.id} 
                            onClick={() => setActiveTab(item.id)} 
                            className={`w-full flex items-center gap-3 px-4 py-3.5 rounded-2xl transition font-bold border cursor-pointer select-none ${activeTab === item.id ? themeConfig.active : `border-transparent ${themeConfig.text} ${themeConfig.hover}`}`}
                        >
                            <span className={activeTab === item.id ? 'scale-110 transition-transform' : ''}>{item.icon}</span>
                            <span>{item.label}</span>
                            <div className="ml-auto flex items-center">
                                <NotificationBadge count={item.badge} />
                            </div>
                        </div>
                    ))}
                </nav>
                
                <div className={`p-4 border-t ${themeConfig.border} shrink-0 bg-black/10`}>
                    {sidebarFooter}
                    {customLogout ? (
                        <div role="button" tabIndex={0} onClick={customLogout.action} className={`w-full flex items-center gap-3 px-4 py-3 rounded-2xl transition font-bold cursor-pointer select-none ${customLogout.className}`}>
                            {customLogout.icon} {customLogout.label}
                        </div>
                    ) : (
                        <div role="button" tabIndex={0} onClick={onLogout} className={`w-full flex items-center gap-3 px-4 py-3 rounded-2xl ${themeConfig.text} ${themeConfig.hover} transition font-bold cursor-pointer select-none`}>
                            {LogOutIcon && <LogOutIcon size={18} />} Déconnexion
                        </div>
                    )}
                </div>
            </aside>

            {/* 4.2 - Contenu principal et Header Mobile */}
            <div className="flex-1 flex flex-col min-h-0 relative">
                <header className="lg:hidden sticky top-0 bg-white h-16 border-b border-slate-200 flex items-center justify-between px-4 shrink-0 z-[150] shadow-sm select-none">
                    <div className="flex items-center gap-3">
                        {LogoSVG && <LogoSVG size={32} />}
                        <div>
                            <p className="font-black text-slate-800 text-sm uppercase tracking-widest break-words leading-tight">{role}</p>
                            <p className="text-[10px] font-bold text-slate-500 break-words leading-tight max-w-[150px]">{user}</p>
                        </div>
                    </div>
                    <div role="button" tabIndex={0} onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} className="p-2 text-slate-600 bg-slate-100 rounded-xl cursor-pointer">
                        {isMobileMenuOpen ? (XIcon && <XIcon size={24} />) : (MenuIcon && <MenuIcon size={24} />)}
                    </div>
                </header>

                {isMobileMenuOpen && (
                    <div className="lg:hidden fixed top-0 left-0 w-full h-[100dvh] z-[140] bg-slate-900/95 backdrop-blur-sm animate-in fade-in flex flex-col pt-16">
                        <nav className="flex-1 min-h-0 p-4 space-y-2 overflow-y-auto select-none custom-scrollbar">
                            {navItems.map(item => (
                                <div 
                                    role="button"
                                    tabIndex={0}
                                    key={item.id} 
                                    onClick={() => { setActiveTab(item.id); setIsMobileMenuOpen(false); }} 
                                    className={`w-full flex items-center gap-3 px-4 py-4 rounded-2xl transition font-bold text-left cursor-pointer ${activeTab === item.id ? 'bg-emerald-500 text-white' : 'text-slate-300 hover:bg-slate-800'}`}
                                >
                                    {item.icon} <span>{item.label}</span>
                                    <div className="ml-auto flex items-center">
                                        <NotificationBadge count={item.badge} />
                                    </div>
                                </div>
                            ))}
                        </nav>
                        <div 
                            className="p-4 sm:p-6 border-t border-slate-800 shrink-0 bg-slate-900 select-none"
                            style={{ paddingBottom: 'calc(1.5rem + env(safe-area-inset-bottom, 0px))' }}
                        >
                            {sidebarFooter}
                            {customLogout ? (
                                <div 
                                    role="button" 
                                    tabIndex={0} 
                                    onClick={customLogout.action} 
                                    className={`w-full flex items-center justify-center gap-2 px-4 py-4 rounded-2xl font-bold mt-2 cursor-pointer ${customLogout.className}`}
                                >
                                    {customLogout.icon} {customLogout.label}
                                </div>
                            ) : (
                                <div 
                                    role="button" 
                                    tabIndex={0} 
                                    onClick={onLogout} 
                                    className="w-full flex items-center justify-center gap-2 px-4 py-4 rounded-2xl text-red-400 bg-red-500/10 font-bold mt-2 cursor-pointer"
                                >
                                    {LogOutIcon && <LogOutIcon size={20} />} Déconnexion
                                </div>
                            )}
                        </div>
                    </div>
                )}

                <main className="flex-1 overflow-y-auto p-4 sm:p-6 custom-scrollbar scroll-smooth">
                    {children}
                </main>
            </div>
        </div>
    );
};

/* EOF ========== [_react/ui/_ui_components.jsx] */